xref: /llvm-project/llvm/test/CodeGen/SystemZ/stack-clash-protection.ll (revision a1710eb3cd5823c5d14899112ca3086acbdbe9cb)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 -O3 -verify-machineinstrs | FileCheck %s
3;
4; Test stack clash protection probing for static allocas.
5
6; Small: one probe.
7define i32 @fun0() #0 {
8; CHECK-LABEL: fun0:
9; CHECK:       # %bb.0:
10; CHECK-NEXT:    aghi %r15, -560
11; CHECK-NEXT:    .cfi_def_cfa_offset 720
12; CHECK-NEXT:    cg %r0, 552(%r15)
13; CHECK-NEXT:    mvhi 552(%r15), 1
14; CHECK-NEXT:    l %r2, 160(%r15)
15; CHECK-NEXT:    aghi %r15, 560
16; CHECK-NEXT:    br %r14
17
18  %a = alloca i32, i64 100
19  %b = getelementptr inbounds i32, ptr %a, i64 98
20  store volatile i32 1, ptr %b
21  %c = load volatile i32, ptr %a
22  ret i32 %c
23}
24
25; Medium: two probes.
26define i32 @fun1() #0 {
27; CHECK-LABEL: fun1:
28; CHECK:       # %bb.0:
29; CHECK-NEXT:    aghi %r15, -4096
30; CHECK-NEXT:    .cfi_def_cfa_offset 4256
31; CHECK-NEXT:    cg %r0, 4088(%r15)
32; CHECK-NEXT:    aghi %r15, -4080
33; CHECK-NEXT:    .cfi_def_cfa_offset 8336
34; CHECK-NEXT:    cg %r0, 4072(%r15)
35; CHECK-NEXT:    mvhi 976(%r15), 1
36; CHECK-NEXT:    l %r2, 176(%r15)
37; CHECK-NEXT:    aghi %r15, 8176
38; CHECK-NEXT:    br %r14
39
40  %a = alloca i32, i64 2000
41  %b = getelementptr inbounds i32, ptr %a, i64 200
42  store volatile i32 1, ptr %b
43  %c = load volatile i32, ptr %a
44  ret i32 %c
45}
46
47; Large: Use a loop to allocate and probe in steps.
48define i32 @fun2() #0 {
49; CHECK-LABEL: fun2:
50; CHECK:       # %bb.0:
51; CHECK-NEXT:    lgr %r0, %r15
52; CHECK-NEXT:    .cfi_def_cfa_register %r0
53; CHECK-NEXT:    agfi %r0, -69632
54; CHECK-NEXT:    .cfi_def_cfa_offset 69792
55; CHECK-NEXT:  .LBB2_1: # =>This Inner Loop Header: Depth=1
56; CHECK-NEXT:    aghi %r15, -4096
57; CHECK-NEXT:    cg %r0, 4088(%r15)
58; CHECK-NEXT:    clgrjh %r15, %r0, .LBB2_1
59; CHECK-NEXT:  # %bb.2:
60; CHECK-NEXT:    .cfi_def_cfa_register %r15
61; CHECK-NEXT:    aghi %r15, -2544
62; CHECK-NEXT:    .cfi_def_cfa_offset 72336
63; CHECK-NEXT:    cg %r0, 2536(%r15)
64; CHECK-NEXT:    lhi %r0, 1
65; CHECK-NEXT:    mvhi 568(%r15), 1
66; CHECK-NEXT:    sty %r0, 28968(%r15)
67; CHECK-NEXT:    l %r2, 176(%r15)
68; CHECK-NEXT:    agfi %r15, 72176
69; CHECK-NEXT:    br %r14
70
71  %a = alloca i32, i64 18000
72  %b0 = getelementptr inbounds i32, ptr %a, i64 98
73  %b1 = getelementptr inbounds i32, ptr %a, i64 7198
74  store volatile i32 1, ptr %b0
75  store volatile i32 1, ptr %b1
76  %c = load volatile i32, ptr %a
77  ret i32 %c
78}
79
80; Ends evenly on the step so no remainder needed.
81define void @fun3() #0 {
82; CHECK-LABEL: fun3:
83; CHECK:       # %bb.0: # %entry
84; CHECK-NEXT:    lgr %r0, %r15
85; CHECK-NEXT:    .cfi_def_cfa_register %r0
86; CHECK-NEXT:    aghi %r0, -28672
87; CHECK-NEXT:    .cfi_def_cfa_offset 28832
88; CHECK-NEXT:  .LBB3_1: # %entry
89; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
90; CHECK-NEXT:    aghi %r15, -4096
91; CHECK-NEXT:    cg %r0, 4088(%r15)
92; CHECK-NEXT:    clgrjh %r15, %r0, .LBB3_1
93; CHECK-NEXT:  # %bb.2: # %entry
94; CHECK-NEXT:    .cfi_def_cfa_register %r15
95; CHECK-NEXT:    mvhi 180(%r15), 0
96; CHECK-NEXT:    l %r0, 180(%r15)
97; CHECK-NEXT:    aghi %r15, 28672
98; CHECK-NEXT:    br %r14
99entry:
100  %stack = alloca [7122 x i32], align 4
101  %i = alloca i32, align 4
102  store volatile i32 0, ptr %i, align 4
103  %i.0.i.0.6 = load volatile i32, ptr %i, align 4
104  ret void
105}
106
107; Loop with bigger step.
108define void @fun4() #0 "stack-probe-size"="8192" {
109; CHECK-LABEL: fun4:
110; CHECK:       # %bb.0: # %entry
111; CHECK-NEXT:    lgr %r0, %r15
112; CHECK-NEXT:    .cfi_def_cfa_register %r0
113; CHECK-NEXT:    aghi %r0, -24576
114; CHECK-NEXT:    .cfi_def_cfa_offset 24736
115; CHECK-NEXT:  .LBB4_1: # %entry
116; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
117; CHECK-NEXT:    aghi %r15, -8192
118; CHECK-NEXT:    cg %r0, 8184(%r15)
119; CHECK-NEXT:    clgrjh %r15, %r0, .LBB4_1
120; CHECK-NEXT:  # %bb.2: # %entry
121; CHECK-NEXT:    .cfi_def_cfa_register %r15
122; CHECK-NEXT:    aghi %r15, -7608
123; CHECK-NEXT:    .cfi_def_cfa_offset 32344
124; CHECK-NEXT:    cg %r0, 7600(%r15)
125; CHECK-NEXT:    mvhi 180(%r15), 0
126; CHECK-NEXT:    l %r0, 180(%r15)
127; CHECK-NEXT:    aghi %r15, 32184
128; CHECK-NEXT:    br %r14
129entry:
130  %stack = alloca [8000 x i32], align 4
131  %i = alloca i32, align 4
132  store volatile i32 0, ptr %i, align 4
133  %i.0.i.0.6 = load volatile i32, ptr %i, align 4
134  ret void
135}
136
137; Probe size should be modulo stack alignment.
138define void @fun5() #0 "stack-probe-size"="4100" {
139; CHECK-LABEL: fun5:
140; CHECK:       # %bb.0: # %entry
141; CHECK-NEXT:    aghi %r15, -4096
142; CHECK-NEXT:    .cfi_def_cfa_offset 4256
143; CHECK-NEXT:    cg %r0, 4088(%r15)
144; CHECK-NEXT:    aghi %r15, -88
145; CHECK-NEXT:    .cfi_def_cfa_offset 4344
146; CHECK-NEXT:    cg %r0, 80(%r15)
147; CHECK-NEXT:    mvhi 180(%r15), 0
148; CHECK-NEXT:    l %r0, 180(%r15)
149; CHECK-NEXT:    aghi %r15, 4184
150; CHECK-NEXT:    br %r14
151entry:
152  %stack = alloca [1000 x i32], align 4
153  %i = alloca i32, align 4
154  store volatile i32 0, ptr %i, align 4
155  %i.0.i.0.6 = load volatile i32, ptr %i, align 4
156  ret void
157}
158
159; The minimum probe size is the stack alignment.
160define void @fun6() #0 "stack-probe-size"="5" {
161; CHECK-LABEL: fun6:
162; CHECK:       # %bb.0: # %entry
163; CHECK-NEXT:    lgr %r0, %r15
164; CHECK-NEXT:    .cfi_def_cfa_register %r0
165; CHECK-NEXT:    aghi %r0, -4184
166; CHECK-NEXT:    .cfi_def_cfa_offset 4344
167; CHECK-NEXT:  .LBB6_1: # %entry
168; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
169; CHECK-NEXT:    aghi %r15, -8
170; CHECK-NEXT:    cg %r0, 0(%r15)
171; CHECK-NEXT:    clgrjh %r15, %r0, .LBB6_1
172; CHECK-NEXT:  # %bb.2: # %entry
173; CHECK-NEXT:    .cfi_def_cfa_register %r15
174; CHECK-NEXT:    mvhi 180(%r15), 0
175; CHECK-NEXT:    l %r0, 180(%r15)
176; CHECK-NEXT:    aghi %r15, 4184
177; CHECK-NEXT:    br %r14
178entry:
179  %stack = alloca [1000 x i32], align 4
180  %i = alloca i32, align 4
181  store volatile i32 0, ptr %i, align 4
182  %i.0.i.0.6 = load volatile i32, ptr %i, align 4
183  ret void
184}
185
186; Small with a natural probe (STMG) - needs no extra probe.
187define i32 @fun7() #0 {
188; CHECK-LABEL: fun7:
189; CHECK:       # %bb.0:
190; CHECK-NEXT:    stmg %r14, %r15, 112(%r15)
191; CHECK-NEXT:    .cfi_offset %r14, -48
192; CHECK-NEXT:    .cfi_offset %r15, -40
193; CHECK-NEXT:    aghi %r15, -3976
194; CHECK-NEXT:    .cfi_def_cfa_offset 4136
195; CHECK-NEXT:    brasl %r14, foo@PLT
196; CHECK-NEXT:    st %r2, 568(%r15)
197; CHECK-NEXT:    l %r2, 176(%r15)
198; CHECK-NEXT:    lmg %r14, %r15, 4088(%r15)
199; CHECK-NEXT:    br %r14
200  %v = call i32 @foo()
201  %a = alloca i32, i64 950
202  %b = getelementptr inbounds i32, ptr %a, i64 98
203  store volatile i32 %v, ptr %b
204  %c = load volatile i32, ptr %a
205  ret i32 %c
206}
207
208; Medium with an STMG - still needs probing.
209define i32 @fun8() #0 {
210; CHECK-LABEL: fun8:
211; CHECK:       # %bb.0:
212; CHECK-NEXT:    stmg %r14, %r15, 112(%r15)
213; CHECK-NEXT:    .cfi_offset %r14, -48
214; CHECK-NEXT:    .cfi_offset %r15, -40
215; CHECK-NEXT:    aghi %r15, -3984
216; CHECK-NEXT:    .cfi_def_cfa_offset 4144
217; CHECK-NEXT:    cg %r0, 3976(%r15)
218; CHECK-NEXT:    brasl %r14, foo@PLT
219; CHECK-NEXT:    st %r2, 976(%r15)
220; CHECK-NEXT:    l %r2, 176(%r15)
221; CHECK-NEXT:    lmg %r14, %r15, 4096(%r15)
222; CHECK-NEXT:    br %r14
223
224  %v = call i32 @foo()
225  %a = alloca i32, i64 952
226  %b = getelementptr inbounds i32, ptr %a, i64 200
227  store volatile i32 %v, ptr %b
228  %c = load volatile i32, ptr %a
229  ret i32 %c
230}
231
232define void @fun9() #0 "backchain" {
233; CHECK-LABEL: fun9:
234; CHECK:       # %bb.0: # %entry
235; CHECK-NEXT:    lgr %r1, %r15
236; CHECK-NEXT:    lgr %r0, %r15
237; CHECK-NEXT:    .cfi_def_cfa_register %r0
238; CHECK-NEXT:    aghi %r0, -28672
239; CHECK-NEXT:    .cfi_def_cfa_offset 28832
240; CHECK-NEXT:  .LBB9_1: # %entry
241; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
242; CHECK-NEXT:    aghi %r15, -4096
243; CHECK-NEXT:    cg %r0, 4088(%r15)
244; CHECK-NEXT:    clgrjh %r15, %r0, .LBB9_1
245; CHECK-NEXT:  # %bb.2: # %entry
246; CHECK-NEXT:    .cfi_def_cfa_register %r15
247; CHECK-NEXT:    stg %r1, 0(%r15)
248; CHECK-NEXT:    mvhi 180(%r15), 0
249; CHECK-NEXT:    l %r0, 180(%r15)
250; CHECK-NEXT:    aghi %r15, 28672
251; CHECK-NEXT:    br %r14
252entry:
253  %stack = alloca [7122 x i32], align 4
254  %i = alloca i32, align 4
255  store volatile i32 0, ptr %i, align 4
256  %i.0.i.0.6 = load volatile i32, ptr %i, align 4
257  ret void
258}
259
260
261declare i32 @foo()
262attributes #0 = {  "probe-stack"="inline-asm"  }
263
264