-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[SelectionDAG] Adaptation for FP operation lowering #138553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/spavloff/fadd
Are you sure you want to change the base?
Conversation
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/pr-subscribers-llvm-ir @llvm/pr-subscribers-llvm-selectiondag Author: Serge Pavlov (spavloff) ChangesFP 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:
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);
|
if (CI.getExceptionBehavior() == fp::ExceptionBehavior::ebIgnore) | ||
Flags.setNoFPExcept(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you reorder this with the use of CI.getExceptionBehavior below, so all of the exception mode dependent code is together
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.