blob: 1b9807399a82d54af2b1406dbf3b557789ec2518 [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
8; CHECK-LABEL: alloca32:
Derek Schuff45cd5a72015-12-16 20:43:06 +00009; Check that there is an extra local for the stack pointer.
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000010; CHECK: .local i32{{$}}
Derek Schuff9769deb2015-12-11 23:49:46 +000011define void @alloca32() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000012 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer{{$}}
13 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
14 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
15 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
16 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +000017 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000018 %retval = alloca i32
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000019 ; CHECK: i32.const $push[[L0:.+]]=, 0
20 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L0]]
Derek Schuff9769deb2015-12-11 23:49:46 +000021 store i32 0, i32* %retval
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000022 ; CHECK: i32.const $push[[L5:.+]]=, 16
23 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L5]]
24 ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
Dan Gohman27a11eef2016-02-21 03:27:22 +000025 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000026 ret void
27}
28
29; CHECK-LABEL: alloca3264:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000030; CHECK: .local i32{{$}}
Derek Schuff9769deb2015-12-11 23:49:46 +000031define void @alloca3264() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000032 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
33 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
34 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
35 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
36 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +000037 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000038 %r1 = alloca i32
39 %r2 = alloca double
40 ; CHECK: i32.const $push[[L3:.+]]=, 0
41 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]]
42 store i32 0, i32* %r1
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000043 ; CHECK: i64.const $push[[L0:.+]]=, 0
44 ; CHECK: i64.store {{.*}}=, 0([[SP]]), $pop[[L0]]
Derek Schuff9769deb2015-12-11 23:49:46 +000045 store double 0.0, double* %r2
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000046 ; CHECK: i32.const $push[[L5:.+]]=, 16
47 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L5]]
48 ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
Dan Gohman27a11eef2016-02-21 03:27:22 +000049 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000050 ret void
51}
52
Derek Schuff45cd5a72015-12-16 20:43:06 +000053; CHECK-LABEL: allocarray:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000054; CHECK: .local i32, i32{{$}}
Derek Schuff9769deb2015-12-11 23:49:46 +000055define void @allocarray() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000056 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
57 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
58 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 32{{$}}
59 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
60 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +000061 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000062 %r = alloca [5 x i32]
Dan Gohman7e649172016-01-20 04:21:16 +000063
Dan Gohmanbb372242016-01-26 03:39:31 +000064 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, 12
Dan Gohman7e649172016-01-20 04:21:16 +000065 ; CHECK-NEXT: i32.const [[L5:.+]]=, 12
66 ; CHECK-NEXT: i32.add [[L5]]=, [[SP]], [[L5]]
67 ; CHECK-NEXT: i32.add $push[[L6:.+]]=, [[L5]], $pop[[L4]]
68 ; CHECK-NEXT: i32.const $push[[L9:.+]]=, 1{{$}}
69 ; CHECK-NEXT: i32.store $push[[L10:.+]]=, 12([[SP]]), $pop[[L9]]{{$}}
70 ; CHECK-NEXT: i32.store $discard=, 0($pop3), $pop[[L10]]{{$}}
Derek Schuff9769deb2015-12-11 23:49:46 +000071 %p = getelementptr [5 x i32], [5 x i32]* %r, i32 0, i32 0
72 store i32 1, i32* %p
Dan Gohmanbb372242016-01-26 03:39:31 +000073 %p2 = getelementptr [5 x i32], [5 x i32]* %r, i32 0, i32 3
Derek Schuff9769deb2015-12-11 23:49:46 +000074 store i32 1, i32* %p2
Dan Gohman7e649172016-01-20 04:21:16 +000075
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000076 ; CHECK: i32.const $push[[L11:.+]]=, 32
77 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L11]]
78 ; CHECK-NEXT: i32.const $push[[L12:.+]]=, __stack_pointer
Dan Gohman27a11eef2016-02-21 03:27:22 +000079 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L12]]), [[SP]]
Derek Schuff9769deb2015-12-11 23:49:46 +000080 ret void
81}
82
Derek Schuff90d9e8d2016-01-26 22:47:43 +000083declare void @ext_func(i64* %ptr)
84; CHECK-LABEL: non_mem_use
Derek Schuffc97ba932016-01-30 21:43:08 +000085define void @non_mem_use(i8** %addr) {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +000086 ; CHECK: i32.const $push[[L1:.+]]=, 48
87 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]]
Derek Schuffc97ba932016-01-30 21:43:08 +000088 %buf = alloca [27 x i8], align 16
Derek Schuff90d9e8d2016-01-26 22:47:43 +000089 %r = alloca i64
90 %r2 = alloca i64
91 ; %r is at SP+8
92 ; CHECK: i32.const [[OFF:.+]]=, 8
93 ; CHECK-NEXT: i32.add [[ARG1:.+]]=, [[SP]], [[OFF]]
94 ; CHECK-NEXT: call ext_func@FUNCTION, [[ARG1]]
95 call void @ext_func(i64* %r)
96 ; %r2 is at SP+0, no add needed
97 ; CHECK-NEXT: call ext_func@FUNCTION, [[SP]]
98 call void @ext_func(i64* %r2)
Derek Schuffc97ba932016-01-30 21:43:08 +000099 ; Use as a value, but in a store
100 ; %buf is at SP+16
101 ; CHECK: i32.const [[OFF:.+]]=, 16
102 ; CHECK-NEXT: i32.add [[VAL:.+]]=, [[SP]], [[OFF]]
103 ; CHECK-NEXT: i32.store {{.*}}=, 0($0), [[VAL]]
104 %gep = getelementptr inbounds [27 x i8], [27 x i8]* %buf, i32 0, i32 0
105 store i8* %gep, i8** %addr
Derek Schuff90d9e8d2016-01-26 22:47:43 +0000106 ret void
107}
108
Dan Gohman7e649172016-01-20 04:21:16 +0000109; CHECK-LABEL: allocarray_inbounds:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000110; CHECK: .local i32{{$}}
Derek Schuff9bfea272016-01-07 18:55:52 +0000111define void @allocarray_inbounds() {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000112 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
113 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
114 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 32{{$}}
115 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
Derek Schuff9bfea272016-01-07 18:55:52 +0000116 %r = alloca [5 x i32]
117 ; CHECK: i32.const $push[[L3:.+]]=, 1
118 ; CHECK: i32.store {{.*}}=, 12([[SP]]), $pop[[L3]]
119 %p = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 0
120 store i32 1, i32* %p
121 ; This store should have both the GEP and the FI folded into it.
Dan Gohmanbb372242016-01-26 03:39:31 +0000122 ; CHECK-NEXT: i32.store {{.*}}=, 24([[SP]]), $pop
123 %p2 = getelementptr inbounds [5 x i32], [5 x i32]* %r, i32 0, i32 3
Derek Schuff9bfea272016-01-07 18:55:52 +0000124 store i32 1, i32* %p2
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000125 ; CHECK: i32.const $push[[L5:.+]]=, 32
126 ; CHECK-NEXT: i32.add [[SP]]=, [[SP]], $pop[[L5]]
127 ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
Dan Gohman27a11eef2016-02-21 03:27:22 +0000128 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), [[SP]]
Derek Schuff9bfea272016-01-07 18:55:52 +0000129 ret void
130}
131
Dan Gohman7e649172016-01-20 04:21:16 +0000132; CHECK-LABEL: dynamic_alloca:
Derek Schuff8bb5f292015-12-16 23:21:30 +0000133define void @dynamic_alloca(i32 %alloc) {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000134 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
135 ; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]])
Derek Schuff6ea637a2016-01-29 18:37:49 +0000136 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
137 ; Target independent codegen bumps the stack pointer
Derek Schuff90dbb8c2016-02-20 22:18:47 +0000138 ; CHECK: i32.const $push[[L4:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +0000139 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L4]]), [[SP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000140 %r = alloca i32, i32 %alloc
141 ; Target-independent codegen also calculates the store addr
142 store i32 0, i32* %r
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000143 ; CHECK: i32.const $push[[L3:.+]]=, __stack_pointer
144 ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L3]]), [[FP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000145 ret void
146}
147
148
149; CHECK-LABEL: dynamic_static_alloca:
150define void @dynamic_static_alloca(i32 %alloc) {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000151 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
152 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
153 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
154 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000155 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000156 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer
157 ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000158 %r1 = alloca i32
159 %r = alloca i32, i32 %alloc
160 store i32 0, i32* %r
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000161 ; CHECK: i32.const $push[[L5:.+]]=, 16
162 ; CHECK-NEXT: i32.add [[SP]]=, [[FP]], $pop[[L5]]
163 ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
Dan Gohman27a11eef2016-02-21 03:27:22 +0000164 ; CHECK-NEXT: i32.store $discard=, 0($pop[[L6]]), [[SP]]
Derek Schuff8bb5f292015-12-16 23:21:30 +0000165 ret void
166}
Derek Schuffc97ba932016-01-30 21:43:08 +0000167
Derek Schuffaadc89c2016-02-16 18:18:36 +0000168; The use of the alloca in a phi causes a CopyToReg DAG node to be generated,
169; which has to have special handling because CopyToReg can't have a FI operand
170; CHECK-LABEL: copytoreg_fi:
171define void @copytoreg_fi(i1 %cond, i32* %b) {
172entry:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000173 ; CHECK: i32.const $push[[L1:.+]]=, 16
174 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]]
Derek Schuffaadc89c2016-02-16 18:18:36 +0000175 %addr = alloca i32
176 ; CHECK: i32.const [[OFF:.+]]=, 12
177 ; CHECK-NEXT: i32.add [[ADDR:.+]]=, [[SP]], [[OFF]]
178 ; CHECK-NEXT: copy_local [[COPY:.+]]=, [[ADDR]]
179 br label %body
180body:
181 %a = phi i32* [%addr, %entry], [%b, %body]
182 store i32 1, i32* %a
183 ; CHECK: i32.store {{.*}}, 0([[COPY]]),
184 br i1 %cond, label %body, label %exit
185exit:
186 ret void
187}
188
Dan Gohman94c65662016-02-16 23:48:04 +0000189declare void @use_i8_star(i8*)
190declare i8* @llvm.frameaddress(i32)
191
192; Test __builtin_frame_address(0).
Dan Gohman94c65662016-02-16 23:48:04 +0000193; CHECK-LABEL: frameaddress_0:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000194; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
195; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]])
196; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
Derek Schuff90dbb8c2016-02-20 22:18:47 +0000197; CHECK-NEXT: i32.const $push[[L2:.+]]=, __stack_pointer{{$}}
Dan Gohman27a11eef2016-02-21 03:27:22 +0000198; CHECK-NEXT: i32.store $discard=, 0($pop[[L2]]), [[SP]]
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000199; CHECK-NEXT: call use_i8_star@FUNCTION, [[FP]]
200; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
201; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[FP]]
Dan Gohman94c65662016-02-16 23:48:04 +0000202define void @frameaddress_0() {
203 %t = call i8* @llvm.frameaddress(i32 0)
204 call void @use_i8_star(i8* %t)
205 ret void
206}
207
208; Test __builtin_frame_address(1).
209
210; CHECK-LABEL: frameaddress_1:
211; CHECK-NEXT: i32.const $push0=, 0{{$}}
212; CHECK-NEXT: call use_i8_star@FUNCTION, $pop0{{$}}
213; CHECK-NEXT: return{{$}}
214define void @frameaddress_1() {
215 %t = call i8* @llvm.frameaddress(i32 1)
216 call void @use_i8_star(i8* %t)
217 ret void
218}
219
Dan Gohman02c08712016-02-20 23:09:44 +0000220; Test a stack address passed to an inline asm.
221; CHECK-LABEL: inline_asm:
222; CHECK: __stack_pointer
223; CHECK: #APP
224; CHECK-NEXT: # %{{[0-9]+}}{{$}}
225; CHECK-NEXT: #NO_APP
226define void @inline_asm() {
227 %tmp = alloca i8
228 call void asm sideeffect "# %0", "r"(i8* %tmp)
229 ret void
230}
231
Derek Schuffc97ba932016-01-30 21:43:08 +0000232; TODO: test over-aligned alloca