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:
parent
2986f40e8a
commit
bb7c898cb7
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user