blob: 09748e6403cf0e47ecdf3819da2dd8534d141e98 [file] [log] [blame]
Derek Schuff9769deb2015-12-11 23:49:46 +00001; RUN: llc < %s -asm-verbose=false | FileCheck %s
2; RUN: llc < %s -asm-verbose=false -fast-isel | FileCheck %s
3
4
Dan Gohman0c6f5ac2016-01-07 03:19:23 +00005target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
Derek Schuff9769deb2015-12-11 23:49:46 +00006target triple = "wasm32-unknown-unknown"
7
Derek Schuff4b3bb212016-02-23 18:13:07 +00008declare void @ext_func(i64* %ptr)
9declare void @ext_func_i32(i32* %ptr)
10
Derek Schuff9769deb2015-12-11 23:49:46 +000011; CHECK-LABEL: alloca32:
Derek Schuff45cd5a72015-12-16 20:43:06 +000012; Check that there is an extra local for the stack pointer.
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000013; CHECK: .local i32{{$}}
Derek Schuff4b3bb212016-02-23 18:13:07 +000014define void @alloca32() noredzone {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000015 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer{{$}}
16 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
17 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
18 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
19 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +000020 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000021 %retval = alloca i32
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000022 ; CHECK: i32.const $push[[L0:.+]]=, 0
23 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L0]]
Derek Schuff9769deb2015-12-11 23:49:46 +000024 store i32 0, i32* %retval
Derek Schuffd4207ba2016-03-17 17:00:29 +000025 ; CHECK: i32.const $push[[L6:.+]]=, __stack_pointer
26 ; CHECK-NEXT: i32.const $push[[L5:.+]]=, 16
27 ; CHECK-NEXT: i32.add $push[[L7:.+]]=, [[SP]], $pop[[L5]]
28 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), $pop[[L7]]
Derek Schuff9769deb2015-12-11 23:49:46 +000029 ret void
30}
31
32; CHECK-LABEL: alloca3264:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000033; CHECK: .local i32{{$}}
Derek Schuff9769deb2015-12-11 23:49:46 +000034define void @alloca3264() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000035 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
36 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
37 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
38 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
Derek Schuff9769deb2015-12-11 23:49:46 +000039 %r1 = alloca i32
40 %r2 = alloca double
Derek Schuff4b3bb212016-02-23 18:13:07 +000041 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 0
42 ; CHECK-NEXT: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]]
Derek Schuff9769deb2015-12-11 23:49:46 +000043 store i32 0, i32* %r1
Derek Schuff4b3bb212016-02-23 18:13:07 +000044 ; CHECK-NEXT: i64.const $push[[L0:.+]]=, 0
45 ; CHECK-NEXT: i64.store {{.*}}=, 0([[SP]]), $pop[[L0]]
Derek Schuff9769deb2015-12-11 23:49:46 +000046 store double 0.0, double* %r2
Derek Schuff4b3bb212016-02-23 18:13:07 +000047 ; CHECK-NEXT: return
Derek Schuff9769deb2015-12-11 23:49:46 +000048 ret void
49}
50
Derek Schuff45cd5a72015-12-16 20:43:06 +000051; CHECK-LABEL: allocarray:
Derek Schuffd4207ba2016-03-17 17:00:29 +000052; CHECK: .local i32{{$}}
Derek Schuff9769deb2015-12-11 23:49:46 +000053define void @allocarray() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000054 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
55 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
Derek Schuff4b3bb212016-02-23 18:13:07 +000056 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 144{{$}}
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000057 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
58 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +000059 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff4b3bb212016-02-23 18:13:07 +000060 %r = alloca [33 x i32]
Dan Gohman7e649172016-01-20 04:21:16 +000061
Derek Schuffd4207ba2016-03-17 17:00:29 +000062 ; CHECK-NEXT: i32.const $push[[L5:.+]]=, 12
63 ; CHECK-NEXT: i32.add $push[[L7:.+]]=, [[SP]], $pop[[L5]]
Dan Gohmanbb372242016-01-26 03:39:31 +000064 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, 12
Derek Schuffd4207ba2016-03-17 17:00:29 +000065 ; CHECK-NEXT: i32.add $push[[L6:.+]]=, $pop[[L7]], $pop[[L4]]
Dan Gohman7e649172016-01-20 04:21:16 +000066 ; CHECK-NEXT: i32.const $push[[L9:.+]]=, 1{{$}}
67 ; CHECK-NEXT: i32.store $push[[L10:.+]]=, 12([[SP]]), $pop[[L9]]{{$}}
68 ; CHECK-NEXT: i32.store $discard=, 0($pop3), $pop[[L10]]{{$}}
Derek Schuff4b3bb212016-02-23 18:13:07 +000069 %p = getelementptr [33 x i32], [33 x i32]* %r, i32 0, i32 0
Derek Schuff9769deb2015-12-11 23:49:46 +000070 store i32 1, i32* %p
Derek Schuff4b3bb212016-02-23 18:13:07 +000071 %p2 = getelementptr [33 x i32], [33 x i32]* %r, i32 0, i32 3
Derek Schuff9769deb2015-12-11 23:49:46 +000072 store i32 1, i32* %p2
Dan Gohman7e649172016-01-20 04:21:16 +000073
Derek Schuffd4207ba2016-03-17 17:00:29 +000074 ; CHECK: i32.const $push[[L12:.+]]=, __stack_pointer
75 ; CHECK-NEXT: i32.const $push[[L11:.+]]=, 144
76 ; CHECK-NEXT: i32.add $push[[L13:.+]]=, [[SP]], $pop[[L11]]
77 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L12]]), $pop[[L13]]
Derek Schuff9769deb2015-12-11 23:49:46 +000078 ret void
79}
80
Derek Schuff90d9e8d2016-01-26 22:47:43 +000081; CHECK-LABEL: non_mem_use
Derek Schuffc97ba932016-01-30 21:43:08 +000082define void @non_mem_use(i8** %addr) {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000083 ; CHECK: i32.const $push[[L1:.+]]=, 48
84 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]]
Derek Schuffc97ba932016-01-30 21:43:08 +000085 %buf = alloca [27 x i8], align 16
Derek Schuff90d9e8d2016-01-26 22:47:43 +000086 %r = alloca i64
87 %r2 = alloca i64
88 ; %r is at SP+8
Derek Schuffd4207ba2016-03-17 17:00:29 +000089 ; CHECK: i32.const $push[[OFF:.+]]=, 8
90 ; CHECK-NEXT: i32.add $push[[ARG1:.+]]=, [[SP]], $pop[[OFF]]
91 ; CHECK-NEXT: call ext_func@FUNCTION, $pop[[ARG1]]
Derek Schuff90d9e8d2016-01-26 22:47:43 +000092 call void @ext_func(i64* %r)
93 ; %r2 is at SP+0, no add needed
94 ; CHECK-NEXT: call ext_func@FUNCTION, [[SP]]
95 call void @ext_func(i64* %r2)
Derek Schuffc97ba932016-01-30 21:43:08 +000096 ; Use as a value, but in a store
97 ; %buf is at SP+16
Derek Schuffd4207ba2016-03-17 17:00:29 +000098 ; CHECK: i32.const $push[[OFF:.+]]=, 16
99 ; CHECK-NEXT: i32.add $push[[VAL:.+]]=, [[SP]], $pop[[OFF]]
100 ; CHECK-NEXT: i32.store {{.*}}=, 0($0), $pop[[VAL]]
Derek Schuffc97ba932016-01-30 21:43:08 +0000101 %gep = getelementptr inbounds [27 x i8], [27 x i8]* %buf, i32 0, i32 0
102 store i8* %gep, i8** %addr
Derek Schuff90d9e8d2016-01-26 22:47:43 +0000103 ret void
104}
105
Dan Gohman7e649172016-01-20 04:21:16 +0000106; CHECK-LABEL: allocarray_inbounds:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000107; CHECK: .local i32{{$}}
Derek Schuff9bfea272016-01-07 18:55:52 +0000108define void @allocarray_inbounds() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000109 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
110 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
111 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 32{{$}}
112 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
Derek Schuff9bfea272016-01-07 18:55:52 +0000113 %r = alloca [5 x i32]
114 ; CHECK: i32.const $push[[L3:.+]]=, 1
115 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]]
116 %p = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 0
117 store i32 1, i32* %p
118 ; This store should have both the GEP and the FI folded into it.
Dan Gohmanbb372242016-01-26 03:39:31 +0000119 ; CHECK-NEXT: i32.store {{.*}}=, 24([[SP]]), $pop
120 %p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 3
Derek Schuff9bfea272016-01-07 18:55:52 +0000121 store i32 1, i32* %p2
Derek Schuff4b3bb212016-02-23 18:13:07 +0000122 call void @ext_func(i64* null);
Derek Schuffd4207ba2016-03-17 17:00:29 +0000123 ; CHECK: i32.const $push[[L6:.+]]=, __stack_pointer
124 ; CHECK-NEXT: i32.const $push[[L5:.+]]=, 32
125 ; CHECK-NEXT: i32.add $push[[L7:.+]]=, [[SP]], $pop[[L5]]
126 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), $pop[[L7]]
Derek Schuff9bfea272016-01-07 18:55:52 +0000127 ret void
128}
129
Dan Gohman7e649172016-01-20 04:21:16 +0000130; CHECK-LABEL: dynamic_alloca:
Derek Schuff8bb5f292015-12-16 23:21:30 +0000131define void @dynamic_alloca(i32 %alloc) {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000132 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
133 ; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]])
Derek Schuff6ea637a2016-01-29 18:37:49 +0000134 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
Derek Schuff27e3b8a2016-02-22 21:57:17 +0000135 ; Target independent codegen bumps the stack pointer.
136 ; CHECK: i32.sub
137 ; CHECK-NEXT: copy_local [[SP]]=,
138 ; Check that SP is written back to memory after decrement
139 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +0000140 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000141 %r = alloca i32, i32 %alloc
142 ; Target-independent codegen also calculates the store addr
Derek Schuff4b3bb212016-02-23 18:13:07 +0000143 ; CHECK: call ext_func_i32@FUNCTION
144 call void @ext_func_i32(i32* %r)
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000145 ; CHECK: i32.const $push[[L3:.+]]=, __stack_pointer
Derek Schuffd4207ba2016-03-17 17:00:29 +0000146 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L3]]), [[FP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000147 ret void
148}
149
Derek Schuff4b3bb212016-02-23 18:13:07 +0000150; CHECK-LABEL: dynamic_alloca_redzone:
151define void @dynamic_alloca_redzone(i32 %alloc) {
152 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
153 ; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]])
154 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
155 ; Target independent codegen bumps the stack pointer
156 ; CHECK: i32.sub [[R:.+]]=,
157 ; CHECK-NEXT: copy_local [[SP]]=, [[R]]
158 %r = alloca i32, i32 %alloc
159 ; check-next here asserts that SP is not written back.
160 ; CHECK-NEXT: i32.const $push[[ZERO:.+]]=, 0
161 ; CHECK-NEXT: i32.store $discard=, 0([[R]]), $pop[[ZERO]]
162 store i32 0, i32* %r
163 ; CHECK-NEXT: return
164 ret void
165}
166
Derek Schuff6ea637a2016-01-29 18:37:49 +0000167; CHECK-LABEL: dynamic_static_alloca:
Derek Schuff4b3bb212016-02-23 18:13:07 +0000168define void @dynamic_static_alloca(i32 %alloc) noredzone {
Derek Schuff27e3b8a2016-02-22 21:57:17 +0000169 ; Decrement SP in the prolog by the static amount and writeback to memory.
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000170 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
171 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
172 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
173 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000174 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000175 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer
176 ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]]
Derek Schuff27e3b8a2016-02-22 21:57:17 +0000177 ; Decrement SP in the body by the dynamic amount.
178 ; CHECK: i32.sub
179 ; CHECK: copy_local [[SP]]=,
180 ; Writeback to memory.
181 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer
182 ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000183 %r1 = alloca i32
184 %r = alloca i32, i32 %alloc
185 store i32 0, i32* %r
Derek Schuffd4207ba2016-03-17 17:00:29 +0000186 ; CHECK: i32.const $push[[L6:.+]]=, __stack_pointer
187 ; CHECK-NEXT: i32.const $push[[L5:.+]]=, 16
188 ; CHECK-NEXT: i32.add $push[[L7:.+]]=, [[FP]], $pop[[L5]]
189 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), $pop[[L7]]
Derek Schuff8bb5f292015-12-16 23:21:30 +0000190 ret void
191}
Derek Schuffc97ba932016-01-30 21:43:08 +0000192
Derek Schuffaadc89c2016-02-16 18:18:36 +0000193; The use of the alloca in a phi causes a CopyToReg DAG node to be generated,
194; which has to have special handling because CopyToReg can't have a FI operand
195; CHECK-LABEL: copytoreg_fi:
196define void @copytoreg_fi(i1 %cond, i32* %b) {
197entry:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000198 ; CHECK: i32.const $push[[L1:.+]]=, 16
199 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]]
Derek Schuffaadc89c2016-02-16 18:18:36 +0000200 %addr = alloca i32
Derek Schuffd4207ba2016-03-17 17:00:29 +0000201 ; CHECK: i32.const $push[[OFF:.+]]=, 12
202 ; CHECK-NEXT: i32.add $push[[ADDR:.+]]=, [[SP]], $pop[[OFF]]
203 ; CHECK-NEXT: copy_local [[COPY:.+]]=, $pop[[ADDR]]
Derek Schuffaadc89c2016-02-16 18:18:36 +0000204 br label %body
205body:
206 %a = phi i32* [%addr, %entry], [%b, %body]
207 store i32 1, i32* %a
208 ; CHECK: i32.store {{.*}}, 0([[COPY]]),
209 br i1 %cond, label %body, label %exit
210exit:
211 ret void
212}
213
Dan Gohman94c65662016-02-16 23:48:04 +0000214declare void @use_i8_star(i8*)
215declare i8* @llvm.frameaddress(i32)
216
217; Test __builtin_frame_address(0).
Dan Gohman94c65662016-02-16 23:48:04 +0000218; CHECK-LABEL: frameaddress_0:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000219; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
220; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]])
221; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
222; CHECK-NEXT: call use_i8_star@FUNCTION, [[FP]]
Derek Schuff4b3bb212016-02-23 18:13:07 +0000223; CHEC K-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
224; CHEC K-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[FP]]
Dan Gohman94c65662016-02-16 23:48:04 +0000225define void @frameaddress_0() {
226 %t = call i8* @llvm.frameaddress(i32 0)
227 call void @use_i8_star(i8* %t)
228 ret void
229}
230
231; Test __builtin_frame_address(1).
232
233; CHECK-LABEL: frameaddress_1:
234; CHECK-NEXT: i32.const $push0=, 0{{$}}
235; CHECK-NEXT: call use_i8_star@FUNCTION, $pop0{{$}}
236; CHECK-NEXT: return{{$}}
237define void @frameaddress_1() {
238 %t = call i8* @llvm.frameaddress(i32 1)
239 call void @use_i8_star(i8* %t)
240 ret void
241}
242
Dan Gohman02c08712016-02-20 23:09:44 +0000243; Test a stack address passed to an inline asm.
244; CHECK-LABEL: inline_asm:
245; CHECK: __stack_pointer
246; CHECK: #APP
247; CHECK-NEXT: # %{{[0-9]+}}{{$}}
248; CHECK-NEXT: #NO_APP
249define void @inline_asm() {
250 %tmp = alloca i8
251 call void asm sideeffect "# %0", "r"(i8* %tmp)
252 ret void
253}
254
Derek Schuffc97ba932016-01-30 21:43:08 +0000255; TODO: test over-aligned alloca