aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/KnownBits.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2021-12-20 09:10:50 -0500
committerSanjay Patel <spatel@rotateright.com>2021-12-20 09:10:50 -0500
commit892c731681df962064828334531f59d29eb8473a (patch)
treee0130b54d9a58f46a6e9e0b0cb29151c92d949fc /llvm/lib/Support/KnownBits.cpp
parentfcaf290d0278bb83387e1a1d972c55e08b8c40e3 (diff)
downloadllvm-892c731681df962064828334531f59d29eb8473a.zip
llvm-892c731681df962064828334531f59d29eb8473a.tar.gz
llvm-892c731681df962064828334531f59d29eb8473a.tar.bz2
[Support] improve known bits analysis for leading zeros of multiply
Instead of summing leading zeros on the input operands, multiply the max possible values of those inputs and count the leading zeros of the result. This can give us an extra zero bit (typically in cases where one of the operands is a known constant). This allows folding away the remaining 'add' ops in the motivating bug (modeled in the PhaseOrdering IR test): https://github.com/llvm/llvm-project/issues/48399 Fixes #48399 Differential Revision: https://reviews.llvm.org/D115969
Diffstat (limited to 'llvm/lib/Support/KnownBits.cpp')
-rw-r--r--llvm/lib/Support/KnownBits.cpp23
1 files changed, 12 insertions, 11 deletions
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index fdc8fdb..8e15406 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -420,18 +420,19 @@ KnownBits KnownBits::mul(const KnownBits &LHS, const KnownBits &RHS,
assert((!SelfMultiply || (LHS.One == RHS.One && LHS.Zero == RHS.Zero)) &&
"Self multiplication knownbits mismatch");
- // Compute a conservative estimate for high known-0 bits.
+ // 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).
- unsigned LHSLeadZ = LHS.countMinLeadingZeros();
- unsigned RHSLeadZ = RHS.countMinLeadingZeros();
-
- // If either operand is a power-of-2, the multiply is only shifting bits in
- // the other operand (there can't be a carry into the M+N bit of the result).
- // Note: if we know that a value is entirely 0, that should simplify below.
- bool BonusLZ = LHS.countMaxPopulation() == 1 || RHS.countMaxPopulation() == 1;
-
- unsigned LeadZ = std::max(LHSLeadZ + RHSLeadZ + BonusLZ, BitWidth) - BitWidth;
- assert(LeadZ <= BitWidth && "More zeros than bits?");
+ 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).
+ bool HasOverflow;
+ APInt UMaxResult = UMaxLHS.umul_ov(UMaxRHS, HasOverflow);
+ unsigned LeadZ = HasOverflow ? 0 : UMaxResult.countLeadingZeros();
// The result of the bottom bits of an integer multiply can be
// inferred by looking at the bottom bits of both operands and