blob: c18a74e9a1d9d3fc3ad667a252e5436e3cfb1ecc [file] [log] [blame]
Dan Gohman1cf96c02015-12-09 16:23:59 +00001; RUN: llc < %s -asm-verbose=false -verify-machineinstrs | FileCheck %s
Dan Gohman81719f82015-11-25 16:55:01 +00002
3; Test the register stackifier pass.
4
Dan Gohman0c6f5ac2016-01-07 03:19:23 +00005target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
Dan Gohman81719f82015-11-25 16:55:01 +00006target triple = "wasm32-unknown-unknown"
7
8; No because of pointer aliasing.
9
10; CHECK-LABEL: no0:
11; CHECK: return $1{{$}}
12define i32 @no0(i32* %p, i32* %q) {
13 %t = load i32, i32* %q
14 store i32 0, i32* %p
15 ret i32 %t
16}
17
18; No because of side effects.
19
20; CHECK-LABEL: no1:
21; CHECK: return $1{{$}}
22define i32 @no1(i32* %p, i32* dereferenceable(4) %q) {
23 %t = load volatile i32, i32* %q, !invariant.load !0
24 store volatile i32 0, i32* %p
25 ret i32 %t
26}
27
28; Yes because of invariant load and no side effects.
29
30; CHECK-LABEL: yes0:
31; CHECK: return $pop0{{$}}
32define i32 @yes0(i32* %p, i32* dereferenceable(4) %q) {
33 %t = load i32, i32* %q, !invariant.load !0
34 store i32 0, i32* %p
35 ret i32 %t
36}
37
38; Yes because of no intervening side effects.
39
40; CHECK-LABEL: yes1:
41; CHECK: return $pop0{{$}}
42define i32 @yes1(i32* %q) {
43 %t = load volatile i32, i32* %q
44 ret i32 %t
45}
46
Dan Gohman4da4abd2015-12-05 00:51:40 +000047; Don't schedule stack uses into the stack. To reduce register pressure, the
48; scheduler might be tempted to move the definition of $2 down. However, this
49; would risk getting incorrect liveness if the instructions are later
50; rearranged to make the stack contiguous.
51
52; CHECK-LABEL: stack_uses:
Dan Gohmanf0b165a2015-12-05 03:03:35 +000053; CHECK-NEXT: .param i32, i32, i32, i32{{$}}
Dan Gohman4da4abd2015-12-05 00:51:40 +000054; CHECK-NEXT: .result i32{{$}}
Dan Gohman1d68e80f2016-01-12 19:14:46 +000055; CHECK-NEXT: block{{$}}
Dan Gohmanb6fd39a2016-01-19 16:59:23 +000056; CHECK-NEXT: i32.const $push13=, 1{{$}}
57; CHECK-NEXT: i32.lt_s $push0=, $0, $pop13{{$}}
58; CHECK-NEXT: i32.const $push1=, 2{{$}}
59; CHECK-NEXT: i32.lt_s $push2=, $1, $pop1{{$}}
60; CHECK-NEXT: i32.xor $push5=, $pop0, $pop2{{$}}
61; CHECK-NEXT: i32.const $push12=, 1{{$}}
62; CHECK-NEXT: i32.lt_s $push3=, $2, $pop12{{$}}
63; CHECK-NEXT: i32.const $push11=, 2{{$}}
64; CHECK-NEXT: i32.lt_s $push4=, $3, $pop11{{$}}
65; CHECK-NEXT: i32.xor $push6=, $pop3, $pop4{{$}}
66; CHECK-NEXT: i32.xor $push7=, $pop5, $pop6{{$}}
67; CHECK-NEXT: i32.const $push10=, 1{{$}}
68; CHECK-NEXT: i32.ne $push8=, $pop7, $pop10{{$}}
Dan Gohman06b49582016-02-08 21:50:13 +000069; CHECK-NEXT: br_if 0, $pop8{{$}}
Dan Gohmanb6fd39a2016-01-19 16:59:23 +000070; CHECK-NEXT: i32.const $push9=, 0{{$}}
71; CHECK-NEXT: return $pop9{{$}}
Dan Gohmana4730cf2016-01-07 18:49:53 +000072; CHECK-NEXT: .LBB4_2:
Dan Gohman1d68e80f2016-01-12 19:14:46 +000073; CHECK-NEXT: end_block{{$}}
Dan Gohmanb6fd39a2016-01-19 16:59:23 +000074; CHECK-NEXT: i32.const $push14=, 1{{$}}
75; CHECK-NEXT: return $pop14{{$}}
Dan Gohmanf0b165a2015-12-05 03:03:35 +000076define i32 @stack_uses(i32 %x, i32 %y, i32 %z, i32 %w) {
Dan Gohman4da4abd2015-12-05 00:51:40 +000077entry:
Dan Gohmanf0b165a2015-12-05 03:03:35 +000078 %c = icmp sle i32 %x, 0
79 %d = icmp sle i32 %y, 1
80 %e = icmp sle i32 %z, 0
81 %f = icmp sle i32 %w, 1
82 %g = xor i1 %c, %d
83 %h = xor i1 %e, %f
84 %i = xor i1 %g, %h
85 br i1 %i, label %true, label %false
Dan Gohman4da4abd2015-12-05 00:51:40 +000086true:
87 ret i32 0
88false:
89 ret i32 1
90}
91
Dan Gohman8887d1f2015-12-25 00:31:02 +000092; Test an interesting case where the load has multiple uses and cannot
Dan Gohmanadf28172016-01-28 01:22:44 +000093; be trivially stackified. However, it can be stackified with a tee_local.
Dan Gohman8887d1f2015-12-25 00:31:02 +000094
95; CHECK-LABEL: multiple_uses:
Dan Gohman1d68e80f2016-01-12 19:14:46 +000096; CHECK-NEXT: .param i32, i32, i32{{$}}
97; CHECK-NEXT: .local i32{{$}}
Dan Gohman1d68e80f2016-01-12 19:14:46 +000098; CHECK-NEXT: block{{$}}
Dan Gohmanadf28172016-01-28 01:22:44 +000099; CHECK-NEXT: i32.load $push0=, 0($2){{$}}
100; CHECK-NEXT: tee_local $push3=, $3=, $pop0{{$}}
101; CHECK-NEXT: i32.ge_u $push1=, $pop3, $1{{$}}
Dan Gohman06b49582016-02-08 21:50:13 +0000102; CHECK-NEXT: br_if 0, $pop1{{$}}
Dan Gohmanadf28172016-01-28 01:22:44 +0000103; CHECK-NEXT: i32.lt_u $push2=, $3, $0{{$}}
Dan Gohman06b49582016-02-08 21:50:13 +0000104; CHECK-NEXT: br_if 0, $pop2{{$}}
Dan Gohman8887d1f2015-12-25 00:31:02 +0000105; CHECK-NEXT: i32.store $discard=, 0($2), $3{{$}}
Dan Gohmana4730cf2016-01-07 18:49:53 +0000106; CHECK-NEXT: .LBB5_3:
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000107; CHECK-NEXT: end_block{{$}}
Dan Gohman8887d1f2015-12-25 00:31:02 +0000108; CHECK-NEXT: return{{$}}
109define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind {
110bb:
111 br label %loop
112
113loop:
114 %tmp7 = load i32, i32* %arg2
115 %tmp8 = inttoptr i32 %tmp7 to i32*
116 %tmp9 = icmp uge i32* %tmp8, %arg1
117 %tmp10 = icmp ult i32* %tmp8, %arg0
118 %tmp11 = or i1 %tmp9, %tmp10
119 br i1 %tmp11, label %back, label %then
120
121then:
122 store i32 %tmp7, i32* %arg2
123 br label %back
124
125back:
126 br i1 undef, label %return, label %loop
127
128return:
129 ret void
130}
131
Dan Gohman7e649172016-01-20 04:21:16 +0000132; Don't stackify stores effects across other instructions with side effects.
133
134; CHECK: side_effects:
135; CHECK: store
136; CHECK-NEXT: call
137; CHECK-NEXT: store
138; CHECK-NEXT: call
139declare void @evoke_side_effects()
140define hidden void @stackify_store_across_side_effects(double* nocapture %d) {
141entry:
142 store double 2.0, double* %d
143 call void @evoke_side_effects()
144 store double 2.0, double* %d
145 call void @evoke_side_effects()
146 ret void
147}
148
Dan Gohmanadf28172016-01-28 01:22:44 +0000149; Div instructions have side effects and can't be reordered, but this entire
150; function should still be able to be stackified because it's already in
151; tree order.
152
153; CHECK-LABEL: div_tree:
154; CHECK-NEXT: .param i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32{{$}}
155; CHECK-NEXT: .result i32{{$}}
156; CHECK-NEXT: i32.div_s $push0=, $0, $1
157; CHECK-NEXT: i32.div_s $push1=, $2, $3
158; CHECK-NEXT: i32.div_s $push2=, $pop0, $pop1
159; CHECK-NEXT: i32.div_s $push3=, $4, $5
160; CHECK-NEXT: i32.div_s $push4=, $6, $7
161; CHECK-NEXT: i32.div_s $push5=, $pop3, $pop4
162; CHECK-NEXT: i32.div_s $push6=, $pop2, $pop5
163; CHECK-NEXT: i32.div_s $push7=, $8, $9
164; CHECK-NEXT: i32.div_s $push8=, $10, $11
165; CHECK-NEXT: i32.div_s $push9=, $pop7, $pop8
166; CHECK-NEXT: i32.div_s $push10=, $12, $13
167; CHECK-NEXT: i32.div_s $push11=, $14, $15
168; CHECK-NEXT: i32.div_s $push12=, $pop10, $pop11
169; CHECK-NEXT: i32.div_s $push13=, $pop9, $pop12
170; CHECK-NEXT: i32.div_s $push14=, $pop6, $pop13
171; CHECK-NEXT: return $pop14
172define i32 @div_tree(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p) {
173entry:
174 %div = sdiv i32 %a, %b
175 %div1 = sdiv i32 %c, %d
176 %div2 = sdiv i32 %div, %div1
177 %div3 = sdiv i32 %e, %f
178 %div4 = sdiv i32 %g, %h
179 %div5 = sdiv i32 %div3, %div4
180 %div6 = sdiv i32 %div2, %div5
181 %div7 = sdiv i32 %i, %j
182 %div8 = sdiv i32 %k, %l
183 %div9 = sdiv i32 %div7, %div8
184 %div10 = sdiv i32 %m, %n
185 %div11 = sdiv i32 %o, %p
186 %div12 = sdiv i32 %div10, %div11
187 %div13 = sdiv i32 %div9, %div12
188 %div14 = sdiv i32 %div6, %div13
189 ret i32 %div14
190}
191
192; A simple multiple-use case.
193
194; CHECK-LABEL: simple_multiple_use:
195; CHECK-NEXT: .param i32, i32{{$}}
196; CHECK-NEXT: i32.mul $push0=, $1, $0{{$}}
197; CHECK-NEXT: tee_local $push1=, $0=, $pop0{{$}}
198; CHECK-NEXT: call use_a@FUNCTION, $pop1{{$}}
199; CHECK-NEXT: call use_b@FUNCTION, $0{{$}}
200; CHECK-NEXT: return{{$}}
201declare void @use_a(i32)
202declare void @use_b(i32)
203define void @simple_multiple_use(i32 %x, i32 %y) {
204 %mul = mul i32 %y, %x
205 call void @use_a(i32 %mul)
206 call void @use_b(i32 %mul)
207 ret void
208}
209
210; Multiple uses of the same value in one instruction.
211
212; CHECK-LABEL: multiple_uses_in_same_insn:
213; CHECK-NEXT: .param i32, i32{{$}}
214; CHECK-NEXT: i32.mul $push0=, $1, $0{{$}}
215; CHECK-NEXT: tee_local $push1=, $0=, $pop0{{$}}
216; CHECK-NEXT: call use_2@FUNCTION, $pop1, $0{{$}}
217; CHECK-NEXT: return{{$}}
218declare void @use_2(i32, i32)
219define void @multiple_uses_in_same_insn(i32 %x, i32 %y) {
220 %mul = mul i32 %y, %x
221 call void @use_2(i32 %mul, i32 %mul)
222 ret void
223}
224
225; Commute operands to achieve better stackifying.
226
227; CHECK-LABEL: commute:
228; CHECK-NEXT: .result i32{{$}}
229; CHECK-NEXT: i32.call $push0=, red@FUNCTION{{$}}
230; CHECK-NEXT: i32.call $push1=, green@FUNCTION{{$}}
231; CHECK-NEXT: i32.add $push2=, $pop0, $pop1{{$}}
232; CHECK-NEXT: i32.call $push3=, blue@FUNCTION{{$}}
233; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}}
234; CHECK-NEXT: return $pop4{{$}}
235declare i32 @red()
236declare i32 @green()
237declare i32 @blue()
238define i32 @commute() {
239 %call = call i32 @red()
240 %call1 = call i32 @green()
241 %add = add i32 %call1, %call
242 %call2 = call i32 @blue()
243 %add3 = add i32 %add, %call2
244 ret i32 %add3
245}
246
Dan Gohmanfbfe5ec2016-01-28 03:59:09 +0000247; Don't stackify a register when it would move a the def of the register past
248; an implicit get_local for the register.
249
250; CHECK-LABEL: no_stackify_past_use:
251; CHECK: i32.call $1=, callee@FUNCTION, $0
252; CHECK: i32.const $push0=, 1
253; CHECK: i32.add $push1=, $0, $pop0
254; CHECK: i32.call $push2=, callee@FUNCTION, $pop1
255; CHECK: i32.add $push3=, $1, $pop2
256; CHECK: i32.mul $push4=, $1, $pop3
257; CHECK: return $pop4
258declare i32 @callee(i32)
259define i32 @no_stackify_past_use(i32 %arg) {
260 %tmp1 = call i32 @callee(i32 %arg)
261 %tmp2 = add i32 %arg, 1
262 %tmp3 = call i32 @callee(i32 %tmp2)
263 %tmp5 = add i32 %tmp3, %tmp1
264 %tmp6 = mul i32 %tmp5, %tmp1
265 ret i32 %tmp6
266}
267
Dan Gohman81719f82015-11-25 16:55:01 +0000268!0 = !{}