OLD | NEW |
1 ; This tests the advanced lowering of switch statements. The advanced lowering | 1 ; This tests the advanced lowering of switch statements. The advanced lowering |
2 ; uses jump tables, range tests and binary search. | 2 ; uses jump tables, range tests and binary search. |
3 | 3 |
4 ; RUN: %p2i -i %s --target=x8632 --filetype=obj --disassemble --args -O2 \ | 4 ; RUN: %p2i -i %s --target=x8632 --filetype=obj --disassemble --args -O2 \ |
5 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X8632 | 5 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X8632 |
6 ; RUN: %p2i -i %s --target=x8664 --filetype=obj --disassemble --args -O2 \ | 6 ; RUN: %p2i -i %s --target=x8664 --filetype=obj --disassemble --args -O2 \ |
7 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X8664 | 7 ; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X8664 |
8 | 8 |
| 9 ; RUN: %if --need=target_MIPS32 --need=allow_dump \ |
| 10 ; RUN: --command %p2i --filetype=asm --assemble --disassemble --target \ |
| 11 ; RUN: mips32 -i %s --args -O2 -allow-externally-defined-symbols \ |
| 12 ; RUN: | %if --need=target_MIPS32 --need=allow_dump \ |
| 13 ; RUN: --command FileCheck --check-prefix MIPS32 %s |
| 14 |
9 ; Dense but non-continuous ranges should be converted into a jump table. | 15 ; Dense but non-continuous ranges should be converted into a jump table. |
10 define internal i32 @testJumpTable(i32 %a) { | 16 define internal i32 @testJumpTable(i32 %a) { |
11 entry: | 17 entry: |
12 switch i32 %a, label %sw.default [ | 18 switch i32 %a, label %sw.default [ |
13 i32 91, label %sw.default | 19 i32 91, label %sw.default |
14 i32 92, label %sw.bb1 | 20 i32 92, label %sw.bb1 |
15 i32 93, label %sw.default | 21 i32 93, label %sw.default |
16 i32 99, label %sw.bb1 | 22 i32 99, label %sw.bb1 |
17 i32 98, label %sw.default | 23 i32 98, label %sw.default |
18 i32 96, label %sw.bb1 | 24 i32 96, label %sw.bb1 |
(...skipping 17 matching lines...) Expand all Loading... |
36 ; CHECK-NEXT: cmp [[IND]],0x8 | 42 ; CHECK-NEXT: cmp [[IND]],0x8 |
37 ; CHECK-NEXT: ja | 43 ; CHECK-NEXT: ja |
38 ; X8632-NEXT: mov [[TARGET:.*]],DWORD PTR {{\[}}[[IND]]*4+0x0] {{[0-9a-f]+}}: R_
386_32 .{{.*}}testJumpTable$jumptable | 44 ; X8632-NEXT: mov [[TARGET:.*]],DWORD PTR {{\[}}[[IND]]*4+0x0] {{[0-9a-f]+}}: R_
386_32 .{{.*}}testJumpTable$jumptable |
39 ; X8632-NEXT: jmp [[TARGET]] | 45 ; X8632-NEXT: jmp [[TARGET]] |
40 ; X8664-NEXT: mov {{.}}[[TARGET:.*]],DWORD PTR {{\[}}[[IND]]*4+0x0] {{[0-9a-f]+}
}: R_X86_64_32S .{{.*}}testJumpTable$jumptable | 46 ; X8664-NEXT: mov {{.}}[[TARGET:.*]],DWORD PTR {{\[}}[[IND]]*4+0x0] {{[0-9a-f]+}
}: R_X86_64_32S .{{.*}}testJumpTable$jumptable |
41 ; X8664-NEXT: jmp {{.}}[[TARGET]] | 47 ; X8664-NEXT: jmp {{.}}[[TARGET]] |
42 ; Note: x86-32 may do "mov eax, [...]; jmp eax", whereas x86-64 may do | 48 ; Note: x86-32 may do "mov eax, [...]; jmp eax", whereas x86-64 may do |
43 ; "mov eax, [...]; jmp rax", so we assume the all characters except the first | 49 ; "mov eax, [...]; jmp rax", so we assume the all characters except the first |
44 ; one in the register name will match. | 50 ; one in the register name will match. |
45 | 51 |
| 52 ; MIPS32-LABEL: testJumpTable |
| 53 ; MIPS32: move [[REG1:.*]],{{.*}} |
| 54 ; MIPS32: li [[REG2:.*]],91 |
| 55 ; MIPS32: beq [[REG1]],[[REG2]],6c <.LtestJumpTable$sw.default> |
| 56 ; MIPS32: nop |
| 57 ; MIPS32: li [[REG2:.*]],92 |
| 58 ; MIPS32: beq [[REG1]],[[REG2]],7c <.LtestJumpTable$sw.bb1> |
| 59 ; MIPS32: nop |
| 60 ; MIPS32: li [[REG2:.*]],93 |
| 61 ; MIPS32: beq [[REG1]],[[REG2]],6c <.LtestJumpTable$sw.default> |
| 62 ; MIPS32: nop |
| 63 ; MIPS32: li [[REG2:.*]],99 |
| 64 ; MIPS32: beq [[REG1]],[[REG2]],7c <.LtestJumpTable$sw.bb1> |
| 65 ; MIPS32: nop |
| 66 ; MIPS32: li [[REG2:.*]],98 |
| 67 ; MIPS32: beq [[REG1]],[[REG2]],6c <.LtestJumpTable$sw.default> |
| 68 ; MIPS32: nop |
| 69 ; MIPS32: li [[REG2:.*]],96 |
| 70 ; MIPS32: beq [[REG1]],[[REG2]],7c <.LtestJumpTable$sw.bb1> |
| 71 ; MIPS32: nop |
| 72 ; MIPS32: li [[REG2:.*]],97 |
| 73 ; MIPS32: beq [[REG1]],[[REG2]],60 <.LtestJumpTable$split_entry_sw.epi
log_0> |
| 74 ; MIPS32: nop |
| 75 ; MIPS32: b 6c <.LtestJumpTable$sw.default> |
| 76 ; MIPS32: nop |
| 77 |
46 ; Continuous ranges which map to the same target should be grouped and | 78 ; Continuous ranges which map to the same target should be grouped and |
47 ; efficiently tested. | 79 ; efficiently tested. |
48 define internal i32 @testRangeTest() { | 80 define internal i32 @testRangeTest() { |
49 entry: | 81 entry: |
50 switch i32 10, label %sw.default [ | 82 switch i32 10, label %sw.default [ |
51 i32 0, label %sw.epilog | 83 i32 0, label %sw.epilog |
52 i32 1, label %sw.epilog | 84 i32 1, label %sw.epilog |
53 i32 2, label %sw.epilog | 85 i32 2, label %sw.epilog |
54 i32 3, label %sw.epilog | 86 i32 3, label %sw.epilog |
55 i32 10, label %sw.bb1 | 87 i32 10, label %sw.bb1 |
(...skipping 13 matching lines...) Expand all Loading... |
69 ret i32 %result.1 | 101 ret i32 %result.1 |
70 } | 102 } |
71 ; CHECK-LABEL: testRangeTest | 103 ; CHECK-LABEL: testRangeTest |
72 ; CHECK: cmp {{.*}},0x3 | 104 ; CHECK: cmp {{.*}},0x3 |
73 ; CHECK-NEXT: jbe | 105 ; CHECK-NEXT: jbe |
74 ; CHECK: sub [[REG:[^,]*]],0xa | 106 ; CHECK: sub [[REG:[^,]*]],0xa |
75 ; CHECK-NEXT: cmp [[REG]],0x3 | 107 ; CHECK-NEXT: cmp [[REG]],0x3 |
76 ; CHECK-NEXT: jbe | 108 ; CHECK-NEXT: jbe |
77 ; CHECK-NEXT: jmp | 109 ; CHECK-NEXT: jmp |
78 | 110 |
| 111 ; MIPS32-LABEL: testRangeTest |
| 112 ; MIPS32: li [[REG1:.*]],10 |
| 113 ; MIPS32: li [[REG2:.*]],0 |
| 114 ; MIPS32: beq [[REG1]],[[REG2]],114 <.LtestRangeTest$split_entry_sw.ep
ilog_0> |
| 115 ; MIPS32: nop |
| 116 ; MIPS32: li [[REG2:.*]],1 |
| 117 ; MIPS32: beq [[REG1]],[[REG2]],114 <.LtestRangeTest$split_entry_sw.ep
ilog_0> |
| 118 ; MIPS32: nop |
| 119 ; MIPS32: li [[REG2:.*]],2 |
| 120 ; MIPS32: beq [[REG1]],[[REG2]],114 <.LtestRangeTest$split_entry_sw.ep
ilog_0> |
| 121 ; MIPS32: nop |
| 122 ; MIPS32: li [[REG2:.*]],3 |
| 123 ; MIPS32: beq [[REG1]],[[REG2]],114 <.LtestRangeTest$split_entry_sw.ep
ilog_0> |
| 124 ; MIPS32: nop |
| 125 ; MIPS32: li [[REG2:.*]],10 |
| 126 ; MIPS32: beq [[REG1]],[[REG2]],fc <.LtestRangeTest$split_sw.bb1_sw.ep
ilog_2> |
| 127 ; MIPS32: nop |
| 128 ; MIPS32: li [[REG2:.*]],11 |
| 129 ; MIPS32: beq [[REG1]],[[REG2]],fc <.LtestRangeTest$split_sw.bb1_sw.ep
ilog_2> |
| 130 ; MIPS32: nop |
| 131 ; MIPS32: li [[REG2:.*]],12 |
| 132 ; MIPS32: beq [[REG1]],[[REG2]],fc <.LtestRangeTest$split_sw.bb1_sw.ep
ilog_2> |
| 133 ; MIPS32: nop |
| 134 ; MIPS32: li [[REG2:.*]],13 |
| 135 ; MIPS32: beq [[REG1]],[[REG2]],fc <.LtestRangeTest$split_sw.bb1_sw.ep
ilog_2> |
| 136 ; MIPS32: nop |
| 137 ; MIPS32: b 108 <.LtestRangeTest$split_sw.default_sw.epilog_1> |
| 138 ; MIPS32: nop |
| 139 |
79 ; Sparse cases should be searched with a binary search. | 140 ; Sparse cases should be searched with a binary search. |
80 define internal i32 @testBinarySearch() { | 141 define internal i32 @testBinarySearch() { |
81 entry: | 142 entry: |
82 switch i32 10, label %sw.default [ | 143 switch i32 10, label %sw.default [ |
83 i32 0, label %sw.epilog | 144 i32 0, label %sw.epilog |
84 i32 10, label %sw.epilog | 145 i32 10, label %sw.epilog |
85 i32 20, label %sw.bb1 | 146 i32 20, label %sw.bb1 |
86 i32 30, label %sw.bb1 | 147 i32 30, label %sw.bb1 |
87 ] | 148 ] |
88 | 149 |
(...skipping 13 matching lines...) Expand all Loading... |
102 ; CHECK-NEXT: je | 163 ; CHECK-NEXT: je |
103 ; CHECK-NEXT: cmp {{.*}},0x1e | 164 ; CHECK-NEXT: cmp {{.*}},0x1e |
104 ; CHECK-NEXT: je | 165 ; CHECK-NEXT: je |
105 ; CHECK-NEXT: jmp | 166 ; CHECK-NEXT: jmp |
106 ; CHECK-NEXT: cmp {{.*}},0x0 | 167 ; CHECK-NEXT: cmp {{.*}},0x0 |
107 ; CHECK-NEXT: je | 168 ; CHECK-NEXT: je |
108 ; CHECK-NEXT: cmp {{.*}},0xa | 169 ; CHECK-NEXT: cmp {{.*}},0xa |
109 ; CHECK-NEXT: je | 170 ; CHECK-NEXT: je |
110 ; CHECK-NEXT: jmp | 171 ; CHECK-NEXT: jmp |
111 | 172 |
| 173 ; MIPS32-LABEL: testBinarySearch |
| 174 ; MIPS32: li [[REG1:.*]],10 |
| 175 ; MIPS32: li [[REG2:.*]],0 |
| 176 ; MIPS32: beq [[REG1]],[[REG2]],174 <.LtestBinarySearch$split_entry_sw
.epilog_0> |
| 177 ; MIPS32: nop |
| 178 ; MIPS32: li [[REG2:.*]],10 |
| 179 ; MIPS32: beq [[REG1]],[[REG2]],174 <.LtestBinarySearch$split_entry_sw
.epilog_0> |
| 180 ; MIPS32: nop |
| 181 ; MIPS32: li [[REG2:.*]],20 |
| 182 ; MIPS32: beq [[REG1]],[[REG2]],15c <.LtestBinarySearch$split_sw.bb1_s
w.epilog_2> |
| 183 ; MIPS32: nop |
| 184 ; MIPS32: li [[REG2:.*]],30 |
| 185 ; MIPS32: beq [[REG1]],[[REG2]],15c <.LtestBinarySearch$split_sw.bb1_s
w.epilog_2> |
| 186 ; MIPS32: nop |
| 187 ; MIPS32: b 168 <.LtestBinarySearch$split_sw.default_sw.epilog_1> |
| 188 ; MIPS32: nop |
| 189 |
112 ; 64-bit switches where the cases are all 32-bit values should be reduced to a | 190 ; 64-bit switches where the cases are all 32-bit values should be reduced to a |
113 ; 32-bit switch after checking the top byte is 0. | 191 ; 32-bit switch after checking the top byte is 0. |
114 define internal i32 @testSwitchSmall64(i64 %a) { | 192 define internal i32 @testSwitchSmall64(i64 %a) { |
115 entry: | 193 entry: |
116 switch i64 %a, label %sw.default [ | 194 switch i64 %a, label %sw.default [ |
117 i64 123, label %return | 195 i64 123, label %return |
118 i64 234, label %sw.bb1 | 196 i64 234, label %sw.bb1 |
119 i64 345, label %sw.bb2 | 197 i64 345, label %sw.bb2 |
120 i64 456, label %sw.bb3 | 198 i64 456, label %sw.bb3 |
121 ] | 199 ] |
(...skipping 21 matching lines...) Expand all Loading... |
143 ; X8632-NEXT: jb | 221 ; X8632-NEXT: jb |
144 ; X8632-NEXT: je | 222 ; X8632-NEXT: je |
145 ; X8632-NEXT: cmp {{.*}},0x1c8 | 223 ; X8632-NEXT: cmp {{.*}},0x1c8 |
146 ; X8632-NEXT: je | 224 ; X8632-NEXT: je |
147 ; X8632-NEXT: jmp | 225 ; X8632-NEXT: jmp |
148 ; X8632-NEXT: cmp {{.*}},0x7b | 226 ; X8632-NEXT: cmp {{.*}},0x7b |
149 ; X8632-NEXT: je | 227 ; X8632-NEXT: je |
150 ; X8632-NEXT: cmp {{.*}},0xea | 228 ; X8632-NEXT: cmp {{.*}},0xea |
151 ; X8632-NEXT: je | 229 ; X8632-NEXT: je |
152 | 230 |
| 231 ; MIPS32-LABEL: testSwitchSmall64 |
| 232 ; MIPS32: li [[REG:.*]],0 |
| 233 ; MIPS32: bne {{.*}},[[REG]],198 <.LtestSwitchSmall64$local$__0> |
| 234 ; MIPS32: nop |
| 235 ; MIPS32: li [[REG:.*]],123 |
| 236 ; MIPS32: beq {{.*}},[[REG]],210 <.LtestSwitchSmall64$split_entry_retu
rn_0> |
| 237 ; MIPS32: nop |
| 238 |
153 ; Test for correct 64-bit lowering. | 239 ; Test for correct 64-bit lowering. |
154 ; TODO(ascull): this should generate better code like the 32-bit version | 240 ; TODO(ascull): this should generate better code like the 32-bit version |
155 define internal i32 @testSwitch64(i64 %a) { | 241 define internal i32 @testSwitch64(i64 %a) { |
156 entry: | 242 entry: |
157 switch i64 %a, label %sw.default [ | 243 switch i64 %a, label %sw.default [ |
158 i64 123, label %return | 244 i64 123, label %return |
159 i64 234, label %sw.bb1 | 245 i64 234, label %sw.bb1 |
160 i64 345, label %sw.bb2 | 246 i64 345, label %sw.bb2 |
161 i64 78187493520, label %sw.bb3 | 247 i64 78187493520, label %sw.bb3 |
162 ] | 248 ] |
(...skipping 25 matching lines...) Expand all Loading... |
188 ; X8632-NEXT: je | 274 ; X8632-NEXT: je |
189 ; X8632: cmp {{.*}},0x159 | 275 ; X8632: cmp {{.*}},0x159 |
190 ; X8632-NEXT: jne | 276 ; X8632-NEXT: jne |
191 ; X8632-NEXT: cmp {{.*}},0x0 | 277 ; X8632-NEXT: cmp {{.*}},0x0 |
192 ; X8632-NEXT: je | 278 ; X8632-NEXT: je |
193 ; X8632: cmp {{.*}},0x34567890 | 279 ; X8632: cmp {{.*}},0x34567890 |
194 ; X8632-NEXT: jne | 280 ; X8632-NEXT: jne |
195 ; X8632-NEXT: cmp {{.*}},0x12 | 281 ; X8632-NEXT: cmp {{.*}},0x12 |
196 ; X8632-NEXT: je | 282 ; X8632-NEXT: je |
197 | 283 |
| 284 ; MIPS32-LABEL: testSwitch64 |
| 285 ; MIPS32: li [[REG:.*]],0 |
| 286 ; MIPS32: bne {{.*}},[[REG]],238 <.LtestSwitch64$local$__0> |
| 287 ; MIPS32: nop |
| 288 ; MIPS32: li [[REG:.*]],123 |
| 289 ; MIPS32: beq {{.*}},[[REG]],2b4 <.LtestSwitch64$split_entry_return_0> |
| 290 ; MIPS32: nop |
| 291 |
198 ; Test for correct 64-bit jump table with UINT64_MAX as one of the values. | 292 ; Test for correct 64-bit jump table with UINT64_MAX as one of the values. |
199 define internal i32 @testJumpTable64(i64 %a) { | 293 define internal i32 @testJumpTable64(i64 %a) { |
200 entry: | 294 entry: |
201 switch i64 %a, label %sw.default [ | 295 switch i64 %a, label %sw.default [ |
202 i64 -6, label %return | 296 i64 -6, label %return |
203 i64 -4, label %sw.bb1 | 297 i64 -4, label %sw.bb1 |
204 i64 -3, label %sw.bb2 | 298 i64 -3, label %sw.bb2 |
205 i64 -1, label %sw.bb3 | 299 i64 -1, label %sw.bb3 |
206 ] | 300 ] |
207 | 301 |
(...skipping 10 matching lines...) Expand all Loading... |
218 br label %return | 312 br label %return |
219 | 313 |
220 return: | 314 return: |
221 %retval.0 = phi i32 [ 5, %sw.default ], [ 4, %sw.bb3 ], [ 3, %sw.bb2 ], [ 2, %
sw.bb1 ], [ 1, %entry ] | 315 %retval.0 = phi i32 [ 5, %sw.default ], [ 4, %sw.bb3 ], [ 3, %sw.bb2 ], [ 2, %
sw.bb1 ], [ 1, %entry ] |
222 ret i32 %retval.0 | 316 ret i32 %retval.0 |
223 } | 317 } |
224 | 318 |
225 ; TODO(ascull): this should generate a jump table. For now, just make sure it | 319 ; TODO(ascull): this should generate a jump table. For now, just make sure it |
226 ; doesn't crash the compiler. | 320 ; doesn't crash the compiler. |
227 ; CHECK-LABEL: testJumpTable64 | 321 ; CHECK-LABEL: testJumpTable64 |
OLD | NEW |