mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
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 llvm-svn: 329235
This commit is contained in:
parent
509e751feb
commit
2f368ec0bb
@ -135,7 +135,7 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
|
||||
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(CallSite CS) {
|
||||
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(BasicBlock *BB,
|
||||
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:
|
||||
|
35
test/Transforms/Inline/inline-brunch-funnel.ll
Normal file
35
test/Transforms/Inline/inline-brunch-funnel.ll
Normal file
@ -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
|
||||
}
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user