[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / llvm / test / CodeGen / RISCV / rvv / strided-load-store.ll
blobb1ece9fa8272db3fa198529e970ef35742a8acf9
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:%.*]]
14 ; CHECK:       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]]
30 vector.ph:
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
36   br label %vector.body
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:%.*]]
59 ; CHECK:       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]]
75 vector.ph:
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)
79   br label %vector.body
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,
92   i32 8,
93   <vscale x 1 x i1> splat (i1 true),
94   <vscale x 1 x i64> poison
95   )
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
127 vector.ph:
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
146   ret void
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,
164   i32 8,
165   <vscale x 1 x i1> splat (i1 1),
166   <vscale x 1 x i64> poison
167   )
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,
186   i32 8,
187   <vscale x 1 x i1> splat (i1 1),
188   <vscale x 1 x i64> poison
189   )
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,
207   i32 8,
208   <vscale x 1 x i1> splat (i1 true),
209   <vscale x 1 x i64> poison
210   )
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,
226   i32 8,
227   <vscale x 1 x i1> splat (i1 1),
228   <vscale x 1 x i64> poison
229   )
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,
250   i32 8,
251   <vscale x 1 x i1> splat (i1 1),
252   <vscale x 1 x i64> poison
253   )
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,
273   i32 8,
274   <vscale x 1 x i1> splat (i1 1),
275   <vscale x 1 x i64> poison
276   )
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,
295   i32 8,
296   <vscale x 1 x i1> splat (i1 1)
297   )
298   ret void
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,
312   i32 8,
313   <vscale x 1 x i1> splat (i1 1)
314   )
315   ret void
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,
331   i32 8,
332   <vscale x 1 x i1> splat (i1 1),
333   <vscale x 1 x i64> poison
334   )
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,
351   i32 8,
352   <vscale x 1 x i1> splat (i1 1),
353   <vscale x 1 x i64> poison
354   )
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,
370   i32 8,
371   <vscale x 1 x i1> splat (i1 1),
372   <vscale x 1 x i64> poison
373   )
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,
391   i32 8,
392   <vscale x 1 x i1> splat (i1 1),
393   <vscale x 1 x i64> poison
394   )
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>)