[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