blob: 5f9e84378c24a36a41b87b6335dbea6bd16bb7ee [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no_x86_scrub_sp
; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
; RUN: llc -mtriple=x86_64-unknown-unknown -O0 < %s | FileCheck %s -check-prefix=CHECK0
%struct.interrupt_frame = type { i64, i64, i64, i64, i64 }
@sink_address = dso_local global ptr null
@sink_i32 = dso_local global i64 0
; Spills rax, putting original esp at +8.
; No stack adjustment if declared with no error code
define x86_intrcc void @test_isr_no_ecode(ptr byval(%struct.interrupt_frame) %frame) nounwind {
; CHECK-LABEL: test_isr_no_ecode:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: cld
; CHECK-NEXT: movq 24(%rsp), %rax
; CHECK-NEXT: #APP
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: popq %rax
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_isr_no_ecode:
; CHECK0: # %bb.0:
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: cld
; CHECK0-NEXT: leaq 8(%rsp), %rax
; CHECK0-NEXT: movq 16(%rax), %rax
; CHECK0-NEXT: #APP
; CHECK0-NEXT: #NO_APP
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: iretq
%pflags = getelementptr inbounds %struct.interrupt_frame, ptr %frame, i32 0, i32 2
%flags = load i64, ptr %pflags, align 4
call void asm sideeffect "", "r"(i64 %flags)
ret void
}
; Spills rax and rcx, putting original rsp at +16. Stack is adjusted up another 8 bytes
; before return, popping the error code.
define x86_intrcc void @test_isr_ecode(ptr byval(%struct.interrupt_frame) %frame, i64 %ecode) nounwind {
; CHECK-LABEL: test_isr_ecode:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rcx
; CHECK-NEXT: cld
; CHECK-NEXT: movq 24(%rsp), %rax
; CHECK-NEXT: movq 48(%rsp), %rcx
; CHECK-NEXT: #APP
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: popq %rax
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_isr_ecode:
; CHECK0: # %bb.0:
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rcx
; CHECK0-NEXT: cld
; CHECK0-NEXT: movq 24(%rsp), %rcx
; CHECK0-NEXT: leaq 32(%rsp), %rax
; CHECK0-NEXT: movq 16(%rax), %rax
; CHECK0-NEXT: #APP
; CHECK0-NEXT: #NO_APP
; CHECK0-NEXT: popq %rcx
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: addq $16, %rsp
; CHECK0-NEXT: iretq
%pflags = getelementptr inbounds %struct.interrupt_frame, ptr %frame, i32 0, i32 2
%flags = load i64, ptr %pflags, align 4
call void asm sideeffect "", "r,r"(i64 %flags, i64 %ecode)
ret void
}
; All clobbered registers must be saved
define x86_intrcc void @test_isr_clobbers(ptr byval(%struct.interrupt_frame) %frame, i64 %ecode) nounwind {
; CHECK-LABEL: test_isr_clobbers:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: pushq %r11
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: movaps %xmm0, -24(%rsp) # 16-byte Spill
; CHECK-NEXT: cld
; CHECK-NEXT: #APP
; CHECK-NEXT: #NO_APP
; CHECK-NEXT: movaps -24(%rsp), %xmm0 # 16-byte Reload
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: popq %r11
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: popq %rax
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_isr_clobbers:
; CHECK0: # %bb.0:
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rbp
; CHECK0-NEXT: pushq %r11
; CHECK0-NEXT: pushq %rbx
; CHECK0-NEXT: movaps %xmm0, -24(%rsp) # 16-byte Spill
; CHECK0-NEXT: cld
; CHECK0-NEXT: #APP
; CHECK0-NEXT: #NO_APP
; CHECK0-NEXT: movaps -24(%rsp), %xmm0 # 16-byte Reload
; CHECK0-NEXT: popq %rbx
; CHECK0-NEXT: popq %r11
; CHECK0-NEXT: popq %rbp
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: addq $16, %rsp
; CHECK0-NEXT: iretq
call void asm sideeffect "", "~{rax},~{rbx},~{rbp},~{r11},~{xmm0}"()
ret void
}
@f80 = common dso_local global x86_fp80 0xK00000000000000000000, align 4
; Test that the presence of x87 does not crash the FP stackifier
define x86_intrcc void @test_isr_x87(ptr byval(%struct.interrupt_frame) %frame) nounwind {
; CHECK-LABEL: test_isr_x87:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fldt f80(%rip)
; CHECK-NEXT: fld1
; CHECK-NEXT: faddp %st, %st(1)
; CHECK-NEXT: fstpt f80(%rip)
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_isr_x87:
; CHECK0: # %bb.0: # %entry
; CHECK0-NEXT: fldt f80(%rip)
; CHECK0-NEXT: fld1
; CHECK0-NEXT: faddp %st, %st(1)
; CHECK0-NEXT: fstpt f80(%rip)
; CHECK0-NEXT: iretq
entry:
%ld = load x86_fp80, ptr @f80, align 4
%add = fadd x86_fp80 %ld, 0xK3FFF8000000000000000
store x86_fp80 %add, ptr @f80, align 4
ret void
}
; Use a frame pointer to check the offsets. No return address, arguments start
; at RBP+4.
define dso_local x86_intrcc void @test_fp_1(ptr byval(%struct.interrupt_frame) %p) #0 {
; CHECK-LABEL: test_fp_1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: movq %rsp, %rbp
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rcx
; CHECK-NEXT: leaq 40(%rbp), %rax
; CHECK-NEXT: leaq 8(%rbp), %rcx
; CHECK-NEXT: movq %rcx, sink_address(%rip)
; CHECK-NEXT: movq %rax, sink_address(%rip)
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: popq %rax
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_fp_1:
; CHECK0: # %bb.0: # %entry
; CHECK0-NEXT: pushq %rbp
; CHECK0-NEXT: movq %rsp, %rbp
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rcx
; CHECK0-NEXT: leaq 8(%rbp), %rcx
; CHECK0-NEXT: movq %rcx, %rax
; CHECK0-NEXT: addq $32, %rax
; CHECK0-NEXT: movq %rcx, sink_address(%rip)
; CHECK0-NEXT: movq %rax, sink_address(%rip)
; CHECK0-NEXT: popq %rcx
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: popq %rbp
; CHECK0-NEXT: iretq
entry:
%arrayidx2 = getelementptr inbounds %struct.interrupt_frame, ptr %p, i64 0, i32 4
store volatile ptr %p, ptr @sink_address
store volatile ptr %arrayidx2, ptr @sink_address
ret void
}
; The error code is between RBP and the interrupt_frame.
define dso_local x86_intrcc void @test_fp_2(ptr byval(%struct.interrupt_frame) %p, i64 %err) #0 {
; CHECK-LABEL: test_fp_2:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: movq %rsp, %rbp
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rdx
; CHECK-NEXT: pushq %rcx
; CHECK-NEXT: movq 16(%rbp), %rax
; CHECK-NEXT: leaq 56(%rbp), %rcx
; CHECK-NEXT: leaq 24(%rbp), %rdx
; CHECK-NEXT: movq %rdx, sink_address(%rip)
; CHECK-NEXT: movq %rcx, sink_address(%rip)
; CHECK-NEXT: movq %rax, sink_i32(%rip)
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: popq %rdx
; CHECK-NEXT: popq %rax
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_fp_2:
; CHECK0: # %bb.0: # %entry
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rbp
; CHECK0-NEXT: movq %rsp, %rbp
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rdx
; CHECK0-NEXT: pushq %rcx
; CHECK0-NEXT: movq 16(%rbp), %rax
; CHECK0-NEXT: leaq 24(%rbp), %rdx
; CHECK0-NEXT: movq %rdx, %rcx
; CHECK0-NEXT: addq $32, %rcx
; CHECK0-NEXT: movq %rdx, sink_address(%rip)
; CHECK0-NEXT: movq %rcx, sink_address(%rip)
; CHECK0-NEXT: movq %rax, sink_i32(%rip)
; CHECK0-NEXT: popq %rcx
; CHECK0-NEXT: popq %rdx
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: popq %rbp
; CHECK0-NEXT: addq $16, %rsp
; CHECK0-NEXT: iretq
; This RAX push is just to align the stack.
; Pop off both the error code and the 8 byte alignment adjustment from the
; prologue.
entry:
%arrayidx2 = getelementptr inbounds %struct.interrupt_frame, ptr %p, i64 0, i32 4
store volatile ptr %p, ptr @sink_address
store volatile ptr %arrayidx2, ptr @sink_address
store volatile i64 %err, ptr @sink_i32
ret void
}
; Test argument copy elision when copied to a local alloca.
define x86_intrcc void @test_copy_elide(ptr byval(%struct.interrupt_frame) %frame, i64 %err) #0 {
; CHECK-LABEL: test_copy_elide:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: movq %rsp, %rbp
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: leaq 16(%rbp), %rax
; CHECK-NEXT: movq %rax, sink_address(%rip)
; CHECK-NEXT: popq %rax
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_copy_elide:
; CHECK0: # %bb.0: # %entry
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rbp
; CHECK0-NEXT: movq %rsp, %rbp
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: movq 16(%rbp), %rax
; CHECK0-NEXT: leaq 16(%rbp), %rax
; CHECK0-NEXT: movq %rax, sink_address(%rip)
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: popq %rbp
; CHECK0-NEXT: addq $16, %rsp
; CHECK0-NEXT: iretq
; This RAX push is just to align the stack.
entry:
%err.addr = alloca i64, align 4
store i64 %err, ptr %err.addr, align 4
store volatile ptr %err.addr, ptr @sink_address
ret void
}
; An error-code handler is entered with RSP 16-byte aligned, so the pushes and
; the subq together have to be a multiple of 16 for the call below to be ABI
; correct. The chain pins the push count as well as the subq so that the total is
; actually checked; it also catches STACKALLOC_W_PROBING, whose comment line
; would break it.
;
; The checked-in output is currently wrong: 10 * 8 + 280 == 360 == 8 mod 16.
define x86_intrcc void @test_stack_allocation(ptr byval(%struct.interrupt_frame) %frame, i64 %err) #1 {
; CHECK-LABEL: test_stack_allocation:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %r11
; CHECK-NEXT: pushq %r10
; CHECK-NEXT: pushq %r9
; CHECK-NEXT: pushq %r8
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: pushq %rsi
; CHECK-NEXT: pushq %rdx
; CHECK-NEXT: pushq %rcx
; CHECK-NEXT: subq $272, %rsp # imm = 0x110
; CHECK-NEXT: movaps %xmm15, 256(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm14, 240(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm13, 224(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm12, 208(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm11, 192(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm10, 176(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm9, 160(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm8, 144(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm7, 128(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm6, 112(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm5, 96(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm4, 80(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm3, 64(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm2, 48(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm1, 32(%rsp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm0, 16(%rsp) # 16-byte Spill
; CHECK-NEXT: cld
; CHECK-NEXT: leaq 8(%rsp), %rdi
; CHECK-NEXT: callq external_function@PLT
; CHECK-NEXT: movaps 16(%rsp), %xmm0 # 16-byte Reload
; CHECK-NEXT: movaps 32(%rsp), %xmm1 # 16-byte Reload
; CHECK-NEXT: movaps 48(%rsp), %xmm2 # 16-byte Reload
; CHECK-NEXT: movaps 64(%rsp), %xmm3 # 16-byte Reload
; CHECK-NEXT: movaps 80(%rsp), %xmm4 # 16-byte Reload
; CHECK-NEXT: movaps 96(%rsp), %xmm5 # 16-byte Reload
; CHECK-NEXT: movaps 112(%rsp), %xmm6 # 16-byte Reload
; CHECK-NEXT: movaps 128(%rsp), %xmm7 # 16-byte Reload
; CHECK-NEXT: movaps 144(%rsp), %xmm8 # 16-byte Reload
; CHECK-NEXT: movaps 160(%rsp), %xmm9 # 16-byte Reload
; CHECK-NEXT: movaps 176(%rsp), %xmm10 # 16-byte Reload
; CHECK-NEXT: movaps 192(%rsp), %xmm11 # 16-byte Reload
; CHECK-NEXT: movaps 208(%rsp), %xmm12 # 16-byte Reload
; CHECK-NEXT: movaps 224(%rsp), %xmm13 # 16-byte Reload
; CHECK-NEXT: movaps 240(%rsp), %xmm14 # 16-byte Reload
; CHECK-NEXT: movaps 256(%rsp), %xmm15 # 16-byte Reload
; CHECK-NEXT: addq $272, %rsp # imm = 0x110
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: popq %rdx
; CHECK-NEXT: popq %rsi
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: popq %r8
; CHECK-NEXT: popq %r9
; CHECK-NEXT: popq %r10
; CHECK-NEXT: popq %r11
; CHECK-NEXT: popq %rax
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_stack_allocation:
; CHECK0: # %bb.0: # %entry
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %r11
; CHECK0-NEXT: pushq %r10
; CHECK0-NEXT: pushq %r9
; CHECK0-NEXT: pushq %r8
; CHECK0-NEXT: pushq %rdi
; CHECK0-NEXT: pushq %rsi
; CHECK0-NEXT: pushq %rdx
; CHECK0-NEXT: pushq %rcx
; CHECK0-NEXT: subq $272, %rsp # imm = 0x110
; CHECK0-NEXT: movaps %xmm15, 256(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm14, 240(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm13, 224(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm12, 208(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm11, 192(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm10, 176(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm9, 160(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm8, 144(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm7, 128(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm6, 112(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm5, 96(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm4, 80(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm3, 64(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm2, 48(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm1, 32(%rsp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm0, 16(%rsp) # 16-byte Spill
; CHECK0-NEXT: cld
; CHECK0-NEXT: leaq 8(%rsp), %rdi
; CHECK0-NEXT: callq external_function@PLT
; CHECK0-NEXT: movaps 16(%rsp), %xmm0 # 16-byte Reload
; CHECK0-NEXT: movaps 32(%rsp), %xmm1 # 16-byte Reload
; CHECK0-NEXT: movaps 48(%rsp), %xmm2 # 16-byte Reload
; CHECK0-NEXT: movaps 64(%rsp), %xmm3 # 16-byte Reload
; CHECK0-NEXT: movaps 80(%rsp), %xmm4 # 16-byte Reload
; CHECK0-NEXT: movaps 96(%rsp), %xmm5 # 16-byte Reload
; CHECK0-NEXT: movaps 112(%rsp), %xmm6 # 16-byte Reload
; CHECK0-NEXT: movaps 128(%rsp), %xmm7 # 16-byte Reload
; CHECK0-NEXT: movaps 144(%rsp), %xmm8 # 16-byte Reload
; CHECK0-NEXT: movaps 160(%rsp), %xmm9 # 16-byte Reload
; CHECK0-NEXT: movaps 176(%rsp), %xmm10 # 16-byte Reload
; CHECK0-NEXT: movaps 192(%rsp), %xmm11 # 16-byte Reload
; CHECK0-NEXT: movaps 208(%rsp), %xmm12 # 16-byte Reload
; CHECK0-NEXT: movaps 224(%rsp), %xmm13 # 16-byte Reload
; CHECK0-NEXT: movaps 240(%rsp), %xmm14 # 16-byte Reload
; CHECK0-NEXT: movaps 256(%rsp), %xmm15 # 16-byte Reload
; CHECK0-NEXT: addq $272, %rsp # imm = 0x110
; CHECK0-NEXT: popq %rcx
; CHECK0-NEXT: popq %rdx
; CHECK0-NEXT: popq %rsi
; CHECK0-NEXT: popq %rdi
; CHECK0-NEXT: popq %r8
; CHECK0-NEXT: popq %r9
; CHECK0-NEXT: popq %r10
; CHECK0-NEXT: popq %r11
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: addq $16, %rsp
; CHECK0-NEXT: iretq
entry:
%some_allocation = alloca i64
;; Call a un-inlineable function to ensure the allocation isn't put in the red zone.
call void @external_function(ptr %some_allocation)
ret void
}
; An over-aligned local realigns the stack. If the frame size carries the extra
; 8 bytes of the parity push, the object lands at 8 mod 64 and
; getFrameIndexReference asserts. The subq must stay a multiple of 64.
define x86_intrcc void @test_realigned_object(ptr byval(%struct.interrupt_frame) %frame, i64 %err) #0 {
; CHECK-LABEL: test_realigned_object:
; CHECK: # %bb.0:
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: movq %rsp, %rbp
; CHECK-NEXT: pushq %rax
; CHECK-NEXT: pushq %r11
; CHECK-NEXT: pushq %r10
; CHECK-NEXT: pushq %r9
; CHECK-NEXT: pushq %r8
; CHECK-NEXT: pushq %rdi
; CHECK-NEXT: pushq %rsi
; CHECK-NEXT: pushq %rdx
; CHECK-NEXT: pushq %rcx
; CHECK-NEXT: andq $-64, %rsp
; CHECK-NEXT: subq $320, %rsp # imm = 0x140
; CHECK-NEXT: movaps %xmm15, -96(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm14, -112(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm13, -128(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm12, -144(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm11, -160(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm10, -176(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm9, -192(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm8, -208(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm7, -224(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm6, -240(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm5, -256(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm4, -272(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm3, -288(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm2, -304(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm1, -320(%rbp) # 16-byte Spill
; CHECK-NEXT: movaps %xmm0, -336(%rbp) # 16-byte Spill
; CHECK-NEXT: cld
; CHECK-NEXT: movq %rsp, %rdi
; CHECK-NEXT: callq external_function@PLT
; CHECK-NEXT: movaps -336(%rbp), %xmm0 # 16-byte Reload
; CHECK-NEXT: movaps -320(%rbp), %xmm1 # 16-byte Reload
; CHECK-NEXT: movaps -304(%rbp), %xmm2 # 16-byte Reload
; CHECK-NEXT: movaps -288(%rbp), %xmm3 # 16-byte Reload
; CHECK-NEXT: movaps -272(%rbp), %xmm4 # 16-byte Reload
; CHECK-NEXT: movaps -256(%rbp), %xmm5 # 16-byte Reload
; CHECK-NEXT: movaps -240(%rbp), %xmm6 # 16-byte Reload
; CHECK-NEXT: movaps -224(%rbp), %xmm7 # 16-byte Reload
; CHECK-NEXT: movaps -208(%rbp), %xmm8 # 16-byte Reload
; CHECK-NEXT: movaps -192(%rbp), %xmm9 # 16-byte Reload
; CHECK-NEXT: movaps -176(%rbp), %xmm10 # 16-byte Reload
; CHECK-NEXT: movaps -160(%rbp), %xmm11 # 16-byte Reload
; CHECK-NEXT: movaps -144(%rbp), %xmm12 # 16-byte Reload
; CHECK-NEXT: movaps -128(%rbp), %xmm13 # 16-byte Reload
; CHECK-NEXT: movaps -112(%rbp), %xmm14 # 16-byte Reload
; CHECK-NEXT: movaps -96(%rbp), %xmm15 # 16-byte Reload
; CHECK-NEXT: leaq -72(%rbp), %rsp
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: popq %rdx
; CHECK-NEXT: popq %rsi
; CHECK-NEXT: popq %rdi
; CHECK-NEXT: popq %r8
; CHECK-NEXT: popq %r9
; CHECK-NEXT: popq %r10
; CHECK-NEXT: popq %r11
; CHECK-NEXT: popq %rax
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: iretq
;
; CHECK0-LABEL: test_realigned_object:
; CHECK0: # %bb.0:
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %rbp
; CHECK0-NEXT: movq %rsp, %rbp
; CHECK0-NEXT: pushq %rax
; CHECK0-NEXT: pushq %r11
; CHECK0-NEXT: pushq %r10
; CHECK0-NEXT: pushq %r9
; CHECK0-NEXT: pushq %r8
; CHECK0-NEXT: pushq %rdi
; CHECK0-NEXT: pushq %rsi
; CHECK0-NEXT: pushq %rdx
; CHECK0-NEXT: pushq %rcx
; CHECK0-NEXT: andq $-64, %rsp
; CHECK0-NEXT: subq $320, %rsp # imm = 0x140
; CHECK0-NEXT: movaps %xmm15, -96(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm14, -112(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm13, -128(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm12, -144(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm11, -160(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm10, -176(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm9, -192(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm8, -208(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm7, -224(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm6, -240(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm5, -256(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm4, -272(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm3, -288(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm2, -304(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm1, -320(%rbp) # 16-byte Spill
; CHECK0-NEXT: movaps %xmm0, -336(%rbp) # 16-byte Spill
; CHECK0-NEXT: cld
; CHECK0-NEXT: movq %rsp, %rdi
; CHECK0-NEXT: callq external_function@PLT
; CHECK0-NEXT: movaps -336(%rbp), %xmm0 # 16-byte Reload
; CHECK0-NEXT: movaps -320(%rbp), %xmm1 # 16-byte Reload
; CHECK0-NEXT: movaps -304(%rbp), %xmm2 # 16-byte Reload
; CHECK0-NEXT: movaps -288(%rbp), %xmm3 # 16-byte Reload
; CHECK0-NEXT: movaps -272(%rbp), %xmm4 # 16-byte Reload
; CHECK0-NEXT: movaps -256(%rbp), %xmm5 # 16-byte Reload
; CHECK0-NEXT: movaps -240(%rbp), %xmm6 # 16-byte Reload
; CHECK0-NEXT: movaps -224(%rbp), %xmm7 # 16-byte Reload
; CHECK0-NEXT: movaps -208(%rbp), %xmm8 # 16-byte Reload
; CHECK0-NEXT: movaps -192(%rbp), %xmm9 # 16-byte Reload
; CHECK0-NEXT: movaps -176(%rbp), %xmm10 # 16-byte Reload
; CHECK0-NEXT: movaps -160(%rbp), %xmm11 # 16-byte Reload
; CHECK0-NEXT: movaps -144(%rbp), %xmm12 # 16-byte Reload
; CHECK0-NEXT: movaps -128(%rbp), %xmm13 # 16-byte Reload
; CHECK0-NEXT: movaps -112(%rbp), %xmm14 # 16-byte Reload
; CHECK0-NEXT: movaps -96(%rbp), %xmm15 # 16-byte Reload
; CHECK0-NEXT: leaq -72(%rbp), %rsp
; CHECK0-NEXT: popq %rcx
; CHECK0-NEXT: popq %rdx
; CHECK0-NEXT: popq %rsi
; CHECK0-NEXT: popq %rdi
; CHECK0-NEXT: popq %r8
; CHECK0-NEXT: popq %r9
; CHECK0-NEXT: popq %r10
; CHECK0-NEXT: popq %r11
; CHECK0-NEXT: popq %rax
; CHECK0-NEXT: popq %rbp
; CHECK0-NEXT: addq $16, %rsp
; CHECK0-NEXT: iretq
%over_aligned = alloca i64, align 64
call void @external_function(ptr %over_aligned)
ret void
}
declare void @external_function(ptr)
attributes #0 = { nounwind "frame-pointer"="all" }
attributes #1 = { nounwind "probe-stack"="inline-asm" }