Skip to content

Commit 169486b

Browse files
[nfc]asm printer jump table
1 parent 659d1fe commit 169486b

File tree

4 files changed

+285
-39
lines changed

4 files changed

+285
-39
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -893,9 +893,8 @@ class AsmPrinter : public MachineFunctionPass {
893893
// Internal Implementation Details
894894
//===------------------------------------------------------------------===//
895895

896-
void emitJumpTableImpl(const MachineJumpTableInfo &MJTI,
897-
ArrayRef<unsigned> JumpTableIndices,
898-
bool JTInDiffSection);
896+
virtual void emitJumpTableImpl(const MachineJumpTableInfo &MJTI,
897+
ArrayRef<unsigned> JumpTableIndices);
899898
void emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
900899
const MachineBasicBlock *MBB, unsigned uid) const;
901900

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2855,22 +2855,12 @@ void AsmPrinter::emitConstantPool() {
28552855
void AsmPrinter::emitJumpTableInfo() {
28562856
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
28572857
if (!MJTI) return;
2858-
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
2858+
28592859
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
28602860
if (JT.empty()) return;
28612861

2862-
// Pick the directive to use to print the jump table entries, and switch to
2863-
// the appropriate section.
2864-
const Function &F = MF->getFunction();
2865-
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
2866-
bool JTInDiffSection = !TLOF.shouldPutJumpTableInFunctionSection(
2867-
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 ||
2868-
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64,
2869-
F);
2870-
28712862
if (!TM.Options.EnableStaticDataPartitioning) {
2872-
emitJumpTableImpl(*MJTI, llvm::to_vector(llvm::seq<unsigned>(JT.size())),
2873-
JTInDiffSection);
2863+
emitJumpTableImpl(*MJTI, llvm::to_vector(llvm::seq<unsigned>(JT.size())));
28742864
return;
28752865
}
28762866

@@ -2886,38 +2876,46 @@ void AsmPrinter::emitJumpTableInfo() {
28862876
}
28872877
}
28882878

2889-
emitJumpTableImpl(*MJTI, HotJumpTableIndices, JTInDiffSection);
2890-
emitJumpTableImpl(*MJTI, ColdJumpTableIndices, JTInDiffSection);
2879+
emitJumpTableImpl(*MJTI, HotJumpTableIndices);
2880+
emitJumpTableImpl(*MJTI, ColdJumpTableIndices);
28912881
}
28922882

28932883
void AsmPrinter::emitJumpTableImpl(const MachineJumpTableInfo &MJTI,
2894-
ArrayRef<unsigned> JumpTableIndices,
2895-
bool JTInDiffSection) {
2896-
if (JumpTableIndices.empty())
2884+
ArrayRef<unsigned> JumpTableIndices) {
2885+
if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_Inline ||
2886+
JumpTableIndices.empty())
28972887
return;
28982888

28992889
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
29002890
const Function &F = MF->getFunction();
29012891
const std::vector<MachineJumpTableEntry> &JT = MJTI.getJumpTables();
29022892
MCSection *JumpTableSection = nullptr;
2903-
if (TM.Options.EnableStaticDataPartitioning) {
2904-
JumpTableSection =
2905-
TLOF.getSectionForJumpTable(F, TM, &JT[JumpTableIndices.front()]);
2906-
} else {
2907-
JumpTableSection = TLOF.getSectionForJumpTable(F, TM);
2908-
}
29092893

2910-
const DataLayout &DL = MF->getDataLayout();
2894+
// Pick the directive to use to print the jump table entries, and switch to
2895+
// the appropriate section.
2896+
const bool JTInDiffSection = !TLOF.shouldPutJumpTableInFunctionSection(
2897+
MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 ||
2898+
MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64,
2899+
F);
29112900
if (JTInDiffSection) {
2901+
if (TM.Options.EnableStaticDataPartitioning) {
2902+
JumpTableSection =
2903+
TLOF.getSectionForJumpTable(F, TM, &JT[JumpTableIndices.front()]);
2904+
} else {
2905+
JumpTableSection = TLOF.getSectionForJumpTable(F, TM);
2906+
}
29122907
OutStreamer->switchSection(JumpTableSection);
29132908
}
29142909

2910+
const DataLayout &DL = MF->getDataLayout();
2911+
29152912
emitAlignment(Align(MJTI.getEntryAlignment(MF->getDataLayout())));
29162913

2917-
// Jump tables in code sections are marked with a data_region directive
2918-
// where that's supported.
2919-
if (!JTInDiffSection)
2914+
if (!JTInDiffSection) {
2915+
// Jump tables in code sections are marked with a data_region directive
2916+
// where that's supported.
29202917
OutStreamer->emitDataRegion(MCDR_DataRegionJT32);
2918+
}
29212919

29222920
for (const unsigned JumpTableIndex : JumpTableIndices) {
29232921
ArrayRef<MachineBasicBlock *> JTBBs = JT[JumpTableIndex].MBBs;

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ class AArch64AsmPrinter : public AsmPrinter {
112112
const MCExpr *lowerBlockAddressConstant(const BlockAddress &BA) override;
113113

114114
void emitStartOfAsmFile(Module &M) override;
115-
void emitJumpTableInfo() override;
115+
void emitJumpTableImpl(const MachineJumpTableInfo &MJTI,
116+
ArrayRef<unsigned> JumpTableIndices) override;
116117
std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
117118
codeview::JumpTableEntrySize>
118119
getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr,
@@ -1273,19 +1274,15 @@ void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
12731274
printOperand(MI, NOps - 2, OS);
12741275
}
12751276

1276-
void AArch64AsmPrinter::emitJumpTableInfo() {
1277-
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1278-
if (!MJTI) return;
1279-
1280-
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1281-
if (JT.empty()) return;
1282-
1277+
void AArch64AsmPrinter::emitJumpTableImpl(const MachineJumpTableInfo &MJTI,
1278+
ArrayRef<unsigned> JumpTableIndices) {
12831279
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
12841280
MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(MF->getFunction(), TM);
12851281
OutStreamer->switchSection(ReadOnlySec);
12861282

1283+
const std::vector<MachineJumpTableEntry> &JT = MJTI.getJumpTables();
12871284
auto AFI = MF->getInfo<AArch64FunctionInfo>();
1288-
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
1285+
for (unsigned JTI : JumpTableIndices) {
12891286
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
12901287

12911288
// If this jump table was deleted, ignore it.
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
2+
3+
; The llc commands override two options
4+
; - 'aarch64-enable-atomic-cfg-tidy' to false to turn off simplifycfg pass,
5+
; which can simplify away switch instructions before isel lowers switch instructions.
6+
; - 'aarch64-min-jump-table-entries' so 'switch' needs fewer cases to generate
7+
; a jump table.
8+
9+
; The static-data-splitter pass doesn't run.
10+
; RUN: llc -mtriple=aarch64-unknown-linux-gnu -function-sections=true \
11+
; RUN: -aarch64-enable-atomic-cfg-tidy=false -aarch64-min-jump-table-entries=2 \
12+
; RUN: -unique-section-names=true %s -o - 2>&1 | FileCheck %s --check-prefixes=DEFAULT
13+
14+
; DEFAULT: .section .rodata.hot.foo,"a",@progbits
15+
; DEFAULT: .LJTI0_0:
16+
; DEFAULT: .LJTI0_1:
17+
; DEFAULT: .LJTI0_2:
18+
; DEFAULT: .LJTI0_3:
19+
; DEFAULT: .section .rodata.func_without_profile,"a",@progbits
20+
; DEFAULT: .LJTI1_0:
21+
; DEFAULT: .section .rodata.bar_prefix.bar,"a",@progbits
22+
; DEFAULT: .LJTI2_0
23+
24+
; RUN: llc -mtriple=aarch64-unknown-linux-gnu -enable-split-machine-functions \
25+
; RUN: -partition-static-data-sections=true -function-sections=true \
26+
; RUN: -aarch64-enable-atomic-cfg-tidy=false -aarch64-min-jump-table-entries=2 \
27+
; RUN: -unique-section-names=false %s -o - 2>&1 | FileCheck %s --check-prefixes=NUM,JT
28+
29+
; Section names will optionally have `.<func>` if -function-sections is enabled.
30+
; RUN: llc -mtriple=aarch64-unknown-linux-gnu -enable-split-machine-functions \
31+
; RUN: -partition-static-data-sections=true -function-sections=true \
32+
; RUN: -aarch64-enable-atomic-cfg-tidy=false -aarch64-min-jump-table-entries=2 \
33+
; RUN: %s -o - 2>&1 | FileCheck %s --check-prefixes=FUNC,JT
34+
35+
; RUN: llc -mtriple=aarch64-unknown-linux-gnu -enable-split-machine-functions \
36+
; RUN: -partition-static-data-sections=true -function-sections=false \
37+
; RUN: -aarch64-enable-atomic-cfg-tidy=false -aarch64-min-jump-table-entries=2 \
38+
; RUN: %s -o - 2>&1 | FileCheck %s --check-prefixes=FUNCLESS,JT
39+
40+
; In function @foo, the 2 switch instructions to jt0.* and jt1.* are placed in
41+
; hot-prefixed sections, and the 2 switch instructions to jt2.* and jt3.* are
42+
; placed in cold-prefixed sections.
43+
; NUM: .section .rodata.hot.,"a",@progbits,unique,2
44+
; FUNC: .section .rodata.hot.foo,"a",@progbits
45+
; FUNCLESS: .section .rodata.hot.,"a",@progbits
46+
; JT: .LJTI0_0:
47+
; JT: .LJTI0_2:
48+
; NUM: .section .rodata.hot.,"a",@progbits,unique,3
49+
; FUNC-NOT: .section .rodata.hot.foo
50+
; FUNCLESS-NOT: .section .rodata.hot.,"a",@progbits
51+
; JT: .LJTI0_1:
52+
; JT: .LJTI0_3:
53+
54+
; @func_without_profile simulates the functions without profile information
55+
; (e.g., not instrumented or not profiled), its jump tables are placed in
56+
; sections without hot or unlikely prefixes.
57+
; NUM: .section .rodata,"a",@progbits,unique,5
58+
; FUNC: .section .rodata.func_without_profile,"a",@progbits
59+
; FUNCLESS: .section .rodata,"a",@progbits
60+
; JT: .LJTI1_0:
61+
62+
; @bar doesn't have profile information and it has a section prefix.
63+
; Tests that its jump tables are placed in sections with function prefixes.
64+
; NUM: .section .rodata.bar_prefix.,"a",@progbits,unique,
65+
; FUNC: .section .rodata.bar_prefix.bar
66+
; FUNCLESS: .section .rodata.bar_prefix.,"a"
67+
; JT: .LJTI2_0
68+
69+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
70+
target triple = "aarch64-unknown-linux-gnu"
71+
72+
@str.9 = private constant [7 x i8] c".str.9\00"
73+
@str.10 = private constant [8 x i8] c".str.10\00"
74+
@str.11 = private constant [8 x i8] c".str.11\00"
75+
76+
@case2 = private constant [7 x i8] c"case 2\00"
77+
@case1 = private constant [7 x i8] c"case 1\00"
78+
@default = private constant [8 x i8] c"default\00"
79+
@jt3 = private constant [4 x i8] c"jt3\00"
80+
81+
; jt0 and jt2 are hot. jt1 and jt3 are cold.
82+
define i32 @foo(i32 %num) !prof !13 {
83+
entry:
84+
%mod3 = sdiv i32 %num, 3
85+
switch i32 %mod3, label %jt0.default [
86+
i32 1, label %jt0.bb1
87+
i32 2, label %jt0.bb2
88+
], !prof !14
89+
90+
jt0.bb1:
91+
call i32 @puts(ptr @case1)
92+
br label %jt0.epilog
93+
94+
jt0.bb2:
95+
call i32 @puts(ptr @case2)
96+
br label %jt0.epilog
97+
98+
jt0.default:
99+
call i32 @puts(ptr @default)
100+
br label %jt0.epilog
101+
102+
jt0.epilog:
103+
%zero = icmp eq i32 %num, 0
104+
br i1 %zero, label %hot, label %cold, !prof !17
105+
106+
hot:
107+
%c2 = call i32 @transform(i32 %num)
108+
switch i32 %c2, label %jt2.default [
109+
i32 1, label %jt2.bb1
110+
i32 2, label %jt2.bb2
111+
], !prof !14
112+
113+
jt2.bb1:
114+
call i32 @puts(ptr @case1)
115+
br label %jt1.epilog
116+
117+
jt2.bb2:
118+
call i32 @puts(ptr @case2)
119+
br label %jt1.epilog
120+
121+
jt2.default:
122+
call i32 @puts(ptr @default)
123+
br label %jt2.epilog
124+
125+
jt2.epilog:
126+
%c2cmp = icmp ne i32 %c2, 0
127+
br i1 %c2cmp, label %return, label %jt3.prologue, !prof !18
128+
129+
cold:
130+
%c1 = call i32 @compute(i32 %num)
131+
switch i32 %c1, label %jt1.default [
132+
i32 1, label %jt1.bb1
133+
i32 2, label %jt1.bb2
134+
], !prof !14
135+
136+
jt1.bb1:
137+
call i32 @puts(ptr @case1)
138+
br label %jt1.epilog
139+
140+
jt1.bb2:
141+
call i32 @puts(ptr @case2)
142+
br label %jt1.epilog
143+
144+
jt1.default:
145+
call i32 @puts(ptr @default)
146+
br label %jt1.epilog
147+
148+
jt1.epilog:
149+
br label %return
150+
151+
jt3.prologue:
152+
%c3 = call i32 @cleanup(i32 %num)
153+
switch i32 %c3, label %jt3.default [
154+
i32 1, label %jt3.bb1
155+
i32 2, label %jt3.bb2
156+
], !prof !14
157+
158+
jt3.bb1:
159+
call i32 @puts(ptr @case1)
160+
br label %jt3.epilog
161+
162+
jt3.bb2:
163+
call i32 @puts(ptr @case2)
164+
br label %jt3.epilog
165+
166+
jt3.default:
167+
call i32 @puts(ptr @default)
168+
br label %jt3.epilog
169+
170+
jt3.epilog:
171+
call i32 @puts(ptr @jt3)
172+
br label %return
173+
174+
return:
175+
ret i32 %mod3
176+
}
177+
178+
define void @func_without_profile(i32 %num) {
179+
entry:
180+
switch i32 %num, label %sw.default [
181+
i32 1, label %sw.bb
182+
i32 2, label %sw.bb1
183+
]
184+
185+
sw.bb:
186+
call i32 @puts(ptr @str.10)
187+
br label %sw.epilog
188+
189+
sw.bb1:
190+
call i32 @puts(ptr @str.9)
191+
br label %sw.epilog
192+
193+
sw.default:
194+
call i32 @puts(ptr @str.11)
195+
br label %sw.epilog
196+
197+
sw.epilog:
198+
ret void
199+
}
200+
201+
define void @bar(i32 %num) !section_prefix !20 {
202+
entry:
203+
switch i32 %num, label %sw.default [
204+
i32 1, label %sw.bb
205+
i32 2, label %sw.bb1
206+
]
207+
208+
sw.bb:
209+
call i32 @puts(ptr @str.10)
210+
br label %sw.epilog
211+
212+
sw.bb1:
213+
call i32 @puts(ptr @str.9)
214+
br label %sw.epilog
215+
216+
sw.default:
217+
call i32 @puts(ptr @str.11)
218+
br label %sw.epilog
219+
220+
sw.epilog:
221+
ret void
222+
}
223+
224+
declare i32 @puts(ptr)
225+
declare i32 @printf(ptr, ...)
226+
declare i32 @compute(i32)
227+
declare i32 @transform(i32)
228+
declare i32 @cleanup(i32)
229+
230+
!llvm.module.flags = !{!0}
231+
232+
!0 = !{i32 1, !"ProfileSummary", !1}
233+
!1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
234+
!2 = !{!"ProfileFormat", !"InstrProf"}
235+
!3 = !{!"TotalCount", i64 230002}
236+
!4 = !{!"MaxCount", i64 100000}
237+
!5 = !{!"MaxInternalCount", i64 50000}
238+
!6 = !{!"MaxFunctionCount", i64 100000}
239+
!7 = !{!"NumCounts", i64 14}
240+
!8 = !{!"NumFunctions", i64 3}
241+
!9 = !{!"DetailedSummary", !10}
242+
!10 = !{!11, !12}
243+
!11 = !{i32 990000, i64 10000, i32 7}
244+
!12 = !{i32 999999, i64 1, i32 9}
245+
!13 = !{!"function_entry_count", i64 100000}
246+
!14 = !{!"branch_weights", i32 60000, i32 20000, i32 20000}
247+
!15 = !{!"function_entry_count", i64 1}
248+
!16 = !{!"branch_weights", i32 1, i32 0, i32 0, i32 0, i32 0, i32 0}
249+
!17 = !{!"branch_weights", i32 99999, i32 1}
250+
!18 = !{!"branch_weights", i32 99998, i32 1}
251+
!19 = !{!"branch_weights", i32 97000, i32 1000, i32 1000, i32 1000}
252+
!20 = !{!"function_section_prefix", !"bar_prefix"}

0 commit comments

Comments
 (0)