[llvm] fix for Issue #139786 - Missed Optimization: max(max(x, c1) << c2, c3) —> max(x << c2, c3) when c3 >= c1 * 2 ^ c2 (PR #140526)

via llvm-commits llvm-commits at lists.llvm.org
Mon May 19 05:50:11 PDT 2025


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {clang-format}-->


:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff HEAD~1 HEAD --extensions cpp -- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
``````````

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 96051fa3f..61a01db37 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1175,51 +1175,62 @@ static Instruction *moveAddAfterMinMax(IntrinsicInst *II,
                   : BinaryOperator::CreateNUWAdd(NewMinMax, Add->getOperand(1));
 }
 
-//Try canonicalize min/max(x << shamt, c<<shamt) into max(x, c) << shamt
-static Instruction *moveShiftAfterMinMax(IntrinsicInst *II, InstCombiner::BuilderTy &Builder) {
+// Try canonicalize min/max(x << shamt, c<<shamt) into max(x, c) << shamt
+static Instruction *moveShiftAfterMinMax(IntrinsicInst *II,
+                                         InstCombiner::BuilderTy &Builder) {
   Intrinsic::ID MinMaxID = II->getIntrinsicID();
   assert((MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin ||
-    MinMaxID == Intrinsic::umax || MinMaxID == Intrinsic::umin) &&
-   "Expected a min or max intrinsic");
-  
+          MinMaxID == Intrinsic::umax || MinMaxID == Intrinsic::umin) &&
+         "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)))) || 
+  if (!match(Op0, m_OneUse(m_BinOp(m_Value(InnerMax), m_APInt(C)))) ||
       !match(Op1, m_APInt(C)))
-      return nullptr;
-  
-  auto* BinOpInst = cast<BinaryOperator>(Op0);
+    return nullptr;
+
+  auto *BinOpInst = cast<BinaryOperator>(Op0);
   Instruction::BinaryOps BinOp = BinOpInst->getOpcode();
   Value *X;
   InnerMax = BinOpInst->getOperand(0);
   // std::cout<< InnerMax->dump() <<std::endl;
-  if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::umax>(m_Value(X),m_APInt(C))))){
-  if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::smax>(m_Value(X),m_APInt(C))))){
-  if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::umin>(m_Value(X),m_APInt(C))))){
-  if(!match(InnerMax,m_OneUse(m_Intrinsic<Intrinsic::smin>(m_Value(X),m_APInt(C))))){
-     return nullptr;
-  }}}}
-  
+  if (!match(InnerMax,
+             m_OneUse(m_Intrinsic<Intrinsic::umax>(m_Value(X), m_APInt(C))))) {
+    if (!match(InnerMax, m_OneUse(m_Intrinsic<Intrinsic::smax>(m_Value(X),
+                                                               m_APInt(C))))) {
+      if (!match(InnerMax, m_OneUse(m_Intrinsic<Intrinsic::umin>(
+                               m_Value(X), m_APInt(C))))) {
+        if (!match(InnerMax, m_OneUse(m_Intrinsic<Intrinsic::smin>(
+                                 m_Value(X), m_APInt(C))))) {
+          return nullptr;
+        }
+      }
+    }
+  }
+
   auto *InnerMaxInst = cast<IntrinsicInst>(InnerMax);
 
   bool IsSigned = MinMaxID == Intrinsic::smax || MinMaxID == Intrinsic::smin;
-  if((IsSigned && !BinOpInst->hasNoSignedWrap()) ||
-     (!IsSigned && !BinOpInst->hasNoUnsignedWrap())) 
-     return nullptr;
+  if ((IsSigned && !BinOpInst->hasNoSignedWrap()) ||
+      (!IsSigned && !BinOpInst->hasNoUnsignedWrap()))
+    return nullptr;
 
   // Check if BinOp is a left shift
   if (BinOp != Instruction::Shl) {
     return nullptr;
   }
 
-  APInt C2=llvm::dyn_cast<llvm::ConstantInt>(BinOpInst->getOperand(1))->getValue() ;
-  APInt C3=llvm::dyn_cast<llvm::ConstantInt>(II->getArgOperand(1))->getValue();
-  APInt C1=llvm::dyn_cast<llvm::ConstantInt>(InnerMaxInst->getOperand(1))->getValue();
+  APInt C2 =
+      llvm::dyn_cast<llvm::ConstantInt>(BinOpInst->getOperand(1))->getValue();
+  APInt C3 =
+      llvm::dyn_cast<llvm::ConstantInt>(II->getArgOperand(1))->getValue();
+  APInt C1 = llvm::dyn_cast<llvm::ConstantInt>(InnerMaxInst->getOperand(1))
+                 ->getValue();
 
   // Compute C1 * 2^C2
   APInt Two = APInt(C2.getBitWidth(), 2);
-  APInt Pow2C2 = Two.shl(C2); // 2^C2
+  APInt Pow2C2 = Two.shl(C2);        // 2^C2
   APInt C1TimesPow2C2 = C1 * Pow2C2; // C1 * 2^C2
 
   // Check C3 >= C1 * 2^C2
@@ -1227,23 +1238,24 @@ static Instruction *moveShiftAfterMinMax(IntrinsicInst *II, InstCombiner::Builde
     return nullptr;
   }
 
-  //Create new x binop c2
-  Value *NewBinOp = Builder.CreateBinOp(BinOp, InnerMaxInst->getOperand(0), BinOpInst->getOperand(1) );
-  
-  //Create new min/max intrinsic with new binop and c3
-  
-    if(IsSigned){
-      cast<Instruction>(NewBinOp) -> setHasNoSignedWrap(true);
-      cast<Instruction>(NewBinOp) -> setHasNoUnsignedWrap(false);
-    }else{
-      cast<Instruction>(NewBinOp) -> setHasNoUnsignedWrap(true);
-      cast<Instruction>(NewBinOp) -> setHasNoSignedWrap(false);
-    }
-  
+  // Create new x binop c2
+  Value *NewBinOp = Builder.CreateBinOp(BinOp, InnerMaxInst->getOperand(0),
+                                        BinOpInst->getOperand(1));
+
+  // Create new min/max intrinsic with new binop and c3
+
+  if (IsSigned) {
+    cast<Instruction>(NewBinOp)->setHasNoSignedWrap(true);
+    cast<Instruction>(NewBinOp)->setHasNoUnsignedWrap(false);
+  } else {
+    cast<Instruction>(NewBinOp)->setHasNoUnsignedWrap(true);
+    cast<Instruction>(NewBinOp)->setHasNoSignedWrap(false);
+  }
 
   // Get the intrinsic function for MinMaxID
   Type *Ty = II->getType();
-  Function *MinMaxFn = Intrinsic::getDeclaration(II->getModule(), MinMaxID, {Ty});
+  Function *MinMaxFn =
+      Intrinsic::getDeclaration(II->getModule(), MinMaxID, {Ty});
 
   // Create new min/max intrinsic: MinMaxID(NewBinOp, C3) (not inserted)
   Value *Args[] = {NewBinOp, Op1};
@@ -2117,10 +2129,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       return I;
 
     // minmax(x << shamt , c << shamt) -> minmax(x, c) << shamt
-    if (Instruction *I = moveShiftAfterMinMax(II, Builder))  
+    if (Instruction *I = moveShiftAfterMinMax(II, Builder))
       return I;
 
-
     // minmax (X & NegPow2C, Y & NegPow2C) --> minmax(X, Y) & NegPow2C
     const APInt *RHSC;
     if (match(I0, m_OneUse(m_And(m_Value(X), m_NegatedPower2(RHSC)))) &&

``````````

</details>


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


More information about the llvm-commits mailing list