[inliner] Fix PR18206 by preventing inlining functions that call setjmp

through an invoke instruction.

The original patch for this was written by Mark Seaborn, but I've
reworked his test case into the existing returns_twice test case and
implemented the fix by the prior refactoring to actually run the cost
analysis over invoke instructions, and then here fixing our detection of
the returns_twice attribute to work for both calls and invokes. We never
noticed because we never saw an invoke. =[

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@197216 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chandler Carruth 2013-12-13 08:00:01 +00:00
parent 0bdc7cd5de
commit a7e2ef7e6e
2 changed files with 58 additions and 15 deletions

View File

@ -713,7 +713,7 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallSite CS) {
}
bool CallAnalyzer::visitCallSite(CallSite CS) {
if (CS.isCall() && cast<CallInst>(CS.getInstruction())->canReturnTwice() &&
if (CS.hasFnAttr(Attribute::ReturnsTwice) &&
!F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
Attribute::ReturnsTwice)) {
// This aborts the entire analysis.

View File

@ -4,38 +4,81 @@
; if they are themselves marked as such.
declare i32 @a() returns_twice
declare i32 @b() returns_twice
define i32 @f() {
define i32 @inner1() {
entry:
%call = call i32 @a() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @g() {
define i32 @outer1() {
entry:
; CHECK-LABEL: define i32 @g(
; CHECK: call i32 @f()
; CHECK-NOT: call i32 @a()
%call = call i32 @f()
; CHECK-LABEL: define i32 @outer1(
; CHECK: call i32 @inner1()
%call = call i32 @inner1()
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @h() returns_twice {
define i32 @inner2() returns_twice {
entry:
%call = call i32 @b() returns_twice
%call = call i32 @a() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @i() {
define i32 @outer2() {
entry:
; CHECK-LABEL: define i32 @i(
; CHECK: call i32 @b()
; CHECK-NOT: call i32 @h()
%call = call i32 @h() returns_twice
; CHECK-LABEL: define i32 @outer2(
; CHECK: call i32 @a()
%call = call i32 @inner2() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @inner3() {
entry:
%invoke = invoke i32 @a() returns_twice
to label %cont unwind label %lpad
cont:
%add = add nsw i32 1, %invoke
ret i32 %add
lpad:
%lp = landingpad i32 personality i8* null cleanup
resume i32 %lp
}
define i32 @outer3() {
entry:
; CHECK-LABEL: define i32 @outer3(
; CHECK: call i32 @inner3()
%call = call i32 @inner3()
%add = add nsw i32 1, %call
ret i32 %add
}
define i32 @inner4() returns_twice {
entry:
%invoke = invoke i32 @a() returns_twice
to label %cont unwind label %lpad
cont:
%add = add nsw i32 1, %invoke
ret i32 %add
lpad:
%lp = landingpad i32 personality i8* null cleanup
resume i32 %lp
}
define i32 @outer4() {
entry:
; CHECK-LABEL: define i32 @outer4(
; CHECK: invoke i32 @a()
%call = call i32 @inner4() returns_twice
%add = add nsw i32 1, %call
ret i32 %add
}