[llvm] KnownBits: generalize high-bits of mul to overflows (PR #114211)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 1 04:22:59 PDT 2024
================
@@ -796,19 +796,76 @@ KnownBits KnownBits::mul(const KnownBits &LHS, const KnownBits &RHS,
assert((!NoUndefSelfMultiply || LHS == RHS) &&
"Self multiplication knownbits mismatch");
- // Compute the high known-0 bits by multiplying the unsigned max of each side.
- // Conservatively, M active bits * N active bits results in M + N bits in the
- // result. But if we know a value is a power-of-2 for example, then this
- // computes one more leading zero.
- // TODO: This could be generalized to number of sign bits (negative numbers).
- APInt UMaxLHS = LHS.getMaxValue();
- APInt UMaxRHS = RHS.getMaxValue();
-
- // For leading zeros in the result to be valid, the unsigned max product must
- // fit in the bitwidth (it must not overflow).
+ // Compute the high known-0 or known-1 bits by multiplying the min and max of
+ // each side.
+ APInt MaxLHS = LHS.isNegative() ? LHS.getMinValue().abs() : LHS.getMaxValue(),
----------------
artagnon wrote:
This is easy to explain with an example:
0001 and ?010
In this case, ?010 can vary between 1010 (-6, 10) and 0010 (2). Now, MaxProduct is (-6, 10) and MinProduct is 2. These are not swapped later, as LHS.isNegative() == RHS.isNegative().
1111 and ?010
In this case, the value varies between 1010 (-6, 10) and 0010 (2), and the other operand is (15, -1). Now, MaxProduct = 6 and MinProduct = (-2, 2). Now, since LHS.isNegative() != RHS.isNegative(), MaxProduct = 2, and MinProduct = (-6, 10).
The trick here is to realize that, since we're in two's complement arithmetic:
- The abs() can be stripped if the signs match, since -LHS * -RHS = LHS * RHS.
- The isNegative() case can be stripped if we don't negate or swap the values when signs mismatch. There might also be an issue with using umul_ov, and we might have to use smul_ov.
The only reason these are in place, in practice, is because we want Min to really represent the minimum value, and Max to really represent the maximum value, to make reasoning about the code easier.
https://github.com/llvm/llvm-project/pull/114211
More information about the llvm-commits
mailing list