| 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 |