; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+push2pop2 | FileCheck %s --check-prefix=CHECK
; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+push2pop2,+ppx | FileCheck %s --check-prefix=PPX
; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+push2pop2 -frame-pointer=all | FileCheck %s --check-prefix=FRAME

define void @csr1() nounwind {
; CHECK-LABEL: csr1:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    pushq %rbp
; CHECK-NEXT:    #APP
; CHECK-NEXT:    #NO_APP
; CHECK-NEXT:    popq %rbp
; CHECK-NEXT:    retq
;
; PPX-LABEL: csr1:
; PPX:       # %bb.0: # %entry
; PPX-NEXT:    pushp %rbp
; PPX-NEXT:    #APP
; PPX-NEXT:    #NO_APP
; PPX-NEXT:    popp %rbp
; PPX-NEXT:    retq
;
; FRAME-LABEL: csr1:
; FRAME:       # %bb.0: # %entry
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    #APP
; FRAME-NEXT:    #NO_APP
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    retq
entry:
  tail call void asm sideeffect "", "~{rbp},~{dirflag},~{fpsr},~{flags}"()
  ret void
}

define void @csr2() nounwind {
; CHECK-LABEL: csr2:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    pushq %rbp
; CHECK-NEXT:    pushq %r15
; CHECK-NEXT:    #APP
; CHECK-NEXT:    #NO_APP
; CHECK-NEXT:    popq %r15
; CHECK-NEXT:    popq %rbp
; CHECK-NEXT:    retq
;
; PPX-LABEL: csr2:
; PPX:       # %bb.0: # %entry
; PPX-NEXT:    pushp %rbp
; PPX-NEXT:    pushp %r15
; PPX-NEXT:    #APP
; PPX-NEXT:    #NO_APP
; PPX-NEXT:    popp %r15
; PPX-NEXT:    popp %rbp
; PPX-NEXT:    retq
;
; FRAME-LABEL: csr2:
; FRAME:       # %bb.0: # %entry
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    pushq %r15
; FRAME-NEXT:    #APP
; FRAME-NEXT:    #NO_APP
; FRAME-NEXT:    popq %r15
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    retq
entry:
  tail call void asm sideeffect "", "~{rbp},~{r15},~{dirflag},~{fpsr},~{flags}"()
  ret void
}

define void @csr3() nounwind {
; CHECK-LABEL: csr3:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    pushq %rbp
; CHECK-NEXT:    push2 %r14, %r15
; CHECK-NEXT:    #APP
; CHECK-NEXT:    #NO_APP
; CHECK-NEXT:    pop2 %r15, %r14
; CHECK-NEXT:    popq %rbp
; CHECK-NEXT:    retq
;
; PPX-LABEL: csr3:
; PPX:       # %bb.0: # %entry
; PPX-NEXT:    pushp %rbp
; PPX-NEXT:    push2p %r14, %r15
; PPX-NEXT:    #APP
; PPX-NEXT:    #NO_APP
; PPX-NEXT:    pop2p %r15, %r14
; PPX-NEXT:    popp %rbp
; PPX-NEXT:    retq
;
; FRAME-LABEL: csr3:
; FRAME:       # %bb.0: # %entry
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    push2 %r14, %r15
; FRAME-NEXT:    #APP
; FRAME-NEXT:    #NO_APP
; FRAME-NEXT:    pop2 %r15, %r14
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    retq
entry:
  tail call void asm sideeffect "", "~{rbp},~{r15},~{r14},~{dirflag},~{fpsr},~{flags}"()
  ret void
}

define void @csr4() nounwind {
; CHECK-LABEL: csr4:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    pushq %rax
; CHECK-NEXT:    push2 %r15, %rbp
; CHECK-NEXT:    push2 %r13, %r14
; CHECK-NEXT:    #APP
; CHECK-NEXT:    #NO_APP
; CHECK-NEXT:    pop2 %r14, %r13
; CHECK-NEXT:    pop2 %rbp, %r15
; CHECK-NEXT:    popq %rax
; CHECK-NEXT:    retq
;
; PPX-LABEL: csr4:
; PPX:       # %bb.0: # %entry
; PPX-NEXT:    pushq %rax
; PPX-NEXT:    push2p %r15, %rbp
; PPX-NEXT:    push2p %r13, %r14
; PPX-NEXT:    #APP
; PPX-NEXT:    #NO_APP
; PPX-NEXT:    pop2p %r14, %r13
; PPX-NEXT:    pop2p %rbp, %r15
; PPX-NEXT:    popq %rax
; PPX-NEXT:    retq
;
; FRAME-LABEL: csr4:
; FRAME:       # %bb.0: # %entry
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    push2 %r14, %r15
; FRAME-NEXT:    pushq %r13
; FRAME-NEXT:    #APP
; FRAME-NEXT:    #NO_APP
; FRAME-NEXT:    popq %r13
; FRAME-NEXT:    pop2 %r15, %r14
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    retq
entry:
  tail call void asm sideeffect "", "~{rbp},~{r15},~{r14},~{r13},~{dirflag},~{fpsr},~{flags}"()
  ret void
}

define void @csr5() nounwind {
; CHECK-LABEL: csr5:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    pushq %rbp
; CHECK-NEXT:    push2 %r14, %r15
; CHECK-NEXT:    push2 %r12, %r13
; CHECK-NEXT:    #APP
; CHECK-NEXT:    #NO_APP
; CHECK-NEXT:    pop2 %r13, %r12
; CHECK-NEXT:    pop2 %r15, %r14
; CHECK-NEXT:    popq %rbp
; CHECK-NEXT:    retq
;
; PPX-LABEL: csr5:
; PPX:       # %bb.0: # %entry
; PPX-NEXT:    pushp %rbp
; PPX-NEXT:    push2p %r14, %r15
; PPX-NEXT:    push2p %r12, %r13
; PPX-NEXT:    #APP
; PPX-NEXT:    #NO_APP
; PPX-NEXT:    pop2p %r13, %r12
; PPX-NEXT:    pop2p %r15, %r14
; PPX-NEXT:    popp %rbp
; PPX-NEXT:    retq
;
; FRAME-LABEL: csr5:
; FRAME:       # %bb.0: # %entry
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    push2 %r14, %r15
; FRAME-NEXT:    push2 %r12, %r13
; FRAME-NEXT:    #APP
; FRAME-NEXT:    #NO_APP
; FRAME-NEXT:    pop2 %r13, %r12
; FRAME-NEXT:    pop2 %r15, %r14
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    retq
entry:
  tail call void asm sideeffect "", "~{rbp},~{r15},~{r14},~{r13},~{r12},~{dirflag},~{fpsr},~{flags}"()
  ret void
}

define void @csr6() nounwind {
; CHECK-LABEL: csr6:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    pushq %rax
; CHECK-NEXT:    push2 %r15, %rbp
; CHECK-NEXT:    push2 %r13, %r14
; CHECK-NEXT:    push2 %rbx, %r12
; CHECK-NEXT:    #APP
; CHECK-NEXT:    #NO_APP
; CHECK-NEXT:    pop2 %r12, %rbx
; CHECK-NEXT:    pop2 %r14, %r13
; CHECK-NEXT:    pop2 %rbp, %r15
; CHECK-NEXT:    popq %rax
; CHECK-NEXT:    retq
;
; PPX-LABEL: csr6:
; PPX:       # %bb.0: # %entry
; PPX-NEXT:    pushq %rax
; PPX-NEXT:    push2p %r15, %rbp
; PPX-NEXT:    push2p %r13, %r14
; PPX-NEXT:    push2p %rbx, %r12
; PPX-NEXT:    #APP
; PPX-NEXT:    #NO_APP
; PPX-NEXT:    pop2p %r12, %rbx
; PPX-NEXT:    pop2p %r14, %r13
; PPX-NEXT:    pop2p %rbp, %r15
; PPX-NEXT:    popq %rax
; PPX-NEXT:    retq
;
; FRAME-LABEL: csr6:
; FRAME:       # %bb.0: # %entry
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    push2 %r14, %r15
; FRAME-NEXT:    push2 %r12, %r13
; FRAME-NEXT:    pushq %rbx
; FRAME-NEXT:    #APP
; FRAME-NEXT:    #NO_APP
; FRAME-NEXT:    popq %rbx
; FRAME-NEXT:    pop2 %r13, %r12
; FRAME-NEXT:    pop2 %r15, %r14
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    retq
entry:
  tail call void asm sideeffect "", "~{rbp},~{r15},~{r14},~{r13},~{r12},~{rbx},~{dirflag},~{fpsr},~{flags}"()
  ret void
}

declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)

define void @lea_in_epilog(i1 %arg, ptr %arg1, ptr %arg2, i64 %arg3, i64 %arg4, i64 %arg5, i64 %arg6, i64 %arg7, i64 %arg8, i64 %arg9, i64 %arg10) nounwind {
; CHECK-LABEL: lea_in_epilog:
; CHECK:       # %bb.0: # %bb
; CHECK-NEXT:    testb $1, %dil
; CHECK-NEXT:    je .LBB6_5
; CHECK-NEXT:  # %bb.1: # %bb13
; CHECK-NEXT:    pushq %rax
; CHECK-NEXT:    push2 %r15, %rbp
; CHECK-NEXT:    push2 %r13, %r14
; CHECK-NEXT:    push2 %rbx, %r12
; CHECK-NEXT:    subq $16, %rsp
; CHECK-NEXT:    movq %r9, %r14
; CHECK-NEXT:    movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; CHECK-NEXT:    addq {{[0-9]+}}(%rsp), %r14
; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %r13
; CHECK-NEXT:    addq %r14, %r13
; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %r15
; CHECK-NEXT:    addq %r14, %r15
; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rbx
; CHECK-NEXT:    addq %r14, %rbx
; CHECK-NEXT:    xorl %ebp, %ebp
; CHECK-NEXT:    xorl %r12d, %r12d
; CHECK-NEXT:    movl %edi, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
; CHECK-NEXT:    .p2align 4, 0x90
; CHECK-NEXT:  .LBB6_2: # %bb15
; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    incq %r12
; CHECK-NEXT:    movl $432, %edx # imm = 0x1B0
; CHECK-NEXT:    xorl %edi, %edi
; CHECK-NEXT:    movq %r15, %rsi
; CHECK-NEXT:    callq memcpy@PLT
; CHECK-NEXT:    movl {{[-0-9]+}}(%r{{[sb]}}p), %edi # 4-byte Reload
; CHECK-NEXT:    movq {{[0-9]+}}(%rsp), %rax
; CHECK-NEXT:    addq %rax, %r13
; CHECK-NEXT:    addq %rax, %r15
; CHECK-NEXT:    addq %rax, %rbx
; CHECK-NEXT:    addq %rax, %r14
; CHECK-NEXT:    addq $8, %rbp
; CHECK-NEXT:    testb $1, %dil
; CHECK-NEXT:    je .LBB6_2
; CHECK-NEXT:  # %bb.3: # %bb11
; CHECK-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rsp
; CHECK-NEXT:    pop2 %r12, %rbx
; CHECK-NEXT:    pop2 %r14, %r13
; CHECK-NEXT:    pop2 %rbp, %r15
; CHECK-NEXT:    leaq {{[0-9]+}}(%rsp), %rsp
; CHECK-NEXT:    jne .LBB6_5
; CHECK-NEXT:  # %bb.4: # %bb12
; CHECK-NEXT:    movq $0, (%rax)
; CHECK-NEXT:  .LBB6_5: # %bb14
; CHECK-NEXT:    retq
;
; PPX-LABEL: lea_in_epilog:
; PPX:       # %bb.0: # %bb
; PPX-NEXT:    testb $1, %dil
; PPX-NEXT:    je .LBB6_5
; PPX-NEXT:  # %bb.1: # %bb13
; PPX-NEXT:    pushq %rax
; PPX-NEXT:    push2p %r15, %rbp
; PPX-NEXT:    push2p %r13, %r14
; PPX-NEXT:    push2p %rbx, %r12
; PPX-NEXT:    subq $16, %rsp
; PPX-NEXT:    movq %r9, %r14
; PPX-NEXT:    movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; PPX-NEXT:    addq {{[0-9]+}}(%rsp), %r14
; PPX-NEXT:    movq {{[0-9]+}}(%rsp), %r13
; PPX-NEXT:    addq %r14, %r13
; PPX-NEXT:    movq {{[0-9]+}}(%rsp), %r15
; PPX-NEXT:    addq %r14, %r15
; PPX-NEXT:    movq {{[0-9]+}}(%rsp), %rbx
; PPX-NEXT:    addq %r14, %rbx
; PPX-NEXT:    xorl %ebp, %ebp
; PPX-NEXT:    xorl %r12d, %r12d
; PPX-NEXT:    movl %edi, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
; PPX-NEXT:    .p2align 4, 0x90
; PPX-NEXT:  .LBB6_2: # %bb15
; PPX-NEXT:    # =>This Inner Loop Header: Depth=1
; PPX-NEXT:    incq %r12
; PPX-NEXT:    movl $432, %edx # imm = 0x1B0
; PPX-NEXT:    xorl %edi, %edi
; PPX-NEXT:    movq %r15, %rsi
; PPX-NEXT:    callq memcpy@PLT
; PPX-NEXT:    movl {{[-0-9]+}}(%r{{[sb]}}p), %edi # 4-byte Reload
; PPX-NEXT:    movq {{[0-9]+}}(%rsp), %rax
; PPX-NEXT:    addq %rax, %r13
; PPX-NEXT:    addq %rax, %r15
; PPX-NEXT:    addq %rax, %rbx
; PPX-NEXT:    addq %rax, %r14
; PPX-NEXT:    addq $8, %rbp
; PPX-NEXT:    testb $1, %dil
; PPX-NEXT:    je .LBB6_2
; PPX-NEXT:  # %bb.3: # %bb11
; PPX-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
; PPX-NEXT:    leaq {{[0-9]+}}(%rsp), %rsp
; PPX-NEXT:    pop2p %r12, %rbx
; PPX-NEXT:    pop2p %r14, %r13
; PPX-NEXT:    pop2p %rbp, %r15
; PPX-NEXT:    leaq {{[0-9]+}}(%rsp), %rsp
; PPX-NEXT:    jne .LBB6_5
; PPX-NEXT:  # %bb.4: # %bb12
; PPX-NEXT:    movq $0, (%rax)
; PPX-NEXT:  .LBB6_5: # %bb14
; PPX-NEXT:    retq
;
; FRAME-LABEL: lea_in_epilog:
; FRAME:       # %bb.0: # %bb
; FRAME-NEXT:    testb $1, %dil
; FRAME-NEXT:    je .LBB6_5
; FRAME-NEXT:  # %bb.1: # %bb13
; FRAME-NEXT:    pushq %rbp
; FRAME-NEXT:    movq %rsp, %rbp
; FRAME-NEXT:    push2 %r14, %r15
; FRAME-NEXT:    push2 %r12, %r13
; FRAME-NEXT:    pushq %rbx
; FRAME-NEXT:    subq $24, %rsp
; FRAME-NEXT:    movq %rsi, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; FRAME-NEXT:    addq 16(%rbp), %r9
; FRAME-NEXT:    movq 48(%rbp), %rbx
; FRAME-NEXT:    addq %r9, %rbx
; FRAME-NEXT:    movq 40(%rbp), %r12
; FRAME-NEXT:    addq %r9, %r12
; FRAME-NEXT:    movq 32(%rbp), %r15
; FRAME-NEXT:    addq %r9, %r15
; FRAME-NEXT:    xorl %r13d, %r13d
; FRAME-NEXT:    xorl %r14d, %r14d
; FRAME-NEXT:    movl %edi, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
; FRAME-NEXT:    .p2align 4, 0x90
; FRAME-NEXT:  .LBB6_2: # %bb15
; FRAME-NEXT:    # =>This Inner Loop Header: Depth=1
; FRAME-NEXT:    movq %r9, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
; FRAME-NEXT:    incq %r14
; FRAME-NEXT:    movl $432, %edx # imm = 0x1B0
; FRAME-NEXT:    xorl %edi, %edi
; FRAME-NEXT:    movq %r12, %rsi
; FRAME-NEXT:    callq memcpy@PLT
; FRAME-NEXT:    movl {{[-0-9]+}}(%r{{[sb]}}p), %edi # 4-byte Reload
; FRAME-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %r9 # 8-byte Reload
; FRAME-NEXT:    movq 16(%rbp), %rax
; FRAME-NEXT:    addq %rax, %rbx
; FRAME-NEXT:    addq %rax, %r12
; FRAME-NEXT:    addq %rax, %r15
; FRAME-NEXT:    addq %rax, %r9
; FRAME-NEXT:    addq $8, %r13
; FRAME-NEXT:    testb $1, %dil
; FRAME-NEXT:    je .LBB6_2
; FRAME-NEXT:  # %bb.3: # %bb11
; FRAME-NEXT:    movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
; FRAME-NEXT:    leaq {{[0-9]+}}(%rsp), %rsp
; FRAME-NEXT:    popq %rbx
; FRAME-NEXT:    pop2 %r13, %r12
; FRAME-NEXT:    pop2 %r15, %r14
; FRAME-NEXT:    popq %rbp
; FRAME-NEXT:    jne .LBB6_5
; FRAME-NEXT:  # %bb.4: # %bb12
; FRAME-NEXT:    movq $0, (%rax)
; FRAME-NEXT:  .LBB6_5: # %bb14
; FRAME-NEXT:    retq
bb:
  br i1 %arg, label %bb13, label %bb14

bb11:
  br i1 %arg, label %bb14, label %bb12

bb12:
  store double 0.000000e+00, ptr %arg1, align 8
  br label %bb14

bb13:
  %getelementptr = getelementptr i8, ptr null, i64 %arg5
  br label %bb15

bb14:
  ret void

bb15:
  %phi = phi i64 [ 0, %bb13 ], [ %add, %bb15 ]
  %getelementptr16 = getelementptr double, ptr null, i64 %phi
  %add = add i64 %phi, 1
  %mul = mul i64 %arg6, %add
  %getelementptr17 = getelementptr i8, ptr %getelementptr, i64 %mul
  call void @llvm.memcpy.p0.p0.i64(ptr %getelementptr16, ptr %getelementptr17, i64 0, i1 false)
  %getelementptr18 = getelementptr i8, ptr %getelementptr17, i64 %arg7
  %getelementptr19 = getelementptr i8, ptr %getelementptr17, i64 %arg8
  call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %getelementptr19, i64 0, i1 false)
  %getelementptr20 = getelementptr i8, ptr %getelementptr17, i64 %arg9
  call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %getelementptr20, i64 432, i1 false)
  %getelementptr21 = getelementptr i8, ptr %getelementptr17, i64 %arg10
  call void @llvm.memcpy.p0.p0.i64(ptr null, ptr %getelementptr21, i64 0, i1 false)
  br i1 %arg, label %bb11, label %bb15
}
