llvm.org GIT mirror llvm / 9054832
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@348091 91177308-0d34-0410-b5e6-96231b3b80d8 Nikita Popov 9 months ago
2 changed file(s) with 69 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
15031503 Known.Zero.setBitsFrom(LowBits);
15041504 // TODO: we could bound KnownOne using the lower bound on the number
15051505 // of bits which might be set provided by popcnt KnownOne2.
1506 break;
1507 }
1508 case Intrinsic::fshr:
1509 case Intrinsic::fshl: {
1510 const APInt *SA;
1511 if (!match(I->getOperand(2), m_APInt(SA)))
1512 break;
1513
1514 // Normalize to funnel shift left.
1515 uint64_t ShiftAmt = SA->urem(BitWidth);
1516 if (II->getIntrinsicID() == Intrinsic::fshr)
1517 ShiftAmt = BitWidth - ShiftAmt;
1518
1519 KnownBits Known3(Known);
1520 computeKnownBits(I->getOperand(0), Known2, Depth + 1, Q);
1521 computeKnownBits(I->getOperand(1), Known3, Depth + 1, Q);
1522
1523 Known.Zero =
1524 Known2.Zero.shl(ShiftAmt) | Known3.Zero.lshr(BitWidth - ShiftAmt);
1525 Known.One =
1526 Known2.One.shl(ShiftAmt) | Known3.One.lshr(BitWidth - ShiftAmt);
15061527 break;
15071528 }
15081529 case Intrinsic::x86_sse42_crc32_64_64:
567567 "}\n");
568568 expectKnownBits(/*zero*/ 95u, /*one*/ 32u);
569569 }
570
571 TEST_F(ComputeKnownBitsTest, ComputeKnownFshl) {
572 // fshl(....1111....0000, 00..1111........, 6)
573 // = 11....000000..11
574 parseAssembly(
575 "define i16 @test(i16 %a, i16 %b) {\n"
576 " %aa = shl i16 %a, 4\n"
577 " %bb = lshr i16 %b, 2\n"
578 " %aaa = or i16 %aa, 3840\n"
579 " %bbb = or i16 %bb, 3840\n"
580 " %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 6)\n"
581 " ret i16 %A\n"
582 "}\n"
583 "declare i16 @llvm.fshl.i16(i16, i16, i16)\n");
584 expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u);
585 }
586
587 TEST_F(ComputeKnownBitsTest, ComputeKnownFshr) {
588 // fshr(....1111....0000, 00..1111........, 26)
589 // = 11....000000..11
590 parseAssembly(
591 "define i16 @test(i16 %a, i16 %b) {\n"
592 " %aa = shl i16 %a, 4\n"
593 " %bb = lshr i16 %b, 2\n"
594 " %aaa = or i16 %aa, 3840\n"
595 " %bbb = or i16 %bb, 3840\n"
596 " %A = call i16 @llvm.fshr.i16(i16 %aaa, i16 %bbb, i16 26)\n"
597 " ret i16 %A\n"
598 "}\n"
599 "declare i16 @llvm.fshr.i16(i16, i16, i16)\n");
600 expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u);
601 }
602
603 TEST_F(ComputeKnownBitsTest, ComputeKnownFshlZero) {
604 // fshl(....1111....0000, 00..1111........, 0)
605 // = ....1111....0000
606 parseAssembly(
607 "define i16 @test(i16 %a, i16 %b) {\n"
608 " %aa = shl i16 %a, 4\n"
609 " %bb = lshr i16 %b, 2\n"
610 " %aaa = or i16 %aa, 3840\n"
611 " %bbb = or i16 %bb, 3840\n"
612 " %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 0)\n"
613 " ret i16 %A\n"
614 "}\n"
615 "declare i16 @llvm.fshl.i16(i16, i16, i16)\n");
616 expectKnownBits(/*zero*/ 15u, /*one*/ 3840u);
617 }