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