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
This commit is contained in:
Sanjoy Das
2016-12-31 22:12:34 +00:00
parent 0945530d4d
commit 3bb2dbd665
2 changed files with 71 additions and 6 deletions

View File

@@ -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++;
}
}