[llvm] [CodeGen] [AMDGPU] Attempt DAGCombine for fmul with select to ldexp (PR #111109)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 21 15:27:45 PDT 2024


================
@@ -14476,6 +14477,66 @@ SDValue SITargetLowering::performFDivCombine(SDNode *N,
   return SDValue();
 }
 
+SDValue SITargetLowering::performFMulCombine(SDNode *N,
+                                             DAGCombinerInfo &DCI) const {
+  SelectionDAG &DAG = DCI.DAG;
+  EVT VT = N->getValueType(0);
+  EVT IntVT = VT.changeElementType(MVT::i32);
+
+  SDLoc SL(N);
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+
+  SDNodeFlags Flags = N->getFlags();
+  SDNodeFlags LHSFlags = LHS->getFlags();
+
+  // It is cheaper to realize i32 inline constants as compared against
+  // as materializing f16 or f64 (or even non-inline f32) values,
+  // possible via ldexp usage, as shown below :
+  //
+  // Given : A = 2^a  &  B = 2^b ; where a and b are integers.
+  // fmul x, (select y, A, B)     -> ldexp( x, (select i32 y, a, b) )
+  // fmul x, (select y, -A, -B)   -> ldexp( (fneg x), (select i32 y, a, b) )
+  if (VT.getScalarType() == MVT::f64 || VT.getScalarType() == MVT::f32 ||
+      VT.getScalarType() == MVT::f16) {
+    if (RHS.hasOneUse() && RHS.getOpcode() == ISD::SELECT) {
+      const ConstantFPSDNode *TrueNode =
+          isConstOrConstSplatFP(RHS.getOperand(1));
+      const ConstantFPSDNode *FalseNode =
+          isConstOrConstSplatFP(RHS.getOperand(2));
+
+      bool AreNodesFP = TrueNode && FalseNode;
+      if (!AreNodesFP)
+        return SDValue();
+
+      if (TrueNode->isNegative() != FalseNode->isNegative())
+        return SDValue();
+
+      // For f32, only non-inline constants should be transformed.
+      const SIInstrInfo *TII = getSubtarget()->getInstrInfo();
+      if (VT.getScalarType() == MVT::f32 &&
+          TII->isInlineConstant(TrueNode->getValueAPF()) &&
+          TII->isInlineConstant(FalseNode->getValueAPF()))
+        return SDValue();
+
+      LHS = TrueNode->isNegative()
+                ? DAG.getNode(ISD::FNEG, SL, VT, LHS, LHSFlags)
+                : LHS;
+      int TrueNodeExpVal = TrueNode->getValueAPF().getExactLog2Abs();
+      int FalseNodeExpVal = FalseNode->getValueAPF().getExactLog2Abs();
+      if (TrueNodeExpVal != INT_MIN && FalseNodeExpVal != INT_MIN) {
----------------
arsenm wrote:

Early exit after one fails 

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


More information about the llvm-commits mailing list