diff options
| author | 2019-06-23 21:36:31 +0000 | |
|---|---|---|
| committer | 2019-06-23 21:36:31 +0000 | |
| commit | 23f101f37937a1bd4a29726cab2f76e0fb038b35 (patch) | |
| tree | f7da7d6b32c2e07114da399150bfa88d72187012 /gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp | |
| parent | sort previous; ok deraadt (diff) | |
| download | wireguard-openbsd-23f101f37937a1bd4a29726cab2f76e0fb038b35.tar.xz wireguard-openbsd-23f101f37937a1bd4a29726cab2f76e0fb038b35.zip | |
Import LLVM 8.0.0 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp')
| -rw-r--r-- | gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp | 435 |
1 files changed, 369 insertions, 66 deletions
diff --git a/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp b/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp index cfdf264da31..5b36d63b390 100644 --- a/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -22,7 +22,7 @@ using namespace llvm; namespace { -class MatchSelectPatternTest : public testing::Test { +class ValueTrackingTest : public testing::Test { protected: void parseAssembly(const char *Assembly) { SMDiagnostic Error; @@ -51,6 +51,13 @@ protected: 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) { Value *LHS, *RHS; Instruction::CastOps CastOp; @@ -59,10 +66,16 @@ protected: EXPECT_EQ(P.NaNBehavior, R.NaNBehavior); EXPECT_EQ(P.Ordered, R.Ordered); } +}; - LLVMContext Context; - std::unique_ptr<Module> M; - Instruction *A, *B; +class ComputeKnownBitsTest : public ValueTrackingTest { +protected: + 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); + } }; } @@ -149,6 +162,262 @@ TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) { expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); } +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero1) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float -0.0, %a\n" + " %A = select i1 %1, float 0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float %a, -0.0\n" + " %A = select i1 %1, float 0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float 0.0, %a\n" + " %A = select i1 %1, float -0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float %a, 0.0\n" + " %A = select i1 %1, float -0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float -0.0, %a\n" + " %A = select i1 %1, float %a, float 0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float %a, -0.0\n" + " %A = select i1 %1, float %a, float 0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float 0.0, %a\n" + " %A = select i1 %1, float %a, float -0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float %a, 0.0\n" + " %A = select i1 %1, float %a, float -0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float -0.0, %a\n" + " %A = select i1 %1, float 0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float %a, -0.0\n" + " %A = select i1 %1, float 0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float 0.0, %a\n" + " %A = select i1 %1, float -0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float %a, 0.0\n" + " %A = select i1 %1, float -0.0, float %a\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float -0.0, %a\n" + " %A = select i1 %1, float %a, float 0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float %a, -0.0\n" + " %A = select i1 %1, float %a, float 0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp olt float 0.0, %a\n" + " %A = select i1 %1, float %a, float -0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) { + parseAssembly( + "define float @test(float %a) {\n" + " %1 = fcmp ogt float %a, 0.0\n" + " %A = select i1 %1, float %a, float -0.0\n" + " ret float %A\n" + "}\n"); + // The sign of zero doesn't matter in fcmp. + expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); +} + +TEST_F(MatchSelectPatternTest, FMinMismatchConstantZeroVecUndef) { + parseAssembly( + "define <2 x float> @test(<2 x float> %a) {\n" + " %1 = fcmp ogt <2 x float> %a, <float -0.0, float -0.0>\n" + " %A = select <2 x i1> %1, <2 x float> <float undef, float 0.0>, <2 x float> %a\n" + " ret <2 x float> %A\n" + "}\n"); + // An undef in a vector constant can not be back-propagated for this analysis. + expectPattern({SPF_UNKNOWN, SPNB_NA, false}); +} + +TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZeroVecUndef) { + parseAssembly( + "define <2 x float> @test(<2 x float> %a) {\n" + " %1 = fcmp ogt <2 x float> %a, zeroinitializer\n" + " %A = select <2 x i1> %1, <2 x float> %a, <2 x float> <float -0.0, float undef>\n" + " ret <2 x float> %A\n" + "}\n"); + // An undef in a vector constant can not be back-propagated for this analysis. + expectPattern({SPF_UNKNOWN, SPNB_NA, false}); +} + +TEST_F(MatchSelectPatternTest, VectorFMinimum) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ule <4 x float> %a, \n" + " <float 5.0, float 5.0, float 5.0, float 5.0>\n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" + " ret <4 x float> %A\n" + "}\n"); + // Check that pattern matching works on vectors where each lane has the same + // unordered pattern. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); +} + +TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ole <4 x float> %a, \n" + " <float 5.0, float 5.0, float 5.0, float 5.0>\n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" + " ret <4 x float> %A\n" + "}\n"); + // Check that pattern matching works on vectors where each lane has the same + // ordered pattern. + expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); +} + +TEST_F(MatchSelectPatternTest, VectorNotFMinimum) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ule <4 x float> %a, \n" + " <float 5.0, float 0x7ff8000000000000, float 5.0, float 5.0>\n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> <float 5.0, float 0x7ff8000000000000, float 5.0, float " + "5.0>\n" + " ret <4 x float> %A\n" + "}\n"); + // The lane that contains a NaN (0x7ff80...) behaves like a + // non-NaN-propagating min and the other lines behave like a NaN-propagating + // min, so check that neither is returned. + expectPattern({SPF_UNKNOWN, SPNB_NA, false}); +} + +TEST_F(MatchSelectPatternTest, VectorNotFMinZero) { + parseAssembly( + "define <4 x float> @test(<4 x float> %a) {\n" + " %1 = fcmp ule <4 x float> %a, \n" + " <float 5.0, float -0.0, float 5.0, float 5.0>\n" + " %A = select <4 x i1> %1, <4 x float> %a,\n" + " <4 x float> <float 5.0, float 0.0, float 5.0, float 5.0>\n" + " ret <4 x float> %A\n" + "}\n"); + // Always selects the second lane of %a if it is positive or negative zero, so + // this is stricter than a min. + expectPattern({SPF_UNKNOWN, SPNB_NA, false}); +} + TEST_F(MatchSelectPatternTest, DoubleCastU) { parseAssembly( "define i32 @test(i8 %a, i8 %b) {\n" @@ -241,75 +510,109 @@ TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) { } } -TEST(ValueTracking, ComputeNumSignBits_PR32045) { - StringRef Assembly = "define i32 @f(i32 %a) { " - " %val = ashr i32 %a, -1 " - " ret i32 %val " - "} "; - - LLVMContext Context; - 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_F(ValueTrackingTest, ComputeNumSignBits_PR32045) { + parseAssembly( + "define i32 @test(i32 %a) {\n" + " %A = ashr i32 %a, -1\n" + " ret i32 %A\n" + "}\n"); + EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u); } -TEST(ValueTracking, ComputeKnownBits) { - StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " - " %ash = mul i32 %a, 8 " - " %aad = add i32 %ash, 7 " - " %aan = and i32 %aad, 4095 " - " %bsh = shl i32 %b, 4 " - " %bad = or i32 %bsh, 6 " - " %ban = and i32 %bad, 4095 " - " %mul = mul i32 %aan, %ban " - " ret i32 %mul " - "} "; - - LLVMContext Context; - SMDiagnostic Error; - auto M = parseAssemblyString(Assembly, Error, Context); - assert(M && "Bad assembly?"); +// No guarantees for canonical IR in this analysis, so this just bails out. +TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle) { + parseAssembly( + "define <2 x i32> @test() {\n" + " %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"); + EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u); +} - auto *F = M->getFunction("f"); - assert(F && "Bad assembly?"); +// 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. +TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle2) { + parseAssembly( + "define <2 x i32> @test(<2 x i1> %x) {\n" + " %sext = sext <2 x i1> %x to <2 x i32>\n" + " %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"); + EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u); +} - 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_F(ComputeKnownBitsTest, ComputeKnownBits) { + parseAssembly( + "define i32 @test(i32 %a, i32 %b) {\n" + " %ash = mul i32 %a, 8\n" + " %aad = add i32 %ash, 7\n" + " %aan = and i32 %aad, 4095\n" + " %bsh = shl i32 %b, 4\n" + " %bad = or i32 %bsh, 6\n" + " %ban = and i32 %bad, 4095\n" + " %A = mul i32 %aan, %ban\n" + " ret i32 %A\n" + "}\n"); + expectKnownBits(/*zero*/ 4278190085u, /*one*/ 10u); } -TEST(ValueTracking, ComputeKnownMulBits) { - StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " - " %aa = shl i32 %a, 5 " - " %bb = shl i32 %b, 5 " - " %aaa = or i32 %aa, 24 " - " %bbb = or i32 %bb, 28 " - " %mul = mul i32 %aaa, %bbb " - " ret i32 %mul " - "} "; +TEST_F(ComputeKnownBitsTest, ComputeKnownMulBits) { + parseAssembly( + "define i32 @test(i32 %a, i32 %b) {\n" + " %aa = shl i32 %a, 5\n" + " %bb = shl i32 %b, 5\n" + " %aaa = or i32 %aa, 24\n" + " %bbb = or i32 %bb, 28\n" + " %A = mul i32 %aaa, %bbb\n" + " ret i32 %A\n" + "}\n"); + expectKnownBits(/*zero*/ 95u, /*one*/ 32u); +} - LLVMContext Context; - SMDiagnostic Error; - auto M = parseAssemblyString(Assembly, Error, Context); - assert(M && "Bad assembly?"); +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); +} - auto *F = M->getFunction("f"); - assert(F && "Bad assembly?"); +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); +} - 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); +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); } |
