blob: ac41c947a49219abb03c23c050b6c58fd0808fae [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{{$}}
17 ; CHECK-NEXT: i32.store [[SP]]=, 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
25 ; CHECK-NEXT: i32.store [[SP]]=, 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{{$}}
37 ; CHECK-NEXT: i32.store [[SP]]=, 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
49 ; CHECK-NEXT: i32.store [[SP]]=, 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{{$}}
61 ; CHECK-NEXT: i32.store [[SP]]=, 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
79 ; CHECK-NEXT: i32.store [[SP]]=, 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
128 ; CHECK-NEXT: i32.store [[SP]]=, 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
138 ; FIXME: we need to write the value back to memory
139 %r = alloca i32, i32 %alloc
140 ; Target-independent codegen also calculates the store addr
141 store i32 0, i32* %r
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000142 ; CHECK: i32.const $push[[L3:.+]]=, __stack_pointer
143 ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L3]]), [[FP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000144 ret void
145}
146
147
148; CHECK-LABEL: dynamic_static_alloca:
149define void @dynamic_static_alloca(i32 %alloc) {
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000150 ; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
151 ; CHECK-NEXT: i32.load $push[[L2:.+]]=, 0($pop[[L1]])
152 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
153 ; CHECK-NEXT: i32.sub [[SP:.+]]=, $pop[[L2]], $pop[[L3]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000154 ; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000155 ; CHECK-NEXT: i32.const $push[[L4:.+]]=, __stack_pointer
156 ; CHECK-NEXT: i32.store {{.*}}=, 0($pop[[L4]]), [[SP]]
Derek Schuff6ea637a2016-01-29 18:37:49 +0000157 %r1 = alloca i32
158 %r = alloca i32, i32 %alloc
159 store i32 0, i32* %r
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000160 ; CHECK: i32.const $push[[L5:.+]]=, 16
161 ; CHECK-NEXT: i32.add [[SP]]=, [[FP]], $pop[[L5]]
162 ; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
163 ; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[SP]]
Derek Schuff8bb5f292015-12-16 23:21:30 +0000164 ret void
165}
Derek Schuffc97ba932016-01-30 21:43:08 +0000166
Derek Schuffaadc89c2016-02-16 18:18:36 +0000167; The use of the alloca in a phi causes a CopyToReg DAG node to be generated,
168; which has to have special handling because CopyToReg can't have a FI operand
169; CHECK-LABEL: copytoreg_fi:
170define void @copytoreg_fi(i1 %cond, i32* %b) {
171entry:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000172 ; CHECK: i32.const $push[[L1:.+]]=, 16
173 ; CHECK-NEXT: i32.sub [[SP:.+]]=, {{.+}}, $pop[[L1]]
Derek Schuffaadc89c2016-02-16 18:18:36 +0000174 %addr = alloca i32
175 ; CHECK: i32.const [[OFF:.+]]=, 12
176 ; CHECK-NEXT: i32.add [[ADDR:.+]]=, [[SP]], [[OFF]]
177 ; CHECK-NEXT: copy_local [[COPY:.+]]=, [[ADDR]]
178 br label %body
179body:
180 %a = phi i32* [%addr, %entry], [%b, %body]
181 store i32 1, i32* %a
182 ; CHECK: i32.store {{.*}}, 0([[COPY]]),
183 br i1 %cond, label %body, label %exit
184exit:
185 ret void
186}
187
Dan Gohman94c65662016-02-16 23:48:04 +0000188declare void @use_i8_star(i8*)
189declare i8* @llvm.frameaddress(i32)
190
191; Test __builtin_frame_address(0).
Dan Gohman94c65662016-02-16 23:48:04 +0000192; CHECK-LABEL: frameaddress_0:
Derek Schuffdc5f6aa2016-02-20 21:46:50 +0000193; CHECK: i32.const $push[[L1:.+]]=, __stack_pointer
194; CHECK-NEXT: i32.load [[SP:.+]]=, 0($pop[[L1]])
195; CHECK-NEXT: copy_local [[FP:.+]]=, [[SP]]
196; CHECK-NEXT: call use_i8_star@FUNCTION, [[FP]]
197; CHECK-NEXT: i32.const $push[[L6:.+]]=, __stack_pointer
198; CHECK-NEXT: i32.store [[SP]]=, 0($pop[[L6]]), [[FP]]
Dan Gohman94c65662016-02-16 23:48:04 +0000199define void @frameaddress_0() {
200 %t = call i8* @llvm.frameaddress(i32 0)
201 call void @use_i8_star(i8* %t)
202 ret void
203}
204
205; Test __builtin_frame_address(1).
206
207; CHECK-LABEL: frameaddress_1:
208; CHECK-NEXT: i32.const $push0=, 0{{$}}
209; CHECK-NEXT: call use_i8_star@FUNCTION, $pop0{{$}}
210; CHECK-NEXT: return{{$}}
211define void @frameaddress_1() {
212 %t = call i8* @llvm.frameaddress(i32 1)
213 call void @use_i8_star(i8* %t)
214 ret void
215}
216
Derek Schuffc97ba932016-01-30 21:43:08 +0000217; TODO: test over-aligned alloca