Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / LoopVectorize / X86 / interleave-cost.ll
blobb1f7516f3c8dcaf97d9a8975faffe429fa667b86
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2 ; RUN: opt -p loop-vectorize -S %s | FileCheck %s
4 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-apple-macosx10.15.0"
7 define void @test_free_instructions_feeding_geps_for_interleave_groups(ptr noalias %p.invar, ptr noalias %dst.1, ptr noalias %dst.2) {
8 ; CHECK-LABEL: define void @test_free_instructions_feeding_geps_for_interleave_groups(
9 ; CHECK-SAME: ptr noalias [[P_INVAR:%.*]], ptr noalias [[DST_1:%.*]], ptr noalias [[DST_2:%.*]]) {
10 ; CHECK-NEXT:  [[ENTRY:.*]]:
11 ; CHECK-NEXT:    br i1 true, label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
12 ; CHECK:       [[VECTOR_SCEVCHECK]]:
13 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[DST_1]], i64 8
14 ; CHECK-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
15 ; CHECK-NEXT:    [[MUL_RESULT:%.*]] = extractvalue { i64, i1 } [[MUL]], 0
16 ; CHECK-NEXT:    [[MUL_OVERFLOW:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
17 ; CHECK-NEXT:    [[TMP0:%.*]] = sub i64 0, [[MUL_RESULT]]
18 ; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[MUL_RESULT]]
19 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult ptr [[TMP1]], [[SCEVGEP]]
20 ; CHECK-NEXT:    [[TMP3:%.*]] = or i1 [[TMP2]], [[MUL_OVERFLOW]]
21 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[DST_1]], i64 12
22 ; CHECK-NEXT:    [[MUL2:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
23 ; CHECK-NEXT:    [[MUL_RESULT3:%.*]] = extractvalue { i64, i1 } [[MUL2]], 0
24 ; CHECK-NEXT:    [[MUL_OVERFLOW4:%.*]] = extractvalue { i64, i1 } [[MUL2]], 1
25 ; CHECK-NEXT:    [[TMP4:%.*]] = sub i64 0, [[MUL_RESULT3]]
26 ; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr i8, ptr [[SCEVGEP1]], i64 [[MUL_RESULT3]]
27 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp ult ptr [[TMP5]], [[SCEVGEP1]]
28 ; CHECK-NEXT:    [[TMP7:%.*]] = or i1 [[TMP6]], [[MUL_OVERFLOW4]]
29 ; CHECK-NEXT:    [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[DST_1]], i64 4
30 ; CHECK-NEXT:    [[MUL6:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
31 ; CHECK-NEXT:    [[MUL_RESULT7:%.*]] = extractvalue { i64, i1 } [[MUL6]], 0
32 ; CHECK-NEXT:    [[MUL_OVERFLOW8:%.*]] = extractvalue { i64, i1 } [[MUL6]], 1
33 ; CHECK-NEXT:    [[TMP8:%.*]] = sub i64 0, [[MUL_RESULT7]]
34 ; CHECK-NEXT:    [[TMP9:%.*]] = getelementptr i8, ptr [[SCEVGEP5]], i64 [[MUL_RESULT7]]
35 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp ult ptr [[TMP9]], [[SCEVGEP5]]
36 ; CHECK-NEXT:    [[TMP11:%.*]] = or i1 [[TMP10]], [[MUL_OVERFLOW8]]
37 ; CHECK-NEXT:    [[MUL9:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
38 ; CHECK-NEXT:    [[MUL_RESULT10:%.*]] = extractvalue { i64, i1 } [[MUL9]], 0
39 ; CHECK-NEXT:    [[MUL_OVERFLOW11:%.*]] = extractvalue { i64, i1 } [[MUL9]], 1
40 ; CHECK-NEXT:    [[TMP12:%.*]] = sub i64 0, [[MUL_RESULT10]]
41 ; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr i8, ptr [[DST_1]], i64 [[MUL_RESULT10]]
42 ; CHECK-NEXT:    [[TMP14:%.*]] = icmp ult ptr [[TMP13]], [[DST_1]]
43 ; CHECK-NEXT:    [[TMP15:%.*]] = or i1 [[TMP14]], [[MUL_OVERFLOW11]]
44 ; CHECK-NEXT:    [[SCEVGEP12:%.*]] = getelementptr i8, ptr [[DST_2]], i64 8
45 ; CHECK-NEXT:    [[MUL13:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
46 ; CHECK-NEXT:    [[MUL_RESULT14:%.*]] = extractvalue { i64, i1 } [[MUL13]], 0
47 ; CHECK-NEXT:    [[MUL_OVERFLOW15:%.*]] = extractvalue { i64, i1 } [[MUL13]], 1
48 ; CHECK-NEXT:    [[TMP16:%.*]] = sub i64 0, [[MUL_RESULT14]]
49 ; CHECK-NEXT:    [[TMP17:%.*]] = getelementptr i8, ptr [[SCEVGEP12]], i64 [[MUL_RESULT14]]
50 ; CHECK-NEXT:    [[TMP18:%.*]] = icmp ult ptr [[TMP17]], [[SCEVGEP12]]
51 ; CHECK-NEXT:    [[TMP19:%.*]] = or i1 [[TMP18]], [[MUL_OVERFLOW15]]
52 ; CHECK-NEXT:    [[SCEVGEP16:%.*]] = getelementptr i8, ptr [[DST_2]], i64 12
53 ; CHECK-NEXT:    [[MUL17:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
54 ; CHECK-NEXT:    [[MUL_RESULT18:%.*]] = extractvalue { i64, i1 } [[MUL17]], 0
55 ; CHECK-NEXT:    [[MUL_OVERFLOW19:%.*]] = extractvalue { i64, i1 } [[MUL17]], 1
56 ; CHECK-NEXT:    [[TMP20:%.*]] = sub i64 0, [[MUL_RESULT18]]
57 ; CHECK-NEXT:    [[TMP21:%.*]] = getelementptr i8, ptr [[SCEVGEP16]], i64 [[MUL_RESULT18]]
58 ; CHECK-NEXT:    [[TMP22:%.*]] = icmp ult ptr [[TMP21]], [[SCEVGEP16]]
59 ; CHECK-NEXT:    [[TMP23:%.*]] = or i1 [[TMP22]], [[MUL_OVERFLOW19]]
60 ; CHECK-NEXT:    [[SCEVGEP20:%.*]] = getelementptr i8, ptr [[DST_2]], i64 4
61 ; CHECK-NEXT:    [[MUL21:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
62 ; CHECK-NEXT:    [[MUL_RESULT22:%.*]] = extractvalue { i64, i1 } [[MUL21]], 0
63 ; CHECK-NEXT:    [[MUL_OVERFLOW23:%.*]] = extractvalue { i64, i1 } [[MUL21]], 1
64 ; CHECK-NEXT:    [[TMP24:%.*]] = sub i64 0, [[MUL_RESULT22]]
65 ; CHECK-NEXT:    [[TMP25:%.*]] = getelementptr i8, ptr [[SCEVGEP20]], i64 [[MUL_RESULT22]]
66 ; CHECK-NEXT:    [[TMP26:%.*]] = icmp ult ptr [[TMP25]], [[SCEVGEP20]]
67 ; CHECK-NEXT:    [[TMP27:%.*]] = or i1 [[TMP26]], [[MUL_OVERFLOW23]]
68 ; CHECK-NEXT:    [[MUL24:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 -1)
69 ; CHECK-NEXT:    [[MUL_RESULT25:%.*]] = extractvalue { i64, i1 } [[MUL24]], 0
70 ; CHECK-NEXT:    [[MUL_OVERFLOW26:%.*]] = extractvalue { i64, i1 } [[MUL24]], 1
71 ; CHECK-NEXT:    [[TMP28:%.*]] = sub i64 0, [[MUL_RESULT25]]
72 ; CHECK-NEXT:    [[TMP29:%.*]] = getelementptr i8, ptr [[DST_2]], i64 [[MUL_RESULT25]]
73 ; CHECK-NEXT:    [[TMP30:%.*]] = icmp ult ptr [[TMP29]], [[DST_2]]
74 ; CHECK-NEXT:    [[TMP31:%.*]] = or i1 [[TMP30]], [[MUL_OVERFLOW26]]
75 ; CHECK-NEXT:    [[TMP32:%.*]] = or i1 [[TMP3]], [[TMP7]]
76 ; CHECK-NEXT:    [[TMP33:%.*]] = or i1 [[TMP32]], [[TMP11]]
77 ; CHECK-NEXT:    [[TMP34:%.*]] = or i1 [[TMP33]], [[TMP15]]
78 ; CHECK-NEXT:    [[TMP35:%.*]] = or i1 [[TMP34]], [[TMP19]]
79 ; CHECK-NEXT:    [[TMP36:%.*]] = or i1 [[TMP35]], [[TMP23]]
80 ; CHECK-NEXT:    [[TMP37:%.*]] = or i1 [[TMP36]], [[TMP27]]
81 ; CHECK-NEXT:    [[TMP38:%.*]] = or i1 [[TMP37]], [[TMP31]]
82 ; CHECK-NEXT:    br i1 [[TMP38]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]]
83 ; CHECK:       [[VECTOR_PH]]:
84 ; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
85 ; CHECK:       [[VECTOR_BODY]]:
86 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
87 ; CHECK-NEXT:    [[TMP39:%.*]] = add i64 [[INDEX]], 0
88 ; CHECK-NEXT:    [[TMP40:%.*]] = load float, ptr [[P_INVAR]], align 4
89 ; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x float> poison, float [[TMP40]], i64 0
90 ; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLATINSERT]], <2 x float> poison, <2 x i32> zeroinitializer
91 ; CHECK-NEXT:    [[TMP41:%.*]] = shl i64 [[TMP39]], 2
92 ; CHECK-NEXT:    [[TMP42:%.*]] = load float, ptr [[P_INVAR]], align 4
93 ; CHECK-NEXT:    [[BROADCAST_SPLATINSERT27:%.*]] = insertelement <2 x float> poison, float [[TMP42]], i64 0
94 ; CHECK-NEXT:    [[BROADCAST_SPLAT28:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLATINSERT27]], <2 x float> poison, <2 x i32> zeroinitializer
95 ; CHECK-NEXT:    [[TMP43:%.*]] = or disjoint i64 [[TMP41]], 3
96 ; CHECK-NEXT:    [[TMP44:%.*]] = getelementptr float, ptr [[DST_1]], i64 [[TMP43]]
97 ; CHECK-NEXT:    [[TMP45:%.*]] = getelementptr float, ptr [[TMP44]], i32 -3
98 ; CHECK-NEXT:    [[TMP46:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLAT]], <2 x float> [[BROADCAST_SPLAT28]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
99 ; CHECK-NEXT:    [[TMP47:%.*]] = shufflevector <4 x float> [[TMP46]], <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
100 ; CHECK-NEXT:    [[INTERLEAVED_VEC:%.*]] = shufflevector <8 x float> [[TMP47]], <8 x float> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
101 ; CHECK-NEXT:    store <8 x float> [[INTERLEAVED_VEC]], ptr [[TMP45]], align 4
102 ; CHECK-NEXT:    [[TMP48:%.*]] = load float, ptr [[P_INVAR]], align 4
103 ; CHECK-NEXT:    [[BROADCAST_SPLATINSERT29:%.*]] = insertelement <2 x float> poison, float [[TMP48]], i64 0
104 ; CHECK-NEXT:    [[BROADCAST_SPLAT30:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLATINSERT29]], <2 x float> poison, <2 x i32> zeroinitializer
105 ; CHECK-NEXT:    [[TMP49:%.*]] = getelementptr float, ptr [[DST_2]], i64 [[TMP43]]
106 ; CHECK-NEXT:    [[TMP50:%.*]] = getelementptr float, ptr [[TMP49]], i32 -3
107 ; CHECK-NEXT:    [[BROADCAST_SPLAT36:%.*]] = shufflevector <2 x float> [[BROADCAST_SPLAT30]], <2 x float> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
108 ; CHECK-NEXT:    [[TMP51:%.*]] = shufflevector <4 x float> [[BROADCAST_SPLAT36]], <4 x float> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
109 ; CHECK-NEXT:    [[INTERLEAVED_VEC31:%.*]] = shufflevector <8 x float> [[TMP51]], <8 x float> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
110 ; CHECK-NEXT:    store <8 x float> [[INTERLEAVED_VEC31]], ptr [[TMP50]], align 4
111 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
112 ; CHECK-NEXT:    [[TMP53:%.*]] = icmp eq i64 [[INDEX_NEXT]], 0
113 ; CHECK-NEXT:    br i1 [[TMP53]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
114 ; CHECK:       [[MIDDLE_BLOCK]]:
115 ; CHECK-NEXT:    br i1 true, label %[[EXIT:.*]], label %[[SCALAR_PH]]
116 ; CHECK:       [[SCALAR_PH]]:
117 ; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 0, %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ], [ 0, %[[VECTOR_SCEVCHECK]] ]
118 ; CHECK-NEXT:    br label %[[LOOP:.*]]
119 ; CHECK:       [[LOOP]]:
120 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
121 ; CHECK-NEXT:    [[L_0:%.*]] = load float, ptr [[P_INVAR]], align 4
122 ; CHECK-NEXT:    [[IV_MUL:%.*]] = shl i64 [[IV]], 2
123 ; CHECK-NEXT:    [[GEP_DST_19:%.*]] = getelementptr float, ptr [[DST_1]], i64 [[IV_MUL]]
124 ; CHECK-NEXT:    store float [[L_0]], ptr [[GEP_DST_19]], align 4
125 ; CHECK-NEXT:    [[L_1:%.*]] = load float, ptr [[P_INVAR]], align 4
126 ; CHECK-NEXT:    [[ADD_1:%.*]] = or disjoint i64 [[IV_MUL]], 1
127 ; CHECK-NEXT:    [[GEP_DST_119:%.*]] = getelementptr float, ptr [[DST_1]], i64 [[ADD_1]]
128 ; CHECK-NEXT:    store float [[L_1]], ptr [[GEP_DST_119]], align 4
129 ; CHECK-NEXT:    [[ADD_2:%.*]] = or disjoint i64 [[IV_MUL]], 2
130 ; CHECK-NEXT:    [[GEP_DST_129:%.*]] = getelementptr float, ptr [[DST_1]], i64 [[ADD_2]]
131 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[GEP_DST_129]], align 4
132 ; CHECK-NEXT:    [[ADD_3:%.*]] = or disjoint i64 [[IV_MUL]], 3
133 ; CHECK-NEXT:    [[GEP_DST_140:%.*]] = getelementptr float, ptr [[DST_1]], i64 [[ADD_3]]
134 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[GEP_DST_140]], align 4
135 ; CHECK-NEXT:    [[L_2:%.*]] = load float, ptr [[P_INVAR]], align 4
136 ; CHECK-NEXT:    [[GEP_DST_247:%.*]] = getelementptr float, ptr [[DST_2]], i64 [[IV_MUL]]
137 ; CHECK-NEXT:    store float [[L_2]], ptr [[GEP_DST_247]], align 4
138 ; CHECK-NEXT:    [[GEP_DST_255:%.*]] = getelementptr float, ptr [[DST_2]], i64 [[ADD_1]]
139 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[GEP_DST_255]], align 4
140 ; CHECK-NEXT:    [[GEP_DST_265:%.*]] = getelementptr float, ptr [[DST_2]], i64 [[ADD_2]]
141 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[GEP_DST_265]], align 4
142 ; CHECK-NEXT:    [[GEP_DST_276:%.*]] = getelementptr float, ptr [[DST_2]], i64 [[ADD_3]]
143 ; CHECK-NEXT:    store float 0.000000e+00, ptr [[GEP_DST_276]], align 4
144 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
145 ; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 0
146 ; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]]
147 ; CHECK:       [[EXIT]]:
148 ; CHECK-NEXT:    ret void
150 entry:
151   br label %loop
153 loop:
154   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
155   %l.0 = load float, ptr %p.invar, align 4
156   %iv.mul = shl i64 %iv, 2
157   %gep.dst.19 = getelementptr float, ptr %dst.1, i64 %iv.mul
158   store float %l.0, ptr %gep.dst.19, align 4
159   %l.1 = load float, ptr %p.invar, align 4
160   %add.1 = or disjoint i64 %iv.mul, 1
161   %gep.dst.119 = getelementptr float, ptr %dst.1, i64 %add.1
162   store float %l.1, ptr %gep.dst.119, align 4
163   %add.2 = or disjoint i64 %iv.mul, 2
164   %gep.dst.129 = getelementptr float, ptr %dst.1, i64 %add.2
165   store float 0.000000e+00, ptr %gep.dst.129, align 4
166   %add.3 = or disjoint i64 %iv.mul, 3
167   %gep.dst.140 = getelementptr float, ptr %dst.1, i64 %add.3
168   store float 0.000000e+00, ptr %gep.dst.140, align 4
169   %l.2 = load float, ptr %p.invar, align 4
170   %gep.dst.247 = getelementptr float, ptr %dst.2, i64 %iv.mul
171   store float %l.2, ptr %gep.dst.247, align 4
172   %gep.dst.255 = getelementptr float, ptr %dst.2, i64 %add.1
173   store float 0.000000e+00, ptr %gep.dst.255, align 4
174   %gep.dst.265 = getelementptr float, ptr %dst.2, i64 %add.2
175   store float 0.000000e+00, ptr %gep.dst.265, align 4
176   %gep.dst.276 = getelementptr float, ptr %dst.2, i64 %add.3
177   store float 0.000000e+00, ptr %gep.dst.276, align 4
178   %iv.next = add i64 %iv, 1
179   %ec = icmp eq i64 %iv.next, 0
180   br i1 %ec, label %exit, label %loop
182 exit:
183   ret void
186 define void @geps_feeding_interleave_groups_with_reuse(ptr %arg, i64 %arg1, ptr %arg2) #0 {
187 ; CHECK-LABEL: define void @geps_feeding_interleave_groups_with_reuse(
188 ; CHECK-SAME: ptr [[ARG:%.*]], i64 [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR0:[0-9]+]] {
189 ; CHECK-NEXT:  [[ENTRY:.*]]:
190 ; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[ARG1]], 1
191 ; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP0]], 30
192 ; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
193 ; CHECK:       [[VECTOR_SCEVCHECK]]:
194 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[ARG2]], i64 8
195 ; CHECK-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 [[ARG1]])
196 ; CHECK-NEXT:    [[MUL_RESULT:%.*]] = extractvalue { i64, i1 } [[MUL]], 0
197 ; CHECK-NEXT:    [[MUL_OVERFLOW:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
198 ; CHECK-NEXT:    [[TMP1:%.*]] = sub i64 0, [[MUL_RESULT]]
199 ; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[MUL_RESULT]]
200 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult ptr [[TMP2]], [[SCEVGEP]]
201 ; CHECK-NEXT:    [[TMP4:%.*]] = or i1 [[TMP3]], [[MUL_OVERFLOW]]
202 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[ARG2]], i64 12
203 ; CHECK-NEXT:    [[MUL2:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 [[ARG1]])
204 ; CHECK-NEXT:    [[MUL_RESULT3:%.*]] = extractvalue { i64, i1 } [[MUL2]], 0
205 ; CHECK-NEXT:    [[MUL_OVERFLOW4:%.*]] = extractvalue { i64, i1 } [[MUL2]], 1
206 ; CHECK-NEXT:    [[TMP5:%.*]] = sub i64 0, [[MUL_RESULT3]]
207 ; CHECK-NEXT:    [[TMP6:%.*]] = getelementptr i8, ptr [[SCEVGEP1]], i64 [[MUL_RESULT3]]
208 ; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult ptr [[TMP6]], [[SCEVGEP1]]
209 ; CHECK-NEXT:    [[TMP8:%.*]] = or i1 [[TMP7]], [[MUL_OVERFLOW4]]
210 ; CHECK-NEXT:    [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[ARG2]], i64 4
211 ; CHECK-NEXT:    [[MUL6:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 [[ARG1]])
212 ; CHECK-NEXT:    [[MUL_RESULT7:%.*]] = extractvalue { i64, i1 } [[MUL6]], 0
213 ; CHECK-NEXT:    [[MUL_OVERFLOW8:%.*]] = extractvalue { i64, i1 } [[MUL6]], 1
214 ; CHECK-NEXT:    [[TMP9:%.*]] = sub i64 0, [[MUL_RESULT7]]
215 ; CHECK-NEXT:    [[TMP10:%.*]] = getelementptr i8, ptr [[SCEVGEP5]], i64 [[MUL_RESULT7]]
216 ; CHECK-NEXT:    [[TMP11:%.*]] = icmp ult ptr [[TMP10]], [[SCEVGEP5]]
217 ; CHECK-NEXT:    [[TMP12:%.*]] = or i1 [[TMP11]], [[MUL_OVERFLOW8]]
218 ; CHECK-NEXT:    [[MUL9:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 16, i64 [[ARG1]])
219 ; CHECK-NEXT:    [[MUL_RESULT10:%.*]] = extractvalue { i64, i1 } [[MUL9]], 0
220 ; CHECK-NEXT:    [[MUL_OVERFLOW11:%.*]] = extractvalue { i64, i1 } [[MUL9]], 1
221 ; CHECK-NEXT:    [[TMP13:%.*]] = sub i64 0, [[MUL_RESULT10]]
222 ; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr i8, ptr [[ARG2]], i64 [[MUL_RESULT10]]
223 ; CHECK-NEXT:    [[TMP15:%.*]] = icmp ult ptr [[TMP14]], [[ARG2]]
224 ; CHECK-NEXT:    [[TMP16:%.*]] = or i1 [[TMP15]], [[MUL_OVERFLOW11]]
225 ; CHECK-NEXT:    [[TMP17:%.*]] = or i1 [[TMP4]], [[TMP8]]
226 ; CHECK-NEXT:    [[TMP18:%.*]] = or i1 [[TMP17]], [[TMP12]]
227 ; CHECK-NEXT:    [[TMP19:%.*]] = or i1 [[TMP18]], [[TMP16]]
228 ; CHECK-NEXT:    br i1 [[TMP19]], label %[[SCALAR_PH]], label %[[VECTOR_MEMCHECK:.*]]
229 ; CHECK:       [[VECTOR_MEMCHECK]]:
230 ; CHECK-NEXT:    [[TMP20:%.*]] = shl i64 [[ARG1]], 4
231 ; CHECK-NEXT:    [[TMP21:%.*]] = add i64 [[TMP20]], 16
232 ; CHECK-NEXT:    [[SCEVGEP12:%.*]] = getelementptr i8, ptr [[ARG2]], i64 [[TMP21]]
233 ; CHECK-NEXT:    [[TMP22:%.*]] = shl i64 [[ARG1]], 5
234 ; CHECK-NEXT:    [[TMP23:%.*]] = add i64 [[TMP22]], 32
235 ; CHECK-NEXT:    [[SCEVGEP13:%.*]] = getelementptr i8, ptr [[ARG]], i64 [[TMP23]]
236 ; CHECK-NEXT:    [[BOUND0:%.*]] = icmp ult ptr [[ARG2]], [[SCEVGEP13]]
237 ; CHECK-NEXT:    [[BOUND1:%.*]] = icmp ult ptr [[ARG]], [[SCEVGEP12]]
238 ; CHECK-NEXT:    [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
239 ; CHECK-NEXT:    br i1 [[FOUND_CONFLICT]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]]
240 ; CHECK:       [[VECTOR_PH]]:
241 ; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i64 [[TMP0]], 2
242 ; CHECK-NEXT:    [[N_VEC:%.*]] = sub i64 [[TMP0]], [[N_MOD_VF]]
243 ; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
244 ; CHECK:       [[VECTOR_BODY]]:
245 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
246 ; CHECK-NEXT:    [[TMP24:%.*]] = add i64 [[INDEX]], 0
247 ; CHECK-NEXT:    [[TMP25:%.*]] = shl i64 [[TMP24]], 5
248 ; CHECK-NEXT:    [[TMP26:%.*]] = getelementptr i8, ptr [[ARG]], i64 [[TMP25]]
249 ; CHECK-NEXT:    [[TMP27:%.*]] = shl i64 [[TMP24]], 4
250 ; CHECK-NEXT:    [[TMP28:%.*]] = getelementptr i8, ptr [[ARG2]], i64 [[TMP27]]
251 ; CHECK-NEXT:    [[TMP29:%.*]] = getelementptr float, ptr [[TMP26]], i32 0
252 ; CHECK-NEXT:    [[WIDE_VEC:%.*]] = load <16 x float>, ptr [[TMP29]], align 4
253 ; CHECK-NEXT:    [[STRIDED_VEC:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 0, i32 8>
254 ; CHECK-NEXT:    [[STRIDED_VEC14:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 1, i32 9>
255 ; CHECK-NEXT:    [[STRIDED_VEC15:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 2, i32 10>
256 ; CHECK-NEXT:    [[STRIDED_VEC16:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 3, i32 11>
257 ; CHECK-NEXT:    [[STRIDED_VEC17:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 4, i32 12>
258 ; CHECK-NEXT:    [[STRIDED_VEC18:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 5, i32 13>
259 ; CHECK-NEXT:    [[STRIDED_VEC19:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 6, i32 14>
260 ; CHECK-NEXT:    [[STRIDED_VEC20:%.*]] = shufflevector <16 x float> [[WIDE_VEC]], <16 x float> poison, <2 x i32> <i32 7, i32 15>
261 ; CHECK-NEXT:    [[TMP30:%.*]] = fadd <2 x float> [[STRIDED_VEC]], [[STRIDED_VEC17]]
262 ; CHECK-NEXT:    [[TMP31:%.*]] = fmul <2 x float> [[TMP30]], zeroinitializer
263 ; CHECK-NEXT:    [[TMP32:%.*]] = fadd <2 x float> [[STRIDED_VEC14]], [[STRIDED_VEC18]]
264 ; CHECK-NEXT:    [[TMP33:%.*]] = fmul <2 x float> [[TMP32]], zeroinitializer
265 ; CHECK-NEXT:    [[TMP34:%.*]] = fadd <2 x float> [[STRIDED_VEC15]], [[STRIDED_VEC19]]
266 ; CHECK-NEXT:    [[TMP35:%.*]] = fmul <2 x float> [[TMP34]], zeroinitializer
267 ; CHECK-NEXT:    [[TMP36:%.*]] = fadd <2 x float> [[STRIDED_VEC16]], [[STRIDED_VEC20]]
268 ; CHECK-NEXT:    [[TMP37:%.*]] = fmul <2 x float> [[TMP36]], zeroinitializer
269 ; CHECK-NEXT:    [[TMP38:%.*]] = getelementptr i8, ptr [[TMP28]], i64 12
270 ; CHECK-NEXT:    [[TMP39:%.*]] = getelementptr float, ptr [[TMP38]], i32 -3
271 ; CHECK-NEXT:    [[TMP40:%.*]] = shufflevector <2 x float> [[TMP31]], <2 x float> [[TMP33]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
272 ; CHECK-NEXT:    [[TMP41:%.*]] = shufflevector <2 x float> [[TMP35]], <2 x float> [[TMP37]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>
273 ; CHECK-NEXT:    [[TMP42:%.*]] = shufflevector <4 x float> [[TMP40]], <4 x float> [[TMP41]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
274 ; CHECK-NEXT:    [[INTERLEAVED_VEC:%.*]] = shufflevector <8 x float> [[TMP42]], <8 x float> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 1, i32 3, i32 5, i32 7>
275 ; CHECK-NEXT:    store <8 x float> [[INTERLEAVED_VEC]], ptr [[TMP39]], align 4
276 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 2
277 ; CHECK-NEXT:    [[TMP43:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
278 ; CHECK-NEXT:    br i1 [[TMP43]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
279 ; CHECK:       [[MIDDLE_BLOCK]]:
280 ; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 [[TMP0]], [[N_VEC]]
281 ; CHECK-NEXT:    br i1 [[CMP_N]], label %[[EXIT:.*]], label %[[SCALAR_PH]]
282 ; CHECK:       [[SCALAR_PH]]:
283 ; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ], [ 0, %[[VECTOR_SCEVCHECK]] ], [ 0, %[[VECTOR_MEMCHECK]] ]
284 ; CHECK-NEXT:    br label %[[LOOP:.*]]
285 ; CHECK:       [[LOOP]]:
286 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
287 ; CHECK-NEXT:    [[SHL_IV_5:%.*]] = shl i64 [[IV]], 5
288 ; CHECK-NEXT:    [[GEP_1:%.*]] = getelementptr i8, ptr [[ARG]], i64 [[SHL_IV_5]]
289 ; CHECK-NEXT:    [[ADD_5:%.*]] = or disjoint i64 [[SHL_IV_5]], 16
290 ; CHECK-NEXT:    [[GEP_2:%.*]] = getelementptr i8, ptr [[ARG]], i64 [[ADD_5]]
291 ; CHECK-NEXT:    [[SHL_IV_4:%.*]] = shl i64 [[IV]], 4
292 ; CHECK-NEXT:    [[GEP_3:%.*]] = getelementptr i8, ptr [[ARG2]], i64 [[SHL_IV_4]]
293 ; CHECK-NEXT:    [[L_1:%.*]] = load float, ptr [[GEP_1]], align 4
294 ; CHECK-NEXT:    [[L_2:%.*]] = load float, ptr [[GEP_2]], align 4
295 ; CHECK-NEXT:    [[ADD_1:%.*]] = fadd float [[L_1]], [[L_2]]
296 ; CHECK-NEXT:    [[MUL_1:%.*]] = fmul float [[ADD_1]], 0.000000e+00
297 ; CHECK-NEXT:    store float [[MUL_1]], ptr [[GEP_3]], align 4
298 ; CHECK-NEXT:    [[GEP_4:%.*]] = getelementptr i8, ptr [[GEP_1]], i64 4
299 ; CHECK-NEXT:    [[L_3:%.*]] = load float, ptr [[GEP_4]], align 4
300 ; CHECK-NEXT:    [[GEP_5:%.*]] = getelementptr i8, ptr [[GEP_2]], i64 4
301 ; CHECK-NEXT:    [[L_4:%.*]] = load float, ptr [[GEP_5]], align 4
302 ; CHECK-NEXT:    [[ADD_2:%.*]] = fadd float [[L_3]], [[L_4]]
303 ; CHECK-NEXT:    [[MUL_2:%.*]] = fmul float [[ADD_2]], 0.000000e+00
304 ; CHECK-NEXT:    [[GEP_6:%.*]] = getelementptr i8, ptr [[GEP_3]], i64 4
305 ; CHECK-NEXT:    store float [[MUL_2]], ptr [[GEP_6]], align 4
306 ; CHECK-NEXT:    [[GEP_7:%.*]] = getelementptr i8, ptr [[GEP_1]], i64 8
307 ; CHECK-NEXT:    [[L_5:%.*]] = load float, ptr [[GEP_7]], align 4
308 ; CHECK-NEXT:    [[GEP_8:%.*]] = getelementptr i8, ptr [[GEP_2]], i64 8
309 ; CHECK-NEXT:    [[L_6:%.*]] = load float, ptr [[GEP_8]], align 4
310 ; CHECK-NEXT:    [[ADD_3:%.*]] = fadd float [[L_5]], [[L_6]]
311 ; CHECK-NEXT:    [[MUL_3:%.*]] = fmul float [[ADD_3]], 0.000000e+00
312 ; CHECK-NEXT:    [[GEP_9:%.*]] = getelementptr i8, ptr [[GEP_3]], i64 8
313 ; CHECK-NEXT:    store float [[MUL_3]], ptr [[GEP_9]], align 4
314 ; CHECK-NEXT:    [[I27:%.*]] = getelementptr i8, ptr [[GEP_1]], i64 12
315 ; CHECK-NEXT:    [[L_7:%.*]] = load float, ptr [[I27]], align 4
316 ; CHECK-NEXT:    [[GEP_10:%.*]] = getelementptr i8, ptr [[GEP_2]], i64 12
317 ; CHECK-NEXT:    [[L_8:%.*]] = load float, ptr [[GEP_10]], align 4
318 ; CHECK-NEXT:    [[ADD_4:%.*]] = fadd float [[L_7]], [[L_8]]
319 ; CHECK-NEXT:    [[MUL_4:%.*]] = fmul float [[ADD_4]], 0.000000e+00
320 ; CHECK-NEXT:    [[GEP_11:%.*]] = getelementptr i8, ptr [[GEP_3]], i64 12
321 ; CHECK-NEXT:    store float [[MUL_4]], ptr [[GEP_11]], align 4
322 ; CHECK-NEXT:    [[IV_NEXT]] = add i64 [[IV]], 1
323 ; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV]], [[ARG1]]
324 ; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
325 ; CHECK:       [[EXIT]]:
326 ; CHECK-NEXT:    ret void
328 entry:
329   br label %loop
331 loop:
332   %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
333   %shl.iv.5 = shl i64 %iv, 5
334   %gep.1 = getelementptr i8, ptr %arg, i64 %shl.iv.5
335   %add.5 = or disjoint i64 %shl.iv.5, 16
336   %gep.2 = getelementptr i8, ptr %arg, i64 %add.5
337   %shl.iv.4 = shl i64 %iv, 4
338   %gep.3 = getelementptr i8, ptr %arg2, i64 %shl.iv.4
339   %l.1 = load float, ptr %gep.1, align 4
340   %l.2 = load float, ptr %gep.2, align 4
341   %add.1 = fadd float %l.1, %l.2
342   %mul.1 = fmul float %add.1, 0.000000e+00
343   store float %mul.1, ptr %gep.3, align 4
344   %gep.4 = getelementptr i8, ptr %gep.1, i64 4
345   %l.3 = load float, ptr %gep.4, align 4
346   %gep.5 = getelementptr i8, ptr %gep.2, i64 4
347   %l.4 = load float, ptr %gep.5, align 4
348   %add.2 = fadd float %l.3, %l.4
349   %mul.2 = fmul float %add.2, 0.000000e+00
350   %gep.6 = getelementptr i8, ptr %gep.3, i64 4
351   store float %mul.2, ptr %gep.6, align 4
352   %gep.7 = getelementptr i8, ptr %gep.1, i64 8
353   %l.5 = load float, ptr %gep.7, align 4
354   %gep.8 = getelementptr i8, ptr %gep.2, i64 8
355   %l.6 = load float, ptr %gep.8, align 4
356   %add.3 = fadd float %l.5, %l.6
357   %mul.3 = fmul float %add.3, 0.000000e+00
358   %gep.9 = getelementptr i8, ptr %gep.3, i64 8
359   store float %mul.3, ptr %gep.9, align 4
360   %i27 = getelementptr i8, ptr %gep.1, i64 12
361   %l.7 = load float, ptr %i27, align 4
362   %gep.10 = getelementptr i8, ptr %gep.2, i64 12
363   %l.8 = load float, ptr %gep.10, align 4
364   %add.4 = fadd float %l.7, %l.8
365   %mul.4 = fmul float %add.4, 0.000000e+00
366   %gep.11 = getelementptr i8, ptr %gep.3, i64 12
367   store float %mul.4, ptr %gep.11, align 4
368   %iv.next = add i64 %iv, 1
369   %ec = icmp eq i64 %iv, %arg1
370   br i1 %ec, label %exit, label %loop
372 exit:
373   ret void
376 define void @geps_feeding_interleave_groups_with_reuse2(ptr %A, ptr %B, i64 %N) #1 {
377 ; CHECK-LABEL: define void @geps_feeding_interleave_groups_with_reuse2(
378 ; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i64 [[N:%.*]]) #[[ATTR1:[0-9]+]] {
379 ; CHECK-NEXT:  [[ENTRY:.*]]:
380 ; CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[N]], 3
381 ; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1
382 ; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[TMP1]], 28
383 ; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]]
384 ; CHECK:       [[VECTOR_SCEVCHECK]]:
385 ; CHECK-NEXT:    [[TMP2:%.*]] = lshr i64 [[N]], 3
386 ; CHECK-NEXT:    [[SCEVGEP:%.*]] = getelementptr i8, ptr [[A]], i64 24
387 ; CHECK-NEXT:    [[MUL:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
388 ; CHECK-NEXT:    [[MUL_RESULT:%.*]] = extractvalue { i64, i1 } [[MUL]], 0
389 ; CHECK-NEXT:    [[MUL_OVERFLOW:%.*]] = extractvalue { i64, i1 } [[MUL]], 1
390 ; CHECK-NEXT:    [[TMP3:%.*]] = sub i64 0, [[MUL_RESULT]]
391 ; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr i8, ptr [[SCEVGEP]], i64 [[MUL_RESULT]]
392 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult ptr [[TMP4]], [[SCEVGEP]]
393 ; CHECK-NEXT:    [[TMP6:%.*]] = or i1 [[TMP5]], [[MUL_OVERFLOW]]
394 ; CHECK-NEXT:    [[SCEVGEP1:%.*]] = getelementptr i8, ptr [[A]], i64 28
395 ; CHECK-NEXT:    [[MUL2:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
396 ; CHECK-NEXT:    [[MUL_RESULT3:%.*]] = extractvalue { i64, i1 } [[MUL2]], 0
397 ; CHECK-NEXT:    [[MUL_OVERFLOW4:%.*]] = extractvalue { i64, i1 } [[MUL2]], 1
398 ; CHECK-NEXT:    [[TMP7:%.*]] = sub i64 0, [[MUL_RESULT3]]
399 ; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr i8, ptr [[SCEVGEP1]], i64 [[MUL_RESULT3]]
400 ; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult ptr [[TMP8]], [[SCEVGEP1]]
401 ; CHECK-NEXT:    [[TMP10:%.*]] = or i1 [[TMP9]], [[MUL_OVERFLOW4]]
402 ; CHECK-NEXT:    [[SCEVGEP5:%.*]] = getelementptr i8, ptr [[A]], i64 20
403 ; CHECK-NEXT:    [[MUL6:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
404 ; CHECK-NEXT:    [[MUL_RESULT7:%.*]] = extractvalue { i64, i1 } [[MUL6]], 0
405 ; CHECK-NEXT:    [[MUL_OVERFLOW8:%.*]] = extractvalue { i64, i1 } [[MUL6]], 1
406 ; CHECK-NEXT:    [[TMP11:%.*]] = sub i64 0, [[MUL_RESULT7]]
407 ; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr i8, ptr [[SCEVGEP5]], i64 [[MUL_RESULT7]]
408 ; CHECK-NEXT:    [[TMP13:%.*]] = icmp ult ptr [[TMP12]], [[SCEVGEP5]]
409 ; CHECK-NEXT:    [[TMP14:%.*]] = or i1 [[TMP13]], [[MUL_OVERFLOW8]]
410 ; CHECK-NEXT:    [[SCEVGEP9:%.*]] = getelementptr i8, ptr [[A]], i64 16
411 ; CHECK-NEXT:    [[MUL10:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
412 ; CHECK-NEXT:    [[MUL_RESULT11:%.*]] = extractvalue { i64, i1 } [[MUL10]], 0
413 ; CHECK-NEXT:    [[MUL_OVERFLOW12:%.*]] = extractvalue { i64, i1 } [[MUL10]], 1
414 ; CHECK-NEXT:    [[TMP15:%.*]] = sub i64 0, [[MUL_RESULT11]]
415 ; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr i8, ptr [[SCEVGEP9]], i64 [[MUL_RESULT11]]
416 ; CHECK-NEXT:    [[TMP17:%.*]] = icmp ult ptr [[TMP16]], [[SCEVGEP9]]
417 ; CHECK-NEXT:    [[TMP18:%.*]] = or i1 [[TMP17]], [[MUL_OVERFLOW12]]
418 ; CHECK-NEXT:    [[SCEVGEP13:%.*]] = getelementptr i8, ptr [[A]], i64 12
419 ; CHECK-NEXT:    [[MUL14:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
420 ; CHECK-NEXT:    [[MUL_RESULT15:%.*]] = extractvalue { i64, i1 } [[MUL14]], 0
421 ; CHECK-NEXT:    [[MUL_OVERFLOW16:%.*]] = extractvalue { i64, i1 } [[MUL14]], 1
422 ; CHECK-NEXT:    [[TMP19:%.*]] = sub i64 0, [[MUL_RESULT15]]
423 ; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr i8, ptr [[SCEVGEP13]], i64 [[MUL_RESULT15]]
424 ; CHECK-NEXT:    [[TMP21:%.*]] = icmp ult ptr [[TMP20]], [[SCEVGEP13]]
425 ; CHECK-NEXT:    [[TMP22:%.*]] = or i1 [[TMP21]], [[MUL_OVERFLOW16]]
426 ; CHECK-NEXT:    [[SCEVGEP17:%.*]] = getelementptr i8, ptr [[A]], i64 8
427 ; CHECK-NEXT:    [[MUL18:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
428 ; CHECK-NEXT:    [[MUL_RESULT19:%.*]] = extractvalue { i64, i1 } [[MUL18]], 0
429 ; CHECK-NEXT:    [[MUL_OVERFLOW20:%.*]] = extractvalue { i64, i1 } [[MUL18]], 1
430 ; CHECK-NEXT:    [[TMP23:%.*]] = sub i64 0, [[MUL_RESULT19]]
431 ; CHECK-NEXT:    [[TMP24:%.*]] = getelementptr i8, ptr [[SCEVGEP17]], i64 [[MUL_RESULT19]]
432 ; CHECK-NEXT:    [[TMP25:%.*]] = icmp ult ptr [[TMP24]], [[SCEVGEP17]]
433 ; CHECK-NEXT:    [[TMP26:%.*]] = or i1 [[TMP25]], [[MUL_OVERFLOW20]]
434 ; CHECK-NEXT:    [[SCEVGEP21:%.*]] = getelementptr i8, ptr [[A]], i64 4
435 ; CHECK-NEXT:    [[MUL22:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
436 ; CHECK-NEXT:    [[MUL_RESULT23:%.*]] = extractvalue { i64, i1 } [[MUL22]], 0
437 ; CHECK-NEXT:    [[MUL_OVERFLOW24:%.*]] = extractvalue { i64, i1 } [[MUL22]], 1
438 ; CHECK-NEXT:    [[TMP27:%.*]] = sub i64 0, [[MUL_RESULT23]]
439 ; CHECK-NEXT:    [[TMP28:%.*]] = getelementptr i8, ptr [[SCEVGEP21]], i64 [[MUL_RESULT23]]
440 ; CHECK-NEXT:    [[TMP29:%.*]] = icmp ult ptr [[TMP28]], [[SCEVGEP21]]
441 ; CHECK-NEXT:    [[TMP30:%.*]] = or i1 [[TMP29]], [[MUL_OVERFLOW24]]
442 ; CHECK-NEXT:    [[MUL25:%.*]] = call { i64, i1 } @llvm.umul.with.overflow.i64(i64 32, i64 [[TMP2]])
443 ; CHECK-NEXT:    [[MUL_RESULT26:%.*]] = extractvalue { i64, i1 } [[MUL25]], 0
444 ; CHECK-NEXT:    [[MUL_OVERFLOW27:%.*]] = extractvalue { i64, i1 } [[MUL25]], 1
445 ; CHECK-NEXT:    [[TMP31:%.*]] = sub i64 0, [[MUL_RESULT26]]
446 ; CHECK-NEXT:    [[TMP32:%.*]] = getelementptr i8, ptr [[A]], i64 [[MUL_RESULT26]]
447 ; CHECK-NEXT:    [[TMP33:%.*]] = icmp ult ptr [[TMP32]], [[A]]
448 ; CHECK-NEXT:    [[TMP34:%.*]] = or i1 [[TMP33]], [[MUL_OVERFLOW27]]
449 ; CHECK-NEXT:    [[TMP35:%.*]] = or i1 [[TMP6]], [[TMP10]]
450 ; CHECK-NEXT:    [[TMP36:%.*]] = or i1 [[TMP35]], [[TMP14]]
451 ; CHECK-NEXT:    [[TMP37:%.*]] = or i1 [[TMP36]], [[TMP18]]
452 ; CHECK-NEXT:    [[TMP38:%.*]] = or i1 [[TMP37]], [[TMP22]]
453 ; CHECK-NEXT:    [[TMP39:%.*]] = or i1 [[TMP38]], [[TMP26]]
454 ; CHECK-NEXT:    [[TMP40:%.*]] = or i1 [[TMP39]], [[TMP30]]
455 ; CHECK-NEXT:    [[TMP41:%.*]] = or i1 [[TMP40]], [[TMP34]]
456 ; CHECK-NEXT:    br i1 [[TMP41]], label %[[SCALAR_PH]], label %[[VECTOR_MEMCHECK:.*]]
457 ; CHECK:       [[VECTOR_MEMCHECK]]:
458 ; CHECK-NEXT:    [[TMP42:%.*]] = lshr i64 [[N]], 3
459 ; CHECK-NEXT:    [[TMP43:%.*]] = shl i64 [[TMP42]], 5
460 ; CHECK-NEXT:    [[TMP44:%.*]] = add i64 [[TMP43]], 32
461 ; CHECK-NEXT:    [[SCEVGEP28:%.*]] = getelementptr i8, ptr [[A]], i64 [[TMP44]]
462 ; CHECK-NEXT:    [[TMP45:%.*]] = add nuw nsw i64 [[TMP43]], 4
463 ; CHECK-NEXT:    [[SCEVGEP29:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP45]]
464 ; CHECK-NEXT:    [[TMP46:%.*]] = shl i64 [[TMP42]], 4
465 ; CHECK-NEXT:    [[TMP47:%.*]] = add nuw nsw i64 [[TMP46]], 8
466 ; CHECK-NEXT:    [[SCEVGEP30:%.*]] = getelementptr i8, ptr [[B]], i64 [[TMP47]]
467 ; CHECK-NEXT:    [[BOUND0:%.*]] = icmp ult ptr [[A]], [[SCEVGEP29]]
468 ; CHECK-NEXT:    [[BOUND1:%.*]] = icmp ult ptr [[B]], [[SCEVGEP28]]
469 ; CHECK-NEXT:    [[FOUND_CONFLICT:%.*]] = and i1 [[BOUND0]], [[BOUND1]]
470 ; CHECK-NEXT:    [[BOUND031:%.*]] = icmp ult ptr [[A]], [[SCEVGEP30]]
471 ; CHECK-NEXT:    [[BOUND132:%.*]] = icmp ult ptr [[B]], [[SCEVGEP28]]
472 ; CHECK-NEXT:    [[FOUND_CONFLICT33:%.*]] = and i1 [[BOUND031]], [[BOUND132]]
473 ; CHECK-NEXT:    [[CONFLICT_RDX:%.*]] = or i1 [[FOUND_CONFLICT]], [[FOUND_CONFLICT33]]
474 ; CHECK-NEXT:    br i1 [[CONFLICT_RDX]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]]
475 ; CHECK:       [[VECTOR_PH]]:
476 ; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i64 [[TMP1]], 4
477 ; CHECK-NEXT:    [[TMP48:%.*]] = icmp eq i64 [[N_MOD_VF]], 0
478 ; CHECK-NEXT:    [[TMP49:%.*]] = select i1 [[TMP48]], i64 4, i64 [[N_MOD_VF]]
479 ; CHECK-NEXT:    [[N_VEC:%.*]] = sub i64 [[TMP1]], [[TMP49]]
480 ; CHECK-NEXT:    [[IND_END:%.*]] = mul i64 [[N_VEC]], 8
481 ; CHECK-NEXT:    br label %[[VECTOR_BODY:.*]]
482 ; CHECK:       [[VECTOR_BODY]]:
483 ; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
484 ; CHECK-NEXT:    [[VEC_IND:%.*]] = phi <4 x i64> [ <i64 0, i64 8, i64 16, i64 24>, %[[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], %[[VECTOR_BODY]] ]
485 ; CHECK-NEXT:    [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], 8
486 ; CHECK-NEXT:    [[TMP50:%.*]] = add i64 [[OFFSET_IDX]], 0
487 ; CHECK-NEXT:    [[TMP51:%.*]] = lshr exact i64 [[TMP50]], 1
488 ; CHECK-NEXT:    [[TMP52:%.*]] = getelementptr i32, ptr [[B]], i64 [[TMP51]]
489 ; CHECK-NEXT:    [[TMP53:%.*]] = getelementptr i32, ptr [[TMP52]], i32 0
490 ; CHECK-NEXT:    [[WIDE_VEC:%.*]] = load <16 x i32>, ptr [[TMP53]], align 4
491 ; CHECK-NEXT:    [[STRIDED_VEC:%.*]] = shufflevector <16 x i32> [[WIDE_VEC]], <16 x i32> poison, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
492 ; CHECK-NEXT:    [[STRIDED_VEC34:%.*]] = shufflevector <16 x i32> [[WIDE_VEC]], <16 x i32> poison, <4 x i32> <i32 1, i32 5, i32 9, i32 13>
493 ; CHECK-NEXT:    [[TMP54:%.*]] = getelementptr i32, ptr [[B]], <4 x i64> [[VEC_IND]]
494 ; CHECK-NEXT:    [[WIDE_MASKED_GATHER:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP54]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> poison), !alias.scope [[META6:![0-9]+]]
495 ; CHECK-NEXT:    [[TMP55:%.*]] = or disjoint i64 [[TMP50]], 7
496 ; CHECK-NEXT:    [[TMP56:%.*]] = getelementptr i32, ptr [[A]], i64 [[TMP55]]
497 ; CHECK-NEXT:    [[TMP57:%.*]] = getelementptr i32, ptr [[TMP56]], i32 -7
498 ; CHECK-NEXT:    [[TMP58:%.*]] = shufflevector <4 x i32> [[STRIDED_VEC]], <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
499 ; CHECK-NEXT:    [[TMP59:%.*]] = shufflevector <4 x i32> [[STRIDED_VEC34]], <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
500 ; CHECK-NEXT:    [[TMP60:%.*]] = shufflevector <4 x i32> [[WIDE_MASKED_GATHER]], <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
501 ; CHECK-NEXT:    [[TMP61:%.*]] = shufflevector <8 x i32> [[TMP58]], <8 x i32> [[TMP59]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
502 ; CHECK-NEXT:    [[TMP62:%.*]] = shufflevector <8 x i32> [[TMP60]], <8 x i32> zeroinitializer, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
503 ; CHECK-NEXT:    [[TMP63:%.*]] = shufflevector <16 x i32> [[TMP61]], <16 x i32> [[TMP62]], <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
504 ; CHECK-NEXT:    [[INTERLEAVED_VEC:%.*]] = shufflevector <32 x i32> [[TMP63]], <32 x i32> poison, <32 x i32> <i32 0, i32 4, i32 8, i32 12, i32 16, i32 20, i32 24, i32 28, i32 1, i32 5, i32 9, i32 13, i32 17, i32 21, i32 25, i32 29, i32 2, i32 6, i32 10, i32 14, i32 18, i32 22, i32 26, i32 30, i32 3, i32 7, i32 11, i32 15, i32 19, i32 23, i32 27, i32 31>
505 ; CHECK-NEXT:    store <32 x i32> [[INTERLEAVED_VEC]], ptr [[TMP57]], align 4
506 ; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
507 ; CHECK-NEXT:    [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], <i64 32, i64 32, i64 32, i64 32>
508 ; CHECK-NEXT:    [[TMP64:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
509 ; CHECK-NEXT:    br i1 [[TMP64]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP9:![0-9]+]]
510 ; CHECK:       [[MIDDLE_BLOCK]]:
511 ; CHECK-NEXT:    br label %[[SCALAR_PH]]
512 ; CHECK:       [[SCALAR_PH]]:
513 ; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], %[[MIDDLE_BLOCK]] ], [ 0, %[[ENTRY]] ], [ 0, %[[VECTOR_SCEVCHECK]] ], [ 0, %[[VECTOR_MEMCHECK]] ]
514 ; CHECK-NEXT:    br label %[[LOOP:.*]]
515 ; CHECK:       [[LOOP]]:
516 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT_7:%.*]], %[[LOOP]] ]
517 ; CHECK-NEXT:    [[SHR_1:%.*]] = lshr exact i64 [[IV]], 1
518 ; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr nusw i32, ptr [[B]], i64 [[SHR_1]]
519 ; CHECK-NEXT:    [[L:%.*]] = load i32, ptr [[GEP_B]], align 4
520 ; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV]]
521 ; CHECK-NEXT:    store i32 [[L]], ptr [[GEP_A]], align 4
522 ; CHECK-NEXT:    [[IV_NEXT:%.*]] = or disjoint i64 [[IV]], 1
523 ; CHECK-NEXT:    [[GEP_A_1:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT]]
524 ; CHECK-NEXT:    store i32 0, ptr [[GEP_A_1]], align 4
525 ; CHECK-NEXT:    [[IV_NEXT_1:%.*]] = or disjoint i64 [[IV]], 2
526 ; CHECK-NEXT:    [[SHR_2:%.*]] = lshr exact i64 [[IV_NEXT_1]], 1
527 ; CHECK-NEXT:    [[GEP_B_2:%.*]] = getelementptr i32, ptr [[B]], i64 [[SHR_2]]
528 ; CHECK-NEXT:    [[TMP65:%.*]] = load i32, ptr [[GEP_B_2]], align 4
529 ; CHECK-NEXT:    [[GEP_A_2:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_1]]
530 ; CHECK-NEXT:    store i32 [[TMP65]], ptr [[GEP_A_2]], align 4
531 ; CHECK-NEXT:    [[IV_NEXT_2:%.*]] = or disjoint i64 [[IV]], 3
532 ; CHECK-NEXT:    [[GEP_A_3:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_2]]
533 ; CHECK-NEXT:    store i32 0, ptr [[GEP_A_3]], align 4
534 ; CHECK-NEXT:    [[IV_NEXT_3:%.*]] = or disjoint i64 [[IV]], 4
535 ; CHECK-NEXT:    [[GEP_B_4:%.*]] = getelementptr i32, ptr [[B]], i64 [[IV]]
536 ; CHECK-NEXT:    [[TMP66:%.*]] = load i32, ptr [[GEP_B_4]], align 4
537 ; CHECK-NEXT:    [[GEP_A_4:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_3]]
538 ; CHECK-NEXT:    store i32 [[TMP66]], ptr [[GEP_A_4]], align 4
539 ; CHECK-NEXT:    [[IV_NEXT_4:%.*]] = or disjoint i64 [[IV]], 5
540 ; CHECK-NEXT:    [[GEP_A_5:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_4]]
541 ; CHECK-NEXT:    store i32 0, ptr [[GEP_A_5]], align 4
542 ; CHECK-NEXT:    [[IV_NEXT_5:%.*]] = or disjoint i64 [[IV]], 6
543 ; CHECK-NEXT:    [[GEP_A_6:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_5]]
544 ; CHECK-NEXT:    store i32 0, ptr [[GEP_A_6]], align 4
545 ; CHECK-NEXT:    [[IV_NEXT_6:%.*]] = or disjoint i64 [[IV]], 7
546 ; CHECK-NEXT:    [[GEP_A_7:%.*]] = getelementptr i32, ptr [[A]], i64 [[IV_NEXT_6]]
547 ; CHECK-NEXT:    store i32 0, ptr [[GEP_A_7]], align 4
548 ; CHECK-NEXT:    [[IV_NEXT_7]] = add nuw nsw i64 [[IV]], 8
549 ; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV]], [[N]]
550 ; CHECK-NEXT:    br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP10:![0-9]+]]
551 ; CHECK:       [[EXIT]]:
552 ; CHECK-NEXT:    ret void
554 entry:
555   br label %loop
557 loop:
558   %iv = phi i64 [ 0, %entry ], [ %iv.next.7, %loop ]
559   %shr.1 = lshr exact i64 %iv, 1
560   %gep.B = getelementptr nusw i32, ptr %B, i64 %shr.1
561   %l = load i32, ptr %gep.B, align 4
562   %gep.A = getelementptr i32, ptr %A, i64 %iv
563   store i32 %l, ptr %gep.A, align 4
564   %iv.next = or disjoint i64 %iv, 1
565   %gep.A.1 = getelementptr i32, ptr %A, i64 %iv.next
566   store i32 0, ptr %gep.A.1, align 4
567   %iv.next.1 = or disjoint i64 %iv, 2
568   %shr.2 = lshr exact i64 %iv.next.1, 1
569   %gep.B.2 = getelementptr i32, ptr %B, i64 %shr.2
570   %1 = load i32, ptr %gep.B.2, align 4
571   %gep.A.2 = getelementptr i32, ptr %A, i64 %iv.next.1
572   store i32 %1, ptr %gep.A.2, align 4
573   %iv.next.2 = or disjoint i64 %iv, 3
574   %gep.A.3 = getelementptr i32, ptr %A, i64 %iv.next.2
575   store i32 0, ptr %gep.A.3, align 4
576   %iv.next.3 = or disjoint i64 %iv, 4
577   %gep.B.4 = getelementptr i32, ptr %B, i64 %iv
578   %2 = load i32, ptr %gep.B.4, align 4
579   %gep.A.4 = getelementptr i32, ptr %A, i64 %iv.next.3
580   store i32 %2, ptr %gep.A.4, align 4
581   %iv.next.4 = or disjoint i64 %iv, 5
582   %gep.A.5 = getelementptr i32, ptr %A, i64 %iv.next.4
583   store i32 0, ptr %gep.A.5, align 4
584   %iv.next.5 = or disjoint i64 %iv, 6
585   %gep.A.6 = getelementptr i32, ptr %A, i64 %iv.next.5
586   store i32 0, ptr %gep.A.6, align 4
587   %iv.next.6 = or disjoint i64 %iv, 7
588   %gep.A.7 = getelementptr i32, ptr %A, i64 %iv.next.6
589   store i32 0, ptr %gep.A.7, align 4
590   %iv.next.7 = add nuw nsw i64 %iv, 8
591   %ec = icmp eq i64 %iv, %N
592   br i1 %ec, label %exit, label %loop
594 exit:
595   ret void
598 attributes #0 = { "target-features"="+sse4.2" }
599 attributes #1 = { "min-legal-vector-width"="0" "target-cpu"="cascadelake" }
602 ; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]}
603 ; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1}
604 ; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"}
605 ; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META1]]}
606 ; CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[META1]], [[META2]]}
607 ; CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[META1]]}
608 ; CHECK: [[META6]] = !{[[META7:![0-9]+]]}
609 ; CHECK: [[META7]] = distinct !{[[META7]], [[META8:![0-9]+]]}
610 ; CHECK: [[META8]] = distinct !{[[META8]], !"LVerDomain"}
611 ; CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[META1]], [[META2]]}
612 ; CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[META1]]}