@@ -1695,19 +1695,23 @@ bool CodeGenPrepare::combineToUAddWithOverflow(CmpInst *Cmp,
16951695 return true ;
16961696}
16971697
1698- bool CodeGenPrepare::combineToUSubWithOverflow (CmpInst *Cmp,
1699- ModifyDT &ModifiedDT ) {
1700- // We are not expecting non-canonical/degenerate code. Just bail out.
1698+ static bool matchUSubWithOverflowConstantEdgeCases (CmpInst *Cmp,
1699+ BinaryOperator *&Sub ) {
1700+ // A - B, A u> B --> usubo(A, B)
17011701 Value *A = Cmp->getOperand (0 ), *B = Cmp->getOperand (1 );
1702+
1703+ // We are not expecting non-canonical/degenerate code. Just bail out.
17021704 if (isa<Constant>(A) && isa<Constant>(B))
17031705 return false ;
17041706
1705- // Convert (A u> B) to (A u< B) to simplify pattern matching.
17061707 ICmpInst::Predicate Pred = Cmp->getPredicate ();
1708+
1709+ // Normalize: convert (A u> B) -> (B u< A)
17071710 if (Pred == ICmpInst::ICMP_UGT) {
17081711 std::swap (A, B);
17091712 Pred = ICmpInst::ICMP_ULT;
17101713 }
1714+
17111715 // Convert special-case: (A == 0) is the same as (A u< 1).
17121716 if (Pred == ICmpInst::ICMP_EQ && match (B, m_ZeroInt ())) {
17131717 B = ConstantInt::get (B->getType (), 1 );
@@ -1718,39 +1722,65 @@ bool CodeGenPrepare::combineToUSubWithOverflow(CmpInst *Cmp,
17181722 std::swap (A, B);
17191723 Pred = ICmpInst::ICMP_ULT;
17201724 }
1725+
17211726 if (Pred != ICmpInst::ICMP_ULT)
17221727 return false ;
17231728
1724- // Walk the users of a variable operand of a compare looking for a subtract or
1725- // add with that same operand. Also match the 2nd operand of the compare to
1726- // the add/sub, but that may be a negated constant operand of an add.
1729+ // Walk the users of the variable operand of the compare looking for a
1730+ // subtract or add with that same operand. Also match the 2nd operand of the
1731+ // compare to the add/sub, but that may be a negated constant operand of an
1732+ // add.
17271733 Value *CmpVariableOperand = isa<Constant>(A) ? B : A;
1728- BinaryOperator *Sub = nullptr ;
1734+ Sub = nullptr ;
1735+
17291736 for (User *U : CmpVariableOperand->users ()) {
17301737 // A - B, A u< B --> usubo(A, B)
17311738 if (match (U, m_Sub (m_Specific (A), m_Specific (B)))) {
17321739 Sub = cast<BinaryOperator>(U);
1733- break ;
1740+ return true ;
17341741 }
17351742
17361743 // A + (-C), A u< C (canonicalized form of (sub A, C))
17371744 const APInt *CmpC, *AddC;
17381745 if (match (U, m_Add (m_Specific (A), m_APInt (AddC))) &&
17391746 match (B, m_APInt (CmpC)) && *AddC == -(*CmpC)) {
17401747 Sub = cast<BinaryOperator>(U);
1741- break ;
1748+ return true ;
17421749 }
17431750 }
1744- if (!Sub)
1745- return false ;
17461751
1752+ return false ;
1753+ }
1754+
1755+ bool CodeGenPrepare::combineToUSubWithOverflow (CmpInst *Cmp,
1756+ ModifyDT &ModifiedDT) {
1757+ bool EdgeCase = false ;
1758+ Value *A = nullptr , *B = nullptr ;
1759+ BinaryOperator *Sub = nullptr ;
1760+
1761+ // If the compare already matches the (sub, icmp) pattern use it directly.
1762+ if (!match (Cmp, m_USubWithOverflow (m_Value (A), m_Value (B), m_BinOp (Sub)))) {
1763+ // Otherwise try to recognize constant-edge-case forms like
1764+ // icmp ne (sub 0, B), 0 or
1765+ // icmp eq (sub A, 1), 0
1766+ if (!matchUSubWithOverflowConstantEdgeCases (Cmp, Sub))
1767+ return false ;
1768+ // Set A/B from the discovered Sub and record that this was an edge-case
1769+ // match.
1770+ A = Sub->getOperand (0 );
1771+ B = Sub->getOperand (1 );
1772+ EdgeCase = true ;
1773+ }
1774+
1775+ // Check target wants the overflow intrinsic formed. When matching an
1776+ // edge-case we allow forming the intrinsic with fewer uses.
17471777 if (!TLI->shouldFormOverflowOp (ISD::USUBO,
17481778 TLI->getValueType (*DL, Sub->getType ()),
1749- Sub->hasNUsesOrMore (1 )))
1779+ Sub->hasNUsesOrMore (EdgeCase ? 1 : 2 )))
17501780 return false ;
17511781
1752- if (!replaceMathCmpWithIntrinsic (Sub, Sub-> getOperand ( 0 ), Sub-> getOperand ( 1 ) ,
1753- Cmp, Intrinsic::usub_with_overflow))
1782+ if (!replaceMathCmpWithIntrinsic (Sub, A, B, Cmp ,
1783+ Intrinsic::usub_with_overflow))
17541784 return false ;
17551785
17561786 // Reset callers - do not crash by iterating over a dead instruction.
0 commit comments