aboutsummaryrefslogtreecommitdiff
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp6
-rw-r--r--llvm/unittests/Analysis/ValueTrackingTest.cpp14
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"