[llvm] [missed-opt][X86] Optimize fptosi+select down to a single cvttsd2si Instruction on X86 (PR #172710)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 5 05:25:41 PST 2026


================
@@ -48163,6 +48150,91 @@ static SDValue combineSelect(SDNode *N, SelectionDAG &DAG,
   bool CondConstantVector = ISD::isBuildVectorOfConstantSDNodes(Cond.getNode());
   unsigned EltBitWidth = VT.getScalarSizeInBits();
 
+  // select in presence of fp_to_sint can be replaced with just fp_to_sint
+  // fold (SELECT (SETCC (FABS X), MAXFLOAT), (FP_TO_SINT X), INT_MIN)
+  // -> (FP_TO_SINT X)
+  using namespace SDPatternMatch;
+  SDValue T;
+  SDValue FloatConst;
+  if (sd_match(Cond, m_SetCC(m_FAbs(m_Value(T)), m_Value(FloatConst),
+                             m_SpecificCondCode(ISD::SETOLT)))) {
+    SDValue FpToInt = LHS;
+    SDValue ConstNode = RHS;
+    if (FpToInt.getOpcode() != ISD::FP_TO_SINT)
+      std::swap(FpToInt, ConstNode);
+
+    if (FpToInt.getOpcode() != ISD::FP_TO_SINT)
+      return SDValue();
+
+    if (!DAG.isConstantValueOfAnyType(ConstNode))
+      return SDValue();
+
+    if (T != FpToInt.getOperand(0))
+      return SDValue();
+
+    EVT IntVT = FpToInt.getValueType();
+    EVT FPVT = T.getValueType();
+
+    EVT IntEltVT = IntVT.isVector() ? IntVT.getVectorElementType() : IntVT;
+
+    EVT FPEltVT = FPVT.isVector() ? FPVT.getVectorElementType() : FPVT;
+
+    if (!FPEltVT.isFloatingPoint())
+      return SDValue();
+
+    APInt IntMin = APInt::getSignedMinValue(IntEltVT.getSizeInBits());
+
+    if (!DAG.isConstantValueOfAnyType(ConstNode))
+      return SDValue();
+
+    if (auto *C = dyn_cast<ConstantSDNode>(ConstNode)) {
+      // scalar INT_MIN
+      if (C->getAPIntValue() != IntMin)
+        return SDValue();
+    } else if (ConstNode.getOpcode() == ISD::BUILD_VECTOR) {
+      // vector INT_MIN splat
+      for (unsigned Idx = 0, NumOperands = ConstNode.getNumOperands();
+           Idx != NumOperands; ++Idx) {
+        SDValue Op = ConstNode.getOperand(Idx);
+        auto *EltC = dyn_cast<ConstantSDNode>(Op);
+        if (!EltC || EltC->getAPIntValue() != IntMin)
+          return SDValue();
+      }
+    } else {
+      return SDValue();
+    }
+
+    APFloat MaxAbsFP(FPEltVT.getFltSemantics(),
+                     APInt::getZero(FPEltVT.getSizeInBits()));
+
+    (void)MaxAbsFP.convertFromAPInt(IntMin, false,
+                                    APFloat::rmNearestTiesToEven);
+
+    bool Match = false;
+
+    if (auto *CFP = dyn_cast<ConstantFPSDNode>(FloatConst)) {
+      // scalar constant
+      Match = CFP->getValueAPF() == MaxAbsFP;
+    } else if (FloatConst.getOpcode() == ISD::BUILD_VECTOR) {
+      // vector splat
+      Match = true;
+      for (unsigned Idx = 0, NumOperands = FloatConst.getNumOperands();
+           Idx != NumOperands; ++Idx) {
+        SDValue Op = FloatConst.getOperand(Idx);
+        auto *EltCFP = dyn_cast<ConstantFPSDNode>(Op);
+        if (!EltCFP || EltCFP->getValueAPF() != MaxAbsFP) {
+          Match = false;
+          break;
+        }
+      }
+    }
+
+    if (!Match)
+      return SDValue();
+
+    return DAG.getNode(ISD::FP_TO_SINT, DL, IntVT, T);
+  }
----------------
RKSimon wrote:

we can't rely on ISD::FP_TO_SINT lowering to CVTTSD2SI to get the functionality we need - you have to use the target specific opcodes for this

You will need to ensure that the types are legal before creating the target nodes

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


More information about the llvm-commits mailing list