1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -S -riscv-gather-scatter-lowering -mtriple=riscv64 -mattr=+m,+v | FileCheck %s --check-prefixes=CHECK
4 %struct.foo = type { i32, i32, i32, i32 }
6 declare <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
8 define <vscale x 1 x i64> @gather(ptr %a, i32 %len) {
9 ; CHECK-LABEL: @gather(
10 ; CHECK-NEXT: vector.ph:
11 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[LEN:%.*]] to i64
12 ; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.vscale.i64()
13 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
15 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
16 ; CHECK-NEXT: [[VEC_IND_SCALAR:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT_SCALAR:%.*]], [[VECTOR_BODY]] ]
17 ; CHECK-NEXT: [[ACCUM:%.*]] = phi <vscale x 1 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[ACCUM_NEXT:%.*]], [[VECTOR_BODY]] ]
18 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[A:%.*]], i64 [[VEC_IND_SCALAR]], i32 3
19 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vscale.i32()
20 ; CHECK-NEXT: [[TMP3:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[TMP1]], i64 16, <vscale x 1 x i1> splat (i1 true), i32 [[TMP2]])
21 ; CHECK-NEXT: [[GATHER:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP3]], <vscale x 1 x i64> undef, i32 [[TMP2]])
22 ; CHECK-NEXT: [[ACCUM_NEXT]] = add <vscale x 1 x i64> [[ACCUM]], [[GATHER]]
23 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP0]]
24 ; CHECK-NEXT: [[VEC_IND_NEXT_SCALAR]] = add i64 [[VEC_IND_SCALAR]], [[TMP0]]
25 ; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[WIDE_TRIP_COUNT]]
26 ; CHECK-NEXT: br i1 [[TMP4]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
27 ; CHECK: for.cond.cleanup:
28 ; CHECK-NEXT: ret <vscale x 1 x i64> [[ACCUM_NEXT]]
31 %wide.trip.count = zext i32 %len to i64
32 %0 = tail call i64 @llvm.vscale.i64()
33 %1 = tail call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
34 %.splatinsert = insertelement <vscale x 1 x i64> poison, i64 %0, i64 0
35 %.splat = shufflevector <vscale x 1 x i64> %.splatinsert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
38 vector.body: ; preds = %vector.body, %vector.ph
39 %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
40 %vec.ind = phi <vscale x 1 x i64> [ %1, %vector.ph ], [ %vec.ind.next, %vector.body ]
41 %accum = phi <vscale x 1 x i64> [ zeroinitializer, %vector.ph ], [ %accum.next, %vector.body ]
42 %2 = getelementptr inbounds %struct.foo, ptr %a, <vscale x 1 x i64> %vec.ind, i32 3
43 %gather = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(<vscale x 1 x ptr> %2, i32 8, <vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> undef)
44 %accum.next = add <vscale x 1 x i64> %accum, %gather
45 %index.next = add nuw i64 %index, %0
46 %vec.ind.next = add <vscale x 1 x i64> %vec.ind, %.splat
47 %3 = icmp ne i64 %index.next, %wide.trip.count
48 br i1 %3, label %for.cond.cleanup, label %vector.body
50 for.cond.cleanup: ; preds = %vector.body
51 ret <vscale x 1 x i64> %accum.next
54 define <vscale x 1 x i64> @gather_disjoint_or(ptr %a, i64 %len) {
55 ; CHECK-LABEL: @gather_disjoint_or(
56 ; CHECK-NEXT: vector.ph:
57 ; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
58 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
60 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
61 ; CHECK-NEXT: [[VEC_IND_SCALAR:%.*]] = phi i64 [ 1, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT_SCALAR:%.*]], [[VECTOR_BODY]] ]
62 ; CHECK-NEXT: [[ACCUM:%.*]] = phi <vscale x 1 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[ACCUM_NEXT:%.*]], [[VECTOR_BODY]] ]
63 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i64, ptr [[A:%.*]], i64 [[VEC_IND_SCALAR]]
64 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
65 ; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[TMP0]], i64 16, <vscale x 1 x i1> splat (i1 true), i32 [[TMP1]])
66 ; CHECK-NEXT: [[GATHER:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP2]], <vscale x 1 x i64> poison, i32 [[TMP1]])
67 ; CHECK-NEXT: [[ACCUM_NEXT]] = add <vscale x 1 x i64> [[ACCUM]], [[GATHER]]
68 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[VSCALE]]
69 ; CHECK-NEXT: [[VEC_IND_NEXT_SCALAR]] = add i64 [[VEC_IND_SCALAR]], 2
70 ; CHECK-NEXT: [[EXIT:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[LEN:%.*]]
71 ; CHECK-NEXT: br i1 [[EXIT]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
72 ; CHECK: for.cond.cleanup:
73 ; CHECK-NEXT: ret <vscale x 1 x i64> [[ACCUM_NEXT]]
76 %vscale = call i64 @llvm.vscale.i64()
77 %step = tail call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
78 %step.mul2 = shl <vscale x 1 x i64> %step, splat (i64 1)
81 vector.body: ; preds = %vector.body, %vector.ph
82 %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
83 %vec.ind = phi <vscale x 1 x i64> [ %step.mul2, %vector.ph ], [ %vec.ind.next, %vector.body ]
85 %accum = phi <vscale x 1 x i64> [ zeroinitializer, %vector.ph ], [ %accum.next, %vector.body ]
87 %vec.ind.or = or disjoint <vscale x 1 x i64> %vec.ind, splat (i64 1)
89 %gep = getelementptr i64, ptr %a, <vscale x 1 x i64> %vec.ind.or
90 %gather = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
91 <vscale x 1 x ptr> %gep,
93 <vscale x 1 x i1> splat (i1 true),
94 <vscale x 1 x i64> poison
97 %accum.next = add <vscale x 1 x i64> %accum, %gather
98 %index.next = add nuw i64 %index, %vscale
99 %vec.ind.next = add <vscale x 1 x i64> %vec.ind, splat (i64 2)
101 %exit = icmp ne i64 %index.next, %len
102 br i1 %exit, label %for.cond.cleanup, label %vector.body
104 for.cond.cleanup: ; preds = %vector.body
105 ret <vscale x 1 x i64> %accum.next
108 define void @scatter(ptr %a, i32 %len) {
109 ; CHECK-LABEL: @scatter(
110 ; CHECK-NEXT: vector.ph:
111 ; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[LEN:%.*]] to i64
112 ; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.vscale.i64()
113 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
114 ; CHECK: vector.body:
115 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
116 ; CHECK-NEXT: [[VEC_IND_SCALAR:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT_SCALAR:%.*]], [[VECTOR_BODY]] ]
117 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_FOO:%.*]], ptr [[A:%.*]], i64 [[VEC_IND_SCALAR]], i32 3
118 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vscale.i32()
119 ; CHECK-NEXT: call void @llvm.experimental.vp.strided.store.nxv1i64.p0.i64(<vscale x 1 x i64> zeroinitializer, ptr [[TMP1]], i64 16, <vscale x 1 x i1> splat (i1 true), i32 [[TMP2]])
120 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], [[TMP0]]
121 ; CHECK-NEXT: [[VEC_IND_NEXT_SCALAR]] = add i64 [[VEC_IND_SCALAR]], [[TMP0]]
122 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[INDEX_NEXT]], [[WIDE_TRIP_COUNT]]
123 ; CHECK-NEXT: br i1 [[TMP3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
124 ; CHECK: for.cond.cleanup:
125 ; CHECK-NEXT: ret void
128 %wide.trip.count = zext i32 %len to i64
129 %0 = tail call i64 @llvm.vscale.i64()
130 %1 = tail call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
131 %.splatinsert = insertelement <vscale x 1 x i64> poison, i64 %0, i64 0
132 %.splat = shufflevector <vscale x 1 x i64> %.splatinsert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
133 br label %vector.body
135 vector.body: ; preds = %vector.body, %vector.ph
136 %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
137 %vec.ind = phi <vscale x 1 x i64> [ %1, %vector.ph ], [ %vec.ind.next, %vector.body ]
138 %2 = getelementptr inbounds %struct.foo, ptr %a, <vscale x 1 x i64> %vec.ind, i32 3
139 tail call void @llvm.masked.scatter.nxv1i64.nxv1p0(<vscale x 1 x i64> zeroinitializer, <vscale x 1 x ptr> %2, i32 8, <vscale x 1 x i1> splat (i1 true))
140 %index.next = add nuw i64 %index, %0
141 %vec.ind.next = add <vscale x 1 x i64> %vec.ind, %.splat
142 %3 = icmp ne i64 %index.next, %wide.trip.count
143 br i1 %3, label %for.cond.cleanup, label %vector.body
145 for.cond.cleanup: ; preds = %vector.body
149 define <vscale x 1 x i64> @gather_loopless(ptr %p, i64 %stride) {
150 ; CHECK-LABEL: @gather_loopless(
151 ; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[STRIDE:%.*]], 4
152 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vscale.i32()
153 ; CHECK-NEXT: [[TMP3:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[P:%.*]], i64 [[TMP1]], <vscale x 1 x i1> splat (i1 true), i32 [[TMP2]])
154 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP3]], <vscale x 1 x i64> poison, i32 [[TMP2]])
155 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
157 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
158 %splat.insert = insertelement <vscale x 1 x i64> poison, i64 %stride, i64 0
159 %splat = shufflevector <vscale x 1 x i64> %splat.insert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
160 %offsets = mul <vscale x 1 x i64> %step, %splat
161 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offsets
162 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
163 <vscale x 1 x ptr> %ptrs,
165 <vscale x 1 x i1> splat (i1 1),
166 <vscale x 1 x i64> poison
168 ret <vscale x 1 x i64> %x
171 define <vscale x 1 x i64> @straightline_offset_add(ptr %p, i64 %offset) {
172 ; CHECK-LABEL: @straightline_offset_add(
173 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 [[OFFSET:%.*]]
174 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vscale.i32()
175 ; CHECK-NEXT: [[TMP3:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[TMP1]], i64 4, <vscale x 1 x i1> splat (i1 true), i32 [[TMP2]])
176 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP3]], <vscale x 1 x i64> poison, i32 [[TMP2]])
177 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
179 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
180 %splat.insert = insertelement <vscale x 1 x i64> poison, i64 %offset, i64 0
181 %splat = shufflevector <vscale x 1 x i64> %splat.insert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
182 %offsetv = add <vscale x 1 x i64> %step, %splat
183 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offsetv
184 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
185 <vscale x 1 x ptr> %ptrs,
187 <vscale x 1 x i1> splat (i1 1),
188 <vscale x 1 x i64> poison
190 ret <vscale x 1 x i64> %x
193 define <vscale x 1 x i64> @straightline_offset_disjoint_or(ptr %p, i64 %offset) {
194 ; CHECK-LABEL: @straightline_offset_disjoint_or(
195 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[P:%.*]], i64 1
196 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vscale.i32()
197 ; CHECK-NEXT: [[TMP3:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[TMP1]], i64 8, <vscale x 1 x i1> splat (i1 true), i32 [[TMP2]])
198 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP3]], <vscale x 1 x i64> poison, i32 [[TMP2]])
199 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
201 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
202 %step.shl = shl <vscale x 1 x i64> %step, splat (i64 1)
203 %offsetv = or disjoint <vscale x 1 x i64> %step.shl, splat (i64 1)
204 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offsetv
205 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
206 <vscale x 1 x ptr> %ptrs,
208 <vscale x 1 x i1> splat (i1 true),
209 <vscale x 1 x i64> poison
211 ret <vscale x 1 x i64> %x
214 define <vscale x 1 x i64> @straightline_offset_shl(ptr %p) {
215 ; CHECK-LABEL: @straightline_offset_shl(
216 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
217 ; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[P:%.*]], i64 32, <vscale x 1 x i1> splat (i1 true), i32 [[TMP1]])
218 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP2]], <vscale x 1 x i64> poison, i32 [[TMP1]])
219 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
221 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
222 %offset = shl <vscale x 1 x i64> %step, splat (i64 3)
223 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offset
224 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
225 <vscale x 1 x ptr> %ptrs,
227 <vscale x 1 x i1> splat (i1 1),
228 <vscale x 1 x i64> poison
230 ret <vscale x 1 x i64> %x
233 define <vscale x 1 x i64> @neg_shl_is_not_commutative(ptr %p) {
234 ; CHECK-LABEL: @neg_shl_is_not_commutative(
235 ; CHECK-NEXT: [[STEP:%.*]] = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
236 ; CHECK-NEXT: [[SPLAT_INSERT:%.*]] = insertelement <vscale x 1 x i64> poison, i64 3, i64 0
237 ; CHECK-NEXT: [[SPLAT:%.*]] = shufflevector <vscale x 1 x i64> [[SPLAT_INSERT]], <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
238 ; CHECK-NEXT: [[OFFSET:%.*]] = shl <vscale x 1 x i64> [[SPLAT]], [[STEP]]
239 ; CHECK-NEXT: [[PTRS:%.*]] = getelementptr i32, ptr [[P:%.*]], <vscale x 1 x i64> [[OFFSET]]
240 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(<vscale x 1 x ptr> [[PTRS]], i32 8, <vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> poison)
241 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
243 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
244 %splat.insert = insertelement <vscale x 1 x i64> poison, i64 3, i64 0
245 %splat = shufflevector <vscale x 1 x i64> %splat.insert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
246 %offset = shl <vscale x 1 x i64> %splat, %step
247 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offset
248 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
249 <vscale x 1 x ptr> %ptrs,
251 <vscale x 1 x i1> splat (i1 1),
252 <vscale x 1 x i64> poison
254 ret <vscale x 1 x i64> %x
257 define <vscale x 1 x i64> @straightline_offset_shl_nonc(ptr %p, i64 %shift) {
258 ; CHECK-LABEL: @straightline_offset_shl_nonc(
259 ; CHECK-NEXT: [[TMP1:%.*]] = shl i64 1, [[SHIFT:%.*]]
260 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
261 ; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.vscale.i32()
262 ; CHECK-NEXT: [[TMP4:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[P:%.*]], i64 [[TMP2]], <vscale x 1 x i1> splat (i1 true), i32 [[TMP3]])
263 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP4]], <vscale x 1 x i64> poison, i32 [[TMP3]])
264 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
266 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
267 %splat.insert = insertelement <vscale x 1 x i64> poison, i64 %shift, i64 0
268 %splat = shufflevector <vscale x 1 x i64> %splat.insert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
269 %offset = shl <vscale x 1 x i64> %step, %splat
270 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offset
271 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
272 <vscale x 1 x ptr> %ptrs,
274 <vscale x 1 x i1> splat (i1 1),
275 <vscale x 1 x i64> poison
277 ret <vscale x 1 x i64> %x
280 define void @scatter_loopless(<vscale x 1 x i64> %x, ptr %p, i64 %stride) {
281 ; CHECK-LABEL: @scatter_loopless(
282 ; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[STRIDE:%.*]], 4
283 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vscale.i32()
284 ; CHECK-NEXT: call void @llvm.experimental.vp.strided.store.nxv1i64.p0.i64(<vscale x 1 x i64> [[X:%.*]], ptr [[P:%.*]], i64 [[TMP1]], <vscale x 1 x i1> splat (i1 true), i32 [[TMP2]])
285 ; CHECK-NEXT: ret void
287 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
288 %splat.insert = insertelement <vscale x 1 x i64> poison, i64 %stride, i64 0
289 %splat = shufflevector <vscale x 1 x i64> %splat.insert, <vscale x 1 x i64> poison, <vscale x 1 x i32> zeroinitializer
290 %offsets = mul <vscale x 1 x i64> %step, %splat
291 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> %offsets
292 call void @llvm.masked.scatter.nxv1i64.nxv1p0(
293 <vscale x 1 x i64> %x,
294 <vscale x 1 x ptr> %ptrs,
296 <vscale x 1 x i1> splat (i1 1)
301 ; We previously crashed expecting a constant to be fixed length.
302 define void @constant_stride(<vscale x 1 x i64> %x, ptr %p, i64 %stride) {
303 ; CHECK-LABEL: @constant_stride(
304 ; CHECK-NEXT: [[PTRS:%.*]] = getelementptr i32, ptr [[P:%.*]], <vscale x 1 x i64> zeroinitializer
305 ; CHECK-NEXT: call void @llvm.masked.scatter.nxv1i64.nxv1p0(<vscale x 1 x i64> [[X:%.*]], <vscale x 1 x ptr> [[PTRS]], i32 8, <vscale x 1 x i1> splat (i1 true))
306 ; CHECK-NEXT: ret void
308 %ptrs = getelementptr i32, ptr %p, <vscale x 1 x i64> zeroinitializer
309 call void @llvm.masked.scatter.nxv1i64.nxv1p0(
310 <vscale x 1 x i64> %x,
311 <vscale x 1 x ptr> %ptrs,
313 <vscale x 1 x i1> splat (i1 1)
318 define <vscale x 1 x i64> @vector_base_scalar_offset(ptr %p, i64 %offset) {
319 ; CHECK-LABEL: @vector_base_scalar_offset(
320 ; CHECK-NEXT: [[PTRS2OFFSET:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[OFFSET:%.*]]
321 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
322 ; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[PTRS2OFFSET]], i64 8, <vscale x 1 x i1> splat (i1 true), i32 [[TMP1]])
323 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP2]], <vscale x 1 x i64> poison, i32 [[TMP1]])
324 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
326 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
327 %ptrs1 = getelementptr i64, ptr %p, <vscale x 1 x i64> %step
328 %ptrs2 = getelementptr i64, <vscale x 1 x ptr> %ptrs1, i64 %offset
329 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
330 <vscale x 1 x ptr> %ptrs2,
332 <vscale x 1 x i1> splat (i1 1),
333 <vscale x 1 x i64> poison
335 ret <vscale x 1 x i64> %x
338 define <vscale x 1 x i64> @splat_base_scalar_offset(ptr %p, i64 %offset) {
339 ; CHECK-LABEL: @splat_base_scalar_offset(
340 ; CHECK-NEXT: [[PTRSOFFSET:%.*]] = getelementptr i64, ptr [[P:%.*]], i64 [[OFFSET:%.*]]
341 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.vscale.i32()
342 ; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 1 x i64> @llvm.experimental.vp.strided.load.nxv1i64.p0.i64(ptr [[PTRSOFFSET]], i64 0, <vscale x 1 x i1> splat (i1 true), i32 [[TMP1]])
343 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.vp.select.nxv1i64(<vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> [[TMP2]], <vscale x 1 x i64> poison, i32 [[TMP1]])
344 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
346 %head = insertelement <vscale x 1 x ptr> poison, ptr %p, i32 0
347 %splat = shufflevector <vscale x 1 x ptr> %head, <vscale x 1 x ptr> poison, <vscale x 1 x i32> zeroinitializer
348 %ptrs = getelementptr i64, <vscale x 1 x ptr> %splat, i64 %offset
349 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
350 <vscale x 1 x ptr> %ptrs,
352 <vscale x 1 x i1> splat (i1 1),
353 <vscale x 1 x i64> poison
355 ret <vscale x 1 x i64> %x
358 ; We shouldn't be able to determine a stride here.
359 define <vscale x 1 x i64> @nonstrided_base_scalar_offset(ptr %p, <vscale x 1 x i64> %v, i64 %offset) {
360 ; CHECK-LABEL: @nonstrided_base_scalar_offset(
361 ; CHECK-NEXT: [[PTRS1:%.*]] = getelementptr i64, ptr [[P:%.*]], <vscale x 1 x i64> [[V:%.*]]
362 ; CHECK-NEXT: [[PTRS2:%.*]] = getelementptr i64, <vscale x 1 x ptr> [[PTRS1]], i64 [[OFFSET:%.*]]
363 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(<vscale x 1 x ptr> [[PTRS2]], i32 8, <vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> poison)
364 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
366 %ptrs1 = getelementptr i64, ptr %p, <vscale x 1 x i64> %v
367 %ptrs2 = getelementptr i64, <vscale x 1 x ptr> %ptrs1, i64 %offset
368 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
369 <vscale x 1 x ptr> %ptrs2,
371 <vscale x 1 x i1> splat (i1 1),
372 <vscale x 1 x i64> poison
374 ret <vscale x 1 x i64> %x
377 ; We shouldn't be able to determine a scalar base here.
378 define <vscale x 1 x i64> @vector_base_vector_offset(ptr %p, <vscale x 1 x i64> %offset) {
379 ; CHECK-LABEL: @vector_base_vector_offset(
380 ; CHECK-NEXT: [[STEP:%.*]] = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
381 ; CHECK-NEXT: [[PTRS1:%.*]] = getelementptr i64, ptr [[P:%.*]], <vscale x 1 x i64> [[STEP]]
382 ; CHECK-NEXT: [[PTRS2:%.*]] = getelementptr i64, <vscale x 1 x ptr> [[PTRS1]], <vscale x 1 x i64> [[OFFSET:%.*]]
383 ; CHECK-NEXT: [[X:%.*]] = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(<vscale x 1 x ptr> [[PTRS2]], i32 8, <vscale x 1 x i1> splat (i1 true), <vscale x 1 x i64> poison)
384 ; CHECK-NEXT: ret <vscale x 1 x i64> [[X]]
386 %step = call <vscale x 1 x i64> @llvm.stepvector.nxv1i64()
387 %ptrs1 = getelementptr i64, ptr %p, <vscale x 1 x i64> %step
388 %ptrs2 = getelementptr i64, <vscale x 1 x ptr> %ptrs1, <vscale x 1 x i64> %offset
389 %x = call <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(
390 <vscale x 1 x ptr> %ptrs2,
392 <vscale x 1 x i1> splat (i1 1),
393 <vscale x 1 x i64> poison
395 ret <vscale x 1 x i64> %x
398 declare i64 @llvm.vscale.i64()
399 declare void @llvm.masked.scatter.nxv1i64.nxv1p0(<vscale x 1 x i64>, <vscale x 1 x ptr>, i32, <vscale x 1 x i1>)
400 declare <vscale x 1 x i64> @llvm.masked.gather.nxv1i64.nxv1p0(<vscale x 1 x ptr>, i32, <vscale x 1 x i1>, <vscale x 1 x i64>)