forked from OSchip/llvm-project
[FPEnv] Teach the IRBuilder about constrained FPTrunc and FPExt
The IRBuilder doesn't know that FPTrunc and FPExt have constrained equivalents. Add the support by building on the strict FP mode now present in the IRBuilder. Reviewed by: John McCall Approved by: John McCall Differential Revision: https://reviews.llvm.org/D64934 llvm-svn: 366477
This commit is contained in:
parent
e21fc8770c
commit
d91998a5ac
|
@ -1931,10 +1931,17 @@ public:
|
||||||
|
|
||||||
Value *CreateFPTrunc(Value *V, Type *DestTy,
|
Value *CreateFPTrunc(Value *V, Type *DestTy,
|
||||||
const Twine &Name = "") {
|
const Twine &Name = "") {
|
||||||
|
if (IsFPConstrained)
|
||||||
|
return CreateConstrainedFPCast(
|
||||||
|
Intrinsic::experimental_constrained_fptrunc, V, DestTy, nullptr,
|
||||||
|
Name);
|
||||||
return CreateCast(Instruction::FPTrunc, V, DestTy, Name);
|
return CreateCast(Instruction::FPTrunc, V, DestTy, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") {
|
Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") {
|
||||||
|
if (IsFPConstrained)
|
||||||
|
return CreateConstrainedFPCast(Intrinsic::experimental_constrained_fpext,
|
||||||
|
V, DestTy, nullptr, Name);
|
||||||
return CreateCast(Instruction::FPExt, V, DestTy, Name);
|
return CreateCast(Instruction::FPExt, V, DestTy, Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2046,6 +2053,29 @@ public:
|
||||||
return Insert(CastInst::CreateFPCast(V, DestTy), Name);
|
return Insert(CastInst::CreateFPCast(V, DestTy), Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CallInst *CreateConstrainedFPCast(
|
||||||
|
Intrinsic::ID ID, Value *V, Type *DestTy,
|
||||||
|
Instruction *FMFSource = nullptr, const Twine &Name = "",
|
||||||
|
MDNode *FPMathTag = nullptr,
|
||||||
|
Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding = None,
|
||||||
|
Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except = None) {
|
||||||
|
Value *RoundingV = getConstrainedFPRounding(Rounding);
|
||||||
|
Value *ExceptV = getConstrainedFPExcept(Except);
|
||||||
|
|
||||||
|
FastMathFlags UseFMF = FMF;
|
||||||
|
if (FMFSource)
|
||||||
|
UseFMF = FMFSource->getFastMathFlags();
|
||||||
|
|
||||||
|
CallInst *C;
|
||||||
|
if (ID == Intrinsic::experimental_constrained_fpext)
|
||||||
|
C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, ExceptV}, nullptr,
|
||||||
|
Name);
|
||||||
|
else
|
||||||
|
C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV},
|
||||||
|
nullptr, Name);
|
||||||
|
return cast<CallInst>(setFPAttrs(C, FPMathTag, UseFMF));
|
||||||
|
}
|
||||||
|
|
||||||
// Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
|
// Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
|
||||||
// compile time error, instead of converting the string to bool for the
|
// compile time error, instead of converting the string to bool for the
|
||||||
// isSigned parameter.
|
// isSigned parameter.
|
||||||
|
|
|
@ -125,10 +125,14 @@ TEST_F(IRBuilderTest, Intrinsics) {
|
||||||
TEST_F(IRBuilderTest, ConstrainedFP) {
|
TEST_F(IRBuilderTest, ConstrainedFP) {
|
||||||
IRBuilder<> Builder(BB);
|
IRBuilder<> Builder(BB);
|
||||||
Value *V;
|
Value *V;
|
||||||
|
Value *VDouble;
|
||||||
CallInst *Call;
|
CallInst *Call;
|
||||||
IntrinsicInst *II;
|
IntrinsicInst *II;
|
||||||
|
GlobalVariable *GVDouble = new GlobalVariable(*M, Type::getDoubleTy(Ctx),
|
||||||
|
true, GlobalValue::ExternalLinkage, nullptr);
|
||||||
|
|
||||||
V = Builder.CreateLoad(GV->getValueType(), GV);
|
V = Builder.CreateLoad(GV->getValueType(), GV);
|
||||||
|
VDouble = Builder.CreateLoad(GVDouble->getValueType(), GVDouble);
|
||||||
|
|
||||||
// See if we get constrained intrinsics instead of non-constrained
|
// See if we get constrained intrinsics instead of non-constrained
|
||||||
// instructions.
|
// instructions.
|
||||||
|
@ -159,6 +163,16 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
|
||||||
II = cast<IntrinsicInst>(V);
|
II = cast<IntrinsicInst>(V);
|
||||||
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
|
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
|
||||||
|
|
||||||
|
V = Builder.CreateFPTrunc(VDouble, Type::getFloatTy(Ctx));
|
||||||
|
ASSERT_TRUE(isa<IntrinsicInst>(V));
|
||||||
|
II = cast<IntrinsicInst>(V);
|
||||||
|
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fptrunc);
|
||||||
|
|
||||||
|
VDouble = Builder.CreateFPExt(V, Type::getDoubleTy(Ctx));
|
||||||
|
ASSERT_TRUE(isa<IntrinsicInst>(VDouble));
|
||||||
|
II = cast<IntrinsicInst>(VDouble);
|
||||||
|
EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fpext);
|
||||||
|
|
||||||
// Verify the codepaths for setting and overriding the default metadata.
|
// Verify the codepaths for setting and overriding the default metadata.
|
||||||
V = Builder.CreateFAdd(V, V);
|
V = Builder.CreateFAdd(V, V);
|
||||||
ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
|
ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
|
||||||
|
|
Loading…
Reference in New Issue