Commit 411ef185 authored by Bill Wendling's avatar Bill Wendling
Browse files

Merging r197216:

------------------------------------------------------------------------
r197216 | chandlerc | 2013-12-13 00:00:01 -0800 (Fri, 13 Dec 2013) | 9 lines

[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. =[
------------------------------------------------------------------------

llvm-svn: 197352
parent 4e547a68
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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.
+57 −14
Original line number Diff line number Diff line
@@ -4,38 +4,81 @@
; if they are themselve 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 @outer2() {
entry:
; 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 @i() {
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 @i(
; CHECK: call i32 @b()
; CHECK-NOT: call i32 @h()
  %call = call i32 @h() returns_twice
; CHECK-LABEL: define i32 @outer4(
; CHECK: invoke i32 @a()
  %call = call i32 @inner4() returns_twice
  %add = add nsw i32 1, %call
  ret i32 %add
}