[llvm-branch-commits] [llvm] [SelectionDAG] Adaptation for FP operation lowering (PR #138553)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon May 5 09:43:32 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-selectiondag

Author: Serge Pavlov (spavloff)

<details>
<summary>Changes</summary>

FP operations listed in FloatingPointOps.def are now lowered to DAG in the same way as constrained intrinsics, using special DAG nodes like STRICT_NEARBYINT.

This is a temporary solution. Existing nodes like STRICT_NEARBYINT cannot carry information about rounding or other control modes, so they cannot implement static rounding, for example. However they can serve as a first step toward a solution based on the FP operand bundles.

---
Full diff: https://github.com/llvm/llvm-project/pull/138553.diff


3 Files Affected:

- (modified) llvm/include/llvm/IR/FloatingPointOps.def (+6-1) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+58-4) 
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h (+1) 


``````````diff
diff --git a/llvm/include/llvm/IR/FloatingPointOps.def b/llvm/include/llvm/IR/FloatingPointOps.def
index 468227e648300..6d653668fe340 100644
--- a/llvm/include/llvm/IR/FloatingPointOps.def
+++ b/llvm/include/llvm/IR/FloatingPointOps.def
@@ -14,12 +14,17 @@
 #define FUNCTION(N,D)
 #endif
 
+#ifndef CONSTRAINED
+#define CONSTRAINED(N,D) FUNCTION(N,D)
+#endif
+
 // Arguments of the entries are:
 // - intrinsic function name,
 // - DAG node corresponding to the intrinsic.
 
-FUNCTION(experimental_constrained_fadd,      FADD)
+CONSTRAINED(experimental_constrained_fadd,   FADD)
 FUNCTION(nearbyint,                          FNEARBYINT)
 FUNCTION(trunc,                              FTRUNC)
 
 #undef FUNCTION
+#undef CONSTRAINED
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8cae34d06c8ba..cd97338cfaa93 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6802,9 +6802,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
   case Intrinsic::exp10:
   case Intrinsic::floor:
   case Intrinsic::ceil:
-  case Intrinsic::trunc:
   case Intrinsic::rint:
-  case Intrinsic::nearbyint:
   case Intrinsic::round:
   case Intrinsic::roundeven:
   case Intrinsic::canonicalize: {
@@ -6826,9 +6824,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
     case Intrinsic::exp10:        Opcode = ISD::FEXP10;        break;
     case Intrinsic::floor:        Opcode = ISD::FFLOOR;        break;
     case Intrinsic::ceil:         Opcode = ISD::FCEIL;         break;
-    case Intrinsic::trunc:        Opcode = ISD::FTRUNC;        break;
     case Intrinsic::rint:         Opcode = ISD::FRINT;         break;
-    case Intrinsic::nearbyint:    Opcode = ISD::FNEARBYINT;    break;
     case Intrinsic::round:        Opcode = ISD::FROUND;        break;
     case Intrinsic::roundeven:    Opcode = ISD::FROUNDEVEN;    break;
     case Intrinsic::canonicalize: Opcode = ISD::FCANONICALIZE; break;
@@ -6959,6 +6955,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
 #include "llvm/IR/ConstrainedOps.def"
     visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(I));
     return;
+#define CONSTRAINED(INTRINSIC, DAGN)
+#define FUNCTION(INTRINSIC, DAGN) case Intrinsic::INTRINSIC:
+#include "llvm/IR/FloatingPointOps.def"
+    visitFPOperationIntrinsic(I, Intrinsic);
+    return;
 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
 #include "llvm/IR/VPIntrinsics.def"
     visitVectorPredicationIntrinsic(cast<VPIntrinsic>(I));
@@ -8350,6 +8351,59 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
   setValue(&FPI, FPResult);
 }
 
+void SelectionDAGBuilder::visitFPOperationIntrinsic(const CallInst &CI,
+                                                    unsigned Intrinsic) {
+  SDLoc sdl = getCurSDLoc();
+  bool StrictFP =
+      FuncInfo.Fn->getAttributes().hasFnAttr(llvm::Attribute::StrictFP);
+
+  int Opcode = -1;
+  switch (Intrinsic) {
+#define CONSTRAINED(NAME, DAGN)
+#define FUNCTION(NAME, DAGN)                                                   \
+  case Intrinsic::NAME:                                                        \
+    Opcode = StrictFP ? ISD::STRICT_##DAGN : ISD::DAGN;                        \
+    break;
+#include "llvm/IR/FloatingPointOps.def"
+  }
+
+  SDNodeFlags Flags;
+  if (CI.getExceptionBehavior() == fp::ExceptionBehavior::ebIgnore)
+    Flags.setNoFPExcept(true);
+  if (auto *FPOp = dyn_cast<FPMathOperator>(&CI))
+    Flags.copyFMF(*FPOp);
+
+  SmallVector<SDValue, 4> Operands;
+  if (StrictFP)
+    Operands.push_back(DAG.getRoot());
+  for (unsigned I = 0, E = CI.arg_size(); I != E; ++I)
+    Operands.push_back(getValue(CI.getArgOperand(I)));
+
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+  EVT VT = TLI.getValueType(DAG.getDataLayout(), CI.getType());
+  SDVTList VTs = StrictFP ? DAG.getVTList(VT, MVT::Other) : DAG.getVTList(VT);
+
+  SDValue Result = DAG.getNode(Opcode, sdl, VTs, Operands, Flags);
+
+  SDValue OutChain;
+  if (StrictFP) {
+    OutChain = Result.getValue(1);
+    switch (CI.getExceptionBehavior()) {
+    case fp::ExceptionBehavior::ebIgnore:
+    case fp::ExceptionBehavior::ebMayTrap:
+      PendingConstrainedFP.push_back(OutChain);
+      break;
+    case fp::ExceptionBehavior::ebStrict:
+      PendingConstrainedFPStrict.push_back(OutChain);
+      break;
+    }
+    SDValue FPResult = Result.getValue(0);
+    setValue(&CI, FPResult);
+  } else {
+    setValue(&CI, Result);
+  }
+}
+
 static unsigned getISDForVPIntrinsic(const VPIntrinsic &VPIntrin) {
   std::optional<unsigned> ResOPC;
   switch (VPIntrin.getIntrinsicID()) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index 35c15bc269d4b..fcd5a4da9e8d9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -627,6 +627,7 @@ class SelectionDAGBuilder {
   void visitIntrinsicCall(const CallInst &I, unsigned Intrinsic);
   void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic);
   void visitConstrainedFPIntrinsic(const ConstrainedFPIntrinsic &FPI);
+  void visitFPOperationIntrinsic(const CallInst &I, unsigned Intrinsic);
   void visitConvergenceControl(const CallInst &I, unsigned Intrinsic);
   void visitVectorHistogram(const CallInst &I, unsigned IntrinsicID);
   void visitVectorExtractLastActive(const CallInst &I, unsigned Intrinsic);

``````````

</details>


https://github.com/llvm/llvm-project/pull/138553


More information about the llvm-branch-commits mailing list