@@ -7728,36 +7728,41 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
7728
7728
}
7729
7729
}
7730
7730
7731
- // In case of a comparison with add/sub instructions having the same operands,
7732
- // check whether cmp operands have same signed no wrap. If so, just compare
7733
- // the sub's second operand and zero.
7734
- // For example:
7735
- // %tmp1 = sub nsw i8 %x, %y
7736
- // %tmp2 = add nsw i8 %x, %y
7737
- // %cmp = icmp sgt i8 %tmp1, %tmp2
7738
- // transform this into:
7739
- // %cmp = icmp slt i32 %y, 0
7731
+ // When comparing results of sub and add instructions with identical operands,
7732
+ // optimization is valid when the comparison type and overflow flags satisfy:
7733
+ // - Signed comparisons (slt/sgt/sle/sge) require 'nsw' flags
7734
+ // - Unsigned comparisons (ult/ugt/ule/uge) require 'nuw' flags
7735
+ // - Equality comparisons (eq/ne) accept either 'nsw' or 'nuw'
7736
+ //
7737
+ // If conditions are met, the comparison simplifies to a zero comparison on
7738
+ // the second operand of the sub instruction with the swapped predicate.
7739
+ // Example transformation for signed comparison:
7740
+ // %sub = sub nsw i8 %x, %y
7741
+ // %add = add nsw i8 %x, %y
7742
+ // %cmp = icmp sgt i8 %sub, %add // (x - y) > (x + y)
7743
+ // becomes:
7744
+ // %cmp = icmp slt i8 %y, 0 // y < 0
7745
+ //
7740
7746
// This handles similar cases to transform.
7741
7747
{
7742
7748
Value *A, *B;
7743
7749
auto *I0 = dyn_cast<OverflowingBinaryOperator>(Op0);
7744
7750
auto *I1 = dyn_cast<OverflowingBinaryOperator>(Op1);
7745
- bool UnsignedCmp = ICmpInst::isUnsigned (Pred);
7746
- bool SignedCmp = ICmpInst::isSigned (Pred);
7747
- bool EqualityCmp = ICmpInst::isEquality (Pred);
7748
-
7749
7751
if (I0 && I1) {
7750
7752
bool I0NUW = I0->hasNoUnsignedWrap ();
7751
7753
bool I1NUW = I1->hasNoUnsignedWrap ();
7752
7754
bool I0NSW = I0->hasNoSignedWrap ();
7753
7755
bool I1NSW = I1->hasNoSignedWrap ();
7756
+ bool UnsignedCmp = ICmpInst::isUnsigned (Pred);
7757
+ bool SignedCmp = ICmpInst::isSigned (Pred);
7758
+ bool EqualityCmp = ICmpInst::isEquality (Pred);
7759
+ CmpPredicate CmpPred;
7754
7760
if ((UnsignedCmp && I0NUW && I1NUW) || (SignedCmp && I0NSW && I1NSW) ||
7755
- (EqualityCmp && ((I0NUW && I1NUW) || ( I0NSW && I1NSW)))) {
7756
- if (match (I0, m_Sub (m_Value (A), m_Value (B))) &&
7757
- match (I1, m_Add ( m_Specific (A), m_Specific (B)))) {
7758
- return new ICmpInst (I. getSwappedPredicate ( ), B,
7761
+ (EqualityCmp && ((I0NUW || I0NSW) && (I1NUW || I1NSW)))) {
7762
+ if (match (&I, m_c_ICmp (CmpPred, m_Sub (m_Value (A), m_Value (B)),
7763
+ m_c_Add ( m_Deferred (A), m_Deferred (B)))))
7764
+ return new ICmpInst (CmpPredicate::getSwapped (CmpPred ), B,
7759
7765
ConstantInt::get (Op0->getType (), 0 ));
7760
- }
7761
7766
}
7762
7767
}
7763
7768
}
0 commit comments