[llvm] r329235 - Don't inline @llvm.icall.branch.funnel

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 4 14:46:27 PDT 2018


Author: vitalybuka
Date: Wed Apr  4 14:46:27 2018
New Revision: 329235

URL: http://llvm.org/viewvc/llvm-project?rev=329235&view=rev
Log:
Don't inline @llvm.icall.branch.funnel

Summary: @llvm.icall.branch.funnel is musttail with variable number of
arguments. After inlining current backend can't separate call targets from call
arguments.

Reviewers: pcc

Subscribers: hiraditya, llvm-commits

Differential Revision: https://reviews.llvm.org/D45116

Added:
    llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll
Modified:
    llvm/trunk/lib/Analysis/InlineCost.cpp
    llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll

Modified: llvm/trunk/lib/Analysis/InlineCost.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InlineCost.cpp?rev=329235&r1=329234&r2=329235&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/InlineCost.cpp (original)
+++ llvm/trunk/lib/Analysis/InlineCost.cpp Wed Apr  4 14:46:27 2018
@@ -135,7 +135,7 @@ class CallAnalyzer : public InstVisitor<
   bool ContainsNoDuplicateCall;
   bool HasReturn;
   bool HasIndirectBr;
-  bool HasFrameEscape;
+  bool HasUninlineableIntrinsic;
   bool UsesVarArgs;
 
   /// Number of bytes allocated statically by the callee.
@@ -281,12 +281,13 @@ public:
         IsCallerRecursive(false), IsRecursiveCall(false),
         ExposesReturnsTwice(false), HasDynamicAlloca(false),
         ContainsNoDuplicateCall(false), HasReturn(false), HasIndirectBr(false),
-        HasFrameEscape(false), UsesVarArgs(false), AllocatedSize(0), NumInstructions(0),
-        NumVectorInstructions(0), VectorBonus(0), SingleBBBonus(0),
-        EnableLoadElimination(true), LoadEliminationCost(0), NumConstantArgs(0),
-        NumConstantOffsetPtrArgs(0), NumAllocaArgs(0), NumConstantPtrCmps(0),
-        NumConstantPtrDiffs(0), NumInstructionsSimplified(0),
-        SROACostSavings(0), SROACostSavingsLost(0) {}
+        HasUninlineableIntrinsic(false), UsesVarArgs(false), AllocatedSize(0),
+        NumInstructions(0), NumVectorInstructions(0), VectorBonus(0),
+        SingleBBBonus(0), EnableLoadElimination(true), LoadEliminationCost(0),
+        NumConstantArgs(0), NumConstantOffsetPtrArgs(0), NumAllocaArgs(0),
+        NumConstantPtrCmps(0), NumConstantPtrDiffs(0),
+        NumInstructionsSimplified(0), SROACostSavings(0),
+        SROACostSavingsLost(0) {}
 
   bool analyzeCall(CallSite CS);
 
@@ -1231,8 +1232,9 @@ bool CallAnalyzer::visitCallSite(CallSit
         disableLoadElimination();
         // SROA can usually chew through these intrinsics, but they aren't free.
         return false;
+      case Intrinsic::icall_branch_funnel:
       case Intrinsic::localescape:
-        HasFrameEscape = true;
+        HasUninlineableIntrinsic = true;
         return false;
       case Intrinsic::vastart:
       case Intrinsic::vaend:
@@ -1572,7 +1574,7 @@ bool CallAnalyzer::analyzeBlock(BasicBlo
     using namespace ore;
     // If the visit this instruction detected an uninlinable pattern, abort.
     if (IsRecursiveCall || ExposesReturnsTwice || HasDynamicAlloca ||
-        HasIndirectBr || HasFrameEscape || UsesVarArgs) {
+        HasIndirectBr || HasUninlineableIntrinsic || UsesVarArgs) {
       if (ORE)
         ORE->emit([&]() {
           return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
@@ -2044,6 +2046,9 @@ bool llvm::isInlineViable(Function &F) {
         switch (CS.getCalledFunction()->getIntrinsicID()) {
         default:
           break;
+        // Disallow inlining of @llvm.icall.branch.funnel because current
+        // backend can't separate call targets from call arguments.
+        case llvm::Intrinsic::icall_branch_funnel:
         // Disallow inlining functions that call @llvm.localescape. Doing this
         // correctly would require major changes to the inliner.
         case llvm::Intrinsic::localescape:

Added: llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll?rev=329235&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-brunch-funnel.ll Wed Apr  4 14:46:27 2018
@@ -0,0 +1,35 @@
+; Test that inliner skips @llvm.icall.branch.funnel
+; RUN: opt < %s -inline -S | FileCheck %s
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @llvm.icall.branch.funnel(...)
+
+; CHECK-LABEL: define void @fn_musttail(
+define void @fn_musttail() {
+  call void (...) @bf_musttail()
+  ; CHECK: call void (...) @bf_musttail(
+  ret void
+}
+
+; CHECK-LABEL: define internal void @bf_musttail(
+define internal void @bf_musttail(...) {
+  musttail call void (...) @llvm.icall.branch.funnel(...)
+  ; CHECK: musttail call void (...) @llvm.icall.branch.funnel(
+  ret void
+}
+
+; CHECK-LABEL: define void @fn_musttail_always(
+define void @fn_musttail_always() {
+  call void (...) @bf_musttail_always()
+  ; CHECK: call void (...) @bf_musttail_always(
+  ret void
+}
+
+; CHECK-LABEL: define internal void @bf_musttail_always(
+define internal void @bf_musttail_always(...) alwaysinline {
+  musttail call void (...) @llvm.icall.branch.funnel(...)
+  ; CHECK: musttail call void (...) @llvm.icall.branch.funnel(
+  ret void
+}

Modified: llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll?rev=329235&r1=329234&r2=329235&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll (original)
+++ llvm/trunk/test/Transforms/WholeProgramDevirt/branch-funnel.ll Wed Apr  4 14:46:27 2018
@@ -1,6 +1,10 @@
 ; RUN: opt -S -wholeprogramdevirt %s | FileCheck --check-prefixes=CHECK,RETP %s
 ; RUN: sed -e 's,+retpoline,-retpoline,g' %s | opt -S -wholeprogramdevirt | FileCheck --check-prefixes=CHECK,NORETP %s
+
 ; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck --check-prefixes=CHECK,RETP %s
+
+; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t  -O3 -S -o - %s | FileCheck --check-prefixes=CHECK %s
+
 ; RUN: FileCheck --check-prefix=SUMMARY %s < %t
 
 ; SUMMARY:      TypeIdMap:       
@@ -89,7 +93,10 @@ declare i32 @vf3_2(i8* %this, i32 %arg)
 declare i32 @vf4_1(i8* %this, i32 %arg)
 declare i32 @vf4_2(i8* %this, i32 %arg)
 
-; CHECK: define i32 @fn1
+
+
+; CHECK-LABEL: define i32 @fn1
+; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
 define i32 @fn1(i8* %obj) #0 {
   %vtableptr = bitcast i8* %obj to [1 x i8*]**
   %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
@@ -107,7 +114,8 @@ define i32 @fn1(i8* %obj) #0 {
   ret i32 %result
 }
 
-; CHECK: define i32 @fn2
+; CHECK-LABEL: define i32 @fn2
+; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
 define i32 @fn2(i8* %obj) #0 {
   %vtableptr = bitcast i8* %obj to [1 x i8*]**
   %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
@@ -122,7 +130,8 @@ define i32 @fn2(i8* %obj) #0 {
   ret i32 %result
 }
 
-; CHECK: define i32 @fn3
+; CHECK-LABEL: define i32 @fn3
+; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
 define i32 @fn3(i8* %obj) #0 {
   %vtableptr = bitcast i8* %obj to [1 x i8*]**
   %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
@@ -138,10 +147,9 @@ define i32 @fn3(i8* %obj) #0 {
   ret i32 %result
 }
 
-; CHECK: define internal void @branch_funnel(i8* nest, ...)
-
+; CHECK-LABEL: define internal void @branch_funnel(i8*
 ; CHECK: define hidden void @__typeid_typeid1_0_branch_funnel(i8* nest, ...)
-; CHECK-NEXT: call void (...) @llvm.icall.branch.funnel(i8* %0, i8* bitcast ([1 x i8*]* @vt1_1 to i8*), i32 (i8*, i32)* @vf1_1, i8* bitcast ([1 x i8*]* @vt1_2 to i8*), i32 (i8*, i32)* @vf1_2, ...)
+; CHECK-NEXT: musttail call void (...) @llvm.icall.branch.funnel(i8* %0, i8* bitcast ([1 x i8*]* {{(nonnull )?}}@vt1_1 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_1, i8* bitcast ([1 x i8*]* {{(nonnull )?}}@vt1_2 to i8*), i32 (i8*, i32)* {{(nonnull )?}}@vf1_2, ...)
 
 declare i1 @llvm.type.test(i8*, metadata)
 declare void @llvm.assume(i1)




More information about the llvm-commits mailing list