Move floating point related entities to namespace level

Enumerations that describe rounding mode and exception behavior were
defined inside ConstrainedFPIntrinsic. It makes sense to use the same
definitions to represent the same properties in other cases, not only
in constrained intrinsics. It was however inconvenient as required to
include constrained intrinsics definitions even if they were not needed.
Also using long scope prefix reduced readability.

This change moves these definitioins to the namespace llvm::fp.
No functional changes.

Differential Revision: https://reviews.llvm.org/D69552
This commit is contained in:
Serge Pavlov 2019-08-29 19:29:11 +07:00
parent 0df4a8f72a
commit e6584b2b7b
9 changed files with 211 additions and 177 deletions

View File

@ -33,6 +33,7 @@
#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/IR/DataLayout.h" #include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h" #include "llvm/IR/Dominators.h"
#include "llvm/IR/FPEnv.h"
#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h" #include "llvm/IR/MDBuilder.h"
@ -106,36 +107,28 @@ CodeGenFunction::~CodeGenFunction() {
// Map the LangOption for rounding mode into // Map the LangOption for rounding mode into
// the corresponding enum in the IR. // the corresponding enum in the IR.
static llvm::ConstrainedFPIntrinsic::RoundingMode ToConstrainedRoundingMD( static llvm::fp::RoundingMode ToConstrainedRoundingMD(
LangOptions::FPRoundingModeKind Kind) { LangOptions::FPRoundingModeKind Kind) {
switch (Kind) { switch (Kind) {
case LangOptions::FPR_ToNearest: case LangOptions::FPR_ToNearest: return llvm::fp::rmToNearest;
return llvm::ConstrainedFPIntrinsic::rmToNearest; case LangOptions::FPR_Downward: return llvm::fp::rmDownward;
case LangOptions::FPR_Downward: case LangOptions::FPR_Upward: return llvm::fp::rmUpward;
return llvm::ConstrainedFPIntrinsic::rmDownward; case LangOptions::FPR_TowardZero: return llvm::fp::rmTowardZero;
case LangOptions::FPR_Upward: case LangOptions::FPR_Dynamic: return llvm::fp::rmDynamic;
return llvm::ConstrainedFPIntrinsic::rmUpward;
case LangOptions::FPR_TowardZero:
return llvm::ConstrainedFPIntrinsic::rmTowardZero;
case LangOptions::FPR_Dynamic:
return llvm::ConstrainedFPIntrinsic::rmDynamic;
} }
llvm_unreachable("Unsupported FP RoundingMode"); llvm_unreachable("Unsupported FP RoundingMode");
} }
// Map the LangOption for exception behavior into // Map the LangOption for exception behavior into
// the corresponding enum in the IR. // the corresponding enum in the IR.
static llvm::ConstrainedFPIntrinsic::ExceptionBehavior ToConstrainedExceptMD( static llvm::fp::ExceptionBehavior ToConstrainedExceptMD(
LangOptions::FPExceptionModeKind Kind) { LangOptions::FPExceptionModeKind Kind) {
switch (Kind) { switch (Kind) {
case LangOptions::FPE_Ignore: case LangOptions::FPE_Ignore: return llvm::fp::ebIgnore;
return llvm::ConstrainedFPIntrinsic::ebIgnore; case LangOptions::FPE_MayTrap: return llvm::fp::ebMayTrap;
case LangOptions::FPE_MayTrap: case LangOptions::FPE_Strict: return llvm::fp::ebStrict;
return llvm::ConstrainedFPIntrinsic::ebMayTrap;
case LangOptions::FPE_Strict:
return llvm::ConstrainedFPIntrinsic::ebStrict;
} }
llvm_unreachable("Unsupported FP Exception Behavior"); llvm_unreachable("Unsupported FP Exception Behavior");
} }
@ -146,8 +139,8 @@ void CodeGenFunction::SetFPModel() {
auto fpExceptionBehavior = ToConstrainedExceptMD( auto fpExceptionBehavior = ToConstrainedExceptMD(
getLangOpts().getFPExceptionMode()); getLangOpts().getFPExceptionMode());
if (fpExceptionBehavior == llvm::ConstrainedFPIntrinsic::ebIgnore && if (fpExceptionBehavior == llvm::fp::ebIgnore &&
fpRoundingMode == llvm::ConstrainedFPIntrinsic::rmToNearest) fpRoundingMode == llvm::fp::rmToNearest)
// Constrained intrinsics are not used. // Constrained intrinsics are not used.
; ;
else { else {

View File

@ -0,0 +1,70 @@
//===- FPEnv.h ---- FP Environment ------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// @file
/// This file contains the declarations of entities that describe floating
/// point environment and related functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_IR_FLOATINGPOINT_H
#define LLVM_IR_FLOATINGPOINT_H
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include <stdint.h>
namespace llvm {
namespace fp {
/// Rounding mode used for floating point operations.
///
/// Each of these values correspond to some metadata argument value of a
/// constrained floating point intrinsic. See the LLVM Language Reference Manual
/// for details.
enum RoundingMode : uint8_t {
rmDynamic, ///< This corresponds to "fpround.dynamic".
rmToNearest, ///< This corresponds to "fpround.tonearest".
rmDownward, ///< This corresponds to "fpround.downward".
rmUpward, ///< This corresponds to "fpround.upward".
rmTowardZero ///< This corresponds to "fpround.tozero".
};
/// Exception behavior used for floating point operations.
///
/// Each of these values correspond to some metadata argument value of a
/// constrained floating point intrinsic. See the LLVM Language Reference Manual
/// for details.
enum ExceptionBehavior : uint8_t {
ebIgnore, ///< This corresponds to "fpexcept.ignore".
ebMayTrap, ///< This corresponds to "fpexcept.maytrap".
ebStrict ///< This corresponds to "fpexcept.strict".
};
}
/// Returns a valid RoundingMode enumerator when given a string
/// that is valid as input in constrained intrinsic rounding mode
/// metadata.
Optional<fp::RoundingMode> StrToRoundingMode(StringRef);
/// For any RoundingMode enumerator, returns a string valid as input in
/// constrained intrinsic rounding mode metadata.
Optional<StringRef> RoundingModeToStr(fp::RoundingMode);
/// Returns a valid ExceptionBehavior enumerator when given a string
/// valid as input in constrained intrinsic exception behavior metadata.
Optional<fp::ExceptionBehavior> StrToExceptionBehavior(StringRef);
/// For any ExceptionBehavior enumerator, returns a string valid as
/// input in constrained intrinsic exception behavior metadata.
Optional<StringRef> ExceptionBehaviorToStr(fp::ExceptionBehavior);
}
#endif

View File

@ -97,8 +97,8 @@ protected:
FastMathFlags FMF; FastMathFlags FMF;
bool IsFPConstrained; bool IsFPConstrained;
ConstrainedFPIntrinsic::ExceptionBehavior DefaultConstrainedExcept; fp::ExceptionBehavior DefaultConstrainedExcept;
ConstrainedFPIntrinsic::RoundingMode DefaultConstrainedRounding; fp::RoundingMode DefaultConstrainedRounding;
ArrayRef<OperandBundleDef> DefaultOperandBundles; ArrayRef<OperandBundleDef> DefaultOperandBundles;
@ -106,8 +106,8 @@ public:
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr, IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None) ArrayRef<OperandBundleDef> OpBundles = None)
: Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false), : Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false),
DefaultConstrainedExcept(ConstrainedFPIntrinsic::ebStrict), DefaultConstrainedExcept(fp::ebStrict),
DefaultConstrainedRounding(ConstrainedFPIntrinsic::rmDynamic), DefaultConstrainedRounding(fp::rmDynamic),
DefaultOperandBundles(OpBundles) { DefaultOperandBundles(OpBundles) {
ClearInsertionPoint(); ClearInsertionPoint();
} }
@ -234,24 +234,22 @@ public:
bool getIsFPConstrained() { return IsFPConstrained; } bool getIsFPConstrained() { return IsFPConstrained; }
/// Set the exception handling to be used with constrained floating point /// Set the exception handling to be used with constrained floating point
void setDefaultConstrainedExcept( void setDefaultConstrainedExcept(fp::ExceptionBehavior NewExcept) {
ConstrainedFPIntrinsic::ExceptionBehavior NewExcept) {
DefaultConstrainedExcept = NewExcept; DefaultConstrainedExcept = NewExcept;
} }
/// Set the rounding mode handling to be used with constrained floating point /// Set the rounding mode handling to be used with constrained floating point
void setDefaultConstrainedRounding( void setDefaultConstrainedRounding(fp::RoundingMode NewRounding) {
ConstrainedFPIntrinsic::RoundingMode NewRounding) {
DefaultConstrainedRounding = NewRounding; DefaultConstrainedRounding = NewRounding;
} }
/// Get the exception handling used with constrained floating point /// Get the exception handling used with constrained floating point
ConstrainedFPIntrinsic::ExceptionBehavior getDefaultConstrainedExcept() { fp::ExceptionBehavior getDefaultConstrainedExcept() {
return DefaultConstrainedExcept; return DefaultConstrainedExcept;
} }
/// Get the rounding mode handling used with constrained floating point /// Get the rounding mode handling used with constrained floating point
ConstrainedFPIntrinsic::RoundingMode getDefaultConstrainedRounding() { fp::RoundingMode getDefaultConstrainedRounding() {
return DefaultConstrainedRounding; return DefaultConstrainedRounding;
} }
@ -1097,32 +1095,26 @@ private:
return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr;
} }
Value *getConstrainedFPRounding( Value *getConstrainedFPRounding(Optional<fp::RoundingMode> Rounding) {
Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding) { fp::RoundingMode UseRounding = DefaultConstrainedRounding;
ConstrainedFPIntrinsic::RoundingMode UseRounding =
DefaultConstrainedRounding;
if (Rounding.hasValue()) if (Rounding.hasValue())
UseRounding = Rounding.getValue(); UseRounding = Rounding.getValue();
Optional<StringRef> RoundingStr = Optional<StringRef> RoundingStr = RoundingModeToStr(UseRounding);
ConstrainedFPIntrinsic::RoundingModeToStr(UseRounding);
assert(RoundingStr.hasValue() && "Garbage strict rounding mode!"); assert(RoundingStr.hasValue() && "Garbage strict rounding mode!");
auto *RoundingMDS = MDString::get(Context, RoundingStr.getValue()); auto *RoundingMDS = MDString::get(Context, RoundingStr.getValue());
return MetadataAsValue::get(Context, RoundingMDS); return MetadataAsValue::get(Context, RoundingMDS);
} }
Value *getConstrainedFPExcept( Value *getConstrainedFPExcept(Optional<fp::ExceptionBehavior> Except) {
Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except) { fp::ExceptionBehavior UseExcept = DefaultConstrainedExcept;
ConstrainedFPIntrinsic::ExceptionBehavior UseExcept =
DefaultConstrainedExcept;
if (Except.hasValue()) if (Except.hasValue())
UseExcept = Except.getValue(); UseExcept = Except.getValue();
Optional<StringRef> ExceptStr = Optional<StringRef> ExceptStr = ExceptionBehaviorToStr(UseExcept);
ConstrainedFPIntrinsic::ExceptionBehaviorToStr(UseExcept);
assert(ExceptStr.hasValue() && "Garbage strict exception behavior!"); assert(ExceptStr.hasValue() && "Garbage strict exception behavior!");
auto *ExceptMDS = MDString::get(Context, ExceptStr.getValue()); auto *ExceptMDS = MDString::get(Context, ExceptStr.getValue());
@ -1483,8 +1475,8 @@ public:
CallInst *CreateConstrainedFPBinOp( CallInst *CreateConstrainedFPBinOp(
Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr, Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr,
const Twine &Name = "", MDNode *FPMathTag = nullptr, const Twine &Name = "", MDNode *FPMathTag = nullptr,
Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding = None, Optional<fp::RoundingMode> Rounding = None,
Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except = None) { Optional<fp::ExceptionBehavior> Except = None) {
Value *RoundingV = getConstrainedFPRounding(Rounding); Value *RoundingV = getConstrainedFPRounding(Rounding);
Value *ExceptV = getConstrainedFPExcept(Except); Value *ExceptV = getConstrainedFPExcept(Except);
@ -2078,8 +2070,8 @@ public:
Intrinsic::ID ID, Value *V, Type *DestTy, Intrinsic::ID ID, Value *V, Type *DestTy,
Instruction *FMFSource = nullptr, const Twine &Name = "", Instruction *FMFSource = nullptr, const Twine &Name = "",
MDNode *FPMathTag = nullptr, MDNode *FPMathTag = nullptr,
Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding = None, Optional<fp::RoundingMode> Rounding = None,
Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except = None) { Optional<fp::ExceptionBehavior> Except = None) {
Value *ExceptV = getConstrainedFPExcept(Except); Value *ExceptV = getConstrainedFPExcept(Except);
FastMathFlags UseFMF = FMF; FastMathFlags UseFMF = FMF;

View File

@ -25,6 +25,7 @@
#include "llvm/IR/Constants.h" #include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/FPEnv.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
@ -208,47 +209,10 @@ namespace llvm {
/// This is the common base class for constrained floating point intrinsics. /// This is the common base class for constrained floating point intrinsics.
class ConstrainedFPIntrinsic : public IntrinsicInst { class ConstrainedFPIntrinsic : public IntrinsicInst {
public: public:
/// Specifies the rounding mode to be assumed. This is only used when
/// when constrained floating point is enabled. See the LLVM Language
/// Reference Manual for details.
enum RoundingMode : uint8_t {
rmDynamic, ///< This corresponds to "fpround.dynamic".
rmToNearest, ///< This corresponds to "fpround.tonearest".
rmDownward, ///< This corresponds to "fpround.downward".
rmUpward, ///< This corresponds to "fpround.upward".
rmTowardZero ///< This corresponds to "fpround.tozero".
};
/// Specifies the required exception behavior. This is only used when
/// when constrained floating point is used. See the LLVM Language
/// Reference Manual for details.
enum ExceptionBehavior : uint8_t {
ebIgnore, ///< This corresponds to "fpexcept.ignore".
ebMayTrap, ///< This corresponds to "fpexcept.maytrap".
ebStrict ///< This corresponds to "fpexcept.strict".
};
bool isUnaryOp() const; bool isUnaryOp() const;
bool isTernaryOp() const; bool isTernaryOp() const;
Optional<RoundingMode> getRoundingMode() const; Optional<fp::RoundingMode> getRoundingMode() const;
Optional<ExceptionBehavior> getExceptionBehavior() const; Optional<fp::ExceptionBehavior> getExceptionBehavior() const;
/// Returns a valid RoundingMode enumerator when given a string
/// that is valid as input in constrained intrinsic rounding mode
/// metadata.
static Optional<RoundingMode> StrToRoundingMode(StringRef);
/// For any RoundingMode enumerator, returns a string valid as input in
/// constrained intrinsic rounding mode metadata.
static Optional<StringRef> RoundingModeToStr(RoundingMode);
/// Returns a valid ExceptionBehavior enumerator when given a string
/// valid as input in constrained intrinsic exception behavior metadata.
static Optional<ExceptionBehavior> StrToExceptionBehavior(StringRef);
/// For any ExceptionBehavior enumerator, returns a string valid as
/// input in constrained intrinsic exception behavior metadata.
static Optional<StringRef> ExceptionBehaviorToStr(ExceptionBehavior);
// Methods for support type inquiry through isa, cast, and dyn_cast: // Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) { static bool classof(const IntrinsicInst *I) {

View File

@ -7020,8 +7020,7 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
SDVTList VTs = DAG.getVTList(ValueVTs); SDVTList VTs = DAG.getVTList(ValueVTs);
SDValue Result = DAG.getNode(Opcode, sdl, VTs, Opers); SDValue Result = DAG.getNode(Opcode, sdl, VTs, Opers);
if (FPI.getExceptionBehavior() != if (FPI.getExceptionBehavior() != fp::ExceptionBehavior::ebIgnore) {
ConstrainedFPIntrinsic::ExceptionBehavior::ebIgnore) {
SDNodeFlags Flags; SDNodeFlags Flags;
Flags.setFPExcept(true); Flags.setFPExcept(true);
Result->setFlags(Flags); Result->setFlags(Flags);

View File

@ -22,6 +22,7 @@ add_llvm_library(LLVMCore
DiagnosticInfo.cpp DiagnosticInfo.cpp
DiagnosticPrinter.cpp DiagnosticPrinter.cpp
Dominators.cpp Dominators.cpp
FPEnv.cpp
Function.cpp Function.cpp
GVMaterializer.cpp GVMaterializer.cpp
Globals.cpp Globals.cpp

78
llvm/lib/IR/FPEnv.cpp Normal file
View File

@ -0,0 +1,78 @@
//===-- FPEnv.cpp ---- FP Environment -------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
/// @file
/// This file contains the implementations of entities that describe floating
/// point environment.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/FPEnv.h"
namespace llvm {
Optional<fp::RoundingMode> StrToRoundingMode(StringRef RoundingArg) {
// For dynamic rounding mode, we use round to nearest but we will set the
// 'exact' SDNodeFlag so that the value will not be rounded.
return StringSwitch<Optional<fp::RoundingMode>>(RoundingArg)
.Case("round.dynamic", fp::rmDynamic)
.Case("round.tonearest", fp::rmToNearest)
.Case("round.downward", fp::rmDownward)
.Case("round.upward", fp::rmUpward)
.Case("round.towardzero", fp::rmTowardZero)
.Default(None);
}
Optional<StringRef> RoundingModeToStr(fp::RoundingMode UseRounding) {
Optional<StringRef> RoundingStr = None;
switch (UseRounding) {
case fp::rmDynamic:
RoundingStr = "round.dynamic";
break;
case fp::rmToNearest:
RoundingStr = "round.tonearest";
break;
case fp::rmDownward:
RoundingStr = "round.downward";
break;
case fp::rmUpward:
RoundingStr = "round.upward";
break;
case fp::rmTowardZero:
RoundingStr = "round.towardzero";
break;
}
return RoundingStr;
}
Optional<fp::ExceptionBehavior> StrToExceptionBehavior(StringRef ExceptionArg) {
return StringSwitch<Optional<fp::ExceptionBehavior>>(ExceptionArg)
.Case("fpexcept.ignore", fp::ebIgnore)
.Case("fpexcept.maytrap", fp::ebMayTrap)
.Case("fpexcept.strict", fp::ebStrict)
.Default(None);
}
Optional<StringRef> ExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
Optional<StringRef> ExceptStr = None;
switch (UseExcept) {
case fp::ebStrict:
ExceptStr = "fpexcept.strict";
break;
case fp::ebIgnore:
ExceptStr = "fpexcept.ignore";
break;
case fp::ebMayTrap:
ExceptStr = "fpexcept.maytrap";
break;
}
return ExceptStr;
}
}

View File

@ -102,8 +102,7 @@ Value *InstrProfIncrementInst::getStep() const {
return ConstantInt::get(Type::getInt64Ty(Context), 1); return ConstantInt::get(Type::getInt64Ty(Context), 1);
} }
Optional<ConstrainedFPIntrinsic::RoundingMode> Optional<fp::RoundingMode> ConstrainedFPIntrinsic::getRoundingMode() const {
ConstrainedFPIntrinsic::getRoundingMode() const {
unsigned NumOperands = getNumArgOperands(); unsigned NumOperands = getNumArgOperands();
Metadata *MD = Metadata *MD =
cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata(); cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
@ -112,43 +111,7 @@ ConstrainedFPIntrinsic::getRoundingMode() const {
return StrToRoundingMode(cast<MDString>(MD)->getString()); return StrToRoundingMode(cast<MDString>(MD)->getString());
} }
Optional<ConstrainedFPIntrinsic::RoundingMode> Optional<fp::ExceptionBehavior>
ConstrainedFPIntrinsic::StrToRoundingMode(StringRef RoundingArg) {
// For dynamic rounding mode, we use round to nearest but we will set the
// 'exact' SDNodeFlag so that the value will not be rounded.
return StringSwitch<Optional<RoundingMode>>(RoundingArg)
.Case("round.dynamic", rmDynamic)
.Case("round.tonearest", rmToNearest)
.Case("round.downward", rmDownward)
.Case("round.upward", rmUpward)
.Case("round.towardzero", rmTowardZero)
.Default(None);
}
Optional<StringRef>
ConstrainedFPIntrinsic::RoundingModeToStr(RoundingMode UseRounding) {
Optional<StringRef> RoundingStr = None;
switch (UseRounding) {
case ConstrainedFPIntrinsic::rmDynamic:
RoundingStr = "round.dynamic";
break;
case ConstrainedFPIntrinsic::rmToNearest:
RoundingStr = "round.tonearest";
break;
case ConstrainedFPIntrinsic::rmDownward:
RoundingStr = "round.downward";
break;
case ConstrainedFPIntrinsic::rmUpward:
RoundingStr = "round.upward";
break;
case ConstrainedFPIntrinsic::rmTowardZero:
RoundingStr = "round.towardzero";
break;
}
return RoundingStr;
}
Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
ConstrainedFPIntrinsic::getExceptionBehavior() const { ConstrainedFPIntrinsic::getExceptionBehavior() const {
unsigned NumOperands = getNumArgOperands(); unsigned NumOperands = getNumArgOperands();
Metadata *MD = Metadata *MD =
@ -158,32 +121,6 @@ ConstrainedFPIntrinsic::getExceptionBehavior() const {
return StrToExceptionBehavior(cast<MDString>(MD)->getString()); return StrToExceptionBehavior(cast<MDString>(MD)->getString());
} }
Optional<ConstrainedFPIntrinsic::ExceptionBehavior>
ConstrainedFPIntrinsic::StrToExceptionBehavior(StringRef ExceptionArg) {
return StringSwitch<Optional<ExceptionBehavior>>(ExceptionArg)
.Case("fpexcept.ignore", ebIgnore)
.Case("fpexcept.maytrap", ebMayTrap)
.Case("fpexcept.strict", ebStrict)
.Default(None);
}
Optional<StringRef>
ConstrainedFPIntrinsic::ExceptionBehaviorToStr(ExceptionBehavior UseExcept) {
Optional<StringRef> ExceptStr = None;
switch (UseExcept) {
case ConstrainedFPIntrinsic::ebStrict:
ExceptStr = "fpexcept.strict";
break;
case ConstrainedFPIntrinsic::ebIgnore:
ExceptStr = "fpexcept.ignore";
break;
case ConstrainedFPIntrinsic::ebMayTrap:
ExceptStr = "fpexcept.maytrap";
break;
}
return ExceptStr;
}
bool ConstrainedFPIntrinsic::isUnaryOp() const { bool ConstrainedFPIntrinsic::isUnaryOp() const {
switch (getIntrinsicID()) { switch (getIntrinsicID()) {
default: default:

View File

@ -242,52 +242,52 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
V = Builder.CreateFAdd(V, V); V = Builder.CreateFAdd(V, V);
ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V)); ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
auto *CII = cast<ConstrainedFPIntrinsic>(V); auto *CII = cast<ConstrainedFPIntrinsic>(V);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict); EXPECT_EQ(fp::ebStrict, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDynamic); EXPECT_EQ(fp::rmDynamic, CII->getRoundingMode());
Builder.setDefaultConstrainedExcept(ConstrainedFPIntrinsic::ebIgnore); Builder.setDefaultConstrainedExcept(fp::ebIgnore);
Builder.setDefaultConstrainedRounding(ConstrainedFPIntrinsic::rmUpward); Builder.setDefaultConstrainedRounding(fp::rmUpward);
V = Builder.CreateFAdd(V, V); V = Builder.CreateFAdd(V, V);
CII = cast<ConstrainedFPIntrinsic>(V); CII = cast<ConstrainedFPIntrinsic>(V);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore); EXPECT_EQ(fp::ebIgnore, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmUpward); EXPECT_EQ(CII->getRoundingMode(), fp::rmUpward);
Builder.setDefaultConstrainedExcept(ConstrainedFPIntrinsic::ebIgnore); Builder.setDefaultConstrainedExcept(fp::ebIgnore);
Builder.setDefaultConstrainedRounding(ConstrainedFPIntrinsic::rmToNearest); Builder.setDefaultConstrainedRounding(fp::rmToNearest);
V = Builder.CreateFAdd(V, V); V = Builder.CreateFAdd(V, V);
CII = cast<ConstrainedFPIntrinsic>(V); CII = cast<ConstrainedFPIntrinsic>(V);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore); EXPECT_EQ(fp::ebIgnore, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmToNearest); EXPECT_EQ(fp::rmToNearest, CII->getRoundingMode());
Builder.setDefaultConstrainedExcept(ConstrainedFPIntrinsic::ebMayTrap); Builder.setDefaultConstrainedExcept(fp::ebMayTrap);
Builder.setDefaultConstrainedRounding(ConstrainedFPIntrinsic::rmDownward); Builder.setDefaultConstrainedRounding(fp::rmDownward);
V = Builder.CreateFAdd(V, V); V = Builder.CreateFAdd(V, V);
CII = cast<ConstrainedFPIntrinsic>(V); CII = cast<ConstrainedFPIntrinsic>(V);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebMayTrap); EXPECT_EQ(fp::ebMayTrap, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDownward); EXPECT_EQ(fp::rmDownward, CII->getRoundingMode());
Builder.setDefaultConstrainedExcept(ConstrainedFPIntrinsic::ebStrict); Builder.setDefaultConstrainedExcept(fp::ebStrict);
Builder.setDefaultConstrainedRounding(ConstrainedFPIntrinsic::rmTowardZero); Builder.setDefaultConstrainedRounding(fp::rmTowardZero);
V = Builder.CreateFAdd(V, V); V = Builder.CreateFAdd(V, V);
CII = cast<ConstrainedFPIntrinsic>(V); CII = cast<ConstrainedFPIntrinsic>(V);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict); EXPECT_EQ(fp::ebStrict, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmTowardZero); EXPECT_EQ(fp::rmTowardZero, CII->getRoundingMode());
Builder.setDefaultConstrainedExcept(ConstrainedFPIntrinsic::ebIgnore); Builder.setDefaultConstrainedExcept(fp::ebIgnore);
Builder.setDefaultConstrainedRounding(ConstrainedFPIntrinsic::rmDynamic); Builder.setDefaultConstrainedRounding(fp::rmDynamic);
V = Builder.CreateFAdd(V, V); V = Builder.CreateFAdd(V, V);
CII = cast<ConstrainedFPIntrinsic>(V); CII = cast<ConstrainedFPIntrinsic>(V);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore); EXPECT_EQ(fp::ebIgnore, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDynamic); EXPECT_EQ(fp::rmDynamic, CII->getRoundingMode());
// Now override the defaults. // Now override the defaults.
Call = Builder.CreateConstrainedFPBinOp( Call = Builder.CreateConstrainedFPBinOp(
Intrinsic::experimental_constrained_fadd, V, V, nullptr, "", nullptr, Intrinsic::experimental_constrained_fadd, V, V, nullptr, "", nullptr,
ConstrainedFPIntrinsic::rmDownward, ConstrainedFPIntrinsic::ebMayTrap); fp::rmDownward, fp::ebMayTrap);
CII = cast<ConstrainedFPIntrinsic>(Call); CII = cast<ConstrainedFPIntrinsic>(Call);
EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd); EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebMayTrap); EXPECT_EQ(fp::ebMayTrap, CII->getExceptionBehavior());
ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDownward); EXPECT_EQ(fp::rmDownward, CII->getRoundingMode());
Builder.CreateRetVoid(); Builder.CreateRetVoid();
EXPECT_FALSE(verifyModule(*M)); EXPECT_FALSE(verifyModule(*M));