[llvm] [InstCombine] Fold max(max(x, c1) << c2, c3) —> max(x << c2, c3) when c3 >= c1 * 2 ^ c2 (PR #140526)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Fri May 30 06:54:13 PDT 2025


================
@@ -1174,6 +1174,163 @@ static Instruction *moveAddAfterMinMax(IntrinsicInst *II,
   return IsSigned ? BinaryOperator::CreateNSWAdd(NewMinMax, Add->getOperand(1))
                   : BinaryOperator::CreateNUWAdd(NewMinMax, Add->getOperand(1));
 }
+
+
+static bool rightDistributesOverLeft(Instruction::BinaryOps ROp, bool HasNUW,
+                                     bool HasNSW, Intrinsic::ID LOp) {
+  switch (LOp) {
+  case Intrinsic::umax:
+  case Intrinsic::umin:
+    // Unsigned min/max distribute over addition and left shift if no unsigned
+    // wrap.
+    if (HasNUW && (ROp == Instruction::Add || ROp == Instruction::Shl))
+      return true;
+    // Multiplication preserves order for unsigned min/max with no unsigned
+    // wrap.
+    if (HasNUW && ROp == Instruction::Mul)
+      return true;
+    return false;
+  case Intrinsic::smax:
+  case Intrinsic::smin:
+    // Signed min/max distribute over addition if no signed wrap.
+    if (HasNSW && ROp == Instruction::Add)
+      return true;
+    // Multiplication preserves order for signed min/max with no signed wrap.
+    if (HasNSW && ROp == Instruction::Mul)
+      return true;
+    return false;
+  default:
+    return false;
+  }
+}
+
+///  Try canonicalize max(max(X,C1) binop C2, C3) -> max(X binop C2, max(C1
+///  binop C2, C3)) -> max(X binop C2, C4) max(max(X,C1) binop C2, C3) -> //
+///  Associative laws max(max(X binop C2, C1 binop C2), C3) -> // Commutative
+///  laws max(X binop C2, max(C1 binop C2, C3)) -> // Constant fold max(X binop
+///  C2, C4)
+
+static Instruction *reduceMinMax(IntrinsicInst *II,
+                                 InstCombiner::BuilderTy &Builder) {
+  Intrinsic::ID MinMaxID = II->getIntrinsicID();
+  assert(isa<MinMaxIntrinsic>(II) && "Expected a min or max intrinsic");
+
+  Value *Op0 = II->getArgOperand(0), *Op1 = II->getArgOperand(1);
+  Value *InnerMax;
+  const APInt *C;
+  if (!match(Op0, m_OneUse(m_BinOp(m_Value(InnerMax), m_APInt(C)))) ||
+      !match(Op1, m_APInt(C)))
----------------
dtcxzyw wrote:

```suggestion
  Constant *C2, *C3;
  if (!match(Op0, m_OneUse(m_BinOp(m_Value(InnerMax), m_ImmConstant(C2)))) ||
      !match(Op1, m_ImmConstant(C3)))
```


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


More information about the llvm-commits mailing list