[llvm] [SelectionDAG] Improve ucmp/scmp codegen (PR #190787)
Takashi Idobe via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 10 05:46:24 PDT 2026
================
@@ -11479,6 +11479,40 @@ SDValue TargetLowering::expandCMP(SDNode *Node, SelectionDAG &DAG) const {
EVT BoolVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
SDLoc dl(Node);
+ // fold scmp(x, 0) -> or(sra(x, bw-1), zext(setne(x, 0)))
+ // This is cheaper than the generic sub(IsGT, IsLT) expansion for wide
+ // integers: the sign mask comes from a single arithmetic shift and the
+ // nonzero test is a single comparison, with no flag-chain dependencies
+ // between them. Only apply when VT is a non-native integer type.
+ if (Opcode == ISD::SCMP && isNullConstant(RHS) && VT.isScalarInteger() &&
+ getTypeAction(*DAG.getContext(), VT) == TypeExpandInteger) {
+ SDValue ShiftAmt =
+ DAG.getShiftAmountConstant(VT.getScalarSizeInBits() - 1, VT, dl);
+ SDValue SignMask = DAG.getNode(ISD::SRA, dl, VT, LHS, ShiftAmt);
+ SDValue IsNZ = DAG.getSetCC(dl, BoolVT, LHS, RHS, ISD::SETNE);
+ SDValue IsNZExt = DAG.getZExtOrTrunc(IsNZ, dl, VT);
+ if (BoolVT.getScalarSizeInBits() != 1 &&
+ getBooleanContents(BoolVT) != ZeroOrOneBooleanContent)
+ IsNZExt =
+ DAG.getNode(ISD::AND, dl, VT, IsNZExt, DAG.getConstant(1, dl, VT));
+ SDValue Result = DAG.getNode(ISD::OR, dl, VT, SignMask, IsNZExt);
+ return DAG.getSExtOrTrunc(Result, dl, ResVT);
+ }
+
+ // fold ucmp(x, 0) -> zext(setne(x, 0))
+ // Since 0 is the minimum unsigned value, ucmp(x, 0) is never -1,
+ // returning 0 when x == 0 and 1 otherwise. This avoids the generic
+ // sub(IsGT, IsLT) expansion and its flag-chain dependencies.
----------------
Takashiidobe wrote:
I'll leave this up to you whether or not you want to see the change in FoldSetCC, it'll change a lot more tests so it's more code review burden but it does seem like a better place than for ucmp.
https://github.com/llvm/llvm-project/pull/190787
More information about the llvm-commits
mailing list