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

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.

>From ef14a9b6151e66ac2b7452d8d7958f55731f35ab Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavl...@gmail.com>
Date: Mon, 28 Apr 2025 00:21:56 +0700
Subject: [PATCH] [SelectionDAG] Adaptation for FP operation lowering

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.
---
 llvm/include/llvm/IR/FloatingPointOps.def     |  7 ++-
 .../SelectionDAG/SelectionDAGBuilder.cpp      | 62 +++++++++++++++++--
 .../SelectionDAG/SelectionDAGBuilder.h        |  1 +
 3 files changed, 65 insertions(+), 5 deletions(-)

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);

_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to