[llvm] [DAGCombiner] Fold smax(X, -1) to or(X, ashr(X, BW-1)) for code size (PR #206242)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 27 14:16:52 PDT 2026
================
@@ -6307,6 +6307,41 @@ SDValue DAGCombiner::visitIMINMAX(SDNode *N) {
if (SDValue RMINMAX = reassociateOps(Opcode, DL, N0, N1, N->getFlags()))
return RMINMAX;
+ // Fold sign-extension masks using arithmetic shift:
+ // smax(X, -1) -> or(X, ashr(X, BW-1))
+ // smin(X, 0) -> and(X, ashr(X, BW-1))
+ // ashr(X, BW-1) sign-extends the sign bit: 0 for X>=0, -1 for X<0.
+ // OR with X yields X (non-negative) or -1 (negative) = smax(X,-1).
+ // AND with X yields 0 (non-negative) or X (negative) = smin(X, 0).
+ // Both reduce to two instructions vs. a compare+cmov on x86-64.
+ // Only fold when the target has no native SMAX/SMIN instruction for this
+ // type (isOperationExpand), the type is legal (not needing splitting), and
+ // the operand is not a min/max chain (preserving saturation patterns such as
+ // RISCV-P sati which combine smin+smax into a single instruction).
+ if (TLI.isTypeLegal(VT) &&
+ !TLI.shouldAvoidTransformToShift(VT, VT.getScalarSizeInBits() - 1)) {
+ SDValue ShiftAmt =
+ DAG.getShiftAmountConstant(VT.getScalarSizeInBits() - 1, VT, DL);
+ if (Opcode == ISD::SMAX && TLI.isOperationExpand(ISD::SMAX, VT) &&
+ N0.getOpcode() != ISD::SMIN) {
+ if (auto *N1C = isConstOrConstSplat(N1)) {
----------------
RKSimon wrote:
Use isAllOnesConstant
https://github.com/llvm/llvm-project/pull/206242
More information about the llvm-commits
mailing list