[llvm] [ValueTracking] Support horizontal vector add in computeKnownBits (PR #174410)

Valeriy Savchenko via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 11 06:13:01 PST 2026


================
@@ -601,6 +601,46 @@ KnownBits KnownBits::abs(bool IntMinIsPoison) const {
   return KnownAbs;
 }
 
+KnownBits KnownBits::reduceAdd(unsigned NumElts) const {
+  if (NumElts == 0)
+    return KnownBits(getBitWidth());
+
+  unsigned BitWidth = getBitWidth();
+  KnownBits Result(BitWidth);
+
+  if (isConstant())
+    // If all elements are the same constant, we can simply compute it
+    return KnownBits::makeConstant(NumElts * getConstant());
+
+  // The main idea is as follows.
+  //
+  // If KnownBits for each element has L leading zeros then
+  // X_i < 2^(W - L) for every i from [1, N].
+  //
+  //   ADD X_i <= ADD max(X_i) = N * max(X_i)
+  //           <  N * 2^(W - L)
+  //           <  2^(W - L + ceil(log2(N)))
+  //
+  // As the result, we can conclude that
+  //
+  //   L' = L - ceil(log2(N)) = L - bit_width(N - 1)
+  //
+  // Similar logic can be applied to leading ones.
+  unsigned LostBits = NumElts > 1 ? llvm::bit_width(NumElts - 1) : 0;
+
+  if (isNonNegative()) {
----------------
SavchenkoValeriy wrote:

Re-implementing `KnownBits::mul` logic in Alive2 or SMT is a bit too involved, so I simply implemented this suggestion and checked what does this exhaustive test produce: 

```
/Users/vsavchenko/source/llvm-project/llvm/unittests/Support/KnownBitsTest.cpp:878: Failure
Value of: checkResult("reduceAdd", Exact, Computed, {EltKnown}, false)
  Actual: false (reduceAdd: Inputs = ????, Computed = ???0, Exact = ????)
Expected: true

/Users/vsavchenko/source/llvm-project/llvm/unittests/Support/KnownBitsTest.cpp:878: Failure
Value of: checkResult("reduceAdd", Exact, Computed, {EltKnown}, false)
  Actual: false (reduceAdd: Inputs = ???1, Computed = ??10, Exact = ???0)
Expected: true
...
```

This happens because we jump from $`\sum {X_i} <= \sum max(X_i) = N * max(X_i)`$ so known-bits of the upper-bound are correct when we try to preserve leading zeros and ones, but not in other cases. And even if I take `countMinLeadingZeros`/`countMinLeadingOnes` from `KnownBits::mul`, I still get counter-examples generated by this test.

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


More information about the llvm-commits mailing list