[llvm] [InstCombine] fold icmp with add/sub instructions having the same operands (PR #143241)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 9 01:02:53 PDT 2025


================
@@ -7728,6 +7728,45 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
     }
   }
 
+  // When comparing results of sub and add instructions with identical operands,
+  // optimization is valid when the comparison type and overflow flags satisfy:
+  //   - Signed comparisons (slt/sgt/sle/sge) require 'nsw' flags
+  //   - Unsigned comparisons (ult/ugt/ule/uge) require 'nuw' flags
+  //   - Equality comparisons (eq/ne) accept either 'nsw' or 'nuw'
+  //
+  // If conditions are met, the comparison simplifies to a zero comparison on
+  // the second operand of the sub instruction with the swapped predicate.
+  // Example transformation for signed comparison:
+  //   %sub = sub nsw i8 %x, %y
+  //   %add = add nsw i8 %x, %y
+  //   %cmp = icmp sgt i8 %sub, %add  // (x - y) > (x + y)
+  // becomes:
+  //   %cmp = icmp slt i8 %y, 0      // y < 0
+  //
+  // This handles similar cases to transform.
+  {
+    Value *A, *B;
+    auto *I0 = dyn_cast<OverflowingBinaryOperator>(Op0);
+    auto *I1 = dyn_cast<OverflowingBinaryOperator>(Op1);
+    if (I0 && I1) {
+      bool I0NUW = I0->hasNoUnsignedWrap();
+      bool I1NUW = I1->hasNoUnsignedWrap();
+      bool I0NSW = I0->hasNoSignedWrap();
+      bool I1NSW = I1->hasNoSignedWrap();
+      bool UnsignedCmp = ICmpInst::isUnsigned(Pred);
+      bool SignedCmp = ICmpInst::isSigned(Pred);
+      bool EqualityCmp = ICmpInst::isEquality(Pred);
----------------
nikic wrote:

These UnsignedCmp/SignedCmp/EqualityCmp variables are unnecessary, just inline them at their single use site.

https://github.com/llvm/llvm-project/pull/143241


More information about the llvm-commits mailing list