[llvm] [InstCombine] Fold umax(nuw_mul(x, C0), x + 1) into (x == 0 ? 1 : nuw_mul(x, C0)) (PR #123468)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 18 18:34:57 PST 2025
================
@@ -1847,6 +1847,30 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
return CastInst::Create(Instruction::ZExt, NarrowMaxMin, II->getType());
}
}
+ // If C0 is not 0:
+ // umax(nuw_shl(x, C0), x + 1) -> x == 0 ? 1 : nuw_shl(x, C0)
+ // If C0 is not 0 or 1:
+ // umax(nuw_mul(x, C0), x + 1) -> x == 0 ? 1 : nuw_mul(x, C0)
+ auto foldMaxMulShift = [&](Value *A, Value *B) -> Instruction * {
+ const APInt *C;
+ Value *X;
+ if (((match(A, m_NUWShl(m_Value(X), m_APInt(C)))) ||
+ (match(A, m_NUWMul(m_Value(X), m_APInt(C))) && !C->isOne())) &&
+ !C->isZero() && match(B, m_OneUse(m_Add(m_Specific(X), m_One())))) {
+ Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(X->getType(), 0));
+ Value *NewSelect =
+ Builder.CreateSelect(Cmp, ConstantInt::get(X->getType(), 1), A);
+ return replaceInstUsesWith(*II, NewSelect);
+ }
+ return nullptr;
+ };
----------------
goldsteinn wrote:
nit: I think its easier to read if you use early returns as opposed to mashing it all together into a single condition ie:
```
auto foldMaxMulShift = [&](Value *A, Value *B) -> Instruction * {
const APInt *C;
Value *X;
if (!(match(A, m_NUWShl(m_Value(X), m_APInt(C)))) &&
!(match(A, m_NUWMul(m_Value(X), m_APInt(C))) && !C->isOne()))
return nullptr;
if (!C->isZero())
return nullptr;
if (!match(B, m_OneUse(m_Add(m_Specific(X), m_One()))))
return nullptr;
Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(X->getType(), 0));
Value *NewSelect =
Builder.CreateSelect(Cmp, ConstantInt::get(X->getType(), 1), A);
return replaceInstUsesWith(*II, NewSelect);
};
```
That being said this is purely stylistic, so do as you do.
https://github.com/llvm/llvm-project/pull/123468
More information about the llvm-commits
mailing list