diff --git a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp index 8146a67d4dfb9..4f23c40b8b2b1 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp @@ -9,7 +9,7 @@ /// Provides analysis for querying information about KnownBits during GISel /// passes. // -//===------------------ +//===----------------------------------------------------------------------===// #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/GlobalISel/Utils.h" @@ -510,6 +510,18 @@ void GISelKnownBits::computeKnownBitsImpl(Register R, KnownBits &Known, Known = Known.reverseBits(); break; } + case TargetOpcode::G_CTPOP: { + computeKnownBitsImpl(MI.getOperand(1).getReg(), Known2, DemandedElts, + Depth + 1); + // We can bound the space the count needs. Also, bits known to be zero can't + // contribute to the population. + unsigned BitsPossiblySet = Known2.countMaxPopulation(); + unsigned LowBits = Log2_32(BitsPossiblySet)+1; + Known.Zero.setBitsFrom(LowBits); + // TODO: we could bound Known.One using the lower bound on the number of + // bits which might be set provided by popcnt KnownOne2. + break; + } case TargetOpcode::G_UBFX: { KnownBits SrcOpKnown, OffsetKnown, WidthKnown; computeKnownBitsImpl(MI.getOperand(1).getReg(), SrcOpKnown, DemandedElts, diff --git a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp index e948f150e6777..5b6c516634df3 100644 --- a/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/KnownBitsTest.cpp @@ -1672,6 +1672,63 @@ TEST_F(AArch64GISelMITest, TestKnownBitsAssertZext) { EXPECT_EQ(0xFFFFFFFFFFFFFFF8u, Res.Zero.getZExtValue()); } +TEST_F(AArch64GISelMITest, TestKnownBitsCTPOP) { + StringRef MIRString = R"( + %src:_(s32) = COPY $w0 + %unknown:_(s32) = G_CTPOP %src + %constant_4294967295:_(s32) = G_CONSTANT i32 4294967295 + %thirtytwo:_(s32) = G_CTPOP %constant_4294967295 + %thirtytwo_copy:_(s32) = COPY %thirtytwo + %constant_15:_(s32) = G_CONSTANT i32 15 + %four:_(s32) = G_CTPOP %constant_15 + %four_copy:_(s32) = COPY %four + %constant_1:_(s32) = G_CONSTANT i32 1 + %one:_(s32) = G_CTPOP %constant_1 + %one_copy:_(s32) = COPY %one +)"; + setUp(MIRString); + if (!TM) + return; + + Register UnknownCopy = Copies[Copies.size() - 4]; + Register ThirtytwoCopy = Copies[Copies.size() - 3]; + Register FourCopy = Copies[Copies.size() - 2]; + Register OneCopy = Copies[Copies.size() - 1]; + + GISelKnownBits Info(*MF); + MachineInstr *Copy; + Register SrcReg; + KnownBits Res; + + Copy = MRI->getVRegDef(UnknownCopy); + SrcReg = Copy->getOperand(1).getReg(); + Res = Info.getKnownBits(SrcReg); + EXPECT_EQ(1u, Res.getBitWidth()); + EXPECT_EQ(0u, Res.One.getZExtValue()); + EXPECT_EQ(0u, Res.Zero.getZExtValue()); + + Copy = MRI->getVRegDef(ThirtytwoCopy); + SrcReg = Copy->getOperand(1).getReg(); + Res = Info.getKnownBits(SrcReg); + EXPECT_EQ(32u, Res.getBitWidth()); + EXPECT_EQ(0u, Res.One.getZExtValue()); + EXPECT_EQ(0xFFFFFFC0u, Res.Zero.getZExtValue()); + + Copy = MRI->getVRegDef(FourCopy); + SrcReg = Copy->getOperand(1).getReg(); + Res = Info.getKnownBits(SrcReg); + EXPECT_EQ(32u, Res.getBitWidth()); + EXPECT_EQ(0u, Res.One.getZExtValue()); + EXPECT_EQ(0xFFFFFFF8u, Res.Zero.getZExtValue()); + + Copy = MRI->getVRegDef(OneCopy); + SrcReg = Copy->getOperand(1).getReg(); + Res = Info.getKnownBits(SrcReg); + EXPECT_EQ(32u, Res.getBitWidth()); + EXPECT_EQ(0u, Res.One.getZExtValue()); + EXPECT_EQ(0xFFFFFFFEu, Res.Zero.getZExtValue()); +} + TEST_F(AMDGPUGISelMITest, TestKnownBitsUBFX) { StringRef MIRString = " %3:_(s32) = G_IMPLICIT_DEF\n" " %4:_(s32) = G_CONSTANT i32 12\n"