[llvm] [ValueTracking] Add a special overflow check on multiplied by power-of-two values (PR #212594)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 12:46:58 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Min-Yih Hsu (mshockwave)

<details>
<summary>Changes</summary>

Aside from our existing signed overflow checks on multiplication, which is based on the number of sign bits, if we're multiplying by a power-of-two value, then as long as the shift amount is less than the number of sign bits in the other operand, then we will never overflow.

This is useful on cases where the existing sign-bit-based approach deems too complicated to solve. Specifically, when `NumSignBits == BitWidth`.  

---
Full diff: https://github.com/llvm/llvm-project/pull/212594.diff


2 Files Affected:

- (modified) llvm/lib/Analysis/ValueTracking.cpp (+17) 
- (modified) llvm/test/Transforms/InstCombine/binop-itofp.ll (+3-3) 


``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 1f974c148af41..14a5292f65cfb 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -7542,6 +7542,23 @@ OverflowResult llvm::computeOverflowForSignedMul(const Value *LHS,
     if (LHSKnown.isNonNegative() || RHSKnown.isNonNegative())
       return OverflowResult::NeverOverflows;
   }
+
+  // Special case when we're multiplying a power-of-two value. In this case,
+  // we will never overflow as long as the shift amount is less than the number
+  // of sign bits.
+  if (isKnownToBeAPowerOfTwo(RHS, /*OrZero=*/false, SQ)) {
+    KnownBits LHSKnown = computeKnownBits(LHS, SQ);
+    KnownBits RHSKnown = computeKnownBits(RHS, SQ);
+    // If RHS is power of two, the only time it is negative would be
+    // the smallest value. In that case it never overflows only if
+    // LHS is zero or one. If LHS is really zero or one we would have
+    // simplified it somewhere else, therefore this pattern checks only
+    // when RHS is positive.
+    if (RHSKnown.isStrictlyPositive() &&
+        LHSKnown.countMinSignBits() > RHSKnown.countMaxTrailingZeros())
+      return OverflowResult::NeverOverflows;
+  }
+
   return OverflowResult::MayOverflow;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/binop-itofp.ll b/llvm/test/Transforms/InstCombine/binop-itofp.ll
index d4f57026174b6..5a848d04adda4 100644
--- a/llvm/test/Transforms/InstCombine/binop-itofp.ll
+++ b/llvm/test/Transforms/InstCombine/binop-itofp.ll
@@ -659,10 +659,10 @@ define half @test_si_si_i16_mul_fail_overflow(i16 noundef %x_in, i16 noundef %y_
 
 define half @test_si_si_i16_mul_C_fail_overflow(i16 noundef %x_in) {
 ; CHECK-LABEL: @test_si_si_i16_mul_C_fail_overflow(
-; CHECK-NEXT:    [[X:%.*]] = or i16 [[X_IN:%.*]], -129
+; CHECK-NEXT:    [[X1:%.*]] = shl i16 [[X_IN:%.*]], 7
+; CHECK-NEXT:    [[X:%.*]] = or i16 [[X1]], -16512
 ; CHECK-NEXT:    [[XF:%.*]] = sitofp i16 [[X]] to half
-; CHECK-NEXT:    [[R:%.*]] = fmul nnan half [[XF]], 1.280000e+02
-; CHECK-NEXT:    ret half [[R]]
+; CHECK-NEXT:    ret half [[XF]]
 ;
   %x = or i16 %x_in, -129
   %xf = sitofp i16 %x to half

``````````

</details>


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


More information about the llvm-commits mailing list