Skip to content

Commit 0d44201

Browse files
MaskRaytstellar
authored andcommitted
[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 (cherry picked from commit a6a07a5)
1 parent 69fcfde commit 0d44201

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
@@ -1922,9 +1922,7 @@ class TargetInstrInfo : public MCInstrInfo {
19221922
/// Optional target hook that returns true if \p MBB is safe to outline from,
19231923
/// and returns any target-specific information in \p Flags.
19241924
virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
1925-
unsigned &Flags) const {
1926-
return true;
1927-
}
1925+
unsigned &Flags) const;
19281926

19291927
/// Insert a custom frame for outlined functions.
19301928
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
@@ -1417,3 +1417,16 @@ std::string TargetInstrInfo::createMIROperandComment(
14171417
}
14181418

14191419
TargetInstrInfo::PipelinerLoopInfo::~PipelinerLoopInfo() {}
1420+
1421+
bool TargetInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
1422+
unsigned &Flags) const {
1423+
// Some instrumentations create special TargetOpcode at the start which
1424+
// expands to special code sequences which must be present.
1425+
auto First = MBB.getFirstNonDebugInstr();
1426+
if (First != MBB.end() &&
1427+
(First->getOpcode() == TargetOpcode::FENTRY_CALL ||
1428+
First->getOpcode() == TargetOpcode::PATCHABLE_FUNCTION_ENTER))
1429+
return false;
1430+
1431+
return true;
1432+
}

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

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

69246924
bool AArch64InstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
69256925
unsigned &Flags) const {
6926+
if (!TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags))
6927+
return false;
69266928
// Check if LR is available through all of the MBB. If it's not, then set
69276929
// a flag.
69286930
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
@@ -999,7 +999,7 @@ bool RISCVInstrInfo::isFunctionSafeToOutlineFrom(
999999
bool RISCVInstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
10001000
unsigned &Flags) const {
10011001
// More accurate safety checking is done in getOutliningCandidateInfo.
1002-
return true;
1002+
return TargetInstrInfo::isMBBSafeToOutlineFrom(MBB, Flags);
10031003
}
10041004

10051005
// 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)