Skip to content

Commit 32a2805

Browse files
Add SROA tests for casts between fixed and scalable types.
1 parent 7e3fe88 commit 32a2805

File tree

2 files changed

+585
-1
lines changed

2 files changed

+585
-1
lines changed
Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG
3+
; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG
4+
5+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64"
6+
7+
; This test checks that SROA runs mem2reg on scalable vectors.
8+
9+
define <vscale x 16 x i1> @alloca_nxv16i1(<vscale x 16 x i1> %pg) vscale_range(1) {
10+
; CHECK-LABEL: @alloca_nxv16i1(
11+
; CHECK-NEXT: ret <vscale x 16 x i1> [[PG:%.*]]
12+
;
13+
%pg.addr = alloca <vscale x 16 x i1>
14+
store <vscale x 16 x i1> %pg, ptr %pg.addr
15+
%1 = load <vscale x 16 x i1>, ptr %pg.addr
16+
ret <vscale x 16 x i1> %1
17+
}
18+
19+
define <vscale x 16 x i8> @alloca_nxv16i8(<vscale x 16 x i8> %vec) vscale_range(1) {
20+
; CHECK-LABEL: @alloca_nxv16i8(
21+
; CHECK-NEXT: ret <vscale x 16 x i8> [[VEC:%.*]]
22+
;
23+
%vec.addr = alloca <vscale x 16 x i8>
24+
store <vscale x 16 x i8> %vec, ptr %vec.addr
25+
%1 = load <vscale x 16 x i8>, ptr %vec.addr
26+
ret <vscale x 16 x i8> %1
27+
}
28+
29+
; Test scalable alloca that can't be promoted. Mem2Reg only considers
30+
; non-volatile loads and stores for promotion.
31+
define <vscale x 16 x i8> @unpromotable_alloca(<vscale x 16 x i8> %vec) vscale_range(1) {
32+
; CHECK-LABEL: @unpromotable_alloca(
33+
; CHECK-NEXT: [[VEC_ADDR:%.*]] = alloca <vscale x 16 x i8>, align 16
34+
; CHECK-NEXT: store volatile <vscale x 16 x i8> [[VEC:%.*]], ptr [[VEC_ADDR]], align 16
35+
; CHECK-NEXT: [[TMP1:%.*]] = load volatile <vscale x 16 x i8>, ptr [[VEC_ADDR]], align 16
36+
; CHECK-NEXT: ret <vscale x 16 x i8> [[TMP1]]
37+
;
38+
%vec.addr = alloca <vscale x 16 x i8>
39+
store volatile <vscale x 16 x i8> %vec, ptr %vec.addr
40+
%1 = load volatile <vscale x 16 x i8>, ptr %vec.addr
41+
ret <vscale x 16 x i8> %1
42+
}
43+
44+
; Test we bail out when using an alloca of a fixed-length vector (VLS) that was
45+
; bitcasted to a scalable vector.
46+
define <vscale x 4 x i32> @cast_alloca_to_svint32_t(<vscale x 4 x i32> %type.coerce) vscale_range(1) {
47+
; CHECK-LABEL: @cast_alloca_to_svint32_t(
48+
; CHECK-NEXT: [[TYPE:%.*]] = alloca <16 x i32>, align 64
49+
; CHECK-NEXT: [[TYPE_ADDR:%.*]] = alloca <16 x i32>, align 64
50+
; CHECK-NEXT: store <vscale x 4 x i32> [[TYPE_COERCE:%.*]], ptr [[TYPE]], align 16
51+
; CHECK-NEXT: [[TYPE1:%.*]] = load <16 x i32>, ptr [[TYPE]], align 64
52+
; CHECK-NEXT: store <16 x i32> [[TYPE1]], ptr [[TYPE_ADDR]], align 64
53+
; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i32>, ptr [[TYPE_ADDR]], align 64
54+
; CHECK-NEXT: [[TMP2:%.*]] = load <vscale x 4 x i32>, ptr [[TYPE_ADDR]], align 16
55+
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP2]]
56+
;
57+
%type = alloca <16 x i32>
58+
%type.addr = alloca <16 x i32>
59+
store <vscale x 4 x i32> %type.coerce, ptr %type
60+
%type1 = load <16 x i32>, ptr %type
61+
store <16 x i32> %type1, ptr %type.addr
62+
%1 = load <16 x i32>, ptr %type.addr
63+
%2 = load <vscale x 4 x i32>, ptr %type.addr
64+
ret <vscale x 4 x i32> %2
65+
}
66+
67+
; When casting from VLA to VLS via memory check we bail out when producing a
68+
; GEP where the element type is a scalable vector.
69+
define <vscale x 4 x i32> @cast_alloca_from_svint32_t() vscale_range(1) {
70+
; CHECK-LABEL: @cast_alloca_from_svint32_t(
71+
; CHECK-NEXT: [[RETVAL_COERCE:%.*]] = alloca <vscale x 4 x i32>, align 16
72+
; CHECK-NEXT: store <16 x i32> zeroinitializer, ptr [[RETVAL_COERCE]], align 16
73+
; CHECK-NEXT: [[TMP1:%.*]] = load <vscale x 4 x i32>, ptr [[RETVAL_COERCE]], align 16
74+
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]]
75+
;
76+
%retval = alloca <16 x i32>
77+
store <16 x i32> zeroinitializer, ptr %retval
78+
%retval.coerce = alloca <vscale x 4 x i32>
79+
call void @llvm.memcpy.p0.p0.i64(ptr align 16 %retval.coerce, ptr align 16 %retval, i64 64, i1 false)
80+
%1 = load <vscale x 4 x i32>, ptr %retval.coerce
81+
ret <vscale x 4 x i32> %1
82+
}
83+
84+
; Test we bail out when using an alloca of a fixed-length vector (VLS) that was
85+
; bitcasted to a scalable vector.
86+
define void @select_load_alloca_to_svdouble_t() vscale_range(1) {
87+
; CHECK-LABEL: @select_load_alloca_to_svdouble_t(
88+
; CHECK-NEXT: [[Z:%.*]] = alloca <16 x half>, align 32
89+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 0, 0
90+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], ptr [[Z]], ptr null
91+
; CHECK-NEXT: [[VAL:%.*]] = load <vscale x 2 x double>, ptr [[COND]], align 16
92+
; CHECK-NEXT: ret void
93+
;
94+
%z = alloca <16 x half>
95+
%cmp = icmp eq i32 0, 0
96+
%cond = select i1 %cmp, ptr %z, ptr null
97+
%val = load <vscale x 2 x double>, ptr %cond, align 16
98+
ret void
99+
}
100+
101+
define void @select_store_alloca_to_svdouble_t(<vscale x 2 x double> %val) vscale_range(1) {
102+
; CHECK-LABEL: @select_store_alloca_to_svdouble_t(
103+
; CHECK-NEXT: [[Z:%.*]] = alloca <16 x half>, align 32
104+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 0, 0
105+
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], ptr [[Z]], ptr null
106+
; CHECK-NEXT: store <vscale x 2 x double> [[VAL:%.*]], ptr [[COND]], align 16
107+
; CHECK-NEXT: ret void
108+
;
109+
%z = alloca <16 x half>
110+
%cmp = icmp eq i32 0, 0
111+
%cond = select i1 %cmp, ptr %z, ptr null
112+
store <vscale x 2 x double> %val, ptr %cond, align 16
113+
ret void
114+
}
115+
116+
define <4 x i32> @fixed_alloca_fixed_from_scalable(<vscale x 4 x i32> %a) vscale_range(1) {
117+
; CHECK-LABEL: @fixed_alloca_fixed_from_scalable(
118+
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16
119+
; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16
120+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr [[TMP]], align 16
121+
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
122+
;
123+
%tmp = alloca <4 x i32>
124+
store <vscale x 4 x i32> %a, ptr %tmp
125+
%cast = load <4 x i32>, ptr %tmp
126+
ret <4 x i32> %cast
127+
}
128+
129+
define <2 x i8> @fixed_alloca_fixed_from_scalable_requires_bitcast(<vscale x 16 x i1> %a) vscale_range(1) {
130+
; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_requires_bitcast(
131+
; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x i8>, align 2
132+
; CHECK-NEXT: store <vscale x 16 x i1> [[A:%.*]], ptr [[TMP]], align 2
133+
; CHECK-NEXT: [[TMP2:%.*]] = load <2 x i8>, ptr [[TMP]], align 2
134+
; CHECK-NEXT: ret <2 x i8> [[TMP2]]
135+
;
136+
%tmp = alloca <2 x i8>
137+
store <vscale x 16 x i1> %a, ptr %tmp
138+
%cast = load <2 x i8>, ptr %tmp
139+
ret <2 x i8> %cast
140+
}
141+
142+
define <2 x ptr> @fixed_alloca_fixed_from_scalable_inttoptr(<vscale x 4 x i32> %a) vscale_range(1) {
143+
; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_inttoptr(
144+
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16
145+
; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16
146+
; CHECK-NEXT: [[TMP2:%.*]] = load <2 x ptr>, ptr [[TMP]], align 16
147+
; CHECK-NEXT: ret <2 x ptr> [[TMP2]]
148+
;
149+
%tmp = alloca <4 x i32>
150+
store <vscale x 4 x i32> %a, ptr %tmp
151+
%cast = load <2 x ptr>, ptr %tmp
152+
ret <2 x ptr> %cast
153+
}
154+
155+
define <4 x i32> @fixed_alloca_fixed_from_scalable_ptrtoint(<vscale x 2 x ptr> %a) vscale_range(1) {
156+
; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_ptrtoint(
157+
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16
158+
; CHECK-NEXT: store <vscale x 2 x ptr> [[A:%.*]], ptr [[TMP]], align 16
159+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <4 x i32>, ptr [[TMP]], align 16
160+
; CHECK-NEXT: ret <4 x i32> [[TMP_0_CAST]]
161+
;
162+
%tmp = alloca <4 x i32>
163+
store <vscale x 2 x ptr> %a, ptr %tmp
164+
%cast = load <4 x i32>, ptr %tmp
165+
ret <4 x i32> %cast
166+
}
167+
168+
define <2 x ptr> @fixed_alloca_fixed_from_scalable_ptrtoptr(<vscale x 2 x ptr> %a) vscale_range(1) {
169+
; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_ptrtoptr(
170+
; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x ptr>, align 16
171+
; CHECK-NEXT: store <vscale x 2 x ptr> [[A:%.*]], ptr [[TMP]], align 16
172+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <2 x ptr>, ptr [[TMP]], align 16
173+
; CHECK-NEXT: ret <2 x ptr> [[TMP_0_CAST]]
174+
;
175+
%tmp = alloca <2 x ptr>
176+
store <vscale x 2 x ptr> %a, ptr %tmp
177+
%cast = load <2 x ptr>, ptr %tmp
178+
ret <2 x ptr> %cast
179+
}
180+
181+
define <2 x ptr> @fixed_alloca_fixed_from_scalable_ptrtoptr_different_addrspace(<vscale x 2 x ptr addrspace(1)> %a) vscale_range(1) {
182+
; CHECK-LABEL: @fixed_alloca_fixed_from_scalable_ptrtoptr_different_addrspace(
183+
; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x ptr>, align 16
184+
; CHECK-NEXT: store <vscale x 2 x ptr addrspace(1)> [[A:%.*]], ptr [[TMP]], align 16
185+
; CHECK-NEXT: [[TMP3:%.*]] = load <2 x ptr>, ptr [[TMP]], align 16
186+
; CHECK-NEXT: ret <2 x ptr> [[TMP3]]
187+
;
188+
%tmp = alloca <2 x ptr>
189+
store <vscale x 2 x ptr addrspace(1)> %a, ptr %tmp
190+
%cast = load <2 x ptr>, ptr %tmp
191+
ret <2 x ptr> %cast
192+
}
193+
194+
define <vscale x 4 x i32> @fixed_alloca_scalable_from_fixed(<4 x i32> %a) vscale_range(1) {
195+
; CHECK-LABEL: @fixed_alloca_scalable_from_fixed(
196+
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16
197+
; CHECK-NEXT: store <4 x i32> [[A:%.*]], ptr [[TMP]], align 16
198+
; CHECK-NEXT: [[TMP1:%.*]] = load <vscale x 4 x i32>, ptr [[TMP]], align 16
199+
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]]
200+
;
201+
%tmp = alloca <4 x i32>
202+
store <4 x i32> %a, ptr %tmp
203+
%cast = load <vscale x 4 x i32>, ptr %tmp
204+
ret <vscale x 4 x i32> %cast
205+
}
206+
207+
define <vscale x 16 x i1> @fixed_alloca_scalable_from_fixed_requires_bitcast(<2 x i8> %a) vscale_range(1) {
208+
; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_requires_bitcast(
209+
; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x i8>, align 2
210+
; CHECK-NEXT: store <2 x i8> [[A:%.*]], ptr [[TMP]], align 2
211+
; CHECK-NEXT: [[TMP2:%.*]] = load <vscale x 16 x i1>, ptr [[TMP]], align 2
212+
; CHECK-NEXT: ret <vscale x 16 x i1> [[TMP2]]
213+
;
214+
%tmp = alloca <2 x i8>
215+
store <2 x i8> %a, ptr %tmp
216+
%cast = load <vscale x 16 x i1>, ptr %tmp
217+
ret <vscale x 16 x i1> %cast
218+
}
219+
220+
define <vscale x 2 x ptr> @fixed_alloca_scalable_from_fixed_inttoptr(<4 x i32> %a) vscale_range(1) {
221+
; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_inttoptr(
222+
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16
223+
; CHECK-NEXT: store <4 x i32> [[A:%.*]], ptr [[TMP]], align 16
224+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 2 x ptr>, ptr [[TMP]], align 16
225+
; CHECK-NEXT: ret <vscale x 2 x ptr> [[TMP_0_CAST]]
226+
;
227+
%tmp = alloca <4 x i32>
228+
store <4 x i32> %a, ptr %tmp
229+
%cast = load <vscale x 2 x ptr>, ptr %tmp
230+
ret <vscale x 2 x ptr> %cast
231+
}
232+
233+
define <vscale x 4 x i32> @fixed_alloca_scalable_from_fixed_ptrtoint(<2 x ptr> %a) vscale_range(1) {
234+
; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_ptrtoint(
235+
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i32>, align 16
236+
; CHECK-NEXT: store <2 x ptr> [[A:%.*]], ptr [[TMP]], align 16
237+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 4 x i32>, ptr [[TMP]], align 16
238+
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP_0_CAST]]
239+
;
240+
%tmp = alloca <4 x i32>
241+
store <2 x ptr> %a, ptr %tmp
242+
%cast = load <vscale x 4 x i32>, ptr %tmp
243+
ret <vscale x 4 x i32> %cast
244+
}
245+
246+
define <vscale x 2 x ptr> @fixed_alloca_scalable_from_fixed_ptrtoptr(<2 x ptr> %a) vscale_range(1) {
247+
; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_ptrtoptr(
248+
; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x ptr>, align 16
249+
; CHECK-NEXT: store <2 x ptr> [[A:%.*]], ptr [[TMP]], align 16
250+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 2 x ptr>, ptr [[TMP]], align 16
251+
; CHECK-NEXT: ret <vscale x 2 x ptr> [[TMP_0_CAST]]
252+
;
253+
%tmp = alloca <2 x ptr>
254+
store <2 x ptr> %a, ptr %tmp
255+
%cast = load <vscale x 2 x ptr>, ptr %tmp
256+
ret <vscale x 2 x ptr> %cast
257+
}
258+
259+
define <vscale x 2 x ptr addrspace(1)> @fixed_alloca_scalable_from_fixed_ptrtoptr_different_addrspace(<2 x ptr> %a) vscale_range(1) {
260+
; CHECK-LABEL: @fixed_alloca_scalable_from_fixed_ptrtoptr_different_addrspace(
261+
; CHECK-NEXT: [[TMP:%.*]] = alloca <2 x ptr>, align 16
262+
; CHECK-NEXT: store <2 x ptr> [[A:%.*]], ptr [[TMP]], align 16
263+
; CHECK-NEXT: [[TMP3:%.*]] = load <vscale x 2 x ptr addrspace(1)>, ptr [[TMP]], align 16
264+
; CHECK-NEXT: ret <vscale x 2 x ptr addrspace(1)> [[TMP3]]
265+
;
266+
%tmp = alloca <2 x ptr>
267+
store <2 x ptr> %a, ptr %tmp
268+
%cast = load <vscale x 2 x ptr addrspace(1)>, ptr %tmp
269+
ret <vscale x 2 x ptr addrspace(1)> %cast
270+
}
271+
272+
define <4 x i32> @scalable_alloca_fixed_from_scalable(<vscale x 4 x i32> %a) vscale_range(1) {
273+
; CHECK-LABEL: @scalable_alloca_fixed_from_scalable(
274+
; CHECK-NEXT: [[TMP:%.*]] = alloca <vscale x 4 x i32>, align 16
275+
; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16
276+
; CHECK-NEXT: [[CAST:%.*]] = load <4 x i32>, ptr [[TMP]], align 16
277+
; CHECK-NEXT: ret <4 x i32> [[CAST]]
278+
;
279+
%tmp = alloca <vscale x 4 x i32>
280+
store <vscale x 4 x i32> %a, ptr %tmp
281+
%cast = load <4 x i32>, ptr %tmp
282+
ret <4 x i32> %cast
283+
}
284+
285+
define <vscale x 4 x i32> @scalable_alloca_scalable_from_fixed(<4 x i32> %a) vscale_range(1) {
286+
; CHECK-LABEL: @scalable_alloca_scalable_from_fixed(
287+
; CHECK-NEXT: [[TMP:%.*]] = alloca <vscale x 4 x i32>, align 16
288+
; CHECK-NEXT: store <4 x i32> [[A:%.*]], ptr [[TMP]], align 16
289+
; CHECK-NEXT: [[CAST:%.*]] = load <vscale x 4 x i32>, ptr [[TMP]], align 16
290+
; CHECK-NEXT: ret <vscale x 4 x i32> [[CAST]]
291+
;
292+
%tmp = alloca <vscale x 4 x i32>
293+
store <4 x i32> %a, ptr %tmp
294+
%cast = load <vscale x 4 x i32>, ptr %tmp
295+
ret <vscale x 4 x i32> %cast
296+
}
297+
298+
define i16 @scalar_alloca_scalar_from_scalable(<vscale x 16 x i1> %a) vscale_range(1) {
299+
; CHECK-LABEL: @scalar_alloca_scalar_from_scalable(
300+
; CHECK-NEXT: [[TMP:%.*]] = alloca i16, align 2
301+
; CHECK-NEXT: store <vscale x 16 x i1> [[A:%.*]], ptr [[TMP]], align 2
302+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load i16, ptr [[TMP]], align 2
303+
; CHECK-NEXT: ret i16 [[TMP_0_CAST]]
304+
;
305+
%tmp = alloca i16
306+
store <vscale x 16 x i1> %a, ptr %tmp
307+
%cast = load i16, ptr %tmp
308+
ret i16 %cast
309+
}
310+
311+
define <vscale x 16 x i1> @scalar_alloca_scalable_from_scalar(i16 %a) vscale_range(1) {
312+
; CHECK-LABEL: @scalar_alloca_scalable_from_scalar(
313+
; CHECK-NEXT: [[TMP:%.*]] = alloca i16, align 2
314+
; CHECK-NEXT: store i16 [[A:%.*]], ptr [[TMP]], align 2
315+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 16 x i1>, ptr [[TMP]], align 2
316+
; CHECK-NEXT: ret <vscale x 16 x i1> [[TMP_0_CAST]]
317+
;
318+
%tmp = alloca i16
319+
store i16 %a, ptr %tmp
320+
%cast = load <vscale x 16 x i1>, ptr %tmp
321+
ret <vscale x 16 x i1> %cast
322+
}
323+
324+
define { <2 x i32>, <2 x i32> } @fixed_struct_alloca_fixed_from_scalable(<vscale x 4 x i32> %a) vscale_range(1) {
325+
; CHECK-LABEL: @fixed_struct_alloca_fixed_from_scalable(
326+
; CHECK-NEXT: [[TMP:%.*]] = alloca { <2 x i32>, <2 x i32> }, align 8
327+
; CHECK-NEXT: store <vscale x 4 x i32> [[A:%.*]], ptr [[TMP]], align 16
328+
; CHECK-NEXT: [[CAST_FCA_0_GEP:%.*]] = getelementptr inbounds { <2 x i32>, <2 x i32> }, ptr [[TMP]], i32 0, i32 0
329+
; CHECK-NEXT: [[TMP_0_CAST_FCA_0_LOAD:%.*]] = load <2 x i32>, ptr [[CAST_FCA_0_GEP]], align 8
330+
; CHECK-NEXT: [[CAST_FCA_0_INSERT:%.*]] = insertvalue { <2 x i32>, <2 x i32> } poison, <2 x i32> [[TMP_0_CAST_FCA_0_LOAD]], 0
331+
; CHECK-NEXT: [[TMP_8_CAST_FCA_1_GEP_SROA_IDX:%.*]] = getelementptr inbounds { <2 x i32>, <2 x i32> }, ptr [[TMP]], i32 0, i32 1
332+
; CHECK-NEXT: [[TMP_8_CAST_FCA_1_LOAD:%.*]] = load <2 x i32>, ptr [[TMP_8_CAST_FCA_1_GEP_SROA_IDX]], align 8
333+
; CHECK-NEXT: [[CAST_FCA_1_INSERT:%.*]] = insertvalue { <2 x i32>, <2 x i32> } [[CAST_FCA_0_INSERT]], <2 x i32> [[TMP_8_CAST_FCA_1_LOAD]], 1
334+
; CHECK-NEXT: ret { <2 x i32>, <2 x i32> } [[CAST_FCA_1_INSERT]]
335+
;
336+
%tmp = alloca { <2 x i32>, <2 x i32> }
337+
store <vscale x 4 x i32> %a, ptr %tmp
338+
%cast = load { <2 x i32>, <2 x i32> }, ptr %tmp
339+
ret { <2 x i32>, <2 x i32> } %cast
340+
}
341+
342+
define <vscale x 4 x i64> @fixed_struct_alloca_scalable_from_fixed({ <2 x ptr>, <2 x ptr> } %a) vscale_range(1) {
343+
; CHECK-LABEL: @fixed_struct_alloca_scalable_from_fixed(
344+
; CHECK-NEXT: [[TMP:%.*]] = alloca { <2 x ptr>, <2 x ptr> }, align 16
345+
; CHECK-NEXT: [[A_FCA_0_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[A:%.*]], 0
346+
; CHECK-NEXT: [[A_FCA_0_GEP:%.*]] = getelementptr inbounds { <2 x ptr>, <2 x ptr> }, ptr [[TMP]], i32 0, i32 0
347+
; CHECK-NEXT: store <2 x ptr> [[A_FCA_0_EXTRACT]], ptr [[A_FCA_0_GEP]], align 16
348+
; CHECK-NEXT: [[A_FCA_1_EXTRACT:%.*]] = extractvalue { <2 x ptr>, <2 x ptr> } [[A]], 1
349+
; CHECK-NEXT: [[TMP_16_A_FCA_1_GEP_SROA_IDX:%.*]] = getelementptr inbounds { <2 x ptr>, <2 x ptr> }, ptr [[TMP]], i32 0, i32 1
350+
; CHECK-NEXT: store <2 x ptr> [[A_FCA_1_EXTRACT]], ptr [[TMP_16_A_FCA_1_GEP_SROA_IDX]], align 16
351+
; CHECK-NEXT: [[TMP_0_CAST:%.*]] = load <vscale x 4 x i64>, ptr [[TMP]], align 32
352+
; CHECK-NEXT: ret <vscale x 4 x i64> [[TMP_0_CAST]]
353+
;
354+
%tmp = alloca { <2 x ptr>, <2 x ptr> }
355+
store { <2 x ptr>, <2 x ptr> } %a, ptr %tmp
356+
%cast = load <vscale x 4 x i64>, ptr %tmp
357+
ret <vscale x 4 x i64> %cast
358+
}
359+
360+
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1) nounwind
361+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
362+
; CHECK-MODIFY-CFG: {{.*}}
363+
; CHECK-PRESERVE-CFG: {{.*}}

0 commit comments

Comments
 (0)