Skip to content

Commit ea06384

Browse files
authored
[CodeGen][AArch64] Only split safe blocks in BBSections (#81553)
Some types of machine function and machine basic block are unsafe to split on AArch64: basic blocks that contain jump table dispatch or targets (D157124), and blocks that contain inline ASM GOTO blocks or their targets (D158647) all cause issues and have been excluded from Machine Function Splitting on AArch64. These issues are caused by any transformation pass that places same-function basic blocks in different text sections (MachineFunctionSplitter and BasicBlockSections) and must be special-cased in both passes.
1 parent 2d5fb27 commit ea06384

File tree

3 files changed

+180
-3
lines changed

3 files changed

+180
-3
lines changed

llvm/lib/CodeGen/BasicBlockSections.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,14 @@ assignSections(MachineFunction &MF,
208208
if (I != FuncClusterInfo.end()) {
209209
MBB.setSectionID(I->second.ClusterID);
210210
} else {
211-
// BB goes into the special cold section if it is not specified in the
212-
// cluster info map.
213-
MBB.setSectionID(MBBSectionID::ColdSectionID);
211+
const TargetInstrInfo &TII =
212+
*MBB.getParent()->getSubtarget().getInstrInfo();
213+
214+
if (TII.isMBBSafeToSplitToCold(MBB)) {
215+
// BB goes into the special cold section if it is not specified in the
216+
// cluster info map.
217+
MBB.setSectionID(MBBSectionID::ColdSectionID);
218+
}
214219
}
215220
}
216221

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
;; Check if basic blocks that don't get unique sections are placed in cold sections.
2+
;; Basic block with id 1 and 2 must be in the cold section.
3+
;;
4+
;; Profile for version 0
5+
; RUN: echo '!_Z3bazb' > %t1
6+
; RUN: echo '!!0' >> %t1
7+
;;
8+
;; Profile for version 1
9+
; RUN: echo 'v1' > %t2
10+
; RUN: echo 'f _Z3bazb' >> %t2
11+
; RUN: echo 'c 0' >> %t2
12+
;;
13+
; RUN: llc < %s -mtriple=aarch64 -function-sections -basic-block-sections=%t1 -unique-basic-block-section-names | FileCheck %s -check-prefix=SECTIONS
14+
; RUN: llc < %s -mtriple=aarch64 -function-sections -basic-block-sections=%t2 -unique-basic-block-section-names | FileCheck %s -check-prefix=SECTIONS
15+
; RUN: llc < %s -mtriple=aarch64 -function-sections -basic-block-sections=%t1 -unique-basic-block-section-names -bbsections-cold-text-prefix=".text.unlikely." | FileCheck %s -check-prefix=SPLIT
16+
17+
define void @_Z3bazb(i1 zeroext %0) nounwind {
18+
br i1 %0, label %2, label %4
19+
20+
2: ; preds = %1
21+
%3 = call i32 @_Z3barv()
22+
br label %6
23+
24+
4: ; preds = %1
25+
%5 = call i32 @_Z3foov()
26+
br label %6
27+
28+
6: ; preds = %2, %4
29+
ret void
30+
}
31+
32+
declare i32 @_Z3barv() #1
33+
34+
declare i32 @_Z3foov() #1
35+
36+
; SECTIONS: .section .text.hot._Z3bazb,"ax",@progbits
37+
; SECTIONS: _Z3bazb:
38+
; Check that the basic block with id 1 doesn't get a section.
39+
; SECTIONS-NOT: .section .text{{.*}}._Z3bazb.1,"ax",@progbits,unique
40+
; Check that a single cold section is started here and id 1 and 2 blocks are placed here.
41+
; SECTIONS: .section .text.split._Z3bazb,"ax",@progbits
42+
; SECTIONS: _Z3bazb.cold:
43+
; SECTIONS-NOT: .section .text.hot._Z3bazb._Z3bazb.2,"ax",@progbits,unique
44+
; SECTIONS: .LBB0_2:
45+
; SECTIONS: .size _Z3bazb, .Lfunc_end{{[0-9]}}-_Z3bazb
46+
47+
; SPLIT: .section .text.unlikely._Z3bazb,"ax",@progbits
48+
; SPLIT-NEXT: _Z3bazb.cold:
49+
; SPLIT-NEXT: bl _Z3barv
50+
; SPLIT: .LBB0_2:
51+
; SPLIT: .LBB_END0_2:
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
;; Check if basic blocks without unique sections are only placed in cold sections if it is safe
2+
;; to do so.
3+
;;
4+
;; Profile for version 0.
5+
; RUN: echo 'v1' > %t1
6+
; RUN: echo 'f _Z3asm_goto' >> %t1
7+
; RUN: echo 'c 0' >> %t1
8+
; RUN: echo 'f _Z3jump_table' >> %t1
9+
; RUN: echo 'c 0' >> %t1
10+
; RUN: echo 'f _Z3red_zone' >> %t1
11+
; RUN: echo 'c 0' >> %t1
12+
;;
13+
; RUN: llc < %s -mtriple=aarch64 -function-sections -basic-block-sections=%t1 -unique-basic-block-section-names -bbsections-cold-text-prefix=".text.unlikely." | FileCheck %s
14+
; RUN: llc < %s -mtriple=aarch64 -function-sections -aarch64-min-jump-table-entries=4 -basic-block-sections=%t1 -unique-basic-block-section-names -bbsections-cold-text-prefix=".text.unlikely." | FileCheck %s -check-prefix=JUMP-TABLES
15+
; RUN: llc < %s -mtriple=aarch64 -function-sections -basic-block-sections=%t1 -unique-basic-block-section-names -bbsections-cold-text-prefix=".text.unlikely." | FileCheck %s -check-prefix=RED-ZONE
16+
17+
define void @_Z3asm_goto(i1 zeroext %0, i1 zeroext %1) nounwind {
18+
;; Check that blocks containing or targeted by asm goto aren't split.
19+
; CHECK-LABEL: _Z3asm_goto
20+
; CHECK: .section .text.unlikely._Z3asm_goto,"ax",@progbits
21+
; CHECK-NEXT: _Z3asm_goto.cold:
22+
; CHECK-NEXT: bl bam
23+
; CHECK: .LBB0_4:
24+
; CHECK: ret
25+
; CHECK: .LBB_END0_4:
26+
27+
br i1 %0, label %3, label %5
28+
29+
3: ; preds = %2
30+
%4 = call i32 @bar()
31+
callbr void asm sideeffect "nop", "!i"() #3
32+
to label %asm.fallthrough [label %5]
33+
34+
35+
asm.fallthrough: ; preds = %3
36+
br label %5
37+
38+
5: ; preds = %2, %asm.fallthrough
39+
%6 = call i32 @bar()
40+
br i1 %1, label %7, label %9
41+
42+
7:
43+
%8 = call i32 @bam()
44+
br label %9
45+
46+
9: ; preds = %7
47+
ret void
48+
}
49+
50+
define i32 @_Z3jump_table(i32 %in) nounwind {
51+
;; Check that a cold block that contains a jump table dispatch or
52+
;; that is targeted by a jump table is not split.
53+
; JUMP-TABLES-LABEL: _Z3jump_table
54+
; JUMP-TABLES: .section .text.unlikely._Z3jump_table,"ax",@progbits
55+
; JUMP-TABLES-NEXT: _Z3jump_table.cold:
56+
; JUMP-TABLES-SAME: %common.ret
57+
; JUMP-TABLES-NOT: b bar
58+
; JUMP-TABLES-NOT: b baz
59+
; JUMP-TABLES-NOT: b qux
60+
; JUMP-TABLES-NOT: b bam
61+
62+
switch i32 %in, label %common.ret [
63+
i32 0, label %cold1
64+
i32 1, label %cold2
65+
i32 2, label %cold3
66+
i32 3, label %cold4
67+
]
68+
69+
common.ret: ; preds = %0
70+
ret i32 0
71+
72+
cold1: ; preds = %0
73+
%1 = tail call i32 @bar()
74+
ret i32 %1
75+
76+
cold2: ; preds = %0
77+
%2 = tail call i32 @baz()
78+
ret i32 %2
79+
80+
cold3: ; preds = %0
81+
%3 = tail call i32 @bam()
82+
ret i32 %3
83+
84+
cold4: ; preds = %0
85+
%4 = tail call i32 @qux()
86+
ret i32 %4
87+
}
88+
89+
define i32 @_Z3red_zone(i1 zeroext %0, i32 %a, i32 %b) nounwind {
90+
;; Check that cold blocks in functions with red zones aren't split.
91+
; RED-ZONE-LABEL: _Z3red_zone
92+
; MFS-REDZONE-AARCH64-NOT: _Z3red_zone.cold:
93+
%a.addr = alloca i32, align 4
94+
%b.addr = alloca i32, align 4
95+
%x = alloca i32, align 4
96+
97+
br i1 %0, label %2, label %3
98+
99+
2: ; preds = %1
100+
store i32 %a, ptr %a.addr, align 4
101+
store i32 %b, ptr %b.addr, align 4
102+
br label %4
103+
104+
3: ; preds = %1
105+
store i32 %a, ptr %b.addr, align 4
106+
store i32 %b, ptr %a.addr, align 4
107+
br label %4
108+
109+
4: ; preds = %3, %2
110+
%tmp = load i32, ptr %a.addr, align 4
111+
%tmp1 = load i32, ptr %b.addr, align 4
112+
%add = add nsw i32 %tmp, %tmp1
113+
store i32 %add, ptr %x, align 4
114+
%tmp2 = load i32, ptr %x, align 4
115+
ret i32 %tmp2
116+
}
117+
118+
declare i32 @bar()
119+
declare i32 @baz()
120+
declare i32 @bam()
121+
declare i32 @qux()

0 commit comments

Comments
 (0)