diff --git a/llvm/include/llvm/Support/KnownBits.h b/llvm/include/llvm/Support/KnownBits.h --- a/llvm/include/llvm/Support/KnownBits.h +++ b/llvm/include/llvm/Support/KnownBits.h @@ -249,7 +249,8 @@ return countMinLeadingZeros(); if (isNegative()) return countMinLeadingOnes(); - return 0; + // Every value has at least 1 sign bit. + return 1; } /// Returns the maximum number of trailing zero bits possible. diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -4626,11 +4626,12 @@ RHSKnown = RHSKnown.trunc(24); if (Opc == AMDGPUISD::MUL_I24) { - unsigned LHSValBits = 24 - LHSKnown.countMinSignBits(); - unsigned RHSValBits = 24 - RHSKnown.countMinSignBits(); - unsigned MaxValBits = std::min(LHSValBits + RHSValBits, 32u); - if (MaxValBits >= 32) + unsigned LHSValBits = 24 - LHSKnown.countMinSignBits() + 1; + unsigned RHSValBits = 24 - RHSKnown.countMinSignBits() + 1; + unsigned MaxValBits = LHSValBits + RHSValBits; + if (MaxValBits > 32) break; + unsigned SignBits = 32 - MaxValBits + 1; bool LHSNegative = LHSKnown.isNegative(); bool LHSNonNegative = LHSKnown.isNonNegative(); bool LHSPositive = LHSKnown.isStrictlyPositive(); @@ -4639,9 +4640,9 @@ bool RHSPositive = RHSKnown.isStrictlyPositive(); if ((LHSNonNegative && RHSNonNegative) || (LHSNegative && RHSNegative)) - Known.Zero.setHighBits(32 - MaxValBits); + Known.Zero.setHighBits(SignBits); else if ((LHSNegative && RHSPositive) || (LHSPositive && RHSNegative)) - Known.One.setHighBits(32 - MaxValBits); + Known.One.setHighBits(SignBits); } else { unsigned LHSValBits = 24 - LHSKnown.countMinLeadingZeros(); unsigned RHSValBits = 24 - RHSKnown.countMinLeadingZeros(); diff --git a/llvm/unittests/Support/KnownBitsTest.cpp b/llvm/unittests/Support/KnownBitsTest.cpp --- a/llvm/unittests/Support/KnownBitsTest.cpp +++ b/llvm/unittests/Support/KnownBitsTest.cpp @@ -442,6 +442,17 @@ }); } +TEST(KnownBitsTest, CountMinSignedBits) { + const unsigned Bits = 4; + ForeachKnownBits(Bits, [&](const KnownBits &Known) { + unsigned Expected = Bits; + ForeachNumInKnownBits(Known, [&](const APInt &N) { + Expected = std::min(Expected, N.getNumSignBits()); + }); + EXPECT_EQ(Expected, Known.countMinSignBits()); + }); +} + TEST(KnownBitsTest, SExtOrTrunc) { const unsigned NarrowerSize = 4; const unsigned BaseSize = 6;