1 # RUN: llc -run-pass x86-flags-copy-lowering -verify-machineinstrs -o - %s | FileCheck %s
3 # Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.
6 target triple = "x86_64-unknown-unknown"
10 define i32 @test_branch(i64 %a, i64 %b) {
16 define i32 @test_branch_fallthrough(i64 %a, i64 %b) {
22 define void @test_setcc(i64 %a, i64 %b) {
28 define void @test_cmov(i64 %a, i64 %b) {
34 define void @test_adc(i64 %a, i64 %b) {
40 define void @test_sbb(i64 %a, i64 %b) {
46 define void @test_rcl(i64 %a, i64 %b) {
52 define void @test_rcr(i64 %a, i64 %b) {
58 define void @test_setb_c(i64 %a, i64 %b) {
64 define i64 @test_branch_with_livein_and_kill(i64 %a, i64 %b) {
70 define i64 @test_branch_with_interleaved_livein_and_kill(i64 %a, i64 %b) {
76 define i64 @test_mid_cycle_copies(i64 %a, i64 %b) {
82 define i32 @test_existing_setcc(i64 %a, i64 %b) {
88 define i32 @test_existing_setcc_memory(i64 %a, i64 %b) {
96 # CHECK-LABEL: name: test_branch
98 - { reg: '$rdi', virtual-reg: '%0' }
99 - { reg: '$rsi', virtual-reg: '%1' }
102 successors: %bb.1, %bb.2, %bb.3
107 CMP64rr %0, %1, implicit-def $eflags
108 %2:gr64 = COPY $eflags
109 ; CHECK-NOT: COPY{{( killed)?}} $eflags
110 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
111 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
112 ; CHECK-NOT: COPY{{( killed)?}} $eflags
114 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
115 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
116 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
119 JCC_1 %bb.1, 7, implicit $eflags
120 JCC_1 %bb.2, 2, implicit $eflags
122 ; CHECK-NOT: $eflags =
124 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
125 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags
126 ; CHECK-SAME: {{$[[:space:]]}}
128 ; CHECK-NEXT: successors: {{.*$}}
129 ; CHECK-SAME: {{$[[:space:]]}}
130 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
131 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags
132 ; CHECK-NEXT: JMP_1 %bb.3
145 %5:gr32 = MOV32r0 implicit-def dead $eflags
151 name: test_branch_fallthrough
152 # CHECK-LABEL: name: test_branch_fallthrough
154 - { reg: '$rdi', virtual-reg: '%0' }
155 - { reg: '$rsi', virtual-reg: '%1' }
158 successors: %bb.1, %bb.2, %bb.3
163 CMP64rr %0, %1, implicit-def $eflags
164 %2:gr64 = COPY $eflags
165 ; CHECK-NOT: COPY{{( killed)?}} $eflags
166 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
167 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
168 ; CHECK-NOT: COPY{{( killed)?}} $eflags
170 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
171 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
172 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
175 JCC_1 %bb.2, 7, implicit $eflags
176 JCC_1 %bb.3, 2, implicit $eflags
177 ; CHECK-NOT: $eflags =
179 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
180 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags
181 ; CHECK-SAME: {{$[[:space:]]}}
183 ; CHECK-NEXT: successors: {{.*$}}
184 ; CHECK-SAME: {{$[[:space:]]}}
185 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
186 ; CHECK-NEXT: JCC_1 %bb.3, 5, implicit killed $eflags
187 ; CHECK-SAME: {{$[[:space:]]}}
191 %5:gr32 = MOV32r0 implicit-def dead $eflags
208 # CHECK-LABEL: name: test_setcc
210 - { reg: '$rdi', virtual-reg: '%0' }
211 - { reg: '$rsi', virtual-reg: '%1' }
218 CMP64rr %0, %1, implicit-def $eflags
219 %2:gr64 = COPY $eflags
220 ; CHECK-NOT: COPY{{( killed)?}} $eflags
221 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
222 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
223 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
224 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags
225 ; CHECK-NOT: COPY{{( killed)?}} $eflags
227 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
228 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
229 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
232 %3:gr8 = SETCCr 7, implicit $eflags
233 %4:gr8 = SETCCr 2, implicit $eflags
234 %5:gr8 = SETCCr 4, implicit $eflags
235 SETCCm $rsp, 1, $noreg, -16, $noreg, 5, implicit killed $eflags
236 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %3
237 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %4
238 MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %5
239 ; CHECK-NOT: $eflags =
240 ; CHECK-NOT: = SET{{.*}}
241 ; CHECK: MOV8mr {{.*}}, %[[A_REG]]
242 ; CHECK-NEXT: MOV8mr {{.*}}, %[[B_REG]]
243 ; CHECK-NEXT: MOV8mr {{.*}}, %[[E_REG]]
244 ; CHECK-NOT: MOV8mr {{.*}}, %[[NE_REG]]
251 # CHECK-LABEL: name: test_cmov
253 - { reg: '$rdi', virtual-reg: '%0' }
254 - { reg: '$rsi', virtual-reg: '%1' }
261 CMP64rr %0, %1, implicit-def $eflags
262 %2:gr64 = COPY $eflags
263 ; CHECK-NOT: COPY{{( killed)?}} $eflags
264 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
265 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
266 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
267 ; CHECK-NOT: COPY{{( killed)?}} $eflags
269 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
270 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
271 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
274 %3:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
275 %4:gr64 = CMOV64rr %0, %1, 2, implicit $eflags
276 %5:gr64 = CMOV64rr %0, %1, 4, implicit $eflags
277 %6:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
278 ; CHECK-NOT: $eflags =
279 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
280 ; CHECK-NEXT: %3:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
281 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
282 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
283 ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
284 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
285 ; CHECK-NEXT: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
286 ; CHECK-NEXT: %6:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
287 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3
288 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4
289 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
290 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6
297 # CHECK-LABEL: name: test_adc
299 - { reg: '$rdi', virtual-reg: '%0' }
300 - { reg: '$rsi', virtual-reg: '%1' }
307 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
308 %3:gr64 = COPY $eflags
309 ; CHECK-NOT: COPY{{( killed)?}} $eflags
310 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
311 ; CHECK-NOT: COPY{{( killed)?}} $eflags
313 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
314 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
315 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
318 %4:gr64 = ADC64ri32 %2:gr64, 42, implicit-def $eflags, implicit $eflags
319 %5:gr64 = ADC64ri32 %4:gr64, 42, implicit-def $eflags, implicit $eflags
320 ; CHECK-NOT: $eflags =
321 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
322 ; CHECK-NEXT: %4:gr64 = ADC64ri32 %2, 42, implicit-def $eflags, implicit killed $eflags
323 ; CHECK-NEXT: %5:gr64 = ADC64ri32 %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
324 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
331 # CHECK-LABEL: name: test_sbb
333 - { reg: '$rdi', virtual-reg: '%0' }
334 - { reg: '$rsi', virtual-reg: '%1' }
341 %2:gr64 = SUB64rr %0, %1, implicit-def $eflags
342 %3:gr64 = COPY killed $eflags
343 ; CHECK-NOT: COPY{{( killed)?}} $eflags
344 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
345 ; CHECK-NOT: COPY{{( killed)?}} $eflags
347 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
348 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
349 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
352 %4:gr64 = SBB64ri32 %2:gr64, 42, implicit-def $eflags, implicit killed $eflags
353 %5:gr64 = SBB64ri32 %4:gr64, 42, implicit-def dead $eflags, implicit killed $eflags
354 ; CHECK-NOT: $eflags =
355 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
356 ; CHECK-NEXT: %4:gr64 = SBB64ri32 %2, 42, implicit-def $eflags, implicit killed $eflags
357 ; CHECK-NEXT: %5:gr64 = SBB64ri32 %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
358 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
365 # CHECK-LABEL: name: test_rcl
367 - { reg: '$rdi', virtual-reg: '%0' }
368 - { reg: '$rsi', virtual-reg: '%1' }
375 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
376 %3:gr64 = COPY $eflags
377 ; CHECK-NOT: COPY{{( killed)?}} $eflags
378 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
379 ; CHECK-NOT: COPY{{( killed)?}} $eflags
381 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
382 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
383 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
386 %4:gr64 = RCL64r1 %2:gr64, implicit-def $eflags, implicit $eflags
387 %5:gr64 = RCL64r1 %4:gr64, implicit-def $eflags, implicit $eflags
388 ; CHECK-NOT: $eflags =
389 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
390 ; CHECK-NEXT: %4:gr64 = RCL64r1 %2, implicit-def $eflags, implicit killed $eflags
391 ; CHECK-NEXT: %5:gr64 = RCL64r1 %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
392 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
399 # CHECK-LABEL: name: test_rcr
401 - { reg: '$rdi', virtual-reg: '%0' }
402 - { reg: '$rsi', virtual-reg: '%1' }
409 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
410 %3:gr64 = COPY $eflags
411 ; CHECK-NOT: COPY{{( killed)?}} $eflags
412 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
413 ; CHECK-NOT: COPY{{( killed)?}} $eflags
415 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
416 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
417 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
420 %4:gr64 = RCR64r1 %2:gr64, implicit-def $eflags, implicit $eflags
421 %5:gr64 = RCR64r1 %4:gr64, implicit-def $eflags, implicit $eflags
422 ; CHECK-NOT: $eflags =
423 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
424 ; CHECK-NEXT: %4:gr64 = RCR64r1 %2, implicit-def $eflags, implicit killed $eflags
425 ; CHECK-NEXT: %5:gr64 = RCR64r1 %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
426 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
433 # CHECK-LABEL: name: test_setb_c
435 - { reg: '$rdi', virtual-reg: '%0' }
436 - { reg: '$rsi', virtual-reg: '%1' }
443 %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
444 %3:gr64 = COPY $eflags
445 ; CHECK-NOT: COPY{{( killed)?}} $eflags
446 ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
447 ; CHECK-NOT: COPY{{( killed)?}} $eflags
449 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
450 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
451 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
454 %4:gr32 = SETB_C32r implicit-def $eflags, implicit $eflags
455 MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %4
456 ; CHECK-NOT: $eflags =
457 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
458 ; CHECK-NEXT: %[[SETB:[^:]*]]:gr32 = SETB_C32r implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
459 ; CHECK-NEXT: MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %[[SETB]]
462 %5:gr64 = SETB_C64r implicit-def $eflags, implicit $eflags
463 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
464 ; CHECK-NOT: $eflags =
465 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
466 ; CHECK-NEXT: %[[SETB:[^:]*]]:gr64 = SETB_C64r implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
467 ; CHECK-NEXT: MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %[[SETB]]
473 name: test_branch_with_livein_and_kill
474 # CHECK-LABEL: name: test_branch_with_livein_and_kill
476 - { reg: '$rdi', virtual-reg: '%0' }
477 - { reg: '$rsi', virtual-reg: '%1' }
480 successors: %bb.1, %bb.2, %bb.3
485 CMP64rr %0, %1, implicit-def $eflags
486 %2:gr64 = COPY $eflags
487 ; CHECK-NOT: COPY{{( killed)?}} $eflags
488 ; CHECK: %[[S_REG:[^:]*]]:gr8 = SETCCr 8, implicit $eflags
489 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags
490 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
491 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
492 ; CHECK-NOT: COPY{{( killed)?}} $eflags
494 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
495 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
496 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
499 JCC_1 %bb.1, 7, implicit $eflags
500 JCC_1 %bb.2, 2, implicit $eflags
502 ; CHECK-NOT: $eflags =
504 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
505 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags
506 ; CHECK-SAME: {{$[[:space:]]}}
508 ; CHECK-NEXT: successors: {{.*$}}
509 ; CHECK-SAME: {{$[[:space:]]}}
510 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
511 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags
512 ; CHECK-NEXT: JMP_1 %bb.3
517 %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
518 ; CHECK-NOT: $eflags =
519 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
520 ; CHECK-NEXT: %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
527 %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
528 ; CHECK-NOT: $eflags =
529 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
530 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
537 %5:gr64 = CMOV64rr %0, %1, 8, implicit killed $eflags
538 ; CHECK-NOT: $eflags =
539 ; CHECK: TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags
540 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
546 name: test_branch_with_interleaved_livein_and_kill
547 # CHECK-LABEL: name: test_branch_with_interleaved_livein_and_kill
549 - { reg: '$rdi', virtual-reg: '%0' }
550 - { reg: '$rsi', virtual-reg: '%1' }
553 successors: %bb.1, %bb.2, %bb.5
558 CMP64rr %0, %1, implicit-def $eflags
559 %2:gr64 = COPY $eflags
560 ; CHECK-NOT: COPY{{( killed)?}} $eflags
561 ; CHECK: %[[S_REG:[^:]*]]:gr8 = SETCCr 8, implicit $eflags
562 ; CHECK-NEXT: %[[P_REG:[^:]*]]:gr8 = SETCCr 10, implicit $eflags
563 ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags
564 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
565 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
566 ; CHECK-NEXT: %[[O_REG:[^:]*]]:gr8 = SETCCr 0, implicit $eflags
567 ; CHECK-NOT: COPY{{( killed)?}} $eflags
569 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
570 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
571 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
574 JCC_1 %bb.1, 7, implicit $eflags
575 JCC_1 %bb.2, 2, implicit $eflags
577 ; CHECK-NOT: $eflags =
579 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
580 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags
581 ; CHECK-SAME: {{$[[:space:]]}}
583 ; CHECK-NEXT: successors: {{.*$}}
584 ; CHECK-SAME: {{$[[:space:]]}}
585 ; CHECK-NEXT: TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
586 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags
587 ; CHECK-NEXT: JMP_1 %bb.5
592 %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
593 ; CHECK-NOT: $eflags =
594 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
595 ; CHECK-NEXT: %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
600 ; The goal is to have another batch of successors discovered in a block
601 ; between two successors which kill $eflags. This ensures that neither of
602 ; the surrounding kills impact recursing through this block.
603 successors: %bb.3, %bb.4
606 JCC_1 %bb.3, 0, implicit $eflags
608 ; CHECK-NOT: $eflags =
610 ; CHECK: TEST8rr %[[O_REG]], %[[O_REG]], implicit-def $eflags
611 ; CHECK-NEXT: JCC_1 %bb.3, 5, implicit killed $eflags
612 ; CHECK-NEXT: JMP_1 %bb.4
617 %4:gr64 = CMOV64rr %0, %1, 5, implicit $eflags
618 ; CHECK-NOT: $eflags =
619 ; CHECK: TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
620 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
627 %5:gr64 = CMOV64rr %0, %1, 10, implicit $eflags
628 ; CHECK-NOT: $eflags =
629 ; CHECK: TEST8rr %[[P_REG]], %[[P_REG]], implicit-def $eflags
630 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
637 %6:gr64 = CMOV64rr %0, %1, 8, implicit killed $eflags
638 ; CHECK-NOT: $eflags =
639 ; CHECK: TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags
640 ; CHECK-NEXT: %6:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
646 # This test case is designed to exercise a particularly challenging situation:
647 # when the flags are copied and restored *inside* of a complex and cyclic CFG
648 # all of which have live-in flags. To correctly handle this case we have to walk
649 # up the dominator tree and locate a viable reaching definition location,
650 # checking for clobbers along any path. The CFG for this function looks like the
651 # following diagram, control flowing out the bottom of blocks and in the top:
654 # | __________________
667 # | ________/ \____/ |
670 # |\__________________/
674 # We set EFLAGS in bb.0, clobber them in bb.3, and copy them in bb.2 and bb.6.
675 # Because of the cycles this requires hoisting the `SETcc` instructions to
676 # capture the flags for the bb.6 copy to bb.1 and using them for the copy in
677 # `bb.2` as well despite the clobber in `bb.3`. The clobber in `bb.3` also
678 # prevents hoisting the `SETcc`s up to `bb.0`.
680 # Throughout the test we use branch instructions that are totally bogus (as the
681 # flags are obviously not changing!) but this is just to allow us to send
682 # a small but complex CFG structure through the backend and force it to choose
683 # plausible lowering decisions based on the core CFG presented, regardless of
684 # the futility of the actual branches.
685 name: test_mid_cycle_copies
686 # CHECK-LABEL: name: test_mid_cycle_copies
688 - { reg: '$rdi', virtual-reg: '%0' }
689 - { reg: '$rsi', virtual-reg: '%1' }
697 CMP64rr %0, %1, implicit-def $eflags
699 ; CHECK-NOT: COPY{{( killed)?}} $eflags
700 ; CHECK: CMP64rr %0, %1, implicit-def $eflags
701 ; CHECK-NOT: COPY{{( killed)?}} $eflags
705 successors: %bb.2, %bb.4
708 ; Outer loop header, target for one set of hoisting.
709 JCC_1 %bb.2, 4, implicit $eflags
712 ; CHECK-NOT: COPY{{( killed)?}} $eflags
713 ; CHECK: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
714 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
715 ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
716 ; CHECK-NOT: COPY{{( killed)?}} $eflags
719 successors: %bb.2, %bb.3
722 ; Inner loop with a local copy. We should eliminate this but can't hoist.
723 %2:gr64 = COPY $eflags
725 JCC_1 %bb.2, 4, implicit $eflags
728 ; CHECK-NOT: COPY{{( killed)?}} $eflags
729 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
730 ; CHECK-NEXT: JCC_1 %bb.2, 5, implicit killed $eflags
731 ; CHECK-NOT: COPY{{( killed)?}} $eflags
737 ; Use and then clobber $eflags. Then hop to the outer loop latch.
738 %3:gr64 = ADC64ri32 %0, 42, implicit-def dead $eflags, implicit $eflags
740 ; CHECK-NOT: COPY{{( killed)?}} $eflags
741 ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri %[[B_REG]], 255, implicit-def $eflags
742 ; CHECK-NEXT: %3:gr64 = ADC64ri32 %0, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
743 ; CHECK-NOT: COPY{{( killed)?}} $eflags
744 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3
748 successors: %bb.5, %bb.6
751 ; Another inner loop, this one with a diamond.
752 JCC_1 %bb.5, 4, implicit $eflags
755 ; CHECK-NOT: COPY{{( killed)?}} $eflags
756 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
757 ; CHECK-NEXT: JCC_1 %bb.5, 5, implicit killed $eflags
758 ; CHECK-NOT: COPY{{( killed)?}} $eflags
764 ; Just use $eflags on this side of the diamond.
765 %4:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
767 ; CHECK-NOT: COPY{{( killed)?}} $eflags
768 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
769 ; CHECK-NEXT: %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
770 ; CHECK-NOT: COPY{{( killed)?}} $eflags
771 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4
778 ; Use, copy, and then use $eflags again.
779 %5:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
781 ; CHECK-NOT: COPY{{( killed)?}} $eflags
782 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
783 ; CHECK-NEXT: %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
784 ; CHECK-NOT: COPY{{( killed)?}} $eflags
785 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
787 %6:gr64 = COPY $eflags
788 $eflags = COPY %6:gr64
790 %7:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
791 ; CHECK-NOT: COPY{{( killed)?}} $eflags
792 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
793 ; CHECK-NEXT: %7:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
794 ; CHECK-NOT: COPY{{( killed)?}} $eflags
795 MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %7
799 successors: %bb.4, %bb.8
803 JCC_1 %bb.4, 4, implicit $eflags
806 ; CHECK-NOT: COPY{{( killed)?}} $eflags
807 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
808 ; CHECK-NEXT: JCC_1 %bb.4, 5, implicit killed $eflags
809 ; CHECK-NOT: COPY{{( killed)?}} $eflags
812 successors: %bb.1, %bb.9
814 ; Outer loop latch. Note that we cannot have EFLAGS live-in here as that
815 ; immediately require PHIs.
816 CMP64rr %0, %1, implicit-def $eflags
817 JCC_1 %bb.1, 4, implicit $eflags
820 ; CHECK-NOT: COPY{{( killed)?}} $eflags
821 ; CHECK: CMP64rr %0, %1, implicit-def $eflags
822 ; CHECK-NEXT: JCC_1 %bb.1, 4, implicit $eflags
823 ; CHECK-NOT: COPY{{( killed)?}} $eflags
829 %8:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
833 ; CHECK-NEXT: liveins: $eflags
835 ; CHECK: %8:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
839 name: test_existing_setcc
840 # CHECK-LABEL: name: test_existing_setcc
842 - { reg: '$rdi', virtual-reg: '%0' }
843 - { reg: '$rsi', virtual-reg: '%1' }
846 successors: %bb.1, %bb.2, %bb.3
851 CMP64rr %0, %1, implicit-def $eflags
852 %2:gr8 = SETCCr 7, implicit $eflags
853 %3:gr8 = SETCCr 3, implicit $eflags
854 %4:gr64 = COPY $eflags
855 ; CHECK: CMP64rr %0, %1, implicit-def $eflags
856 ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
857 ; CHECK-NEXT: %[[AE_REG:[^:]*]]:gr8 = SETCCr 3, implicit $eflags
858 ; CHECK-NOT: COPY{{( killed)?}} $eflags
860 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
861 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
862 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
865 JCC_1 %bb.1, 7, implicit $eflags
866 JCC_1 %bb.2, 2, implicit $eflags
868 ; CHECK-NOT: $eflags =
870 ; CHECK: TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
871 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags
872 ; CHECK-SAME: {{$[[:space:]]}}
874 ; CHECK-NEXT: successors: {{.*$}}
875 ; CHECK-SAME: {{$[[:space:]]}}
876 ; CHECK-NEXT: TEST8rr %[[AE_REG]], %[[AE_REG]], implicit-def $eflags
877 ; CHECK-NEXT: JCC_1 %bb.2, 4, implicit killed $eflags
878 ; CHECK-NEXT: JMP_1 %bb.3
891 %7:gr32 = MOV32r0 implicit-def dead $eflags
897 name: test_existing_setcc_memory
898 # CHECK-LABEL: name: test_existing_setcc_memory
900 - { reg: '$rdi', virtual-reg: '%0' }
901 - { reg: '$rsi', virtual-reg: '%1' }
904 successors: %bb.1, %bb.2
909 CMP64rr %0, %1, implicit-def $eflags
910 SETCCm %0, 1, $noreg, -16, $noreg, 4, implicit $eflags
911 %2:gr64 = COPY $eflags
912 ; CHECK: CMP64rr %0, %1, implicit-def $eflags
913 ; We cannot reuse this SETE because it stores the flag directly to memory,
914 ; so we have two SETEs here. FIXME: It'd be great if something could fold
915 ; these automatically. If not, maybe we want to unfold SETcc instructions
916 ; writing to memory so we can reuse them.
917 ; CHECK-NEXT: SETCCm {{.*}} 4, implicit $eflags
918 ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
919 ; CHECK-NOT: COPY{{( killed)?}} $eflags
921 ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
922 CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
923 ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
926 JCC_1 %bb.1, 4, implicit $eflags
928 ; CHECK-NOT: $eflags =
930 ; CHECK: TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
931 ; CHECK-NEXT: JCC_1 %bb.1, 5, implicit killed $eflags
932 ; CHECK-NEXT: JMP_1 %bb.2