[llvm] [InstCombine]: Replace overflow calculation with intrinsic (PR #168195)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 03:07:33 PST 2025


================
@@ -7161,6 +7164,66 @@ Instruction *InstCombinerImpl::foldICmpUsingBoolRange(ICmpInst &I) {
   return nullptr;
 }
 
+/// Fold icmp(ult, sub(add(sext(X), Cst1), sext(Y)), Cst2) -->
+/// extract(__builtin_ssub_overflow(X, Y), 1)
+Instruction *InstCombinerImpl::foldICmpsToSignedSubOverflow(Instruction &I) {
+  CmpPredicate Pred;
+  ConstantInt *Cst1, *Cst2;
+  Value *X, *Y;
+
+  /*
+    This transformation detects the pattern used to check for
+    a signed subtraction overflow.
+
+    The matched sequence performs the following steps:
+
+      1. X = sext(x)
+         Y = sext(y)
+         // Sign-extend 32-bit operands to 64 bits.
+
+      2. Shifted = X + Cst1
+         // Shift the signed range [-2^31, 2^31-1] by adding the minimum
+         // signed value (Cst1 = INT_MIN), producing an unsigned range
+         // [0, 2^32).
+
+      3. Sub = Shifted - Y
+         // Compute the shifted subtraction result.
+
+      4. icmp ult Sub, Cst2
+         // Check whether the result fits in [0, 2^32).
+         // If not, the subtraction overflowed.
+  */
+
+  auto SExtX = m_SExt(m_Value(X));
+  auto SExtY = m_SExt(m_Value(Y));
+  auto Shifted = m_Add(SExtX, m_ConstantInt(Cst1));
+  auto Sub = m_Sub(Shifted, SExtY);
+
+  if (!match(&I, m_ICmp(Pred, Sub, m_ConstantInt(Cst2))) ||
+      Pred != CmpInst::ICMP_ULT)
+    return nullptr;
+
+  const auto SignedMin =
+      APInt::getSignedMinValue(X->getType()->getScalarSizeInBits());
+  const auto ExpectedRange = SignedMin.getSExtValue() << 1;
+
+  // Cst1 must equal to SignedMin
+  // Cst2 must equal to ExpectedRange
+  if (SignedMin.getSExtValue() != Cst1->getValue().getSExtValue() ||
+      ExpectedRange != Cst2->getValue().getSExtValue())
+    return nullptr;
+
+  Module *M = I.getModule();
+  Function *F = Intrinsic::getOrInsertDeclaration(
+      M, Intrinsic::ssub_with_overflow, X->getType());
+
+  Builder.SetInsertPoint(&I);
----------------
nikic wrote:

There should be no need to explicitly set the insert point.

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


More information about the llvm-commits mailing list