Skip to content

Commit b394bab

Browse files
[HotColdSplit] Don't outline musttail calls. (llvm#133177)
musttail calls have several restrictions, generally enforcing matching calling conventions between the caller parent and musttail callee. We can't usually honor them, because the extracted function has a different signature altogether, taking inputs/outputs and returning a control-flow identifier rather than the actual return value. Don't consider musttail calls as valid for extraction.
1 parent 934f255 commit b394bab

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ static bool isBlockValidForExtraction(const BasicBlock &BB,
170170
}
171171

172172
if (const CallInst *CI = dyn_cast<CallInst>(I)) {
173+
// musttail calls have several restrictions, generally enforcing matching
174+
// calling conventions between the caller parent and musttail callee.
175+
// We can't usually honor them, because the extracted function has a
176+
// different signature altogether, taking inputs/outputs and returning
177+
// a control-flow identifier rather than the actual return value.
178+
if (CI->isMustTailCall())
179+
return false;
180+
173181
if (const Function *F = CI->getCalledFunction()) {
174182
auto IID = F->getIntrinsicID();
175183
if (IID == Intrinsic::vastart) {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -passes=hotcoldsplit -hotcoldsplit-threshold=0 -S < %s | FileCheck %s
3+
4+
; musttail calls can't be outlined, because they have several restrictions
5+
; enforcing matching calling conventions between the parent and callee.
6+
7+
define void @test_musttail(i1 %b) {
8+
; CHECK-LABEL: define void @test_musttail(
9+
; CHECK-SAME: i1 [[B:%.*]]) {
10+
; CHECK-NEXT: [[ENTRY:.*:]]
11+
; CHECK-NEXT: br i1 [[B]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
12+
; CHECK: [[IF_THEN]]:
13+
; CHECK-NEXT: ret void
14+
; CHECK: [[IF_ELSE]]:
15+
; CHECK-NEXT: musttail call void @target(i1 [[B]])
16+
; CHECK-NEXT: ret void
17+
;
18+
entry:
19+
br i1 %b, label %if.then, label %if.else
20+
21+
if.then:
22+
ret void
23+
24+
if.else:
25+
musttail call void @target(i1 %b)
26+
ret void
27+
}
28+
29+
define void @test_tail(i1 %b) {
30+
; CHECK-LABEL: define void @test_tail(
31+
; CHECK-SAME: i1 [[B:%.*]]) {
32+
; CHECK-NEXT: [[ENTRY:.*:]]
33+
; CHECK-NEXT: br i1 [[B]], label %[[IF_THEN:.*]], label %[[CODEREPL:.*]]
34+
; CHECK: [[IF_THEN]]:
35+
; CHECK-NEXT: ret void
36+
; CHECK: [[CODEREPL]]:
37+
; CHECK-NEXT: call void @test_tail.cold.1(i1 [[B]]) #[[ATTR2:[0-9]+]]
38+
; CHECK-NEXT: br label %[[IF_ELSE_RET:.*]]
39+
; CHECK: [[IF_ELSE_RET]]:
40+
; CHECK-NEXT: ret void
41+
;
42+
entry:
43+
br i1 %b, label %if.then, label %if.else
44+
45+
if.then:
46+
ret void
47+
48+
if.else:
49+
tail call void @target(i1 %b)
50+
ret void
51+
}
52+
53+
declare void @target() cold

0 commit comments

Comments
 (0)