Skip to content

Commit a6a07a5

Browse files
committed
[MachineOutliner] Don't outline functions starting with PATCHABLE_FUNCTION_ENTER/FENTRL_CALL
MachineOutliner may outline a "patchable-function-entry" function whose body has a TargetOpcode::PATCHABLE_FUNCTION_ENTER MachineInstr. This is incorrect because the special code sequence must stay unchanged to be used at run-time. Avoid outlining PATCHABLE_FUNCTION_ENTER. While here, avoid outlining FENTRY_CALL too (which doesn't reproduce currently) to allow phase ordering flexibility. Fixes #52635 Reviewed By: paquette Differential Revision: https://reviews.llvm.org/D115614
1 parent f212032 commit a6a07a5

File tree

6 files changed

+208
-4
lines changed

6 files changed

+208
-4
lines changed

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1927,9 +1927,7 @@ class TargetInstrInfo : public MCInstrInfo {
19271927
/// Optional target hook that returns true if \p MBB is safe to outline from,
19281928
/// and returns any target-specific information in \p Flags.
19291929
virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
1930-
unsigned &Flags) const {
1931-
return true;
1932-
}
1930+
unsigned &Flags) const;
19331931

19341932
/// Insert a custom frame for outlined functions.
19351933
virtual void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,

llvm/lib/CodeGen/TargetInstrInfo.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,3 +1418,16 @@ void TargetInstrInfo::mergeOutliningCandidateAttributes(
14181418
}))
14191419
F.addFnAttr(Attribute::NoUnwind);
14201420
}
1421+
1422+
bool TargetInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
1423+
unsigned &Flags) const {
1424+
// Some instrumentations create special TargetOpcode at the start which
1425+
// expands to special code sequences which must be present.
1426+
auto First = MBB.getFirstNonDebugInstr();
1427+
if (First != MBB.end() &&
1428+
(First->getOpcode() == TargetOpcode::FENTRY_CALL ||
1429+
First->getOpcode() == TargetOpcode::PATCHABLE_FUNCTION_ENTER))
1430+
return false;
1431+
1432+
return true;
1433+
}

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7055,6 +7055,8 @@ bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
70557055

70567056
bool AArch64InstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
70577057
unsigned &Flags) const {
7058+
if (!TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags))
7059+
return false;
70587060
// Check if LR is available through all of the MBB. If it's not, then set
70597061
// a flag.
70607062
assert(MBB.getParent()->getRegInfo().tracksLiveness() &&

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,7 @@ bool RISCVInstrInfo::isFunctionSafeToOutlineFrom(
12541254
bool RISCVInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
12551255
unsigned &Flags) const {
12561256
// More accurate safety checking is done in getOutliningCandidateInfo.
1257-
return true;
1257+
return TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags);
12581258
}
12591259

12601260
// Enum values indicating how an outlined call should be constructed.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
; RUN: llc < %s -verify-machineinstrs -enable-machine-outliner | FileCheck %s
2+
3+
target triple = "aarch64-unknown-linux-gnu"
4+
5+
declare void @foo(i32, i32, i32, i32) minsize
6+
7+
;; TargetOpcode::FENTRY_CALL at the start of the function expands to a __fentry__
8+
;; call which must be present. Don't outline it.
9+
define void @fentry0(i1 %a) nounwind "fentry-call"="true" {
10+
; CHECK-LABEL: fentry0:
11+
; CHECK-NEXT: // %bb.0:
12+
; CHECK-NEXT: # FEntry call
13+
; CHECK: // %bb.1:
14+
; CHECK-NEXT: bl OUTLINED_FUNCTION_1
15+
entry:
16+
br i1 %a, label %if.then, label %if.end
17+
if.then:
18+
call void @foo(i32 1, i32 2, i32 3, i32 4)
19+
br label %if.end
20+
if.end:
21+
call void @foo(i32 5, i32 6, i32 7, i32 8)
22+
ret void
23+
}
24+
25+
define void @fentry1(i1 %a) nounwind "fentry-call"="true" {
26+
; CHECK-LABEL: fentry1:
27+
; CHECK-NEXT: // %bb.0:
28+
; CHECK-NEXT: # FEntry call
29+
; CHECK: // %bb.1:
30+
; CHECK-NEXT: bl OUTLINED_FUNCTION_1
31+
entry:
32+
br i1 %a, label %if.then, label %if.end
33+
if.then:
34+
call void @foo(i32 1, i32 2, i32 3, i32 4)
35+
br label %if.end
36+
if.end:
37+
call void @foo(i32 5, i32 6, i32 7, i32 8)
38+
ret void
39+
}
40+
41+
;; TargetOpcode::PATCHABLE_FUNCTION_ENTER at the start of the function expands to
42+
;; NOPs which must be present. Don't outline them.
43+
define void @patchable0(i1 %a) nounwind "patchable-function-entry"="2" {
44+
; CHECK-LABEL: patchable0:
45+
; CHECK-NEXT: .Lfunc_begin0:
46+
; CHECK-NEXT: // %bb.0:
47+
; CHECK-NEXT: nop
48+
; CHECK-NEXT: nop
49+
; CHECK: // %bb.1:
50+
; CHECK-NEXT: bl OUTLINED_FUNCTION_1
51+
entry:
52+
br i1 %a, label %if.then, label %if.end
53+
if.then:
54+
call void @foo(i32 1, i32 2, i32 3, i32 4)
55+
br label %if.end
56+
if.end:
57+
call void @foo(i32 5, i32 6, i32 7, i32 8)
58+
ret void
59+
}
60+
61+
define void @patchable1(i1 %a) nounwind "patchable-function-entry"="2" {
62+
; CHECK-LABEL: patchable1:
63+
; CHECK-NEXT: .Lfunc_begin1:
64+
; CHECK-NEXT: // %bb.0:
65+
; CHECK-NEXT: nop
66+
; CHECK-NEXT: nop
67+
; CHECK: // %bb.1:
68+
; CHECK-NEXT: bl OUTLINED_FUNCTION_1
69+
entry:
70+
br i1 %a, label %if.then, label %if.end
71+
if.then:
72+
call void @foo(i32 1, i32 2, i32 3, i32 4)
73+
br label %if.end
74+
if.end:
75+
call void @foo(i32 5, i32 6, i32 7, i32 8)
76+
ret void
77+
}
78+
79+
;; Similar to "patchable-function-entry".
80+
define void @xray0(i1 %a) nounwind "function-instrument"="xray-always" {
81+
; CHECK-LABEL: xray0:
82+
; CHECK-NEXT: .Lfunc_begin2:
83+
; CHECK-NEXT: // %bb.0:
84+
; CHECK-NEXT: .p2align 2
85+
; CHECK-NEXT: .Lxray_sled_0:
86+
; CHECK: // %bb.1:
87+
; CHECK-NEXT: bl OUTLINED_FUNCTION_1
88+
entry:
89+
br i1 %a, label %if.then, label %if.end
90+
if.then:
91+
call void @foo(i32 1, i32 2, i32 3, i32 4)
92+
br label %if.end
93+
if.end:
94+
call void @foo(i32 5, i32 6, i32 7, i32 8)
95+
ret void
96+
}
97+
98+
define void @xray1(i1 %a) nounwind "function-instrument"="xray-always" {
99+
; CHECK-LABEL: xray1:
100+
; CHECK-NEXT: .Lfunc_begin3:
101+
; CHECK-NEXT: // %bb.0:
102+
; CHECK-NEXT: .p2align 2
103+
; CHECK-NEXT: .Lxray_sled_2:
104+
; CHECK: // %bb.1:
105+
; CHECK-NEXT: bl OUTLINED_FUNCTION_1
106+
entry:
107+
br i1 %a, label %if.then, label %if.end
108+
if.then:
109+
call void @foo(i32 1, i32 2, i32 3, i32 4)
110+
br label %if.end
111+
if.end:
112+
call void @foo(i32 5, i32 6, i32 7, i32 8)
113+
ret void
114+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
; RUN: llc < %s -verify-machineinstrs -enable-machine-outliner | FileCheck %s
2+
3+
target triple = "riscv64-unknown-linux-gnu"
4+
5+
declare void @foo(i32, i32, i32, i32) minsize
6+
7+
;; TargetOpcode::FENTRY_CALL at the start of the function expands to a __fentry__
8+
;; call which must be present. Don't outline it.
9+
define void @fentry0(i1 %a) nounwind "fentry-call"="true" {
10+
; CHECK-LABEL: fentry0:
11+
; CHECK-NEXT: # %bb.0:
12+
; CHECK-NEXT: # FEntry call
13+
; CHECK: # %bb.1:
14+
; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1
15+
entry:
16+
br i1 %a, label %if.then, label %if.end
17+
if.then:
18+
call void @foo(i32 1, i32 2, i32 3, i32 4)
19+
br label %if.end
20+
if.end:
21+
call void @foo(i32 5, i32 6, i32 7, i32 8)
22+
ret void
23+
}
24+
25+
define void @fentry1(i1 %a) nounwind "fentry-call"="true" {
26+
; CHECK-LABEL: fentry1:
27+
; CHECK-NEXT: # %bb.0:
28+
; CHECK-NEXT: # FEntry call
29+
; CHECK: # %bb.1:
30+
; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1
31+
entry:
32+
br i1 %a, label %if.then, label %if.end
33+
if.then:
34+
call void @foo(i32 1, i32 2, i32 3, i32 4)
35+
br label %if.end
36+
if.end:
37+
call void @foo(i32 5, i32 6, i32 7, i32 8)
38+
ret void
39+
}
40+
41+
;; TargetOpcode::PATCHABLE_FUNCTION_ENTER at the start of the function expands to
42+
;; NOPs which must be present. Don't outline them.
43+
define void @patchable0(i1 %a) nounwind "patchable-function-entry"="2" {
44+
; CHECK-LABEL: patchable0:
45+
; CHECK-NEXT: .Lfunc_begin0:
46+
; CHECK-NEXT: # %bb.0:
47+
; CHECK-NEXT: nop
48+
; CHECK-NEXT: nop
49+
; CHECK: # %bb.1:
50+
; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1
51+
entry:
52+
br i1 %a, label %if.then, label %if.end
53+
if.then:
54+
call void @foo(i32 1, i32 2, i32 3, i32 4)
55+
br label %if.end
56+
if.end:
57+
call void @foo(i32 5, i32 6, i32 7, i32 8)
58+
ret void
59+
}
60+
61+
define void @patchable1(i1 %a) nounwind "patchable-function-entry"="2" {
62+
; CHECK-LABEL: patchable1:
63+
; CHECK-NEXT: .Lfunc_begin1:
64+
; CHECK-NEXT: # %bb.0:
65+
; CHECK-NEXT: nop
66+
; CHECK-NEXT: nop
67+
; CHECK: # %bb.1:
68+
; CHECK-NEXT: call t0, OUTLINED_FUNCTION_1
69+
entry:
70+
br i1 %a, label %if.then, label %if.end
71+
if.then:
72+
call void @foo(i32 1, i32 2, i32 3, i32 4)
73+
br label %if.end
74+
if.end:
75+
call void @foo(i32 5, i32 6, i32 7, i32 8)
76+
ret void
77+
}

0 commit comments

Comments
 (0)