[llvm] r259403 - Avoid inlining call sites in unreachable-terminated block

Jun Bum Lim via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 1 12:55:11 PST 2016


Author: junbuml
Date: Mon Feb  1 14:55:11 2016
New Revision: 259403

URL: http://llvm.org/viewvc/llvm-project?rev=259403&view=rev
Log:
Avoid inlining call sites in unreachable-terminated block

Summary:
If the normal destination of the invoke or the parent block of the call site is unreachable-terminated, there is little point in inlining the call site unless there is literally zero cost. Unlike my previous change (D15289), this change specifically handle the call sites followed by unreachable in the same basic block for call or in the normal destination for the invoke. This change could be a reasonable first step to conservatively inline call sites leading to an unreachable-terminated block while BFI / BPI is not yet available in inliner.

Reviewers: manmanren, majnemer, hfinkel, davidxl, mcrosier, dblaikie, eraman

Subscribers: dblaikie, davidxl, mcrosier, llvm-commits

Differential Revision: http://reviews.llvm.org/D16616

Added:
    llvm/trunk/test/Transforms/Inline/inline_unreachable.ll
Modified:
    llvm/trunk/lib/Analysis/InlineCost.cpp
    llvm/trunk/test/Transforms/JumpThreading/pr26096.ll

Modified: llvm/trunk/lib/Analysis/InlineCost.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InlineCost.cpp?rev=259403&r1=259402&r2=259403&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InlineCost.cpp (original)
+++ llvm/trunk/lib/Analysis/InlineCost.cpp Mon Feb  1 14:55:11 2016
@@ -1214,15 +1214,26 @@ bool CallAnalyzer::analyzeCall(CallSite
   if (OnlyOneCallAndLocalLinkage)
     Cost += InlineConstants::LastCallToStaticBonus;
 
-  // If the instruction after the call, or if the normal destination of the
-  // invoke is an unreachable instruction, the function is noreturn. As such,
-  // there is little point in inlining this unless there is literally zero
-  // cost.
+  // If the normal destination of the invoke or the parent block of the call
+  // site is unreachable-terminated, there is little point in inlining this
+  // unless there is literally zero cost.
+  // FIXME: Note that it is possible that an unreachable-terminated block has a
+  // hot entry. For example, in below scenario inlining hot_call_X() may be
+  // beneficial :
+  // main() {
+  //   hot_call_1();
+  //   ...
+  //   hot_call_N()
+  //   exit(0);
+  // }
+  // For now, we are not handling this corner case here as it is rare in real
+  // code. In future, we should elaborate this based on BPI and BFI in more
+  // general threshold adjusting heuristics in updateThreshold().
   Instruction *Instr = CS.getInstruction();
   if (InvokeInst *II = dyn_cast<InvokeInst>(Instr)) {
-    if (isa<UnreachableInst>(II->getNormalDest()->begin()))
+    if (isa<UnreachableInst>(II->getNormalDest()->getTerminator()))
       Threshold = 0;
-  } else if (isa<UnreachableInst>(++BasicBlock::iterator(Instr)))
+  } else if (isa<UnreachableInst>(Instr->getParent()->getTerminator()))
     Threshold = 0;
 
   // If this function uses the coldcc calling convention, prefer not to inline

Added: llvm/trunk/test/Transforms/Inline/inline_unreachable.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline_unreachable.ll?rev=259403&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline_unreachable.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline_unreachable.ll Mon Feb  1 14:55:11 2016
@@ -0,0 +1,130 @@
+; RUN: opt < %s -inline -S | FileCheck %s
+
+ at a = global i32 4
+ at _ZTIi = external global i8*
+
+; CHECK-LABEL: callSimpleFunction
+; CHECK: call i32 @simpleFunction
+define i32 @callSimpleFunction(i32 %idx, i32 %limit) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %s = call i32 @simpleFunction(i32 %idx)
+  store i32 %s, i32* @a
+  unreachable
+
+if.end:
+  ret i32 %idx
+}
+
+; CHECK-LABEL: callSmallFunction
+; CHECK-NOT: call i32 @smallFunction
+define i32 @callSmallFunction(i32 %idx, i32 %limit) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:
+  %s = call i32 @smallFunction(i32 %idx)
+  store i32 %s, i32* @a
+  unreachable
+
+if.end:
+  ret i32 %idx
+}
+
+; CHECK-LABEL: throwSimpleException
+; CHECK: invoke i32 @simpleFunction
+define i32 @throwSimpleException(i32 %idx, i32 %limit) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %exception = call i8* @__cxa_allocate_exception(i64 1) #0
+  invoke i32 @simpleFunction(i32 %idx)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %if.then
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi  to i8*), i8* null) #1
+  unreachable
+
+lpad:                                             ; preds = %if.then
+  %ll = landingpad { i8*, i32 }
+          cleanup
+  ret i32 %idx
+
+if.end:                                           ; preds = %entry
+  ret i32 %idx
+}
+
+; CHECK-LABEL: throwSmallException
+; CHECK-NOT: invoke i32 @smallFunction
+define i32 @throwSmallException(i32 %idx, i32 %limit) #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+entry:
+  %cmp = icmp sge i32 %idx, %limit
+  br i1 %cmp, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  %exception = call i8* @__cxa_allocate_exception(i64 1) #0
+  invoke i32 @smallFunction(i32 %idx)
+          to label %invoke.cont unwind label %lpad
+
+invoke.cont:                                      ; preds = %if.then
+  call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi  to i8*), i8* null) #1
+  unreachable
+
+lpad:                                             ; preds = %if.then
+  %ll = landingpad { i8*, i32 }
+          cleanup
+  ret i32 %idx
+
+if.end:                                           ; preds = %entry
+  ret i32 %idx
+}
+
+define i32 @simpleFunction(i32 %a) #0 {
+entry:
+  %a1 = load volatile i32, i32* @a
+  %x1 = add i32 %a1,  %a1
+  %a2 = load volatile i32, i32* @a
+  %x2 = add i32 %x1, %a2
+  %a3 = load volatile i32, i32* @a
+  %x3 = add i32 %x2, %a3
+  %a4 = load volatile i32, i32* @a
+  %x4 = add i32 %x3, %a4
+  %a5 = load volatile i32, i32* @a
+  %x5 = add i32 %x4, %a5
+  %a6 = load volatile i32, i32* @a
+  %x6 = add i32 %x5, %a6
+  %a7 = load volatile i32, i32* @a
+  %x7 = add i32 %x6, %a6
+  %a8 = load volatile i32, i32* @a
+  %x8 = add i32 %x7, %a8
+  %a9 = load volatile i32, i32* @a
+  %x9 = add i32 %x8, %a9
+  %a10 = load volatile i32, i32* @a
+  %x10 = add i32 %x9, %a10
+  %a11 = load volatile i32, i32* @a
+  %x11 = add i32 %x10, %a11
+  %a12 = load volatile i32, i32* @a
+  %x12 = add i32 %x11, %a12
+  %add = add i32 %x12, %a
+  ret i32 %add
+}
+
+define i32 @smallFunction(i32 %a) {
+entry:
+  %r = load volatile i32, i32* @a
+  ret i32 %r
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { noreturn }
+
+declare i8* @__cxa_allocate_exception(i64)
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_throw(i8*, i8*, i8*)
+

Modified: llvm/trunk/test/Transforms/JumpThreading/pr26096.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr26096.ll?rev=259403&r1=259402&r2=259403&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr26096.ll (original)
+++ llvm/trunk/test/Transforms/JumpThreading/pr26096.ll Mon Feb  1 14:55:11 2016
@@ -10,19 +10,24 @@ entry:
   br i1 %B, label %if.end, label %if.then
 
 if.then:                                          ; preds = %entry
-  call void @fn2()
+  call void @fn2(i1 %B)
   ret void
 
 if.end:                                           ; preds = %entry
-  call void @fn2()
+  call void @fn2(i1 %B)
   ret void
 }
 
-define internal void @fn2() unnamed_addr {
+define internal void @fn2(i1 %B) unnamed_addr {
 entry:
   call void @fn1()
   call void @fn1()
   call void @fn1()
+  br i1 %B, label %if.end, label %if.then
+if.then:
+  unreachable
+
+if.end:
   unreachable
 }
 




More information about the llvm-commits mailing list