1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[ValueTracking] Support funnel shifts in computeKnownBits()

If the shift amount is known, we can determine the known bits of the
output based on the known bits of two inputs.

This is essentially the same functionality as implemented in D54869,
but for ValueTracking rather than InstCombine SimplifyDemandedBits.

Differential Revision: https://reviews.llvm.org/D55140

llvm-svn: 348091
This commit is contained in:
Nikita Popov 2018-12-02 14:14:11 +00:00
parent 2986f40e8a
commit bb7c898cb7
2 changed files with 69 additions and 0 deletions

View File

@ -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;

View File

@ -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);
}