@@ -7728,36 +7728,41 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
77287728 }
77297729 }
77307730
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+ //
77407746 // This handles similar cases to transform.
77417747 {
77427748 Value *A, *B;
77437749 auto *I0 = dyn_cast<OverflowingBinaryOperator>(Op0);
77447750 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-
77497751 if (I0 && I1) {
77507752 bool I0NUW = I0->hasNoUnsignedWrap ();
77517753 bool I1NUW = I1->hasNoUnsignedWrap ();
77527754 bool I0NSW = I0->hasNoSignedWrap ();
77537755 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;
77547760 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,
77597765 ConstantInt::get (Op0->getType (), 0 ));
7760- }
77617766 }
77627767 }
77637768 }
0 commit comments