Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / Thumb2 / mve-gather-optimisation-deep.ll
blobb91800c48cec4f43ac43e7ba54515ed7c3e348fc
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt --arm-mve-gather-scatter-lowering -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp %s -S -o - | FileCheck %s
4 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
6 define arm_aapcs_vfpcc void @push_out_add_sub_block(ptr noalias nocapture readonly %data, ptr noalias nocapture %dst, i32 %n.vec) {
7 ; CHECK-LABEL: @push_out_add_sub_block(
8 ; CHECK-NEXT:  vector.ph:
9 ; CHECK-NEXT:    [[PUSHEDOUTADD:%.*]] = add <4 x i32> <i32 0, i32 2, i32 4, i32 6>, <i32 6, i32 6, i32 6, i32 6>
10 ; CHECK-NEXT:    [[SCALEDINDEX:%.*]] = shl <4 x i32> [[PUSHEDOUTADD]], <i32 2, i32 2, i32 2, i32 2>
11 ; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[DATA:%.*]] to i32
12 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i64 0
13 ; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
14 ; CHECK-NEXT:    [[STARTINDEX:%.*]] = add <4 x i32> [[SCALEDINDEX]], [[DOTSPLAT]]
15 ; CHECK-NEXT:    [[PREINCREMENTSTARTINDEX:%.*]] = sub <4 x i32> [[STARTINDEX]], <i32 32, i32 32, i32 32, i32 32>
16 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
17 ; CHECK:       vector.body:
18 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY_END:%.*]] ]
19 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i32> [ [[PREINCREMENTSTARTINDEX]], [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY_END]] ]
20 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[INDEX]], 48
21 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOWER_BLOCK:%.*]], label [[END:%.*]]
22 ; CHECK:       lower.block:
23 ; CHECK-NEXT:    [[TMP2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4i32.v4i32(<4 x i32> [[VEC_IND]], i32 32)
24 ; CHECK-NEXT:    [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 0
25 ; CHECK-NEXT:    [[TMP4]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 1
26 ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[INDEX]]
27 ; CHECK-NEXT:    store <4 x i32> [[TMP3]], ptr [[TMP5]], align 4
28 ; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 4
29 ; CHECK-NEXT:    br label [[VECTOR_BODY_END]]
30 ; CHECK:       vector.body.end:
31 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC:%.*]]
32 ; CHECK-NEXT:    br i1 [[TMP6]], label [[END]], label [[VECTOR_BODY]]
33 ; CHECK:       end:
34 ; CHECK-NEXT:    ret void
37 vector.ph:
38   br label %vector.body
40 vector.body:                                      ; preds = %vector.body, %vector.ph
41   %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body.end ]
42   %vec.ind = phi <4 x i32> [ <i32 0, i32 2, i32 4, i32 6>, %vector.ph ], [ %vec.ind.next, %vector.body.end ]
43   %0 = icmp eq i32 %index, 48
44   br i1 %0, label %lower.block, label %end
46 lower.block:                             ; preds = %vector.body
47   %1 = add <4 x i32> %vec.ind, <i32 6, i32 6, i32 6, i32 6>
48   %2 = getelementptr inbounds i32, ptr %data, <4 x i32> %1
49   %wide.masked.gather = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %2, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
50   %3 = getelementptr inbounds i32, ptr %dst, i32 %index
51   %4 = bitcast ptr %3 to ptr
52   store <4 x i32> %wide.masked.gather, ptr %4, align 4
53   %index.next = add i32 %index, 4
54   %vec.ind.next = add <4 x i32> %vec.ind, <i32 8, i32 8, i32 8, i32 8>
55   br label %vector.body.end
57 vector.body.end:                             ; preds = %lower.block
58   %5 = icmp eq i32 %index.next, %n.vec
59   br i1 %5, label %end, label %vector.body
61 end:
62   ret void;
65 define arm_aapcs_vfpcc void @push_out_add_sub_block_commutedphi(ptr noalias nocapture readonly %data, ptr noalias nocapture %dst, i32 %n.vec) {
66 ; CHECK-LABEL: @push_out_add_sub_block_commutedphi(
67 ; CHECK-NEXT:  vector.ph:
68 ; CHECK-NEXT:    [[PUSHEDOUTADD:%.*]] = add <4 x i32> <i32 0, i32 2, i32 4, i32 6>, <i32 6, i32 6, i32 6, i32 6>
69 ; CHECK-NEXT:    [[SCALEDINDEX:%.*]] = shl <4 x i32> [[PUSHEDOUTADD]], <i32 2, i32 2, i32 2, i32 2>
70 ; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[DATA:%.*]] to i32
71 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i64 0
72 ; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
73 ; CHECK-NEXT:    [[STARTINDEX:%.*]] = add <4 x i32> [[SCALEDINDEX]], [[DOTSPLAT]]
74 ; CHECK-NEXT:    [[PREINCREMENTSTARTINDEX:%.*]] = sub <4 x i32> [[STARTINDEX]], <i32 32, i32 32, i32 32, i32 32>
75 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
76 ; CHECK:       vector.body:
77 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY_END:%.*]] ]
78 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i32> [ [[PREINCREMENTSTARTINDEX]], [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY_END]] ]
79 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[INDEX]], 48
80 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOWER_BLOCK:%.*]], label [[END:%.*]]
81 ; CHECK:       lower.block:
82 ; CHECK-NEXT:    [[TMP2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4i32.v4i32(<4 x i32> [[VEC_IND]], i32 32)
83 ; CHECK-NEXT:    [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 0
84 ; CHECK-NEXT:    [[TMP4]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 1
85 ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[INDEX]]
86 ; CHECK-NEXT:    store <4 x i32> [[TMP3]], ptr [[TMP5]], align 4
87 ; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 4
88 ; CHECK-NEXT:    br label [[VECTOR_BODY_END]]
89 ; CHECK:       vector.body.end:
90 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC:%.*]]
91 ; CHECK-NEXT:    br i1 [[TMP6]], label [[END]], label [[VECTOR_BODY]]
92 ; CHECK:       end:
93 ; CHECK-NEXT:    ret void
96 vector.ph:
97   br label %vector.body
99 vector.body:                                      ; preds = %vector.body, %vector.ph
100   %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body.end ]
101   %vec.ind = phi <4 x i32> [ %vec.ind.next, %vector.body.end ], [ <i32 0, i32 2, i32 4, i32 6>, %vector.ph ]
102   %0 = icmp eq i32 %index, 48
103   br i1 %0, label %lower.block, label %end
105 lower.block:                             ; preds = %vector.body
106   %1 = add <4 x i32> %vec.ind, <i32 6, i32 6, i32 6, i32 6>
107   %2 = getelementptr inbounds i32, ptr %data, <4 x i32> %1
108   %wide.masked.gather = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %2, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
109   %3 = getelementptr inbounds i32, ptr %dst, i32 %index
110   %4 = bitcast ptr %3 to ptr
111   store <4 x i32> %wide.masked.gather, ptr %4, align 4
112   %index.next = add i32 %index, 4
113   %vec.ind.next = add <4 x i32> %vec.ind, <i32 8, i32 8, i32 8, i32 8>
114   br label %vector.body.end
116 vector.body.end:                             ; preds = %lower.block
117   %5 = icmp eq i32 %index.next, %n.vec
118   br i1 %5, label %end, label %vector.body
120 end:
121   ret void;
124 define arm_aapcs_vfpcc void @push_out_mul_sub_block(ptr noalias nocapture readonly %data, ptr noalias nocapture %dst, i32 %n.vec) {
125 ; CHECK-LABEL: @push_out_mul_sub_block(
126 ; CHECK-NEXT:  vector.ph:
127 ; CHECK-NEXT:    [[PUSHEDOUTMUL:%.*]] = mul <4 x i32> <i32 0, i32 2, i32 4, i32 6>, <i32 3, i32 3, i32 3, i32 3>
128 ; CHECK-NEXT:    [[PRODUCT:%.*]] = mul <4 x i32> <i32 8, i32 8, i32 8, i32 8>, <i32 3, i32 3, i32 3, i32 3>
129 ; CHECK-NEXT:    [[PUSHEDOUTADD:%.*]] = add <4 x i32> [[PUSHEDOUTMUL]], <i32 6, i32 6, i32 6, i32 6>
130 ; CHECK-NEXT:    [[SCALEDINDEX:%.*]] = shl <4 x i32> [[PUSHEDOUTADD]], <i32 2, i32 2, i32 2, i32 2>
131 ; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[DATA:%.*]] to i32
132 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> poison, i32 [[TMP0]], i64 0
133 ; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
134 ; CHECK-NEXT:    [[STARTINDEX:%.*]] = add <4 x i32> [[SCALEDINDEX]], [[DOTSPLAT]]
135 ; CHECK-NEXT:    [[PREINCREMENTSTARTINDEX:%.*]] = sub <4 x i32> [[STARTINDEX]], <i32 96, i32 96, i32 96, i32 96>
136 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
137 ; CHECK:       vector.body:
138 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY_END:%.*]] ]
139 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i32> [ [[PREINCREMENTSTARTINDEX]], [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY_END]] ]
140 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i32 [[INDEX]], 48
141 ; CHECK-NEXT:    br i1 [[TMP1]], label [[LOWER_BLOCK:%.*]], label [[END:%.*]]
142 ; CHECK:       lower.block:
143 ; CHECK-NEXT:    [[TMP2:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.arm.mve.vldr.gather.base.wb.v4i32.v4i32(<4 x i32> [[VEC_IND]], i32 96)
144 ; CHECK-NEXT:    [[TMP3:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 0
145 ; CHECK-NEXT:    [[TMP4]] = extractvalue { <4 x i32>, <4 x i32> } [[TMP2]], 1
146 ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[INDEX]]
147 ; CHECK-NEXT:    store <4 x i32> [[TMP3]], ptr [[TMP5]], align 4
148 ; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 4
149 ; CHECK-NEXT:    br label [[VECTOR_BODY_END]]
150 ; CHECK:       vector.body.end:
151 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC:%.*]]
152 ; CHECK-NEXT:    br i1 [[TMP6]], label [[END]], label [[VECTOR_BODY]]
153 ; CHECK:       end:
154 ; CHECK-NEXT:    ret void
157 vector.ph:
158   br label %vector.body
160 vector.body:                                      ; preds = %vector.body, %vector.ph
161   %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body.end ]
162   %vec.ind = phi <4 x i32> [ <i32 0, i32 2, i32 4, i32 6>, %vector.ph ], [ %vec.ind.next, %vector.body.end ]
163   %0 = icmp eq i32 %index, 48
164   br i1 %0, label %lower.block, label %end
166 lower.block:                             ; preds = %vector.body
167   %1 = mul <4 x i32> %vec.ind, <i32 3, i32 3, i32 3, i32 3>
168   %2 = add <4 x i32> %1, <i32 6, i32 6, i32 6, i32 6>
169   %3 = getelementptr inbounds i32, ptr %data, <4 x i32> %2
170   %wide.masked.gather = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %3, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
171   %4 = getelementptr inbounds i32, ptr %dst, i32 %index
172   %5 = bitcast ptr %4 to ptr
173   store <4 x i32> %wide.masked.gather, ptr %5, align 4
174   %index.next = add i32 %index, 4
175   %vec.ind.next = add <4 x i32> %vec.ind, <i32 8, i32 8, i32 8, i32 8>
176   br label %vector.body.end
178 vector.body.end:                             ; preds = %lower.block
179   %6 = icmp eq i32 %index.next, %n.vec
180   br i1 %6, label %end, label %vector.body
182 end:
183   ret void;
187 define arm_aapcs_vfpcc void @push_out_mul_sub_loop(ptr noalias nocapture readonly %data, ptr noalias nocapture %dst, i32 %n.vec) {
188 ; CHECK-LABEL: @push_out_mul_sub_loop(
189 ; CHECK-NEXT:  vector.ph:
190 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
191 ; CHECK:       vector.body:
192 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY_END:%.*]] ]
193 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i32> [ <i32 0, i32 2, i32 4, i32 6>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY_END]] ]
194 ; CHECK-NEXT:    br label [[VECTOR_2_PH:%.*]]
195 ; CHECK:       vector.2.ph:
196 ; CHECK-NEXT:    br label [[VECTOR_2_BODY:%.*]]
197 ; CHECK:       vector.2.body:
198 ; CHECK-NEXT:    [[TMP0:%.*]] = mul <4 x i32> [[VEC_IND]], <i32 3, i32 3, i32 3, i32 3>
199 ; CHECK-NEXT:    [[SCALEDINDEX:%.*]] = shl <4 x i32> [[TMP0]], <i32 2, i32 2, i32 2, i32 2>
200 ; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint ptr [[DATA:%.*]] to i32
201 ; CHECK-NEXT:    [[DOTSPLATINSERT:%.*]] = insertelement <4 x i32> poison, i32 [[TMP1]], i64 0
202 ; CHECK-NEXT:    [[DOTSPLAT:%.*]] = shufflevector <4 x i32> [[DOTSPLATINSERT]], <4 x i32> poison, <4 x i32> zeroinitializer
203 ; CHECK-NEXT:    [[STARTINDEX:%.*]] = add <4 x i32> [[SCALEDINDEX]], [[DOTSPLAT]]
204 ; CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vldr.gather.base.v4i32.v4i32(<4 x i32> [[STARTINDEX]], i32 24)
205 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[INDEX]]
206 ; CHECK-NEXT:    store <4 x i32> [[TMP2]], ptr [[TMP3]], align 4
207 ; CHECK-NEXT:    br label [[VECTOR_2_BODY_END:%.*]]
208 ; CHECK:       vector.2.body.end:
209 ; CHECK-NEXT:    [[INDEX_2_NEXT:%.*]] = add i32 [[INDEX]], 4
210 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[INDEX_2_NEXT]], 16
211 ; CHECK-NEXT:    br i1 [[TMP4]], label [[VECTOR_BODY_END]], label [[VECTOR_2_BODY]]
212 ; CHECK:       vector.body.end:
213 ; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 4
214 ; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <4 x i32> [[VEC_IND]], <i32 8, i32 8, i32 8, i32 8>
215 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC:%.*]]
216 ; CHECK-NEXT:    br i1 [[TMP5]], label [[END:%.*]], label [[VECTOR_BODY]]
217 ; CHECK:       end:
218 ; CHECK-NEXT:    ret void
221 vector.ph:
222   br label %vector.body
224 vector.body:                                      ; preds = %vector.body, %vector.ph
225   %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body.end ]
226   %vec.ind = phi <4 x i32> [ <i32 0, i32 2, i32 4, i32 6>, %vector.ph ], [ %vec.ind.next, %vector.body.end ]
227   br label %vector.2.ph
229 vector.2.ph:
230   br label %vector.2.body
232 vector.2.body:                             ; preds = %vector.body
233   %0 = mul <4 x i32> %vec.ind, <i32 3, i32 3, i32 3, i32 3>
234   %1 = add <4 x i32> %0, <i32 6, i32 6, i32 6, i32 6>
235   %2 = getelementptr inbounds i32, ptr %data, <4 x i32> %1
236   %wide.masked.gather = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %2, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
237   %3 = getelementptr inbounds i32, ptr %dst, i32 %index
238   %4 = bitcast ptr %3 to ptr
239   store <4 x i32> %wide.masked.gather, ptr %4, align 4
240   br label %vector.2.body.end
242 vector.2.body.end:                             ; preds = %lower.block
243   %index.2.next = add i32 %index, 4
244   %5 = icmp eq i32 %index.2.next, 16
245   br i1 %5, label %vector.body.end, label %vector.2.body
247 vector.body.end:                             ; preds = %lower.block
248   %index.next = add i32 %index, 4
249   %vec.ind.next = add <4 x i32> %vec.ind, <i32 8, i32 8, i32 8, i32 8>
250   %6 = icmp eq i32 %index.next, %n.vec
251   br i1 %6, label %end, label %vector.body
253 end:
254   ret void;
257 define arm_aapcs_vfpcc void @invariant_add(ptr noalias nocapture readonly %data, ptr noalias nocapture %dst, i32 %n.vec) {
258 ; CHECK-LABEL: @invariant_add(
259 ; CHECK-NEXT:  vector.ph:
260 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
261 ; CHECK:       vector.body:
262 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
263 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i32> [ <i32 0, i32 2, i32 4, i32 6>, [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[VECTOR_BODY]] ]
264 ; CHECK-NEXT:    [[L0:%.*]] = mul <4 x i32> [[VEC_IND]], <i32 3, i32 3, i32 3, i32 3>
265 ; CHECK-NEXT:    [[L1:%.*]] = add <4 x i32> [[L0]], [[VEC_IND]]
266 ; CHECK-NEXT:    [[TMP0:%.*]] = call <4 x i32> @llvm.arm.mve.vldr.gather.offset.v4i32.p0.v4i32(ptr [[DATA:%.*]], <4 x i32> [[L1]], i32 32, i32 2, i32 1)
267 ; CHECK-NEXT:    [[L3:%.*]] = getelementptr inbounds i32, ptr [[DST:%.*]], i32 [[INDEX]]
268 ; CHECK-NEXT:    store <4 x i32> [[TMP0]], ptr [[L3]], align 4
269 ; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 4
270 ; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <4 x i32> [[VEC_IND]], <i32 8, i32 8, i32 8, i32 8>
271 ; CHECK-NEXT:    [[L5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC:%.*]]
272 ; CHECK-NEXT:    br i1 [[L5]], label [[END:%.*]], label [[VECTOR_BODY]]
273 ; CHECK:       end:
274 ; CHECK-NEXT:    ret void
277 vector.ph:
278   br label %vector.body
280 vector.body:                                      ; preds = %vector.body, %vector.ph
281   %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
282   %vec.ind = phi <4 x i32> [ <i32 0, i32 2, i32 4, i32 6>, %vector.ph ], [ %vec.ind.next, %vector.body ]
283   %l0 = mul <4 x i32> %vec.ind, <i32 3, i32 3, i32 3, i32 3>
284   %l1 = add <4 x i32> %l0, %vec.ind
285   %l2 = getelementptr inbounds i32, ptr %data, <4 x i32> %l1
286   %wide.masked.gather = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %l2, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
287   %l3 = getelementptr inbounds i32, ptr %dst, i32 %index
288   %l4 = bitcast ptr %l3 to ptr
289   store <4 x i32> %wide.masked.gather, ptr %l4, align 4
290   %index.next = add i32 %index, 4
291   %vec.ind.next = add <4 x i32> %vec.ind, <i32 8, i32 8, i32 8, i32 8>
292   %l5 = icmp eq i32 %index.next, %n.vec
293   br i1 %l5, label %end, label %vector.body
295 end:
296   ret void;
299 define void @gatherload(i32 %n, i32 %m, ptr nocapture %a, ptr nocapture readonly %b, i32 %call.us.us) {
300 ; CHECK-LABEL: @gatherload(
301 ; CHECK-NEXT:  entry:
302 ; CHECK-NEXT:    [[CMP38:%.*]] = icmp sgt i32 [[N:%.*]], 0
303 ; CHECK-NEXT:    br i1 [[CMP38]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END16:%.*]]
304 ; CHECK:       for.body.lr.ph:
305 ; CHECK-NEXT:    [[CMP636:%.*]] = icmp sgt i32 [[M:%.*]], 0
306 ; CHECK-NEXT:    br i1 [[CMP636]], label [[FOR_BODY_US_US_PREHEADER:%.*]], label [[FOR_BODY:%.*]]
307 ; CHECK:       for.body.us.us.preheader:
308 ; CHECK-NEXT:    [[TMP0:%.*]] = shl nuw i32 [[M]], 2
309 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i32, ptr [[A:%.*]], i32 [[M]]
310 ; CHECK-NEXT:    [[SCEVGEP64:%.*]] = getelementptr i32, ptr [[B:%.*]], i32 [[M]]
311 ; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[M]], 4
312 ; CHECK-NEXT:    [[BOUND0:%.*]] = icmp ugt ptr [[SCEVGEP64]], [[A]]
313 ; CHECK-NEXT:    [[BOUND1:%.*]] = icmp ugt ptr [[SCEVGEP]], [[B]]
314 ; CHECK-NEXT:    [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
315 ; CHECK-NEXT:    [[N_VEC:%.*]] = and i32 [[M]], -4
316 ; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i32 [[N_VEC]], [[M]]
317 ; CHECK-NEXT:    br label [[FOR_BODY_US_US:%.*]]
318 ; CHECK:       for.body.us.us:
319 ; CHECK-NEXT:    [[I_039_US_US:%.*]] = phi i32 [ [[INC15_US_US:%.*]], [[FOR_COND5_FOR_END13_CRIT_EDGE_US_US:%.*]] ], [ 0, [[FOR_BODY_US_US_PREHEADER]] ]
320 ; CHECK-NEXT:    [[VLA_US_US:%.*]] = alloca i32, i32 [[CALL_US_US:%.*]], align 4
321 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr nonnull align 4 [[VLA_US_US]], ptr align 4 [[A]], i32 [[TMP0]], i1 false)
322 ; CHECK-NEXT:    [[BRMERGE:%.*]] = select i1 [[MIN_ITERS_CHECK]], i1 true, i1 [[FOUND_CONFLICT]]
323 ; CHECK-NEXT:    br i1 [[BRMERGE]], label [[FOR_BODY7_US_US_PREHEADER:%.*]], label [[VECTOR_BODY:%.*]]
324 ; CHECK:       vector.body:
325 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ], [ 0, [[FOR_BODY_US_US]] ]
326 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[B]], i32 [[INDEX]]
327 ; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[TMP1]], align 4
328 ; CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.vldr.gather.offset.v4i32.p0.v4i32(ptr [[VLA_US_US]], <4 x i32> [[WIDE_LOAD]], i32 32, i32 2, i32 1)
329 ; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[INDEX]]
330 ; CHECK-NEXT:    store <4 x i32> [[TMP2]], ptr [[TMP3]], align 4
331 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4
332 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
333 ; CHECK-NEXT:    br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]]
334 ; CHECK:       middle.block:
335 ; CHECK-NEXT:    br i1 [[CMP_N]], label [[FOR_COND5_FOR_END13_CRIT_EDGE_US_US]], label [[FOR_BODY7_US_US_PREHEADER]]
336 ; CHECK:       for.body7.us.us.preheader:
337 ; CHECK-NEXT:    [[J_137_US_US_PH:%.*]] = phi i32 [ 0, [[FOR_BODY_US_US]] ], [ [[N_VEC]], [[MIDDLE_BLOCK]] ]
338 ; CHECK-NEXT:    br label [[FOR_BODY7_US_US:%.*]]
339 ; CHECK:       for.body7.us.us:
340 ; CHECK-NEXT:    [[J_137_US_US:%.*]] = phi i32 [ [[INC12_US_US:%.*]], [[FOR_BODY7_US_US]] ], [ [[J_137_US_US_PH]], [[FOR_BODY7_US_US_PREHEADER]] ]
341 ; CHECK-NEXT:    [[ARRAYIDX8_US_US:%.*]] = getelementptr inbounds i32, ptr [[B]], i32 [[J_137_US_US]]
342 ; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[ARRAYIDX8_US_US]], align 4
343 ; CHECK-NEXT:    [[ARRAYIDX9_US_US:%.*]] = getelementptr inbounds i32, ptr [[VLA_US_US]], i32 [[TMP5]]
344 ; CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[ARRAYIDX9_US_US]], align 4
345 ; CHECK-NEXT:    [[ARRAYIDX10_US_US:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[J_137_US_US]]
346 ; CHECK-NEXT:    store i32 [[TMP6]], ptr [[ARRAYIDX10_US_US]], align 4
347 ; CHECK-NEXT:    [[INC12_US_US]] = add nuw nsw i32 [[J_137_US_US]], 1
348 ; CHECK-NEXT:    [[EXITCOND58_NOT:%.*]] = icmp eq i32 [[INC12_US_US]], [[M]]
349 ; CHECK-NEXT:    br i1 [[EXITCOND58_NOT]], label [[FOR_COND5_FOR_END13_CRIT_EDGE_US_US]], label [[FOR_BODY7_US_US]]
350 ; CHECK:       for.cond5.for.end13_crit_edge.us.us:
351 ; CHECK-NEXT:    [[INC15_US_US]] = add nuw nsw i32 [[I_039_US_US]], 1
352 ; CHECK-NEXT:    [[EXITCOND59_NOT:%.*]] = icmp eq i32 [[INC15_US_US]], [[N]]
353 ; CHECK-NEXT:    br i1 [[EXITCOND59_NOT]], label [[FOR_END16]], label [[FOR_BODY_US_US]]
354 ; CHECK:       for.body:
355 ; CHECK-NEXT:    [[I_039:%.*]] = phi i32 [ [[INC15:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_LR_PH]] ]
356 ; CHECK-NEXT:    [[INC15]] = add nuw nsw i32 [[I_039]], 1
357 ; CHECK-NEXT:    [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC15]], [[N]]
358 ; CHECK-NEXT:    br i1 [[EXITCOND_NOT]], label [[FOR_END16]], label [[FOR_BODY]]
359 ; CHECK:       for.end16:
360 ; CHECK-NEXT:    ret void
362 entry:
363   %a57 = bitcast ptr %a to ptr
364   %cmp38 = icmp sgt i32 %n, 0
365   br i1 %cmp38, label %for.body.lr.ph, label %for.end16
367 for.body.lr.ph:                                   ; preds = %entry
368   %cmp636 = icmp sgt i32 %m, 0
369   br i1 %cmp636, label %for.body.us.us.preheader, label %for.body
371 for.body.us.us.preheader:                         ; preds = %for.body.lr.ph
372   %0 = shl nuw i32 %m, 2
373   %scevgep = getelementptr i32, ptr %a, i32 %m
374   %scevgep64 = getelementptr i32, ptr %b, i32 %m
375   %min.iters.check = icmp ult i32 %m, 4
376   %bound0 = icmp ugt ptr %scevgep64, %a
377   %bound1 = icmp ugt ptr %scevgep, %b
378   %found.conflict = and i1 %bound0, %bound1
379   %n.vec = and i32 %m, -4
380   %cmp.n = icmp eq i32 %n.vec, %m
381   br label %for.body.us.us
383 for.body.us.us:                                   ; preds = %for.body.us.us.preheader, %for.cond5.for.end13_crit_edge.us.us
384   %i.039.us.us = phi i32 [ %inc15.us.us, %for.cond5.for.end13_crit_edge.us.us ], [ 0, %for.body.us.us.preheader ]
385   %1 = add i32 0, 0
386   %vla.us.us = alloca i32, i32 %call.us.us, align 4
387   %vla.us.us56 = bitcast ptr %vla.us.us to ptr
388   call void @llvm.memcpy.p0.p0.i32(ptr nonnull align 4 %vla.us.us56, ptr align 4 %a57, i32 %0, i1 false)
389   %brmerge = select i1 %min.iters.check, i1 true, i1 %found.conflict
390   br i1 %brmerge, label %for.body7.us.us.preheader, label %vector.body
392 vector.body:                                      ; preds = %for.body.us.us, %vector.body
393   %index = phi i32 [ %index.next, %vector.body ], [ 0, %for.body.us.us ]
394   %2 = getelementptr inbounds i32, ptr %b, i32 %index
395   %3 = bitcast ptr %2 to ptr
396   %wide.load = load <4 x i32>, ptr %3, align 4
397   %4 = getelementptr inbounds i32, ptr %vla.us.us, <4 x i32> %wide.load
398   %wide.masked.gather = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %4, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
399   %5 = getelementptr inbounds i32, ptr %a, i32 %index
400   %6 = bitcast ptr %5 to ptr
401   store <4 x i32> %wide.masked.gather, ptr %6, align 4
402   %index.next = add nuw i32 %index, 4
403   %7 = icmp eq i32 %index.next, %n.vec
404   br i1 %7, label %middle.block, label %vector.body
406 middle.block:                                     ; preds = %vector.body
407   br i1 %cmp.n, label %for.cond5.for.end13_crit_edge.us.us, label %for.body7.us.us.preheader
409 for.body7.us.us.preheader:                        ; preds = %for.body.us.us, %middle.block
410   %j.137.us.us.ph = phi i32 [ 0, %for.body.us.us ], [ %n.vec, %middle.block ]
411   br label %for.body7.us.us
413 for.body7.us.us:                                  ; preds = %for.body7.us.us.preheader, %for.body7.us.us
414   %j.137.us.us = phi i32 [ %inc12.us.us, %for.body7.us.us ], [ %j.137.us.us.ph, %for.body7.us.us.preheader ]
415   %arrayidx8.us.us = getelementptr inbounds i32, ptr %b, i32 %j.137.us.us
416   %8 = load i32, ptr %arrayidx8.us.us, align 4
417   %arrayidx9.us.us = getelementptr inbounds i32, ptr %vla.us.us, i32 %8
418   %9 = load i32, ptr %arrayidx9.us.us, align 4
419   %arrayidx10.us.us = getelementptr inbounds i32, ptr %a, i32 %j.137.us.us
420   store i32 %9, ptr %arrayidx10.us.us, align 4
421   %inc12.us.us = add nuw nsw i32 %j.137.us.us, 1
422   %exitcond58.not = icmp eq i32 %inc12.us.us, %m
423   br i1 %exitcond58.not, label %for.cond5.for.end13_crit_edge.us.us, label %for.body7.us.us
425 for.cond5.for.end13_crit_edge.us.us:              ; preds = %for.body7.us.us, %middle.block
426   %inc15.us.us = add nuw nsw i32 %i.039.us.us, 1
427   %exitcond59.not = icmp eq i32 %inc15.us.us, %n
428   br i1 %exitcond59.not, label %for.end16, label %for.body.us.us
430 for.body:                                         ; preds = %for.body.lr.ph, %for.body
431   %i.039 = phi i32 [ %inc15, %for.body ], [ 0, %for.body.lr.ph ]
432   %inc15 = add nuw nsw i32 %i.039, 1
433   %exitcond.not = icmp eq i32 %inc15, %n
434   br i1 %exitcond.not, label %for.end16, label %for.body
436 for.end16:                                        ; preds = %for.body, %for.cond5.for.end13_crit_edge.us.us, %entry
437   ret void
440 declare <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr>, i32, <4 x i1>, <4 x i32>)
441 declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1)