[llvm] [ConstantRange] Bail out early in unsignedMulMayOverflow for wide integer types (PR #192275)

Max Graey via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 09:25:05 PDT 2026


================
@@ -2009,11 +2009,40 @@ APInt APInt::smul_ov(const APInt &RHS, bool &Overflow) const {
 }
 
 APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const {
-  if (countl_zero() + RHS.countl_zero() + 2 <= BitWidth) {
+  if (BitWidth == 0) {
+    Overflow = false;
+    return APInt(BitWidth, 0);
+  }
+  unsigned LZ = countl_zero() + RHS.countl_zero();
+
+  // No-overflow: product fits in BitWidth bits (bitlen(a)+bitlen(b) <=
+  // BitWidth).
+  if (LZ >= BitWidth) {
+    Overflow = false;
+    return *this * RHS;
+  }
+
+  // Guaranteed overflow: product needs more than BitWidth bits.
+  if (LZ < BitWidth - 1) {
     Overflow = true;
     return *this * RHS;
   }
 
+  // Borderline (LZ == BitWidth-1): skip the slow path for trivial multipliers.
+  // *this==1: 1*x=x always fits, and avoids a wasteful lshr(1)==0 multiply.
+  // RHS==1:   x*1=x always fits.
+  if (isOne()) {
+    Overflow = false;
+    return RHS;
+  }
+  if (RHS.isOne()) {
+    Overflow = false;
+    return *this;
+  }
----------------
MaxGraey wrote:

How about merge these two blocks into one more compact?
```suggestion
  if (isOne() || RHS.isOne()) {
    Overflow = false;
    return isOne() ? RHS : *this;;
  }
```

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


More information about the llvm-commits mailing list