summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Analysis/ValueTrackingTest.cpp
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2016-12-31 22:12:34 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2016-12-31 22:12:34 +0000
commit3bb2dbd66586d03e9586294f0964ec05f3322cd6 (patch)
treee859f82b426760a7fc2d34326e3e23baa04b3ac7 /llvm/unittests/Analysis/ValueTrackingTest.cpp
parent0945530d4dc3c36a03cbd5c62fdccb870bcb21ab (diff)
downloadbcm5719-llvm-3bb2dbd66586d03e9586294f0964ec05f3322cd6.tar.gz
bcm5719-llvm-3bb2dbd66586d03e9586294f0964ec05f3322cd6.zip
Fix an issue with isGuaranteedToTransferExecutionToSuccessor
I'm not sure if this was intentional, but today isGuaranteedToTransferExecutionToSuccessor returns true for readonly and argmemonly calls that may throw. This commit changes the function to not implicitly infer nounwind this way. Even if we eventually specify readonly calls as not throwing, isGuaranteedToTransferExecutionToSuccessor is not the best place to infer that. We should instead teach FunctionAttrs or some other such pass to tag readonly functions / calls as nounwind instead. llvm-svn: 290794
Diffstat (limited to 'llvm/unittests/Analysis/ValueTrackingTest.cpp')
-rw-r--r--llvm/unittests/Analysis/ValueTrackingTest.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp
index f429c3b9914..ba0d30d59b6 100644
--- a/llvm/unittests/Analysis/ValueTrackingTest.cpp
+++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -188,3 +188,54 @@ TEST_F(MatchSelectPatternTest, DoubleCastBad) {
// The cast types here aren't the same, so we cannot match an UMIN.
expectPattern({SPF_UNKNOWN, SPNB_NA, false});
}
+
+TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) {
+ StringRef Assembly =
+ "declare void @nounwind_readonly(i32*) nounwind readonly "
+ "declare void @nounwind_argmemonly(i32*) nounwind argmemonly "
+ "declare void @throws_but_readonly(i32*) readonly "
+ "declare void @throws_but_argmemonly(i32*) argmemonly "
+ " "
+ "declare void @unknown(i32*) "
+ " "
+ "define void @f(i32* %p) { "
+ " call void @nounwind_readonly(i32* %p) "
+ " call void @nounwind_argmemonly(i32* %p) "
+ " call void @throws_but_readonly(i32* %p) "
+ " call void @throws_but_argmemonly(i32* %p) "
+ " call void @unknown(i32* %p) nounwind readonly "
+ " call void @unknown(i32* %p) nounwind argmemonly "
+ " call void @unknown(i32* %p) readonly "
+ " call void @unknown(i32* %p) argmemonly "
+ " ret void "
+ "} ";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+ auto M = parseAssemblyString(Assembly, Error, Context);
+ assert(M && "Bad assembly?");
+
+ auto *F = M->getFunction("f");
+ assert(F && "Bad assembly?");
+
+ auto &BB = F->getEntryBlock();
+ ArrayRef<bool> ExpectedAnswers = {
+ true, // call void @nounwind_readonly(i32* %p)
+ true, // call void @nounwind_argmemonly(i32* %p)
+ false, // call void @throws_but_readonly(i32* %p)
+ false, // call void @throws_but_argmemonly(i32* %p)
+ true, // call void @unknown(i32* %p) nounwind readonly
+ true, // call void @unknown(i32* %p) nounwind argmemonly
+ false, // call void @unknown(i32* %p) readonly
+ false, // call void @unknown(i32* %p) argmemonly
+ false, // ret void
+ };
+
+ int Index = 0;
+ for (auto &I : BB) {
+ EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I),
+ ExpectedAnswers[Index])
+ << "Incorrect answer at instruction " << Index << " = " << I;
+ Index++;
+ }
+}
OpenPOWER on IntegriCloud