summaryrefslogtreecommitdiff
path: root/llvm/lib/Support/KnownBits.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/KnownBits.cpp')
-rw-r--r--llvm/lib/Support/KnownBits.cpp18
1 files changed, 13 insertions, 5 deletions
diff --git a/llvm/lib/Support/KnownBits.cpp b/llvm/lib/Support/KnownBits.cpp
index 554e3248524c..8e154067abc0 100644
--- a/llvm/lib/Support/KnownBits.cpp
+++ b/llvm/lib/Support/KnownBits.cpp
@@ -420,11 +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.
- unsigned LHSLeadZ = LHS.countMinLeadingZeros();
- unsigned RHSLeadZ = RHS.countMinLeadingZeros();
- unsigned LeadZ = std::max(LHSLeadZ + RHSLeadZ, BitWidth) - BitWidth;
- assert(LeadZ <= BitWidth && "More zeros than 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).
+ 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