diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 6 | ||||
-rw-r--r-- | llvm/unittests/Analysis/ValueTrackingTest.cpp | 14 |
2 files changed, 20 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 52ae9f0..6d0e79e 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1476,6 +1476,12 @@ static void computeKnownBitsFromOperator(const Operator *I, if (RV->getType() == I->getType()) { computeKnownBits(RV, Known2, Depth + 1, Q); Known = Known.unionWith(Known2); + // If the function doesn't return properly for all input values + // (e.g. unreachable exits) then there might be conflicts between the + // argument value and the range metadata. Simply discard the known bits + // in case of conflicts. + if (Known.hasConflict()) + Known.resetAll(); } } if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index 9e0abe7..6c6897d 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -2359,6 +2359,20 @@ TEST_F(ComputeKnownBitsTest, ComputeKnownBitsFreeze) { EXPECT_EQ(Known.One.getZExtValue(), 0u); } +TEST_F(ComputeKnownBitsTest, ComputeKnownBitsReturnedRangeConflict) { + parseAssembly( + "declare i16 @foo(i16 returned)\n" + "\n" + "define i16 @test() {\n" + " %A = call i16 @foo(i16 4095), !range !{i16 32, i16 33}\n" + " ret i16 %A\n" + "}\n"); + // The call returns 32 according to range metadata, but 4095 according to the + // returned arg operand. Given the conflicting information we expect that the + // known bits information simply is cleared. + expectKnownBits(/*zero*/ 0u, /*one*/ 0u); +} + TEST_F(ComputeKnownBitsTest, ComputeKnownBitsAddWithRange) { parseAssembly("define void @test(ptr %p) {\n" " %A = load i64, ptr %p, !range !{i64 64, i64 65536}\n" |