157 lines
3.5 KiB
LLVM
157 lines
3.5 KiB
LLVM
|
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s
|
||
|
; RUN: llc < %s -mtriple=i686-pc-win32 -O0
|
||
|
|
||
|
%struct.S = type { [1024 x i8] }
|
||
|
%struct.T = type { [3000 x i8] }
|
||
|
%struct.U = type { [10000 x i8] }
|
||
|
|
||
|
define void @basics() {
|
||
|
; CHECK-LABEL: basics:
|
||
|
entry:
|
||
|
br label %bb1
|
||
|
|
||
|
; Allocation move sizes should have been removed.
|
||
|
; CHECK-NOT: movl $1024
|
||
|
; CHECK-NOT: movl $3000
|
||
|
|
||
|
bb1:
|
||
|
%p0 = alloca %struct.S
|
||
|
; The allocation is small enough not to require stack probing, but the %esp
|
||
|
; offset after the prologue is not known, so the stack must be touched before
|
||
|
; the pointer is adjusted.
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $1020, %esp
|
||
|
|
||
|
%saved_stack = tail call i8* @llvm.stacksave()
|
||
|
|
||
|
%p1 = alloca %struct.S
|
||
|
; We know the %esp offset from above, so there is no need to touch the stack
|
||
|
; before adjusting it.
|
||
|
; CHECK: subl $1024, %esp
|
||
|
|
||
|
%p2 = alloca %struct.T
|
||
|
; The offset is now 2048 bytes, so allocating a T must touch the stack again.
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $2996, %esp
|
||
|
|
||
|
call void @f(%struct.S* %p0)
|
||
|
; CHECK: calll
|
||
|
|
||
|
%p3 = alloca %struct.T
|
||
|
; The call above touched the stack, so there is room for a T object.
|
||
|
; CHECK: subl $3000, %esp
|
||
|
|
||
|
%p4 = alloca %struct.U
|
||
|
; The U object is large enough to require stack probing.
|
||
|
; CHECK: movl $10000, %eax
|
||
|
; CHECK: calll __chkstk
|
||
|
|
||
|
%p5 = alloca %struct.T
|
||
|
; The stack probing above touched the tip of the stack, so there's room for a T.
|
||
|
; CHECK: subl $3000, %esp
|
||
|
|
||
|
call void @llvm.stackrestore(i8* %saved_stack)
|
||
|
%p6 = alloca %struct.S
|
||
|
; The stack restore means we lose track of the stack pointer and must probe.
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $1020, %esp
|
||
|
|
||
|
; Use the pointers so they're not optimized away.
|
||
|
call void @f(%struct.S* %p1)
|
||
|
call void @g(%struct.T* %p2)
|
||
|
call void @g(%struct.T* %p3)
|
||
|
call void @h(%struct.U* %p4)
|
||
|
call void @g(%struct.T* %p5)
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @loop() {
|
||
|
; CHECK-LABEL: loop:
|
||
|
entry:
|
||
|
br label %bb1
|
||
|
|
||
|
bb1:
|
||
|
%p1 = alloca %struct.S
|
||
|
; The entry offset is unknown; touch-and-sub.
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $1020, %esp
|
||
|
br label %loop1
|
||
|
|
||
|
loop1:
|
||
|
%i1 = phi i32 [ 10, %bb1 ], [ %dec1, %loop1 ]
|
||
|
%p2 = alloca %struct.S
|
||
|
; We know the incoming offset from bb1, but from the back-edge, we assume the
|
||
|
; worst, and therefore touch-and-sub to allocate.
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $1020, %esp
|
||
|
%dec1 = sub i32 %i1, 1
|
||
|
%cmp1 = icmp sgt i32 %i1, 0
|
||
|
br i1 %cmp1, label %loop1, label %end
|
||
|
; CHECK: decl
|
||
|
; CHECK: jg
|
||
|
|
||
|
end:
|
||
|
call void @f(%struct.S* %p1)
|
||
|
call void @f(%struct.S* %p2)
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @probe_size_attribute() "stack-probe-size"="512" {
|
||
|
; CHECK-LABEL: probe_size_attribute:
|
||
|
entry:
|
||
|
br label %bb1
|
||
|
|
||
|
bb1:
|
||
|
%p0 = alloca %struct.S
|
||
|
; The allocation would be small enough not to require probing, if it wasn't
|
||
|
; for the stack-probe-size attribute.
|
||
|
; CHECK: movl $1024, %eax
|
||
|
; CHECK: calll __chkstk
|
||
|
call void @f(%struct.S* %p0)
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @cfg(i1 %x, i1 %y) {
|
||
|
; Test that the blocks are analyzed in the correct order.
|
||
|
; CHECK-LABEL: cfg:
|
||
|
entry:
|
||
|
br i1 %x, label %bb1, label %bb3
|
||
|
|
||
|
bb1:
|
||
|
%p1 = alloca %struct.S
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $1020, %esp
|
||
|
br label %bb4
|
||
|
|
||
|
bb2:
|
||
|
%p5 = alloca %struct.T
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $2996, %esp
|
||
|
call void @g(%struct.T* %p5)
|
||
|
ret void
|
||
|
|
||
|
bb3:
|
||
|
%p2 = alloca %struct.T
|
||
|
; CHECK: pushl %eax
|
||
|
; CHECK: subl $2996, %esp
|
||
|
br label %bb4
|
||
|
|
||
|
bb4:
|
||
|
br i1 %y, label %bb5, label %bb2
|
||
|
|
||
|
bb5:
|
||
|
%p4 = alloca %struct.S
|
||
|
; CHECK: subl $1024, %esp
|
||
|
call void @f(%struct.S* %p4)
|
||
|
ret void
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
declare void @f(%struct.S*)
|
||
|
declare void @g(%struct.T*)
|
||
|
declare void @h(%struct.U*)
|
||
|
|
||
|
declare i8* @llvm.stacksave()
|
||
|
declare void @llvm.stackrestore(i8*)
|