blob: 3b700e94e2b23836da5776d103c2996e62a4964f [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{{$}}
69; CHECK-NEXT: br_if $pop8, 0{{$}}
70; 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
93; be trivially stackified.
94
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 Gohman8887d1f2015-12-25 00:31:02 +000098; CHECK-NEXT: i32.load $3=, 0($2){{$}}
Dan Gohman1d68e80f2016-01-12 19:14:46 +000099; CHECK-NEXT: block{{$}}
Dan Gohman8887d1f2015-12-25 00:31:02 +0000100; CHECK-NEXT: i32.ge_u $push0=, $3, $1{{$}}
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000101; CHECK-NEXT: br_if $pop0, 0{{$}}
Dan Gohman8887d1f2015-12-25 00:31:02 +0000102; CHECK-NEXT: i32.lt_u $push1=, $3, $0{{$}}
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000103; CHECK-NEXT: br_if $pop1, 0{{$}}
Dan Gohman8887d1f2015-12-25 00:31:02 +0000104; CHECK-NEXT: i32.store $discard=, 0($2), $3{{$}}
Dan Gohmana4730cf2016-01-07 18:49:53 +0000105; CHECK-NEXT: .LBB5_3:
Dan Gohman1d68e80f2016-01-12 19:14:46 +0000106; CHECK-NEXT: end_block{{$}}
Dan Gohman8887d1f2015-12-25 00:31:02 +0000107; CHECK-NEXT: return{{$}}
108define void @multiple_uses(i32* %arg0, i32* %arg1, i32* %arg2) nounwind {
109bb:
110 br label %loop
111
112loop:
113 %tmp7 = load i32, i32* %arg2
114 %tmp8 = inttoptr i32 %tmp7 to i32*
115 %tmp9 = icmp uge i32* %tmp8, %arg1
116 %tmp10 = icmp ult i32* %tmp8, %arg0
117 %tmp11 = or i1 %tmp9, %tmp10
118 br i1 %tmp11, label %back, label %then
119
120then:
121 store i32 %tmp7, i32* %arg2
122 br label %back
123
124back:
125 br i1 undef, label %return, label %loop
126
127return:
128 ret void
129}
130
Dan Gohman7e649172016-01-20 04:21:16 +0000131; Don't stackify stores effects across other instructions with side effects.
132
133; CHECK: side_effects:
134; CHECK: store
135; CHECK-NEXT: call
136; CHECK-NEXT: store
137; CHECK-NEXT: call
138declare void @evoke_side_effects()
139define hidden void @stackify_store_across_side_effects(double* nocapture %d) {
140entry:
141 store double 2.0, double* %d
142 call void @evoke_side_effects()
143 store double 2.0, double* %d
144 call void @evoke_side_effects()
145 ret void
146}
147
Dan Gohman81719f82015-11-25 16:55:01 +0000148!0 = !{}