[llvm] [InstCombine] Extend canonicalization of addition to positive numbers (PR #179343)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 3 06:23:41 PST 2026
================
@@ -1147,51 +1147,84 @@ static Value *canonicalizeSaturatedAddSigned(ICmpInst *Cmp, Value *TVal,
Value *Cmp0 = Cmp->getOperand(0);
Value *Cmp1 = Cmp->getOperand(1);
ICmpInst::Predicate Pred = Cmp->getPredicate();
- Value *X;
- const APInt *C;
- // Canonicalize INT_MAX to true value of the select.
- if (match(FVal, m_MaxSignedValue())) {
+ // Canonicalize TVal to be the saturation constant.
+ if (match(FVal, m_MaxSignedValue()) || match(FVal, m_SignMask())) {
std::swap(TVal, FVal);
Pred = CmpInst::getInversePredicate(Pred);
}
- if (!match(TVal, m_MaxSignedValue()))
+ const APInt *SatC;
+ if (!match(TVal, m_APInt(SatC)) ||
+ !(SatC->isMaxSignedValue() || SatC->isSignMask()))
return nullptr;
+ bool IsMax = SatC->isMaxSignedValue();
+
// sge maximum signed value is canonicalized to eq maximum signed value and
- // requires special handling (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a,
- // 1)
- if (Pred == ICmpInst::ICMP_EQ) {
- if (match(FVal, m_Add(m_Specific(Cmp0), m_One())) && Cmp1 == TVal) {
+ // requires special handling. sle minimum signed value is similarly
+ // canonicalized to eq minimum signed value.
+ if (Pred == ICmpInst::ICMP_EQ && Cmp1 == TVal) {
+ // (a == INT_MAX) ? INT_MAX : a + 1 -> sadd.sat(a, 1)
+ if (IsMax && match(FVal, m_Add(m_Specific(Cmp0), m_One()))) {
return Builder.CreateBinaryIntrinsic(
Intrinsic::sadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), 1));
}
+
+ // (a == INT_MIN) ? INT_MIN : a + -1 -> sadd.sat(a, -1)
+ if (!IsMax && match(FVal, m_Add(m_Specific(Cmp0), m_AllOnes()))) {
+ return Builder.CreateBinaryIntrinsic(
+ Intrinsic::sadd_sat, Cmp0,
+ ConstantInt::get(Cmp0->getType(), -1, /*IsSigned=*/true));
+ }
return nullptr;
}
+ const APInt *C;
+
// (X > Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
// (X >= Y) ? INT_MAX : (X + C) --> sadd.sat(X, C)
- // where Y is INT_MAX - C or INT_MAX - C - 1, and C > 0
- if ((Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) &&
+ // where C > 0
+ if (IsMax && (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE) &&
isa<Constant>(Cmp1) &&
match(FVal, m_Add(m_Specific(Cmp0), m_StrictlyPositive(C)))) {
- APInt IntMax =
- APInt::getSignedMaxValue(Cmp1->getType()->getScalarSizeInBits());
-
- // For SGE, try to flip to SGT to normalize the comparison constant.
+ // Normalize SGE to SGT for threshold comparison.
if (Pred == ICmpInst::ICMP_SGE) {
if (auto Flipped = getFlippedStrictnessPredicateAndConstant(
Pred, cast<Constant>(Cmp1))) {
Pred = Flipped->first;
Cmp1 = Flipped->second;
}
}
-
- // Check the pattern: X > INT_MAX - C or X > INT_MAX - C - 1
+ // Check: X > INT_MAX - C or X > INT_MAX - C - 1
+ APInt Threshold = *SatC - *C;
if (Pred == ICmpInst::ICMP_SGT &&
- (match(Cmp1, m_SpecificIntAllowPoison(IntMax - *C)) ||
- match(Cmp1, m_SpecificIntAllowPoison(IntMax - *C - 1))))
+ (match(Cmp1, m_SpecificIntAllowPoison(Threshold)) ||
+ match(Cmp1, m_SpecificIntAllowPoison(Threshold - 1))))
+ return Builder.CreateBinaryIntrinsic(
+ Intrinsic::sadd_sat, Cmp0, ConstantInt::get(Cmp0->getType(), *C));
+ }
+
+ // (X < Y) ? INT_MIN : (X + C) --> sadd.sat(X, C)
+ // (X <= Y) ? INT_MIN : (X + C) --> sadd.sat(X, C)
+ // where C < 0
----------------
dtcxzyw wrote:
Missing definition for Y.
https://github.com/llvm/llvm-project/pull/179343
More information about the llvm-commits
mailing list