Skip to content

Commit 112ee87

Browse files
committed
[ValueTracking] Let ComputeKnownSignBits handle (shl (zext X), C)
Add simple support for looking through a zext when doing ComputeKnownSignBits for shl. This is valid for the case when all extended bits are shifted out, because then the number of sign bits can be found by analysing the zext operand. The solution here is simple as it only handle a single zext (not passing remaining left shift amount during recursion). It could be possible to generalize this in the future by for example passing an 'OffsetFromMSB' parameter to ComputeNumSignBitsImpl, telling it to calculate number of sign bits starting at some offset from the most significant bit.
1 parent c02e8f7 commit 112ee87

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3757,11 +3757,21 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
37573757
}
37583758
case Instruction::Shl: {
37593759
const APInt *ShAmt;
3760+
Value *X = nullptr;
37603761
if (match(U->getOperand(1), m_APInt(ShAmt))) {
37613762
// shl destroys sign bits.
3762-
Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q);
3763-
if (ShAmt->uge(TyBits) || // Bad shift.
3764-
ShAmt->uge(Tmp)) break; // Shifted all sign bits out.
3763+
if (ShAmt->uge(TyBits))
3764+
break; // Bad shift.
3765+
// We can look through a zext (more or less treating it as a sext) if
3766+
// all extended bits are shifted out.
3767+
if (match(U->getOperand(0), m_ZExt(m_Value(X))) &&
3768+
ShAmt->uge(TyBits - X->getType()->getScalarSizeInBits())) {
3769+
Tmp = ComputeNumSignBits(X, Depth + 1, Q);
3770+
Tmp += TyBits - X->getType()->getScalarSizeInBits();
3771+
} else
3772+
Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q);
3773+
if (ShAmt->uge(Tmp))
3774+
break; // Shifted all sign bits out.
37653775
Tmp2 = ShAmt->getZExtValue();
37663776
return Tmp - Tmp2;
37673777
}

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,36 @@ TEST_F(ValueTrackingTest, ComputeNumSignBits_PR32045) {
697697
EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 32u);
698698
}
699699

700+
TEST_F(ValueTrackingTest, ComputeNumSignBits_shl_ext1) {
701+
parseAssembly("define i32 @test(i8 %a) {\n"
702+
" %b = ashr i8 %a, 4\n"
703+
" %c = zext i8 %b to i32\n"
704+
" %A = shl i32 %c, 24\n"
705+
" ret i32 %A\n"
706+
"}\n");
707+
EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 5u);
708+
}
709+
710+
TEST_F(ValueTrackingTest, ComputeNumSignBits_shl_ext2) {
711+
parseAssembly("define i32 @test(i8 %a) {\n"
712+
" %b = ashr i8 %a, 4\n"
713+
" %c = zext i8 %b to i32\n"
714+
" %A = shl i32 %c, 26\n"
715+
" ret i32 %A\n"
716+
"}\n");
717+
EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 3u);
718+
}
719+
720+
TEST_F(ValueTrackingTest, ComputeNumSignBits_shl_ext3) {
721+
parseAssembly("define i32 @test(i8 %a) {\n"
722+
" %b = ashr i8 %a, 4\n"
723+
" %c = zext i8 %b to i32\n"
724+
" %A = shl i32 %c, 30\n"
725+
" ret i32 %A\n"
726+
"}\n");
727+
EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
728+
}
729+
700730
// No guarantees for canonical IR in this analysis, so this just bails out.
701731
TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle) {
702732
parseAssembly(

0 commit comments

Comments
 (0)