[llvm] 881350a - Mapping of FP operations to constrained intrinsics

Serge Pavlov via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 30 21:08:55 PDT 2022


Author: Serge Pavlov
Date: 2022-03-31T11:07:47+07:00
New Revision: 881350a92d821d4f8e4fa648443ed1d17e251188

URL: https://github.com/llvm/llvm-project/commit/881350a92d821d4f8e4fa648443ed1d17e251188
DIFF: https://github.com/llvm/llvm-project/commit/881350a92d821d4f8e4fa648443ed1d17e251188.diff

LOG: Mapping of FP operations to constrained intrinsics

A new function 'getConstrainedIntrinsic' is added, which for any gived
instruction returns id of the corresponding constrained intrinsic. If
there is no constrained counterpart for the instruction or the instruction
is already a constrained intrinsic, the function returns zero.

This is recommit of 115b3ace369254f573ca28934ef30ab9d8f497ef, reverted in
8160dd582b67430a5c24c836a57ae3c15cfa973c.

Differential Revision: https://reviews.llvm.org/D69562

Added: 
    

Modified: 
    llvm/include/llvm/IR/FPEnv.h
    llvm/lib/IR/FPEnv.cpp
    llvm/unittests/IR/InstructionsTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/FPEnv.h b/llvm/include/llvm/IR/FPEnv.h
index cbcba37c3bb8a..e598db224211b 100644
--- a/llvm/include/llvm/IR/FPEnv.h
+++ b/llvm/include/llvm/IR/FPEnv.h
@@ -22,6 +22,12 @@
 namespace llvm {
 class StringRef;
 
+namespace Intrinsic {
+typedef unsigned ID;
+}
+
+class Instruction;
+
 namespace fp {
 
 /// Exception behavior used for floating point operations.
@@ -60,6 +66,12 @@ inline bool isDefaultFPEnvironment(fp::ExceptionBehavior EB, RoundingMode RM) {
   return EB == fp::ebIgnore && RM == RoundingMode::NearestTiesToEven;
 }
 
+/// Returns constrained intrinsic id to represent the given instruction in
+/// strictfp function. If the instruction is already a constrained intrinsic or
+/// does not have a constrained intrinsic counterpart, the function returns
+/// zero.
+Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr);
+
 /// Returns true if the rounding mode RM may be QRM at compile time or
 /// at run time.
 inline bool canRoundingModeBe(RoundingMode RM, RoundingMode QRM) {

diff  --git a/llvm/lib/IR/FPEnv.cpp b/llvm/lib/IR/FPEnv.cpp
index c6e0938e71a6e..06c5da03ef523 100644
--- a/llvm/lib/IR/FPEnv.cpp
+++ b/llvm/lib/IR/FPEnv.cpp
@@ -14,6 +14,9 @@
 
 #include "llvm/IR/FPEnv.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
 
 namespace llvm {
 
@@ -82,4 +85,46 @@ convertExceptionBehaviorToStr(fp::ExceptionBehavior UseExcept) {
   }
   return ExceptStr;
 }
+
+Intrinsic::ID getConstrainedIntrinsicID(const Instruction &Instr) {
+  Intrinsic::ID IID = Intrinsic::not_intrinsic;
+  switch (Instr.getOpcode()) {
+  case Instruction::FCmp:
+    // Unlike other instructions FCmp can be mapped to one of two intrinsic
+    // functions. We choose the non-signaling variant.
+    IID = Intrinsic::experimental_constrained_fcmp;
+    break;
+
+    // Instructions
+#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                         \
+  case Instruction::NAME:                                                      \
+    IID = Intrinsic::INTRINSIC;                                                \
+    break;
+#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
+#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
+#include "llvm/IR/ConstrainedOps.def"
+
+  // Intrinsic calls.
+  case Instruction::Call:
+    if (auto *IntrinCall = dyn_cast<IntrinsicInst>(&Instr)) {
+      switch (IntrinCall->getIntrinsicID()) {
+#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)                            \
+  case Intrinsic::NAME:                                                        \
+    IID = Intrinsic::INTRINSIC;                                                \
+    break;
+#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
+#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)
+#include "llvm/IR/ConstrainedOps.def"
+      default:
+        break;
+      }
+    }
+    break;
+  default:
+    break;
+  }
+
+  return IID;
+}
+
 } // namespace llvm

diff  --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index 2bb1d47e82d9c..086ad691821e3 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -17,6 +17,7 @@
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/FPEnv.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
@@ -507,6 +508,59 @@ TEST(InstructionsTest, FPMathOperator) {
   I->deleteValue();
 }
 
+TEST(InstructionTest, ConstrainedTrans) {
+  LLVMContext Context;
+  std::unique_ptr<Module> M(new Module("MyModule", Context));
+  FunctionType *FTy =
+      FunctionType::get(Type::getVoidTy(Context),
+                        {Type::getFloatTy(Context), Type::getFloatTy(Context),
+                         Type::getInt32Ty(Context)},
+                        false);
+  auto *F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
+  auto *BB = BasicBlock::Create(Context, "bb", F);
+  IRBuilder<> Builder(Context);
+  Builder.SetInsertPoint(BB);
+  auto *Arg0 = F->arg_begin();
+  auto *Arg1 = F->arg_begin() + 1;
+
+  {
+    auto *I = cast<Instruction>(Builder.CreateFAdd(Arg0, Arg1));
+    EXPECT_EQ(Intrinsic::experimental_constrained_fadd,
+              getConstrainedIntrinsicID(*I));
+  }
+
+  {
+    auto *I = cast<Instruction>(
+        Builder.CreateFPToSI(Arg0, Type::getInt32Ty(Context)));
+    EXPECT_EQ(Intrinsic::experimental_constrained_fptosi,
+              getConstrainedIntrinsicID(*I));
+  }
+
+  {
+    auto *I = cast<Instruction>(Builder.CreateIntrinsic(
+        Intrinsic::ceil, {Type::getFloatTy(Context)}, {Arg0}));
+    EXPECT_EQ(Intrinsic::experimental_constrained_ceil,
+              getConstrainedIntrinsicID(*I));
+  }
+
+  {
+    auto *I = cast<Instruction>(Builder.CreateFCmpOEQ(Arg0, Arg1));
+    EXPECT_EQ(Intrinsic::experimental_constrained_fcmp,
+              getConstrainedIntrinsicID(*I));
+  }
+
+  {
+    auto *Arg2 = F->arg_begin() + 2;
+    auto *I = cast<Instruction>(Builder.CreateAdd(Arg2, Arg2));
+    EXPECT_EQ(Intrinsic::not_intrinsic, getConstrainedIntrinsicID(*I));
+  }
+
+  {
+    auto *I = cast<Instruction>(Builder.CreateConstrainedFPBinOp(
+        Intrinsic::experimental_constrained_fadd, Arg0, Arg0));
+    EXPECT_EQ(Intrinsic::not_intrinsic, getConstrainedIntrinsicID(*I));
+  }
+}
 
 TEST(InstructionsTest, isEliminableCastPair) {
   LLVMContext C;


        


More information about the llvm-commits mailing list