Compiler projects using llvm
# RUN: llc -run-pass x86-flags-copy-lowering -verify-machineinstrs -o - %s | FileCheck %s
#
# Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.

--- |
  target triple = "x86_64-unknown-unknown"

  declare void @foo()

  define i32 @test_branch(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i32 0
  }

  define i32 @test_branch_fallthrough(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i32 0
  }

  define void @test_setcc(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_cmov(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_adc(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_sbb(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_adcx(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_adox(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_rcl(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_rcr(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define void @test_setb_c(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret void
  }

  define i64 @test_branch_with_livein_and_kill(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i64 0
  }

  define i64 @test_branch_with_interleaved_livein_and_kill(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i64 0
  }

  define i64 @test_mid_cycle_copies(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i64 0
  }

  define i32 @test_existing_setcc(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i32 0
  }

  define i32 @test_existing_setcc_memory(i64 %a, i64 %b) {
  entry:
    call void @foo()
    ret i32 0
  }
...
---
name:            test_branch
# CHECK-LABEL: name: test_branch
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1, %bb.2, %bb.3
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    JCC_1 %bb.1, 7, implicit $eflags
    JCC_1 %bb.2, 2, implicit $eflags
    JMP_1 %bb.3
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.1, 5, implicit killed $eflags
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT: bb.4:
  ; CHECK-NEXT:   successors: {{.*$}}
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT:   TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.2, 5, implicit killed $eflags
  ; CHECK-NEXT:   JMP_1 %bb.3

  bb.1:
    %3:gr32 = MOV32ri 42
    $eax = COPY %3
    RET 0, $eax

  bb.2:
    %4:gr32 = MOV32ri 43
    $eax = COPY %4
    RET 0, $eax

  bb.3:
    %5:gr32 = MOV32r0 implicit-def dead $eflags
    $eax = COPY %5
    RET 0, $eax

...
---
name:            test_branch_fallthrough
# CHECK-LABEL: name: test_branch_fallthrough
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1, %bb.2, %bb.3
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    JCC_1 %bb.2, 7, implicit $eflags
    JCC_1 %bb.3, 2, implicit $eflags
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.2, 5, implicit killed $eflags
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT: bb.4:
  ; CHECK-NEXT:   successors: {{.*$}}
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT:   TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.3, 5, implicit killed $eflags
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT:   bb.1:

  bb.1:
    %5:gr32 = MOV32r0 implicit-def dead $eflags
    $eax = COPY %5
    RET 0, $eax

  bb.2:
    %3:gr32 = MOV32ri 42
    $eax = COPY %3
    RET 0, $eax

  bb.3:
    %4:gr32 = MOV32ri 43
    $eax = COPY %4
    RET 0, $eax

...
---
name:            test_setcc
# CHECK-LABEL: name: test_setcc
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
  ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    %3:gr8 = SETCCr 7, implicit $eflags
    %4:gr8 = SETCCr 2, implicit $eflags
    %5:gr8 = SETCCr 4, implicit $eflags
    SETCCm $rsp, 1, $noreg, -16, $noreg, 5, implicit killed $eflags
    MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %3
    MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %4
    MOV8mr $rsp, 1, $noreg, -16, $noreg, killed %5
  ; CHECK-NOT:     $eflags =
  ; CHECK-NOT:             = SET{{.*}}
  ; CHECK:         MOV8mr {{.*}}, %[[A_REG]]
  ; CHECK-NEXT:    MOV8mr {{.*}}, %[[B_REG]]
  ; CHECK-NEXT:    MOV8mr {{.*}}, %[[E_REG]]
  ; CHECK-NOT:     MOV8mr {{.*}}, %[[NE_REG]]

    RET 0

...
---
name:            test_cmov
# CHECK-LABEL: name: test_cmov
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    %3:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
    %4:gr64 = CMOV64rr %0, %1, 2, implicit $eflags
    %5:gr64 = CMOV64rr %0, %1, 4, implicit $eflags
    %6:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %3:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NEXT:    TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NEXT:    TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NEXT:    TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %6:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6

    RET 0

...
---
name:            test_adc
# CHECK-LABEL: name: test_adc
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr64 = ADC64ri32 %2:gr64, 42, implicit-def $eflags, implicit $eflags
    %5:gr64 = ADC64ri32 %4:gr64, 42, implicit-def $eflags, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = ADC64ri32 %2, 42, implicit-def $eflags, implicit killed $eflags
  ; CHECK-NEXT:    %5:gr64 = ADC64ri32 %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5

    RET 0

...
---
name:            test_sbb
# CHECK-LABEL: name: test_sbb
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = SUB64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY killed $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr64 = SBB64ri32 %2:gr64, 42, implicit-def $eflags, implicit killed $eflags
    %5:gr64 = SBB64ri32 %4:gr64, 42, implicit-def dead $eflags, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = SBB64ri32 %2, 42, implicit-def $eflags, implicit killed $eflags
  ; CHECK-NEXT:    %5:gr64 = SBB64ri32 %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5

    RET 0

...
---
name:            test_adcx
# CHECK-LABEL: name: test_adcx
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
  ; CHECK-NEXT:   %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr64 = CMOV64rr %0, %1, 4, implicit $eflags
    %5:gr64 = MOV64ri32 42
    %6:gr64 = ADCX64rr %2, %5, implicit-def $eflags, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NEXT:    %5:gr64 = MOV64ri32 42
  ; CHECK-NEXT:    dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %6:gr64 = ADCX64rr %2, %5, implicit-def{{( dead)?}} $eflags, implicit killed $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6

    RET 0

...
---
name:            test_adox
# CHECK-LABEL: name: test_adox
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
  ; CHECK-NEXT:   %[[OF_REG:[^:]*]]:gr8 = SETCCr 0, implicit $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr64 = CMOV64rr %0, %1, 4, implicit $eflags
    %5:gr64 = MOV64ri32 42
    %6:gr64 = ADOX64rr %2, %5, implicit-def $eflags, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NEXT:    %5:gr64 = MOV64ri32 42
  ; CHECK-NEXT:    dead %{{[^:]*}}:gr8 = ADD8ri %[[OF_REG]], 127, implicit-def $eflags
  ; CHECK-NEXT:    %6:gr64 = ADOX64rr %2, %5, implicit-def{{( dead)?}} $eflags, implicit killed $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %6

    RET 0

...
---
name:            test_rcl
# CHECK-LABEL: name: test_rcl
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr64 = RCL64r1 %2:gr64, implicit-def $eflags, implicit $eflags
    %5:gr64 = RCL64r1 %4:gr64, implicit-def $eflags, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = RCL64r1 %2, implicit-def $eflags, implicit killed $eflags
  ; CHECK-NEXT:    %5:gr64 = RCL64r1 %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5

    RET 0

...
---
name:            test_rcr
# CHECK-LABEL: name: test_rcr
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr64 = RCR64r1 %2:gr64, implicit-def $eflags, implicit $eflags
    %5:gr64 = RCR64r1 %4:gr64, implicit-def $eflags, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = RCR64r1 %2, implicit-def $eflags, implicit killed $eflags
  ; CHECK-NEXT:    %5:gr64 = RCR64r1 %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5

    RET 0

...
---
name:            test_setb_c
# CHECK-LABEL: name: test_setb_c
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    %2:gr64 = ADD64rr %0, %1, implicit-def $eflags
    %3:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %3
    %4:gr32 = SETB_C32r implicit-def $eflags, implicit $eflags
    MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %4
  ; CHECK-NOT:     $eflags =
  ; CHECK:         dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %[[SETB:[^:]*]]:gr32 = SETB_C32r implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
  ; CHECK-NEXT:    MOV32mr $rsp, 1, $noreg, -16, $noreg, killed %[[SETB]]

    $eflags = COPY %3
    %5:gr64 = SETB_C64r implicit-def $eflags, implicit $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
  ; CHECK-NOT:     $eflags =
  ; CHECK:         dead %{{[^:]*}}:gr8 = ADD8ri %[[CF_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:    %[[SETB:[^:]*]]:gr64 = SETB_C64r implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
  ; CHECK-NEXT:    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %[[SETB]]

    RET 0

...
---
name:            test_branch_with_livein_and_kill
# CHECK-LABEL: name: test_branch_with_livein_and_kill
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1, %bb.2, %bb.3
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[S_REG:[^:]*]]:gr8 = SETCCr 8, implicit $eflags
  ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags
  ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    JCC_1 %bb.1, 7, implicit $eflags
    JCC_1 %bb.2, 2, implicit $eflags
    JMP_1 %bb.3
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.1, 5, implicit killed $eflags
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT: bb.4:
  ; CHECK-NEXT:   successors: {{.*$}}
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT:   TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.2, 5, implicit killed $eflags
  ; CHECK-NEXT:   JMP_1 %bb.3

  bb.1:
    liveins: $eflags

    %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
    $rax = COPY %3
    RET 0, $rax

  bb.2:
    liveins: $eflags

    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
    $rax = COPY %4
    RET 0, $rax

  bb.3:
    liveins: $eflags

    %5:gr64 = CMOV64rr %0, %1, 8, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
    $rax = COPY %5
    RET 0, $rax

...
---
name:            test_branch_with_interleaved_livein_and_kill
# CHECK-LABEL: name: test_branch_with_interleaved_livein_and_kill
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1, %bb.2, %bb.5
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr64 = COPY $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags
  ; CHECK:      %[[S_REG:[^:]*]]:gr8 = SETCCr 8, implicit $eflags
  ; CHECK-NEXT: %[[P_REG:[^:]*]]:gr8 = SETCCr 10, implicit $eflags
  ; CHECK-NEXT: %[[NE_REG:[^:]*]]:gr8 = SETCCr 5, implicit $eflags
  ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NEXT: %[[O_REG:[^:]*]]:gr8 = SETCCr 0, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    JCC_1 %bb.1, 7, implicit $eflags
    JCC_1 %bb.2, 2, implicit $eflags
    JMP_1 %bb.5
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.1, 5, implicit killed $eflags
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT: bb.6:
  ; CHECK-NEXT:   successors: {{.*$}}
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT:   TEST8rr %[[B_REG]], %[[B_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.2, 5, implicit killed $eflags
  ; CHECK-NEXT:   JMP_1 %bb.5

  bb.1:
    liveins: $eflags

    %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %3:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
    $rax = COPY %3
    RET 0, $rax

  bb.2:
    ; The goal is to have another batch of successors discovered in a block
    ; between two successors which kill $eflags. This ensures that neither of
    ; the surrounding kills impact recursing through this block.
    successors: %bb.3, %bb.4
    liveins: $eflags

    JCC_1 %bb.3, 0, implicit $eflags
    JMP_1 %bb.4
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[O_REG]], %[[O_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.3, 5, implicit killed $eflags
  ; CHECK-NEXT:   JMP_1 %bb.4

  bb.3:
    liveins: $eflags

    %4:gr64 = CMOV64rr %0, %1, 5, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[NE_REG]], %[[NE_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
    $rax = COPY %4
    RET 0, $rax

  bb.4:
    liveins: $eflags

    %5:gr64 = CMOV64rr %0, %1, 10, implicit $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[P_REG]], %[[P_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
    $rax = COPY %5
    RET 0, $rax

  bb.5:
    liveins: $eflags

    %6:gr64 = CMOV64rr %0, %1, 8, implicit killed $eflags
  ; CHECK-NOT:     $eflags =
  ; CHECK:         TEST8rr %[[S_REG]], %[[S_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %6:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
    $rax = COPY %6
    RET 0, $rax

...
---
# This test case is designed to exercise a particularly challenging situation:
# when the flags are copied and restored *inside* of a complex and cyclic CFG
# all of which have live-in flags. To correctly handle this case we have to walk
# up the dominator tree and locate a viable reaching definition location,
# checking for clobbers along any path. The CFG for this function looks like the
# following diagram, control flowing out the bottom of blocks and in the top:
#
#  bb.0
#   | __________________
#   |/                  \
#  bb.1                  |
#   |\_________          |
#   | __       \ ____    |
#   |/  \      |/    \   |
#  bb.2  |    bb.4    |  |
#   |\__/     / \     |  |
#   |        /   \    |  |
#  bb.3    bb.5  bb.6 |  |
#   |        \   /    |  |
#   |         \ /     |  |
#   |         bb.7    |  |
#   | ________/ \____/   |
#   |/                   |
#  bb.8                  |
#   |\__________________/
#   |
#  bb.9
#
# We set EFLAGS in bb.0, clobber them in bb.3, and copy them in bb.2 and bb.6.
# Because of the cycles this requires hoisting the `SETcc` instructions to
# capture the flags for the bb.6 copy to bb.1 and using them for the copy in
# `bb.2` as well despite the clobber in `bb.3`. The clobber in `bb.3` also
# prevents hoisting the `SETcc`s up to `bb.0`.
#
# Throughout the test we use branch instructions that are totally bogus (as the
# flags are obviously not changing!) but this is just to allow us to send
# a small but complex CFG structure through the backend and force it to choose
# plausible lowering decisions based on the core CFG presented, regardless of
# the futility of the actual branches.
name:            test_mid_cycle_copies
# CHECK-LABEL: name: test_mid_cycle_copies
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
  ; CHECK:      bb.0:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        CMP64rr %0, %1, implicit-def $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
    JMP_1 %bb.1

  bb.1:
    successors: %bb.2, %bb.4
    liveins: $eflags

    ; Outer loop header, target for one set of hoisting.
    JCC_1 %bb.2, 4, implicit $eflags
    JMP_1 %bb.4
  ; CHECK:      bb.1:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT:   %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
  ; CHECK-NEXT:   %[[B_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

  bb.2:
    successors: %bb.2, %bb.3
    liveins: $eflags

    ; Inner loop with a local copy. We should eliminate this but can't hoist.
    %2:gr64 = COPY $eflags
    $eflags = COPY %2
    JCC_1 %bb.2, 4, implicit $eflags
    JMP_1 %bb.3
  ; CHECK:      bb.2:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.2, 5, implicit killed $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

  bb.3:
    successors: %bb.8
    liveins: $eflags

    ; Use and then clobber $eflags. Then hop to the outer loop latch.
    %3:gr64 = ADC64ri32 %0, 42, implicit-def dead $eflags, implicit $eflags
  ; CHECK:      bb.3:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        dead %{{[^:]*}}:gr8 = ADD8ri %[[B_REG]], 255, implicit-def $eflags
  ; CHECK-NEXT:   %3:gr64 = ADC64ri32 %0, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %3
    JMP_1 %bb.8

  bb.4:
    successors: %bb.5, %bb.6
    liveins: $eflags

    ; Another inner loop, this one with a diamond.
    JCC_1 %bb.5, 4, implicit $eflags
    JMP_1 %bb.6
  ; CHECK:      bb.4:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.5, 5, implicit killed $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

  bb.5:
    successors: %bb.7
    liveins: $eflags

    ; Just use $eflags on this side of the diamond.
    %4:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
  ; CHECK:      bb.5:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:         TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:    %4:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %4
    JMP_1 %bb.7

  bb.6:
    successors: %bb.7
    liveins: $eflags

    ; Use, copy, and then use $eflags again.
    %5:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
  ; CHECK:      bb.6:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   %5:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5

    %6:gr64 = COPY $eflags
    $eflags = COPY %6:gr64

    %7:gr64 = CMOV64rr %0, %1, 7, implicit $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   %7:gr64 = CMOV64rr %0, %1, 5, implicit killed $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
    MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %7
    JMP_1 %bb.7

  bb.7:
    successors: %bb.4, %bb.8
    liveins: $eflags

    ; Inner loop latch.
    JCC_1 %bb.4, 4, implicit $eflags
    JMP_1 %bb.8
  ; CHECK:      bb.7:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.4, 5, implicit killed $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

  bb.8:
    successors: %bb.1, %bb.9

    ; Outer loop latch. Note that we cannot have EFLAGS live-in here as that
    ; immediately require PHIs.
    CMP64rr %0, %1, implicit-def $eflags
    JCC_1 %bb.1, 4, implicit $eflags
    JMP_1 %bb.9
  ; CHECK:      bb.8:
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags
  ; CHECK:        CMP64rr %0, %1, implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.1, 4, implicit $eflags
  ; CHECK-NOT:    COPY{{( killed)?}} $eflags

  bb.9:
    liveins: $eflags

    ; And we're done.
    %8:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags
    $rax = COPY %8
    RET 0, $rax
  ; CHECK:      bb.9:
  ; CHECK-NEXT: liveins: $eflags
  ; CHECK-NOT:     $eflags
  ; CHECK:         %8:gr64 = CMOV64rr %0, %1, 4, implicit killed $eflags

...
---
name:            test_existing_setcc
# CHECK-LABEL: name: test_existing_setcc
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1, %bb.2, %bb.3
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    %2:gr8 = SETCCr 7, implicit $eflags
    %3:gr8 = SETCCr 3, implicit $eflags
    %4:gr64 = COPY $eflags
  ; CHECK:      CMP64rr %0, %1, implicit-def $eflags
  ; CHECK-NEXT: %[[A_REG:[^:]*]]:gr8 = SETCCr 7, implicit $eflags
  ; CHECK-NEXT: %[[AE_REG:[^:]*]]:gr8 = SETCCr 3, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %4
    JCC_1 %bb.1, 7, implicit $eflags
    JCC_1 %bb.2, 2, implicit $eflags
    JMP_1 %bb.3
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[A_REG]], %[[A_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.1, 5, implicit killed $eflags
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT: bb.4:
  ; CHECK-NEXT:   successors: {{.*$}}
  ; CHECK-SAME: {{$[[:space:]]}}
  ; CHECK-NEXT:   TEST8rr %[[AE_REG]], %[[AE_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.2, 4, implicit killed $eflags
  ; CHECK-NEXT:   JMP_1 %bb.3

  bb.1:
    %5:gr32 = MOV32ri 42
    $eax = COPY %5
    RET 0, $eax

  bb.2:
    %6:gr32 = MOV32ri 43
    $eax = COPY %6
    RET 0, $eax

  bb.3:
    %7:gr32 = MOV32r0 implicit-def dead $eflags
    $eax = COPY %7
    RET 0, $eax

...
---
name:            test_existing_setcc_memory
# CHECK-LABEL: name: test_existing_setcc_memory
liveins:
  - { reg: '$rdi', virtual-reg: '%0' }
  - { reg: '$rsi', virtual-reg: '%1' }
body:             |
  bb.0:
    successors: %bb.1, %bb.2
    liveins: $rdi, $rsi

    %0:gr64 = COPY $rdi
    %1:gr64 = COPY $rsi
    CMP64rr %0, %1, implicit-def $eflags
    SETCCm %0, 1, $noreg, -16, $noreg, 4, implicit $eflags
    %2:gr64 = COPY $eflags
  ; CHECK:      CMP64rr %0, %1, implicit-def $eflags
  ; We cannot reuse this SETE because it stores the flag directly to memory,
  ; so we have two SETEs here. FIXME: It'd be great if something could fold
  ; these automatically. If not, maybe we want to unfold SETcc instructions
  ; writing to memory so we can reuse them.
  ; CHECK-NEXT: SETCCm {{.*}} 4, implicit $eflags
  ; CHECK-NEXT: %[[E_REG:[^:]*]]:gr8 = SETCCr 4, implicit $eflags
  ; CHECK-NOT:  COPY{{( killed)?}} $eflags

    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp

    $eflags = COPY %2
    JCC_1 %bb.1, 4, implicit $eflags
    JMP_1 %bb.2
  ; CHECK-NOT: $eflags =
  ;
  ; CHECK:        TEST8rr %[[E_REG]], %[[E_REG]], implicit-def $eflags
  ; CHECK-NEXT:   JCC_1 %bb.1, 5, implicit killed $eflags
  ; CHECK-NEXT:   JMP_1 %bb.2

  bb.1:
    %3:gr32 = MOV32ri 42
    $eax = COPY %3
    RET 0, $eax

  bb.2:
    %4:gr32 = MOV32ri 43
    $eax = COPY %4
    RET 0, $eax

...