1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-01 00:12:50 +01:00
llvm-mirror/test/CodeGen/X86/force-align-stack-alloca.ll
Alexey Samsonov c68bb48704 This CL changes the function prologue and epilogue emitted on X86 when stack needs realignment.
It is intended to fix PR11468.

Old prologue and epilogue looked like this:
push %rbp
mov %rsp, %rbp
and $alignment, %rsp
push %r14
push %r15
...
pop %r15
pop %r14
mov %rbp, %rsp
pop %rbp

The problem was to reference the locations of callee-saved registers in exception handling:
locations of callee-saved had to be re-calculated regarding the stack alignment operation. It would
take some effort to implement this in LLVM, as currently MachineLocation can only have the form
"Register + Offset". Funciton prologue and epilogue are now changed to:

push %rbp
mov %rsp, %rbp
push %14
push %15
and $alignment, %rsp
...
lea -$size_of_saved_registers(%rbp), %rsp
pop %r15
pop %r14
pop %rbp

Reviewed by Chad Rosier.

llvm-svn: 160248
2012-07-16 06:54:09 +00:00

71 lines
2.1 KiB
LLVM

; This test is attempting to detect when we request forced re-alignment of the
; stack to an alignment greater than would be available due to the ABI. We
; arbitrarily force alignment up to 32-bytes for i386 hoping that this will
; exceed any ABI provisions.
;
; RUN: llc < %s -force-align-stack -stack-alignment=32 | FileCheck %s
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
target triple = "i386-unknown-linux-gnu"
define i32 @f(i8* %p) nounwind {
entry:
%0 = load i8* %p
%conv = sext i8 %0 to i32
ret i32 %conv
}
define i64 @g(i32 %i) nounwind {
; CHECK: g:
; CHECK: pushl %ebp
; CHECK-NEXT: movl %esp, %ebp
; CHECK-NEXT: pushl
; CHECK-NEXT: pushl
; CHECK-NEXT: andl $-32, %esp
; CHECK-NEXT: subl $32, %esp
;
; Now setup the base pointer (%ebx).
; CHECK-NEXT: movl %esp, %ebx
; CHECK-NOT: {{[^ ,]*}}, %esp
;
; The next adjustment of the stack is due to the alloca.
; CHECK: movl %{{...}}, %esp
; CHECK-NOT: {{[^ ,]*}}, %esp
;
; Next we set up the memset call, and then undo it.
; CHECK: subl $32, %esp
; CHECK-NOT: {{[^ ,]*}}, %esp
; CHECK: calll memset
; CHECK-NEXT: addl $32, %esp
; CHECK-NOT: {{[^ ,]*}}, %esp
;
; Next we set up the call to 'f'.
; CHECK: subl $32, %esp
; CHECK-NOT: {{[^ ,]*}}, %esp
; CHECK: calll f
; CHECK-NEXT: addl $32, %esp
; CHECK-NOT: {{[^ ,]*}}, %esp
;
; Restore %esp from %ebp (frame pointer) and subtract the size of
; zone with callee-saved registers to pop them.
; This is the state prior to stack realignment and the allocation of VLAs.
; CHECK-NOT: popl
; CHECK: leal -8(%ebp), %esp
; CHECK-NEXT: popl
; CHECK-NEXT: popl
; CHECK-NEXT: popl %ebp
; CHECK-NEXT: ret
entry:
br label %if.then
if.then:
%0 = alloca i8, i32 %i
call void @llvm.memset.p0i8.i32(i8* %0, i8 0, i32 %i, i32 1, i1 false)
%call = call i32 @f(i8* %0)
%conv = sext i32 %call to i64
ret i64 %conv
}
declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i32, i1) nounwind