[mlir][LLVM] `LLVMTypeConverter`: Tighten materialization checks (#116532)
[llvm-project.git] / llvm / test / Transforms / VectorCombine / load-insert-store.ll
blob93565c1a708eba039881b84ca7f0caab3e39c201
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=vector-combine -data-layout=e < %s | FileCheck %s
3 ; RUN: opt -S -passes=vector-combine -data-layout=E < %s | FileCheck %s
5 define void @insert_store(ptr %q, i8 zeroext %s) {
6 ; CHECK-LABEL: @insert_store(
7 ; CHECK-NEXT:  entry:
8 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 3
9 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
10 ; CHECK-NEXT:    ret void
12 entry:
13   %0 = load <16 x i8>, ptr %q
14   %vecins = insertelement <16 x i8> %0, i8 %s, i32 3
15   store <16 x i8> %vecins, ptr %q, align 16
16   ret void
19 define void @insert_store_i16_align1(ptr %q, i16 zeroext %s) {
20 ; CHECK-LABEL: @insert_store_i16_align1(
21 ; CHECK-NEXT:  entry:
22 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <8 x i16>, ptr [[Q:%.*]], i32 0, i32 3
23 ; CHECK-NEXT:    store i16 [[S:%.*]], ptr [[TMP0]], align 2
24 ; CHECK-NEXT:    ret void
26 entry:
27   %0 = load <8 x i16>, ptr %q
28   %vecins = insertelement <8 x i16> %0, i16 %s, i32 3
29   store <8 x i16> %vecins, ptr %q, align 1
30   ret void
33 ; To verify case when index is out of bounds
34 define void @insert_store_outofbounds(ptr %q, i16 zeroext %s) {
35 ; CHECK-LABEL: @insert_store_outofbounds(
36 ; CHECK-NEXT:  entry:
37 ; CHECK-NEXT:    [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16
38 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 9
39 ; CHECK-NEXT:    store <8 x i16> [[VECINS]], ptr [[Q]], align 16
40 ; CHECK-NEXT:    ret void
42 entry:
43   %0 = load <8 x i16>, ptr %q
44   %vecins = insertelement <8 x i16> %0, i16 %s, i32 9
45   store <8 x i16> %vecins, ptr %q
46   ret void
49 define void @insert_store_vscale(ptr %q, i16 zeroext %s) {
50 ; CHECK-LABEL: @insert_store_vscale(
51 ; CHECK-NEXT:  entry:
52 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <vscale x 8 x i16>, ptr [[Q:%.*]], i32 0, i32 3
53 ; CHECK-NEXT:    store i16 [[S:%.*]], ptr [[TMP0]], align 2
54 ; CHECK-NEXT:    ret void
56 entry:
57   %0 = load <vscale x 8 x i16>, ptr %q
58   %vecins = insertelement <vscale x 8 x i16> %0, i16 %s, i32 3
59   store <vscale x 8 x i16> %vecins, ptr %q
60   ret void
63 ; To verify the case that index exceeds the minimum number
64 ; of elements of a scalable vector type.
65 define void @insert_store_vscale_exceeds(ptr %q, i16 zeroext %s) {
66 ; CHECK-LABEL: @insert_store_vscale_exceeds(
67 ; CHECK-NEXT:  entry:
68 ; CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 8 x i16>, ptr [[Q:%.*]], align 16
69 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <vscale x 8 x i16> [[TMP0]], i16 [[S:%.*]], i32 9
70 ; CHECK-NEXT:    store <vscale x 8 x i16> [[VECINS]], ptr [[Q]], align 16
71 ; CHECK-NEXT:    ret void
73 entry:
74   %0 = load <vscale x 8 x i16>, ptr %q
75   %vecins = insertelement <vscale x 8 x i16> %0, i16 %s, i32 9
76   store <vscale x 8 x i16> %vecins, ptr %q
77   ret void
80 define void @insert_store_v9i4(ptr %q, i4 zeroext %s) {
81 ; CHECK-LABEL: @insert_store_v9i4(
82 ; CHECK-NEXT:  entry:
83 ; CHECK-NEXT:    [[TMP0:%.*]] = load <9 x i4>, ptr [[Q:%.*]], align 8
84 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <9 x i4> [[TMP0]], i4 [[S:%.*]], i32 3
85 ; CHECK-NEXT:    store <9 x i4> [[VECINS]], ptr [[Q]], align 1
86 ; CHECK-NEXT:    ret void
88 entry:
89   %0 = load <9 x i4>, ptr %q
90   %vecins = insertelement <9 x i4> %0, i4 %s, i32 3
91   store <9 x i4> %vecins, ptr %q, align 1
92   ret void
95 define void @insert_store_v4i27(ptr %q, i27 zeroext %s) {
96 ; CHECK-LABEL: @insert_store_v4i27(
97 ; CHECK-NEXT:  entry:
98 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x i27>, ptr [[Q:%.*]], align 16
99 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x i27> [[TMP0]], i27 [[S:%.*]], i32 3
100 ; CHECK-NEXT:    store <4 x i27> [[VECINS]], ptr [[Q]], align 1
101 ; CHECK-NEXT:    ret void
103 entry:
104   %0 = load <4 x i27>, ptr %q
105   %vecins = insertelement <4 x i27> %0, i27 %s, i32 3
106   store <4 x i27> %vecins, ptr %q, align 1
107   ret void
110 define void @insert_store_v32i1(ptr %p) {
111 ; CHECK-LABEL: @insert_store_v32i1(
112 ; CHECK-NEXT:    [[VEC:%.*]] = load <32 x i1>, ptr [[P:%.*]], align 4
113 ; CHECK-NEXT:    [[INS:%.*]] = insertelement <32 x i1> [[VEC]], i1 true, i64 0
114 ; CHECK-NEXT:    store <32 x i1> [[INS]], ptr [[P]], align 4
115 ; CHECK-NEXT:    ret void
117   %vec = load <32 x i1>, ptr %p
118   %ins = insertelement <32 x i1> %vec, i1 true, i64 0
119   store <32 x i1> %ins, ptr %p
120   ret void
123 define void @insert_store_blk_differ(ptr %q, i16 zeroext %s) {
124 ; CHECK-LABEL: @insert_store_blk_differ(
125 ; CHECK-NEXT:  entry:
126 ; CHECK-NEXT:    [[TMP0:%.*]] = load <8 x i16>, ptr [[Q:%.*]], align 16
127 ; CHECK-NEXT:    br label [[CONT:%.*]]
128 ; CHECK:       cont:
129 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <8 x i16> [[TMP0]], i16 [[S:%.*]], i32 3
130 ; CHECK-NEXT:    store <8 x i16> [[VECINS]], ptr [[Q]], align 16
131 ; CHECK-NEXT:    ret void
133 entry:
134   %0 = load <8 x i16>, ptr %q
135   br label %cont
136 cont:
137   %vecins = insertelement <8 x i16> %0, i16 %s, i32 3
138   store <8 x i16> %vecins, ptr %q
139   ret void
142 define void @insert_store_nonconst(ptr %q, i8 zeroext %s, i32 %idx) {
143 ; CHECK-LABEL: @insert_store_nonconst(
144 ; CHECK-NEXT:  entry:
145 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
146 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]]
147 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
148 ; CHECK-NEXT:    ret void
150 entry:
151   %0 = load <16 x i8>, ptr %q
152   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx
153   store <16 x i8> %vecins, ptr %q
154   ret void
157 ; To verify the case that the index is not a constant, and
158 ; the vector type is scalable.
159 define void @insert_store_vscale_nonconst(ptr %q, i8 zeroext %s, i32 %idx) {
160 ; CHECK-LABEL: @insert_store_vscale_nonconst(
161 ; CHECK-NEXT:  entry:
162 ; CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16
163 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX:%.*]]
164 ; CHECK-NEXT:    store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16
165 ; CHECK-NEXT:    ret void
167 entry:
168   %0 = load <vscale x 16 x i8>, ptr %q
169   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx
170   store <vscale x 16 x i8> %vecins, ptr %q
171   ret void
174 ; To verify align here is narrowed to scalar store size
175 define void @insert_store_nonconst_large_alignment(ptr %q, i32 zeroext %s, i32 %idx) {
176 ; CHECK-LABEL: @insert_store_nonconst_large_alignment(
177 ; CHECK-NEXT:  entry:
178 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4
179 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
180 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <4 x i32>, ptr [[Q:%.*]], i32 0, i32 [[IDX]]
181 ; CHECK-NEXT:    store i32 [[S:%.*]], ptr [[TMP0]], align 4
182 ; CHECK-NEXT:    ret void
184 entry:
185   %cmp = icmp ult i32 %idx, 4
186   call void @llvm.assume(i1 %cmp)
187   %i = load <4 x i32>, ptr %q, align 128
188   %vecins = insertelement <4 x i32> %i, i32 %s, i32 %idx
189   store <4 x i32> %vecins, ptr %q, align 128
190   ret void
193 define void @insert_store_nonconst_align_maximum_8(ptr %q, i64 %s, i32 %idx) {
194 ; CHECK-LABEL: @insert_store_nonconst_align_maximum_8(
195 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2
196 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
197 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]]
198 ; CHECK-NEXT:    store i64 [[S:%.*]], ptr [[TMP1]], align 8
199 ; CHECK-NEXT:    ret void
201   %cmp = icmp ult i32 %idx, 2
202   call void @llvm.assume(i1 %cmp)
203   %i = load <8 x i64>, ptr %q, align 8
204   %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx
205   store <8 x i64> %vecins, ptr %q, align 8
206   ret void
209 define void @insert_store_nonconst_align_maximum_4(ptr %q, i64 %s, i32 %idx) {
210 ; CHECK-LABEL: @insert_store_nonconst_align_maximum_4(
211 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2
212 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
213 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]]
214 ; CHECK-NEXT:    store i64 [[S:%.*]], ptr [[TMP1]], align 4
215 ; CHECK-NEXT:    ret void
217   %cmp = icmp ult i32 %idx, 2
218   call void @llvm.assume(i1 %cmp)
219   %i = load <8 x i64>, ptr %q, align 4
220   %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx
221   store <8 x i64> %vecins, ptr %q, align 4
222   ret void
225 define void @insert_store_nonconst_align_larger(ptr %q, i64 %s, i32 %idx) {
226 ; CHECK-LABEL: @insert_store_nonconst_align_larger(
227 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 2
228 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
229 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds <8 x i64>, ptr [[Q:%.*]], i32 0, i32 [[IDX]]
230 ; CHECK-NEXT:    store i64 [[S:%.*]], ptr [[TMP1]], align 4
231 ; CHECK-NEXT:    ret void
233   %cmp = icmp ult i32 %idx, 2
234   call void @llvm.assume(i1 %cmp)
235   %i = load <8 x i64>, ptr %q, align 4
236   %vecins = insertelement <8 x i64> %i, i64 %s, i32 %idx
237   store <8 x i64> %vecins, ptr %q, align 2
238   ret void
241 define void @insert_store_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) {
242 ; CHECK-LABEL: @insert_store_nonconst_index_known_valid_by_assume(
243 ; CHECK-NEXT:  entry:
244 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4
245 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
246 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX]]
247 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
248 ; CHECK-NEXT:    ret void
250 entry:
251   %cmp = icmp ult i32 %idx, 4
252   call void @llvm.assume(i1 %cmp)
253   %0 = load <16 x i8>, ptr %q
254   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx
255   store <16 x i8> %vecins, ptr %q
256   ret void
259 ; To verify the index is not a constant but valid by assume,
260 ; for scalable vector types.
261 define void @insert_store_vscale_nonconst_index_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) {
262 ; CHECK-LABEL: @insert_store_vscale_nonconst_index_known_valid_by_assume(
263 ; CHECK-NEXT:  entry:
264 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4
265 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
266 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <vscale x 16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX]]
267 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
268 ; CHECK-NEXT:    ret void
270 entry:
271   %cmp = icmp ult i32 %idx, 4
272   call void @llvm.assume(i1 %cmp)
273   %0 = load <vscale x 16 x i8>, ptr %q
274   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx
275   store <vscale x 16 x i8> %vecins, ptr %q
276   ret void
279 declare void @maythrow() readnone
281 define void @insert_store_nonconst_index_not_known_valid_by_assume_after_load(ptr %q, i8 zeroext %s, i32 %idx) {
282 ; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume_after_load(
283 ; CHECK-NEXT:  entry:
284 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 4
285 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
286 ; CHECK-NEXT:    call void @maythrow()
287 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
288 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]]
289 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
290 ; CHECK-NEXT:    ret void
292 entry:
293   %cmp = icmp ult i32 %idx, 4
294   %0 = load <16 x i8>, ptr %q
295   call void @maythrow()
296   call void @llvm.assume(i1 %cmp)
297   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx
298   store <16 x i8> %vecins, ptr %q
299   ret void
302 define void @insert_store_nonconst_index_not_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) {
303 ; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_assume(
304 ; CHECK-NEXT:  entry:
305 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17
306 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
307 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
308 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]]
309 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
310 ; CHECK-NEXT:    ret void
312 entry:
313   %cmp = icmp ult i32 %idx, 17
314   call void @llvm.assume(i1 %cmp)
315   %0 = load <16 x i8>, ptr %q
316   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx
317   store <16 x i8> %vecins, ptr %q
318   ret void
321 ; To verify the index is not a constant and may not be valid by assume,
322 ; for scalable vector types.
323 define void @insert_store_vscale_nonconst_index_not_known_valid_by_assume(ptr %q, i8 zeroext %s, i32 %idx) {
324 ; CHECK-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_assume(
325 ; CHECK-NEXT:  entry:
326 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[IDX:%.*]], 17
327 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP]])
328 ; CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16
329 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX]]
330 ; CHECK-NEXT:    store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16
331 ; CHECK-NEXT:    ret void
333 entry:
334   %cmp = icmp ult i32 %idx, 17
335   call void @llvm.assume(i1 %cmp)
336   %0 = load <vscale x 16 x i8>, ptr %q
337   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx
338   store <vscale x 16 x i8> %vecins, ptr %q
339   ret void
342 declare void @llvm.assume(i1)
344 define void @insert_store_nonconst_index_known_noundef_and_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) {
345 ; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_and(
346 ; CHECK-NEXT:  entry:
347 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7
348 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
349 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
350 ; CHECK-NEXT:    ret void
352 entry:
353   %0 = load <16 x i8>, ptr %q
354   %idx.clamped = and i32 %idx, 7
355   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
356   store <16 x i8> %vecins, ptr %q
357   ret void
360 ; To verify the index is not a constant but valid by and,
361 ; for scalable vector types.
362 define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) {
363 ; CHECK-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_and(
364 ; CHECK-NEXT:  entry:
365 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7
366 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <vscale x 16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
367 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
368 ; CHECK-NEXT:    ret void
370 entry:
371   %0 = load <vscale x 16 x i8>, ptr %q
372   %idx.clamped = and i32 %idx, 7
373   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped
374   store <vscale x 16 x i8> %vecins, ptr %q
375   ret void
378 define void @insert_store_nonconst_index_base_frozen_and_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) {
379 ; CHECK-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_and(
380 ; CHECK-NEXT:  entry:
381 ; CHECK-NEXT:    [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]]
382 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7
383 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
384 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
385 ; CHECK-NEXT:    ret void
387 entry:
388   %0 = load <16 x i8>, ptr %q
389   %idx.frozen = freeze i32 %idx
390   %idx.clamped = and i32 %idx.frozen, 7
391   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
392   store <16 x i8> %vecins, ptr %q
393   ret void
396 define void @insert_store_nonconst_index_frozen_and_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) {
397 ; CHECK-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_and(
398 ; CHECK-NEXT:  entry:
399 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
400 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 7
401 ; CHECK-NEXT:    [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]]
402 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]]
403 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
404 ; CHECK-NEXT:    ret void
406 entry:
407   %0 = load <16 x i8>, ptr %q
408   %idx.clamped = and i32 %idx, 7
409   %idx.clamped.frozen = freeze i32 %idx.clamped
410   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped.frozen
411   store <16 x i8> %vecins, ptr %q
412   ret void
415 define void @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison(ptr %q, i8 zeroext %s, i32 %idx) {
416 ; CHECK-LABEL: @insert_store_nonconst_index_known_valid_by_and_but_may_be_poison(
417 ; CHECK-NEXT:  entry:
418 ; CHECK-NEXT:    [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]]
419 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX_FROZEN]], 7
420 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
421 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
422 ; CHECK-NEXT:    ret void
424 entry:
425   %0 = load <16 x i8>, ptr %q
426   %idx.clamped = and i32 %idx, 7
427   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
428   store <16 x i8> %vecins, ptr %q
429   ret void
432 define void @insert_store_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) {
433 ; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_and(
434 ; CHECK-NEXT:  entry:
435 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
436 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16
437 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]]
438 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
439 ; CHECK-NEXT:    ret void
441 entry:
442   %0 = load <16 x i8>, ptr %q
443   %idx.clamped = and i32 %idx, 16
444   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
445   store <16 x i8> %vecins, ptr %q
446   ret void
449 define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 noundef %idx) {
450 ; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_and(
451 ; CHECK-NEXT:  entry:
452 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
453 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 16
454 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]]
455 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
456 ; CHECK-NEXT:    ret void
458 entry:
459   %0 = load <16 x i8>, ptr %q
460   %idx.clamped = and i32 %idx, 16
461   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
462   store <16 x i8> %vecins, ptr %q
463   ret void
466 ; To verify the index is not a constant and may not be valid by and,
467 ; for scalable vector types.
468 define void @insert_store_vscale_nonconst_index_not_known_valid_by_and(ptr %q, i8 zeroext %s, i32 %idx) {
469 ; CHECK-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_and(
470 ; CHECK-NEXT:  entry:
471 ; CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16
472 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = and i32 [[IDX:%.*]], 31
473 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]]
474 ; CHECK-NEXT:    store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16
475 ; CHECK-NEXT:    ret void
477 entry:
478   %0 = load <vscale x 16 x i8>, ptr %q
479   %idx.clamped = and i32 %idx, 31
480   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped
481   store <vscale x 16 x i8> %vecins, ptr %q
482   ret void
485 define void @insert_store_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) {
486 ; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_and_valid_by_urem(
487 ; CHECK-NEXT:  entry:
488 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16
489 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
490 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
491 ; CHECK-NEXT:    ret void
493 entry:
494   %0 = load <16 x i8>, ptr %q
495   %idx.clamped = urem i32 %idx, 16
496   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
497   store <16 x i8> %vecins, ptr %q
498   ret void
501 ; To verify the index is not a constant but valid by urem,
502 ; for scalable vector types.
503 define void @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) {
504 ; CHECK-LABEL: @insert_store_vscale_nonconst_index_known_noundef_and_valid_by_urem(
505 ; CHECK-NEXT:  entry:
506 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16
507 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <vscale x 16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
508 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
509 ; CHECK-NEXT:    ret void
511 entry:
512   %0 = load <vscale x 16 x i8>, ptr %q
513   %idx.clamped = urem i32 %idx, 16
514   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped
515   store <vscale x 16 x i8> %vecins, ptr %q
516   ret void
519 define void @insert_store_nonconst_index_base_frozen_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) {
520 ; CHECK-LABEL: @insert_store_nonconst_index_base_frozen_and_valid_by_urem(
521 ; CHECK-NEXT:  entry:
522 ; CHECK-NEXT:    [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]]
523 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16
524 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
525 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
526 ; CHECK-NEXT:    ret void
528 entry:
529   %0 = load <16 x i8>, ptr %q
530   %idx.frozen = freeze i32 %idx
531   %idx.clamped = urem i32 %idx.frozen, 16
532   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
533   store <16 x i8> %vecins, ptr %q
534   ret void
537 define void @insert_store_nonconst_index_frozen_and_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) {
538 ; CHECK-LABEL: @insert_store_nonconst_index_frozen_and_valid_by_urem(
539 ; CHECK-NEXT:  entry:
540 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
541 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 16
542 ; CHECK-NEXT:    [[IDX_CLAMPED_FROZEN:%.*]] = freeze i32 [[IDX_CLAMPED]]
543 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED_FROZEN]]
544 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
545 ; CHECK-NEXT:    ret void
547 entry:
548   %0 = load <16 x i8>, ptr %q
549   %idx.clamped = urem i32 %idx, 16
550   %idx.clamped.frozen = freeze i32 %idx.clamped
551   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped.frozen
552   store <16 x i8> %vecins, ptr %q
553   ret void
556 define void @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison(ptr %q, i8 zeroext %s, i32 %idx) {
557 ; CHECK-LABEL: @insert_store_nonconst_index_known_valid_by_urem_but_may_be_poison(
558 ; CHECK-NEXT:  entry:
559 ; CHECK-NEXT:    [[IDX_FROZEN:%.*]] = freeze i32 [[IDX:%.*]]
560 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX_FROZEN]], 16
561 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 [[IDX_CLAMPED]]
562 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
563 ; CHECK-NEXT:    ret void
565 entry:
566   %0 = load <16 x i8>, ptr %q
567   %idx.clamped = urem i32 %idx, 16
568   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
569   store <16 x i8> %vecins, ptr %q
570   ret void
573 define void @insert_store_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) {
574 ; CHECK-LABEL: @insert_store_nonconst_index_not_known_valid_by_urem(
575 ; CHECK-NEXT:  entry:
576 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
577 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17
578 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]]
579 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
580 ; CHECK-NEXT:    ret void
582 entry:
583   %0 = load <16 x i8>, ptr %q
584   %idx.clamped = urem i32 %idx, 17
585   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
586   store <16 x i8> %vecins, ptr %q
587   ret void
590 ; To verify the index is not a constant and may not be vaild by urem,
591 ; for scalable vector types.
592 define void @insert_store_vscale_nonconst_index_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 %idx) {
593 ; CHECK-LABEL: @insert_store_vscale_nonconst_index_not_known_valid_by_urem(
594 ; CHECK-NEXT:  entry:
595 ; CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i8>, ptr [[Q:%.*]], align 16
596 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17
597 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <vscale x 16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]]
598 ; CHECK-NEXT:    store <vscale x 16 x i8> [[VECINS]], ptr [[Q]], align 16
599 ; CHECK-NEXT:    ret void
601 entry:
602   %0 = load <vscale x 16 x i8>, ptr %q
603   %idx.clamped = urem i32 %idx, 17
604   %vecins = insertelement <vscale x 16 x i8> %0, i8 %s, i32 %idx.clamped
605   store <vscale x 16 x i8> %vecins, ptr %q
606   ret void
609 define void @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem(ptr %q, i8 zeroext %s, i32 noundef %idx) {
610 ; CHECK-LABEL: @insert_store_nonconst_index_known_noundef_not_known_valid_by_urem(
611 ; CHECK-NEXT:  entry:
612 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
613 ; CHECK-NEXT:    [[IDX_CLAMPED:%.*]] = urem i32 [[IDX:%.*]], 17
614 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 [[IDX_CLAMPED]]
615 ; CHECK-NEXT:    store <16 x i8> [[VECINS]], ptr [[Q]], align 16
616 ; CHECK-NEXT:    ret void
618 entry:
619   %0 = load <16 x i8>, ptr %q
620   %idx.clamped = urem i32 %idx, 17
621   %vecins = insertelement <16 x i8> %0, i8 %s, i32 %idx.clamped
622   store <16 x i8> %vecins, ptr %q
623   ret void
626 define void @insert_store_ptr_strip(ptr %q, i8 zeroext %s) {
627 ; CHECK-LABEL: @insert_store_ptr_strip(
628 ; CHECK-NEXT:  entry:
629 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q:%.*]], i32 0, i32 3
630 ; CHECK-NEXT:    store i8 [[S:%.*]], ptr [[TMP0]], align 1
631 ; CHECK-NEXT:    ret void
633 entry:
634   %0 = load <16 x i8>, ptr %q
635   %vecins = insertelement <16 x i8> %0, i8 %s, i32 3
636   store <16 x i8> %vecins, ptr %q
637   ret void
640 define void @volatile_update(ptr %q, ptr %p, i8 zeroext %s) {
641 ; CHECK-LABEL: @volatile_update(
642 ; CHECK-NEXT:  entry:
643 ; CHECK-NEXT:    [[TMP0:%.*]] = load <16 x i8>, ptr [[Q:%.*]], align 16
644 ; CHECK-NEXT:    [[VECINS0:%.*]] = insertelement <16 x i8> [[TMP0]], i8 [[S:%.*]], i32 3
645 ; CHECK-NEXT:    store volatile <16 x i8> [[VECINS0]], ptr [[Q]], align 16
646 ; CHECK-NEXT:    [[TMP1:%.*]] = load volatile <16 x i8>, ptr [[P:%.*]], align 16
647 ; CHECK-NEXT:    [[VECINS1:%.*]] = insertelement <16 x i8> [[TMP1]], i8 [[S]], i32 1
648 ; CHECK-NEXT:    store <16 x i8> [[VECINS1]], ptr [[P]], align 16
649 ; CHECK-NEXT:    ret void
651 entry:
652   %0 = load <16 x i8>, ptr %q
653   %vecins0 = insertelement <16 x i8> %0, i8 %s, i32 3
654   store volatile <16 x i8> %vecins0, ptr %q
656   %1 = load volatile <16 x i8>, ptr %p
657   %vecins1 = insertelement <16 x i8> %1, i8 %s, i32 1
658   store <16 x i8> %vecins1, ptr %p
659   ret void
662 define void @insert_store_addr_differ(ptr %p, ptr %q, i8 %s) {
663 ; CHECK-LABEL: @insert_store_addr_differ(
664 ; CHECK-NEXT:  entry:
665 ; CHECK-NEXT:    [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16
666 ; CHECK-NEXT:    [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3
667 ; CHECK-NEXT:    store <16 x i8> [[INS]], ptr [[Q:%.*]], align 16
668 ; CHECK-NEXT:    ret void
670 entry:
671   %ld = load <16 x i8>, ptr %p
672   %ins = insertelement <16 x i8> %ld, i8 %s, i32 3
673   store <16 x i8> %ins, ptr %q
674   ret void
677 ; We can't transform if any instr could modify memory in between.
678 define void @insert_store_mem_modify(ptr %p, ptr %q, ptr noalias %r, i8 %s, i32 %m) {
679 ; CHECK-LABEL: @insert_store_mem_modify(
680 ; CHECK-NEXT:  entry:
681 ; CHECK-NEXT:    [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16
682 ; CHECK-NEXT:    store <16 x i8> zeroinitializer, ptr [[Q:%.*]], align 16
683 ; CHECK-NEXT:    [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3
684 ; CHECK-NEXT:    store <16 x i8> [[INS]], ptr [[P]], align 16
685 ; CHECK-NEXT:    store <16 x i8> zeroinitializer, ptr [[R:%.*]], align 16
686 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[Q]], i32 0, i32 7
687 ; CHECK-NEXT:    store i8 [[S]], ptr [[TMP0]], align 1
688 ; CHECK-NEXT:    [[LD3:%.*]] = load <4 x i32>, ptr [[P]], align 16
689 ; CHECK-NEXT:    store <16 x i8> zeroinitializer, ptr [[P]], align 16
690 ; CHECK-NEXT:    [[INS3:%.*]] = insertelement <4 x i32> [[LD3]], i32 [[M:%.*]], i32 0
691 ; CHECK-NEXT:    store <4 x i32> [[INS3]], ptr [[P]], align 16
692 ; CHECK-NEXT:    ret void
694 entry:
695   ; p may alias q
696   %ld = load <16 x i8>, ptr %p
697   store <16 x i8> zeroinitializer, ptr %q
698   %ins = insertelement <16 x i8> %ld, i8 %s, i32 3
699   store <16 x i8> %ins, ptr %p
701   ; p never aliases r
702   %ld2 = load <16 x i8>, ptr %q
703   store <16 x i8> zeroinitializer, ptr %r
704   %ins2 = insertelement <16 x i8> %ld2, i8 %s, i32 7
705   store <16 x i8> %ins2, ptr %q
707   ; p must alias ptr0
708   %ld3 = load <4 x i32>, ptr %p
709   store <16 x i8> zeroinitializer, ptr %p
710   %ins3 = insertelement <4 x i32> %ld3, i32 %m, i32 0
711   store <4 x i32> %ins3, ptr %p
713   ret void
716 ; Check cases when calls may modify memory
717 define void @insert_store_with_call(ptr %p, ptr %q, i8 %s) {
718 ; CHECK-LABEL: @insert_store_with_call(
719 ; CHECK-NEXT:  entry:
720 ; CHECK-NEXT:    [[LD:%.*]] = load <16 x i8>, ptr [[P:%.*]], align 16
721 ; CHECK-NEXT:    call void @maywrite(ptr [[P]])
722 ; CHECK-NEXT:    [[INS:%.*]] = insertelement <16 x i8> [[LD]], i8 [[S:%.*]], i32 3
723 ; CHECK-NEXT:    store <16 x i8> [[INS]], ptr [[P]], align 16
724 ; CHECK-NEXT:    call void @foo()
725 ; CHECK-NEXT:    call void @nowrite(ptr [[P]])
726 ; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds <16 x i8>, ptr [[P]], i32 0, i32 7
727 ; CHECK-NEXT:    store i8 [[S]], ptr [[TMP0]], align 1
728 ; CHECK-NEXT:    ret void
730 entry:
731   %ld = load <16 x i8>, ptr %p
732   call void @maywrite(ptr %p)
733   %ins = insertelement <16 x i8> %ld, i8 %s, i32 3
734   store <16 x i8> %ins, ptr %p
735   call void @foo()  ; Barrier
736   %ld2 = load <16 x i8>, ptr %p
737   call void @nowrite(ptr %p)
738   %ins2 = insertelement <16 x i8> %ld2, i8 %s, i32 7
739   store <16 x i8> %ins2, ptr %p
740   ret void
743 declare void @foo()
744 declare void @maywrite(ptr)
745 declare void @nowrite(ptr) readonly
747 ; To test if number of instructions in-between exceeds the limit (default 30),
748 ; the combine will quit.
749 define i32 @insert_store_maximum_scan_instrs(i32 %arg, ptr %arg1, ptr %arg2, i8 zeroext %arg3) {
750 ; CHECK-LABEL: @insert_store_maximum_scan_instrs(
751 ; CHECK-NEXT:  bb:
752 ; CHECK-NEXT:    [[I:%.*]] = or i32 [[ARG:%.*]], 1
753 ; CHECK-NEXT:    [[I4:%.*]] = load <16 x i8>, ptr [[ARG2:%.*]], align 16
754 ; CHECK-NEXT:    [[I5:%.*]] = tail call i32 @bar(i32 [[I]], i1 true)
755 ; CHECK-NEXT:    [[I6:%.*]] = shl i32 [[ARG]], [[I5]]
756 ; CHECK-NEXT:    [[I7:%.*]] = lshr i32 [[I6]], 26
757 ; CHECK-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
758 ; CHECK-NEXT:    [[I9:%.*]] = and i8 [[I8]], 31
759 ; CHECK-NEXT:    [[I10:%.*]] = lshr i32 [[I6]], 11
760 ; CHECK-NEXT:    [[I11:%.*]] = and i32 [[I10]], 32767
761 ; CHECK-NEXT:    [[I12:%.*]] = zext i8 [[I9]] to i64
762 ; CHECK-NEXT:    [[I13:%.*]] = getelementptr inbounds i16, ptr [[ARG1:%.*]], i64 [[I12]]
763 ; CHECK-NEXT:    [[I14:%.*]] = load i16, ptr [[I13]], align 2
764 ; CHECK-NEXT:    [[I15:%.*]] = zext i16 [[I14]] to i32
765 ; CHECK-NEXT:    [[I16:%.*]] = add nuw nsw i8 [[I9]], 1
766 ; CHECK-NEXT:    [[I17:%.*]] = zext i8 [[I16]] to i64
767 ; CHECK-NEXT:    [[I18:%.*]] = getelementptr inbounds i16, ptr [[ARG1]], i64 [[I17]]
768 ; CHECK-NEXT:    [[I19:%.*]] = load i16, ptr [[I18]], align 2
769 ; CHECK-NEXT:    [[I20:%.*]] = zext i16 [[I19]] to i32
770 ; CHECK-NEXT:    [[I21:%.*]] = sub nsw i32 [[I20]], [[I15]]
771 ; CHECK-NEXT:    [[I22:%.*]] = mul nsw i32 [[I11]], [[I21]]
772 ; CHECK-NEXT:    [[I23:%.*]] = ashr i32 [[I22]], 15
773 ; CHECK-NEXT:    [[I24:%.*]] = shl nuw nsw i32 [[I5]], 15
774 ; CHECK-NEXT:    [[I25:%.*]] = xor i32 [[I24]], 1015808
775 ; CHECK-NEXT:    [[I26:%.*]] = add nuw nsw i32 [[I25]], [[I15]]
776 ; CHECK-NEXT:    [[I27:%.*]] = add nsw i32 [[I26]], [[I23]]
777 ; CHECK-NEXT:    [[I28:%.*]] = sitofp i32 [[ARG]] to double
778 ; CHECK-NEXT:    [[I29:%.*]] = tail call double @llvm.log2.f64(double [[I28]])
779 ; CHECK-NEXT:    [[I30:%.*]] = fptosi double [[I29]] to i32
780 ; CHECK-NEXT:    [[I31:%.*]] = shl nsw i32 [[I30]], 15
781 ; CHECK-NEXT:    [[I32:%.*]] = or i32 [[I31]], 4
782 ; CHECK-NEXT:    [[I33:%.*]] = icmp eq i32 [[I27]], [[I32]]
783 ; CHECK-NEXT:    [[I34:%.*]] = select i1 [[I33]], i32 [[ARG]], i32 [[I31]]
784 ; CHECK-NEXT:    [[I35:%.*]] = lshr i32 [[I34]], 1
785 ; CHECK-NEXT:    [[I36:%.*]] = insertelement <16 x i8> [[I4]], i8 [[ARG3:%.*]], i32 3
786 ; CHECK-NEXT:    store <16 x i8> [[I36]], ptr [[ARG2]], align 16
787 ; CHECK-NEXT:    ret i32 [[I35]]
790   %i = or i32 %arg, 1
791   %i4 = load <16 x i8>, ptr %arg2, align 16
792   %i5 = tail call i32 @bar(i32 %i, i1 true)
793   %i6 = shl i32 %arg, %i5
794   %i7 = lshr i32 %i6, 26
795   %i8 = trunc i32 %i7 to i8
796   %i9 = and i8 %i8, 31
797   %i10 = lshr i32 %i6, 11
798   %i11 = and i32 %i10, 32767
799   %i12 = zext i8 %i9 to i64
800   %i13 = getelementptr inbounds i16, ptr %arg1, i64 %i12
801   %i14 = load i16, ptr %i13, align 2
802   %i15 = zext i16 %i14 to i32
803   %i16 = add nuw nsw i8 %i9, 1
804   %i17 = zext i8 %i16 to i64
805   %i18 = getelementptr inbounds i16, ptr %arg1, i64 %i17
806   %i19 = load i16, ptr %i18, align 2
807   %i20 = zext i16 %i19 to i32
808   %i21 = sub nsw i32 %i20, %i15
809   %i22 = mul nsw i32 %i11, %i21
810   %i23 = ashr i32 %i22, 15
811   %i24 = shl nuw nsw i32 %i5, 15
812   %i25 = xor i32 %i24, 1015808
813   %i26 = add nuw nsw i32 %i25, %i15
814   %i27 = add nsw i32 %i26, %i23
815   %i28 = sitofp i32 %arg to double
816   %i29 = tail call double @llvm.log2.f64(double %i28)
817   %i30 = fptosi double %i29 to i32
818   %i31 = shl nsw i32 %i30, 15
819   %i32 = or i32 %i31, 4
820   %i33 = icmp eq i32 %i27, %i32
821   %i34 = select i1 %i33, i32 %arg, i32 %i31
822   %i35 = lshr i32 %i34, 1
823   %i36 = insertelement <16 x i8> %i4, i8 %arg3, i32 3
824   store <16 x i8> %i36, ptr %arg2, align 16
825   ret i32 %i35
828 declare i32 @bar(i32, i1) readonly
829 declare double @llvm.log2.f64(double)