diff options
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 21 | ||||
-rw-r--r-- | llvm/unittests/Analysis/ValueTrackingTest.cpp | 48 |
2 files changed, 69 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index a6ad6bf8cae..6f0196069f2 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1506,6 +1506,27 @@ static void computeKnownBitsFromOperator(const Operator *I, KnownBits &Known, // of bits which might be set provided by popcnt KnownOne2. break; } + case Intrinsic::fshr: + case Intrinsic::fshl: { + const APInt *SA; + if (!match(I->getOperand(2), m_APInt(SA))) + break; + + // Normalize to funnel shift left. + uint64_t ShiftAmt = SA->urem(BitWidth); + if (II->getIntrinsicID() == Intrinsic::fshr) + ShiftAmt = BitWidth - ShiftAmt; + + KnownBits Known3(Known); + computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q); + computeKnownBits(I->getOperand(1), Known3, Depth + 1, Q); + + Known.Zero = + Known2.Zero.shl(ShiftAmt) | Known3.Zero.lshr(BitWidth - ShiftAmt); + Known.One = + Known2.One.shl(ShiftAmt) | Known3.One.lshr(BitWidth - ShiftAmt); + break; + } case Intrinsic::x86_sse42_crc32_64_64: Known.Zero.setBitsFrom(32); break; diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index eeefb605867..5b36d63b390 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -568,3 +568,51 @@ TEST_F(ComputeKnownBitsTest, ComputeKnownMulBits) { "}\n"); expectKnownBits(/*zero*/ 95u, /*one*/ 32u); } + +TEST_F(ComputeKnownBitsTest, ComputeKnownFshl) { + // fshl(....1111....0000, 00..1111........, 6) + // = 11....000000..11 + parseAssembly( + "define i16 @test(i16 %a, i16 %b) {\n" + " %aa = shl i16 %a, 4\n" + " %bb = lshr i16 %b, 2\n" + " %aaa = or i16 %aa, 3840\n" + " %bbb = or i16 %bb, 3840\n" + " %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 6)\n" + " ret i16 %A\n" + "}\n" + "declare i16 @llvm.fshl.i16(i16, i16, i16)\n"); + expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u); +} + +TEST_F(ComputeKnownBitsTest, ComputeKnownFshr) { + // fshr(....1111....0000, 00..1111........, 26) + // = 11....000000..11 + parseAssembly( + "define i16 @test(i16 %a, i16 %b) {\n" + " %aa = shl i16 %a, 4\n" + " %bb = lshr i16 %b, 2\n" + " %aaa = or i16 %aa, 3840\n" + " %bbb = or i16 %bb, 3840\n" + " %A = call i16 @llvm.fshr.i16(i16 %aaa, i16 %bbb, i16 26)\n" + " ret i16 %A\n" + "}\n" + "declare i16 @llvm.fshr.i16(i16, i16, i16)\n"); + expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u); +} + +TEST_F(ComputeKnownBitsTest, ComputeKnownFshlZero) { + // fshl(....1111....0000, 00..1111........, 0) + // = ....1111....0000 + parseAssembly( + "define i16 @test(i16 %a, i16 %b) {\n" + " %aa = shl i16 %a, 4\n" + " %bb = lshr i16 %b, 2\n" + " %aaa = or i16 %aa, 3840\n" + " %bbb = or i16 %bb, 3840\n" + " %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 0)\n" + " ret i16 %A\n" + "}\n" + "declare i16 @llvm.fshl.i16(i16, i16, i16)\n"); + expectKnownBits(/*zero*/ 15u, /*one*/ 3840u); +} |