diff options
author | Sanjay Patel <spatel@rotateright.com> | 2021-12-20 09:10:50 -0500 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2021-12-20 09:10:50 -0500 |
commit | 892c731681df962064828334531f59d29eb8473a (patch) | |
tree | e0130b54d9a58f46a6e9e0b0cb29151c92d949fc /llvm/lib/Support/KnownBits.cpp | |
parent | fcaf290d0278bb83387e1a1d972c55e08b8c40e3 (diff) | |
download | llvm-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.cpp | 23 |
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 |