forked from OSchip/llvm-project
[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:
parent
5842df93dd
commit
219e5367d0
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue