Pārlūkot izejas kodu

[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


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366477 91177308-0d34-0410-b5e6-96231b3b80d8
Kevin P. Neal 6 gadi atpakaļ
vecāks
revīzija
71411a6861
2 mainītis faili ar 44 papildinājumiem un 0 dzēšanām
  1. 30 0
      include/llvm/IR/IRBuilder.h
  2. 14 0
      unittests/IR/IRBuilderTest.cpp

+ 30 - 0
include/llvm/IR/IRBuilder.h

@@ -1931,10 +1931,17 @@ public:
 
   Value *CreateFPTrunc(Value *V, Type *DestTy,
                        const Twine &Name = "") {
+    if (IsFPConstrained)
+      return CreateConstrainedFPCast(
+          Intrinsic::experimental_constrained_fptrunc, V, DestTy, nullptr,
+          Name);
     return CreateCast(Instruction::FPTrunc, V, DestTy, 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);
   }
 
@@ -2046,6 +2053,29 @@ public:
     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
   // compile time error, instead of converting the string to bool for the
   // isSigned parameter.

+ 14 - 0
unittests/IR/IRBuilderTest.cpp

@@ -125,10 +125,14 @@ TEST_F(IRBuilderTest, Intrinsics) {
 TEST_F(IRBuilderTest, ConstrainedFP) {
   IRBuilder<> Builder(BB);
   Value *V;
+  Value *VDouble;
   CallInst *Call;
   IntrinsicInst *II;
+  GlobalVariable *GVDouble = new GlobalVariable(*M, Type::getDoubleTy(Ctx),
+                            true, GlobalValue::ExternalLinkage, nullptr);
 
   V = Builder.CreateLoad(GV->getValueType(), GV);
+  VDouble = Builder.CreateLoad(GVDouble->getValueType(), GVDouble);
 
   // See if we get constrained intrinsics instead of non-constrained
   // instructions.
@@ -159,6 +163,16 @@ TEST_F(IRBuilderTest, ConstrainedFP) {
   II = cast<IntrinsicInst>(V);
   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.
   V = Builder.CreateFAdd(V, V);
   ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));