; 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: pushq %rbp
; FRAME-NEXT: pushq %rax
; FRAME-NEXT: #APP
; FRAME-NEXT: #NO_APP
; FRAME-NEXT: popq %rax
; FRAME-NEXT: popq %rbp
; 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: pushq %rbp
; FRAME-NEXT: pushq %rax
; FRAME-NEXT: #APP
; FRAME-NEXT: #NO_APP
; FRAME-NEXT: popq %rax
; FRAME-NEXT: popq %rbp
; 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: pushq %rbp
; FRAME-NEXT: pushq %rax
; FRAME-NEXT: #APP
; FRAME-NEXT: #NO_APP
; FRAME-NEXT: popq %rax
; FRAME-NEXT: popq %rbp
; 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: pushq %rbp
; FRAME-NEXT: pushq %rax
; FRAME-NEXT: #APP
; FRAME-NEXT: #NO_APP
; FRAME-NEXT: popq %rax
; FRAME-NEXT: popq %rbp
; 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: pushq %rbp
; FRAME-NEXT: pushq %rax
; FRAME-NEXT: #APP
; FRAME-NEXT: #NO_APP
; FRAME-NEXT: popq %rax
; FRAME-NEXT: popq %rbp
; 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: pushq %rbp
; FRAME-NEXT: pushq %rax
; FRAME-NEXT: #APP
; FRAME-NEXT: #NO_APP
; FRAME-NEXT: popq %rax
; FRAME-NEXT: popq %rbp
; 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
; 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
; 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
; 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
}