Index: llvm/lib/Analysis/InlineCost.cpp =================================================================== --- llvm/lib/Analysis/InlineCost.cpp +++ llvm/lib/Analysis/InlineCost.cpp @@ -1960,6 +1960,16 @@ if (!Callee) return llvm::InlineCost::getNever(); + // Never inline functions with musttail intrinsics. Currently the only + // possible such intrinsic is llvm.icall.branch.funnel and it does not work + // with inlining. + for (const auto &BB : *Callee) + for (const auto &I : BB) + if (const CallInst *CI = dyn_cast(&I)) + if (const Function *F = CI->getCalledFunction()) + if (CI->isMustTailCall() && F->isIntrinsic()) + return llvm::InlineCost::getNever(); + // Never inline calls with byval arguments that does not have the alloca // address space. Since byval arguments can be replaced with a copy to an // alloca, the inlined code would need to be adjusted to handle that the Index: llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll =================================================================== --- llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll +++ llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll @@ -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 @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 @@ 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 @@ 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 @@ 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)