1; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck %s
2; RUN: llc < %s -mtriple=i686-pc-win32 -O0
3
4%struct.S = type { [1024 x i8] }
5%struct.T = type { [3000 x i8] }
6%struct.U = type { [10000 x i8] }
7
8define void @basics() {
9; CHECK-LABEL: basics:
10entry:
11  br label %bb1
12
13; Allocation move sizes should have been removed.
14; CHECK-NOT: movl $1024
15; CHECK-NOT: movl $3000
16
17bb1:
18  %p0 = alloca %struct.S
19; The allocation is small enough not to require stack probing, but the %esp
20; offset after the prologue is not known, so the stack must be touched before
21; the pointer is adjusted.
22; CHECK: pushl %eax
23; CHECK: subl $1020, %esp
24
25  %saved_stack = tail call i8* @llvm.stacksave()
26
27  %p1 = alloca %struct.S
28; We know the %esp offset from above, so there is no need to touch the stack
29; before adjusting it.
30; CHECK: subl $1024, %esp
31
32  %p2 = alloca %struct.T
33; The offset is now 2048 bytes, so allocating a T must touch the stack again.
34; CHECK: pushl %eax
35; CHECK: subl $2996, %esp
36
37  call void @f(%struct.S* %p0)
38; CHECK: calll
39
40  %p3 = alloca %struct.T
41; The call above touched the stack, so there is room for a T object.
42; CHECK: subl $3000, %esp
43
44  %p4 = alloca %struct.U
45; The U object is large enough to require stack probing.
46; CHECK: movl $10000, %eax
47; CHECK: calll __chkstk
48
49  %p5 = alloca %struct.T
50; The stack probing above touched the tip of the stack, so there's room for a T.
51; CHECK: subl $3000, %esp
52
53  call void @llvm.stackrestore(i8* %saved_stack)
54  %p6 = alloca %struct.S
55; The stack restore means we lose track of the stack pointer and must probe.
56; CHECK: pushl %eax
57; CHECK: subl $1020, %esp
58
59; Use the pointers so they're not optimized away.
60  call void @f(%struct.S* %p1)
61  call void @g(%struct.T* %p2)
62  call void @g(%struct.T* %p3)
63  call void @h(%struct.U* %p4)
64  call void @g(%struct.T* %p5)
65  ret void
66}
67
68define void @loop() {
69; CHECK-LABEL: loop:
70entry:
71  br label %bb1
72
73bb1:
74  %p1 = alloca %struct.S
75; The entry offset is unknown; touch-and-sub.
76; CHECK: pushl %eax
77; CHECK: subl $1020, %esp
78  br label %loop1
79
80loop1:
81  %i1 = phi i32 [ 10, %bb1 ], [ %dec1, %loop1 ]
82  %p2 = alloca %struct.S
83; We know the incoming offset from bb1, but from the back-edge, we assume the
84; worst, and therefore touch-and-sub to allocate.
85; CHECK: pushl %eax
86; CHECK: subl $1020, %esp
87  %dec1 = sub i32 %i1, 1
88  %cmp1 = icmp sgt i32 %i1, 0
89  br i1 %cmp1, label %loop1, label %end
90; CHECK: decl
91; CHECK: jg
92
93end:
94  call void @f(%struct.S* %p1)
95  call void @f(%struct.S* %p2)
96  ret void
97}
98
99define void @probe_size_attribute() "stack-probe-size"="512" {
100; CHECK-LABEL: probe_size_attribute:
101entry:
102  br label %bb1
103
104bb1:
105  %p0 = alloca %struct.S
106; The allocation would be small enough not to require probing, if it wasn't
107; for the stack-probe-size attribute.
108; CHECK: movl $1024, %eax
109; CHECK: calll __chkstk
110  call void @f(%struct.S* %p0)
111  ret void
112}
113
114define void @cfg(i1 %x, i1 %y) {
115; Test that the blocks are analyzed in the correct order.
116; CHECK-LABEL: cfg:
117entry:
118  br i1 %x, label %bb1, label %bb3
119
120bb1:
121  %p1 = alloca %struct.S
122; CHECK: pushl %eax
123; CHECK: subl $1020, %esp
124  br label %bb4
125
126bb2:
127  %p5 = alloca %struct.T
128; CHECK: pushl %eax
129; CHECK: subl $2996, %esp
130  call void @g(%struct.T* %p5)
131  ret void
132
133bb3:
134  %p2 = alloca %struct.T
135; CHECK: pushl %eax
136; CHECK: subl $2996, %esp
137  br label %bb4
138
139bb4:
140  br i1 %y, label %bb5, label %bb2
141
142bb5:
143  %p4 = alloca %struct.S
144; CHECK: subl $1024, %esp
145  call void @f(%struct.S* %p4)
146  ret void
147
148}
149
150
151declare void @f(%struct.S*)
152declare void @g(%struct.T*)
153declare void @h(%struct.U*)
154
155declare i8* @llvm.stacksave()
156declare void @llvm.stackrestore(i8*)
157