[ValueTracking] Make unit tests easier to write; NFC

Generalize the existing MatchSelectPatternTest class to also work
with other types of tests. This reduces the amount of boilerplate
necessary to write ValueTracking tests in general, and computeKnownBits
tests in particular.

The inherited convention is that the function must be @test and the
tested instruction %A.

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

llvm-svn: 348043
This commit is contained in:
Nikita Popov 2018-11-30 22:22:30 +00:00
parent 5842df93dd
commit 219e5367d0
1 changed files with 63 additions and 106 deletions

View File

@ -22,7 +22,7 @@ using namespace llvm;
namespace { namespace {
class MatchSelectPatternTest : public testing::Test { class ValueTrackingTest : public testing::Test {
protected: protected:
void parseAssembly(const char *Assembly) { void parseAssembly(const char *Assembly) {
SMDiagnostic Error; SMDiagnostic Error;
@ -51,6 +51,13 @@ protected:
report_fatal_error("@test must have an instruction %A"); report_fatal_error("@test must have an instruction %A");
} }
LLVMContext Context;
std::unique_ptr<Module> M;
Instruction *A;
};
class MatchSelectPatternTest : public ValueTrackingTest {
protected:
void expectPattern(const SelectPatternResult &P) { void expectPattern(const SelectPatternResult &P) {
Value *LHS, *RHS; Value *LHS, *RHS;
Instruction::CastOps CastOp; Instruction::CastOps CastOp;
@ -59,10 +66,16 @@ protected:
EXPECT_EQ(P.NaNBehavior, R.NaNBehavior); EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
EXPECT_EQ(P.Ordered, R.Ordered); EXPECT_EQ(P.Ordered, R.Ordered);
} }
};
LLVMContext Context; class ComputeKnownBitsTest : public ValueTrackingTest {
std::unique_ptr<Module> M; protected:
Instruction *A, *B; void expectKnownBits(uint64_t Zero, uint64_t One) {
auto Known = computeKnownBits(A, M->getDataLayout());
ASSERT_FALSE(Known.hasConflict());
EXPECT_EQ(Known.One.getZExtValue(), One);
EXPECT_EQ(Known.Zero.getZExtValue(), Zero);
}
}; };
} }
@ -497,117 +510,61 @@ TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) {
} }
} }
TEST(ValueTracking, ComputeNumSignBits_PR32045) { TEST_F(ValueTrackingTest, ComputeNumSignBits_PR32045) {
StringRef Assembly = "define i32 @f(i32 %a) { " parseAssembly(
" %val = ashr i32 %a, -1 " "define i32 @test(i32 %a) {\n"
" ret i32 %val " " %A = ashr i32 %a, -1\n"
"} "; " ret i32 %A\n"
"}\n");
LLVMContext Context; EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
SMDiagnostic Error;
auto M = parseAssemblyString(Assembly, Error, Context);
assert(M && "Bad assembly?");
auto *F = M->getFunction("f");
assert(F && "Bad assembly?");
auto *RVal =
cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u);
} }
// No guarantees for canonical IR in this analysis, so this just bails out. // No guarantees for canonical IR in this analysis, so this just bails out.
TEST(ValueTracking, ComputeNumSignBits_Shuffle) { TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle) {
StringRef Assembly = "define <2 x i32> @f() { " parseAssembly(
" %val = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> <i32 0, i32 0> " "define <2 x i32> @test() {\n"
" ret <2 x i32> %val " " %A = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> <i32 0, i32 0>\n"
"} "; " ret <2 x i32> %A\n"
"}\n");
LLVMContext Context; EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
SMDiagnostic Error;
auto M = parseAssemblyString(Assembly, Error, Context);
assert(M && "Bad assembly?");
auto *F = M->getFunction("f");
assert(F && "Bad assembly?");
auto *RVal =
cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u);
} }
// No guarantees for canonical IR in this analysis, so a shuffle element that // No guarantees for canonical IR in this analysis, so a shuffle element that
// references an undef value means this can't return any extra information. // references an undef value means this can't return any extra information.
TEST(ValueTracking, ComputeNumSignBits_Shuffle2) { TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle2) {
StringRef Assembly = "define <2 x i32> @f(<2 x i1> %x) { " parseAssembly(
" %sext = sext <2 x i1> %x to <2 x i32> " "define <2 x i32> @test(<2 x i1> %x) {\n"
" %val = shufflevector <2 x i32> %sext, <2 x i32> undef, <2 x i32> <i32 0, i32 2> " " %sext = sext <2 x i1> %x to <2 x i32>\n"
" ret <2 x i32> %val " " %A = shufflevector <2 x i32> %sext, <2 x i32> undef, <2 x i32> <i32 0, i32 2>\n"
"} "; " ret <2 x i32> %A\n"
"}\n");
LLVMContext Context; EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
SMDiagnostic Error;
auto M = parseAssemblyString(Assembly, Error, Context);
assert(M && "Bad assembly?");
auto *F = M->getFunction("f");
assert(F && "Bad assembly?");
auto *RVal =
cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u);
} }
TEST(ValueTracking, ComputeKnownBits) { TEST_F(ComputeKnownBitsTest, ComputeKnownBits) {
StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " parseAssembly(
" %ash = mul i32 %a, 8 " "define i32 @test(i32 %a, i32 %b) {\n"
" %aad = add i32 %ash, 7 " " %ash = mul i32 %a, 8\n"
" %aan = and i32 %aad, 4095 " " %aad = add i32 %ash, 7\n"
" %bsh = shl i32 %b, 4 " " %aan = and i32 %aad, 4095\n"
" %bad = or i32 %bsh, 6 " " %bsh = shl i32 %b, 4\n"
" %ban = and i32 %bad, 4095 " " %bad = or i32 %bsh, 6\n"
" %mul = mul i32 %aan, %ban " " %ban = and i32 %bad, 4095\n"
" ret i32 %mul " " %A = mul i32 %aan, %ban\n"
"} "; " ret i32 %A\n"
"}\n");
LLVMContext Context; expectKnownBits(/*zero*/ 4278190085u, /*one*/ 10u);
SMDiagnostic Error;
auto M = parseAssemblyString(Assembly, Error, Context);
assert(M && "Bad assembly?");
auto *F = M->getFunction("f");
assert(F && "Bad assembly?");
auto *RVal =
cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
auto Known = computeKnownBits(RVal, M->getDataLayout());
ASSERT_FALSE(Known.hasConflict());
EXPECT_EQ(Known.One.getZExtValue(), 10u);
EXPECT_EQ(Known.Zero.getZExtValue(), 4278190085u);
} }
TEST(ValueTracking, ComputeKnownMulBits) { TEST_F(ComputeKnownBitsTest, ComputeKnownMulBits) {
StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " parseAssembly(
" %aa = shl i32 %a, 5 " "define i32 @test(i32 %a, i32 %b) {\n"
" %bb = shl i32 %b, 5 " " %aa = shl i32 %a, 5\n"
" %aaa = or i32 %aa, 24 " " %bb = shl i32 %b, 5\n"
" %bbb = or i32 %bb, 28 " " %aaa = or i32 %aa, 24\n"
" %mul = mul i32 %aaa, %bbb " " %bbb = or i32 %bb, 28\n"
" ret i32 %mul " " %A = mul i32 %aaa, %bbb\n"
"} "; " ret i32 %A\n"
"}\n");
LLVMContext Context; expectKnownBits(/*zero*/ 95u, /*one*/ 32u);
SMDiagnostic Error;
auto M = parseAssemblyString(Assembly, Error, Context);
assert(M && "Bad assembly?");
auto *F = M->getFunction("f");
assert(F && "Bad assembly?");
auto *RVal =
cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
auto Known = computeKnownBits(RVal, M->getDataLayout());
ASSERT_FALSE(Known.hasConflict());
EXPECT_EQ(Known.One.getZExtValue(), 32u);
EXPECT_EQ(Known.Zero.getZExtValue(), 95u);
} }