[llvm] [DAGCombiner] Fold smax(X, -1)/smin(X, 0) to bitwise shift forms (PR #206242)
Aayush Shrivastava via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 29 04:02:42 PDT 2026
================
@@ -6307,6 +6307,35 @@ 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)) {
+ if (Opcode == ISD::SMAX && TLI.isOperationExpand(ISD::SMAX, VT) &&
+ N0.getOpcode() != ISD::SMIN && isAllOnesConstant(N1)) {
----------------
iamaayushrivastava wrote:
Done. Switched to `sd_match(N1, m_AllOnes())` and `sd_match(N1, m_Zero())` for both patterns.
https://github.com/llvm/llvm-project/pull/206242
More information about the llvm-commits
mailing list