kpn updated this revision to Diff 205371.
kpn added a comment.
Add static methods to convert between a StringRef and the enums for
RoundingMode or ExceptionBehavior.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D53157/new/
https://reviews.llvm.org/D53157
Files:
include/llvm/IR/IRBuilder.h
include/llvm/IR/IntrinsicInst.h
lib/IR/IntrinsicInst.cpp
unittests/IR/IRBuilderTest.cpp
Index: unittests/IR/IRBuilderTest.cpp
===================================================================
--- unittests/IR/IRBuilderTest.cpp
+++ unittests/IR/IRBuilderTest.cpp
@@ -122,6 +122,70 @@
EXPECT_FALSE(II->hasNoNaNs());
}
+TEST_F(IRBuilderTest, ConstrainedFP) {
+ IRBuilder<> Builder(BB);
+ Value *V;
+ CallInst *Call;
+ IntrinsicInst *II;
+
+ V = Builder.CreateLoad(GV);
+
+ // See if we get constrained intrinsics instead of non-constrained
+ // instructions.
+ Builder.setIsFPConstrained(true);
+
+ V = Builder.CreateFAdd(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
+
+ V = Builder.CreateFSub(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fsub);
+
+ V = Builder.CreateFMul(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fmul);
+
+ V = Builder.CreateFDiv(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fdiv);
+
+ V = Builder.CreateFRem(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
+
+ // Verify the codepaths for setting and overriding the default metadata.
+ V = Builder.CreateFAdd(V, V);
+ ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+ auto *CII = cast<ConstrainedFPIntrinsic>(V);
+ ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict);
+ ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDynamic);
+
+ Builder.setDefaultConstrainedExcept(ConstrainedFPIntrinsic::ebIgnore);
+ Builder.setDefaultConstrainedRounding(ConstrainedFPIntrinsic::rmUpward);
+ V = Builder.CreateFAdd(V, V);
+ CII = cast<ConstrainedFPIntrinsic>(V);
+ ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore);
+ ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmUpward);
+
+ // Now override the defaults.
+ Call = Builder.CreateConstrainedFPBinOp(
+ Intrinsic::experimental_constrained_fadd, V, V, nullptr, "",
+ ConstrainedFPIntrinsic::rmDownward, ConstrainedFPIntrinsic::ebMayTrap);
+ CII = cast<ConstrainedFPIntrinsic>(Call);
+ EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
+ ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebMayTrap);
+ ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDownward);
+
+ Builder.CreateRetVoid();
+ EXPECT_FALSE(verifyModule(*M));
+}
+
TEST_F(IRBuilderTest, Lifetime) {
IRBuilder<> Builder(BB);
AllocaInst *Var1 = Builder.CreateAlloca(Builder.getInt8Ty());
Index: lib/IR/IntrinsicInst.cpp
===================================================================
--- lib/IR/IntrinsicInst.cpp
+++ lib/IR/IntrinsicInst.cpp
@@ -110,8 +110,11 @@
dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();
if (!MD || !isa<MDString>(MD))
return rmInvalid;
- StringRef RoundingArg = cast<MDString>(MD)->getString();
+ return StrToRoundingMode(cast<MDString>(MD)->getString());
+}
+ConstrainedFPIntrinsic::RoundingMode
+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<RoundingMode>(RoundingArg)
@@ -123,6 +126,30 @@
.Default(rmInvalid);
}
+StringRef
+ConstrainedFPIntrinsic::RoundingModeToStr(RoundingMode UseRounding) {
+ StringRef RoundingStr;
+ switch (UseRounding) {
+ case ConstrainedFPIntrinsic::rmUnspecified:
+ 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.tozero";
+ break;
+ }
+ return RoundingStr;
+}
+
ConstrainedFPIntrinsic::ExceptionBehavior
ConstrainedFPIntrinsic::getExceptionBehavior() const {
unsigned NumOperands = getNumArgOperands();
@@ -130,7 +157,11 @@
dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();
if (!MD || !isa<MDString>(MD))
return ebInvalid;
- StringRef ExceptionArg = cast<MDString>(MD)->getString();
+ return StrToExceptionBehavior(cast<MDString>(MD)->getString());
+}
+
+ConstrainedFPIntrinsic::ExceptionBehavior
+ConstrainedFPIntrinsic::StrToExceptionBehavior(StringRef ExceptionArg) {
return StringSwitch<ExceptionBehavior>(ExceptionArg)
.Case("fpexcept.ignore", ebIgnore)
.Case("fpexcept.maytrap", ebMayTrap)
@@ -138,6 +169,24 @@
.Default(ebInvalid);
}
+StringRef
+ConstrainedFPIntrinsic::ExceptionBehaviorToStr(ExceptionBehavior UseExcept) {
+ StringRef ExceptStr;
+ switch (UseExcept) {
+ case ConstrainedFPIntrinsic::ebUnspecified:
+ 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 {
switch (getIntrinsicID()) {
default:
Index: include/llvm/IR/IntrinsicInst.h
===================================================================
--- include/llvm/IR/IntrinsicInst.h
+++ include/llvm/IR/IntrinsicInst.h
@@ -208,20 +208,30 @@
/// This is the common base class for constrained floating point intrinsics.
class ConstrainedFPIntrinsic : public IntrinsicInst {
public:
- enum RoundingMode {
- rmInvalid,
- rmDynamic,
- rmToNearest,
- rmDownward,
- rmUpward,
- rmTowardZero
+ /// 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 {
+ rmUnspecified = 0, ///< Use as a placeholder to not affect rounding
+ ///< behavior in the IRBuilder.
+ rmInvalid = 0,
+ 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".
};
- enum ExceptionBehavior {
- ebInvalid,
- ebIgnore,
- ebMayTrap,
- ebStrict
+ /// 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 {
+ ebUnspecified = 0, ///< Use as a placeholder to not affect exception
+ ///< behavior in the IRBuilder.
+ ebInvalid = 0,
+ ebIgnore, ///< This corresponds to "fpexcept.ignore".
+ ebMayTrap, ///< This corresponds to "fpexcept.maytrap".
+ ebStrict ///< This corresponds to "fpexcept.strict".
};
bool isUnaryOp() const;
@@ -229,6 +239,11 @@
RoundingMode getRoundingMode() const;
ExceptionBehavior getExceptionBehavior() const;
+ static RoundingMode StrToRoundingMode(StringRef);
+ static StringRef RoundingModeToStr(RoundingMode);
+ static ExceptionBehavior StrToExceptionBehavior(StringRef);
+ static StringRef ExceptionBehaviorToStr(ExceptionBehavior);
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
Index: include/llvm/IR/IRBuilder.h
===================================================================
--- include/llvm/IR/IRBuilder.h
+++ include/llvm/IR/IRBuilder.h
@@ -31,7 +31,7 @@
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
@@ -96,12 +96,18 @@
MDNode *DefaultFPMathTag;
FastMathFlags FMF;
+ bool IsFPConstrained;
+ ConstrainedFPIntrinsic::ExceptionBehavior DefaultConstrainedExcept;
+ ConstrainedFPIntrinsic::RoundingMode DefaultConstrainedRounding;
+
ArrayRef<OperandBundleDef> DefaultOperandBundles;
public:
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
- : Context(context), DefaultFPMathTag(FPMathTag),
+ : Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false),
+ DefaultConstrainedExcept(ConstrainedFPIntrinsic::ebUnspecified),
+ DefaultConstrainedRounding(ConstrainedFPIntrinsic::rmUnspecified),
DefaultOperandBundles(OpBundles) {
ClearInsertionPoint();
}
@@ -218,6 +224,36 @@
/// Set the fast-math flags to be used with generated fp-math operators
void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; }
+ /// Enable/Disable use of constrained floating point math. When
+ /// enabled the CreateF<op>() calls instead create constrained
+ /// floating point intrinsic calls.
+ void setIsFPConstrained(bool IsCon) { IsFPConstrained = IsCon; }
+
+ /// Query for the use of constrained floating point math
+ bool getIsFPConstrained() { return IsFPConstrained; }
+
+ /// Set the exception handling to be used with constrained floating point
+ void setDefaultConstrainedExcept(
+ ConstrainedFPIntrinsic::ExceptionBehavior NewExcept) {
+ DefaultConstrainedExcept = NewExcept;
+ }
+
+ /// Set the rounding mode handling to be used with constrained floating point
+ void setDefaultConstrainedRounding(
+ ConstrainedFPIntrinsic::RoundingMode NewRounding) {
+ DefaultConstrainedRounding = NewRounding;
+ }
+
+ /// Get the exception handling used with constrained floating point
+ ConstrainedFPIntrinsic::ExceptionBehavior getDefaultConstrainedExcept() {
+ return DefaultConstrainedExcept;
+ }
+
+ /// Get the rounding mode handling used with constrained floating point
+ ConstrainedFPIntrinsic::RoundingMode getDefaultConstrainedRounding() {
+ return DefaultConstrainedRounding;
+ }
+
//===--------------------------------------------------------------------===//
// RAII helpers.
//===--------------------------------------------------------------------===//
@@ -1045,6 +1081,35 @@
return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr;
}
+ Value *
+ getConstrainedFPRounding(ConstrainedFPIntrinsic::RoundingMode Rounding) {
+ // ConstrainedRoundingKind UseRounding = DefaultConstrainedRounding;
+ ConstrainedFPIntrinsic::RoundingMode UseRounding =
+ DefaultConstrainedRounding;
+
+ if (Rounding != ConstrainedFPIntrinsic::rmUnspecified)
+ UseRounding = Rounding;
+
+ auto RoundingStr = ConstrainedFPIntrinsic::RoundingModeToStr(UseRounding);
+ auto *RoundingMDS = MDString::get(Context, RoundingStr);
+
+ return MetadataAsValue::get(Context, RoundingMDS);
+ }
+
+ Value *
+ getConstrainedFPExcept(ConstrainedFPIntrinsic::ExceptionBehavior Except) {
+ ConstrainedFPIntrinsic::ExceptionBehavior UseExcept =
+ DefaultConstrainedExcept;
+
+ if (Except != ConstrainedFPIntrinsic::ebUnspecified)
+ UseExcept = Except;
+
+ auto ExceptStr = ConstrainedFPIntrinsic::ExceptionBehaviorToStr(UseExcept);
+ auto *ExceptMDS = MDString::get(Context, ExceptStr);
+
+ return MetadataAsValue::get(Context, ExceptMDS);
+ }
+
public:
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
@@ -1247,6 +1312,10 @@
Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1256,6 +1325,10 @@
/// default FMF.
Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
+ L, R, FMFSource, Name);
+
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr,
FMFSource->getFastMathFlags());
@@ -1264,6 +1337,10 @@
Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1273,6 +1350,10 @@
/// default FMF.
Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
+ L, R, FMFSource, Name);
+
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr,
FMFSource->getFastMathFlags());
@@ -1281,6 +1362,10 @@
Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1290,6 +1375,10 @@
/// default FMF.
Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
+ L, R, FMFSource, Name);
+
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr,
FMFSource->getFastMathFlags());
@@ -1298,6 +1387,10 @@
Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1307,6 +1400,10 @@
/// default FMF.
Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
+ L, R, FMFSource, Name);
+
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr,
FMFSource->getFastMathFlags());
@@ -1315,6 +1412,10 @@
Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1324,6 +1425,10 @@
/// default FMF.
Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
+ L, R, FMFSource, Name);
+
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr,
FMFSource->getFastMathFlags());
@@ -1340,6 +1445,21 @@
return Insert(BinOp, Name);
}
+ CallInst *
+ CreateConstrainedFPBinOp(Intrinsic::ID ID, Value *L, Value *R,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "",
+ ConstrainedFPIntrinsic::RoundingMode Rounding =
+ ConstrainedFPIntrinsic::rmUnspecified,
+ ConstrainedFPIntrinsic::ExceptionBehavior Except =
+ ConstrainedFPIntrinsic::ebUnspecified) {
+ Value *RoundingV = getConstrainedFPRounding(Rounding);
+ Value *ExceptV = getConstrainedFPExcept(Except);
+
+ return CreateIntrinsic(ID, {L->getType()}, {L, R, RoundingV, ExceptV},
+ FMFSource, Name);
+ }
+
Value *CreateNeg(Value *V, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
if (auto *VC = dyn_cast<Constant>(V))
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits