1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -O2 -mtriple=arm64-apple-ios -S %s | FileCheck %s
4 %vec = type { i64*, i64* }
6 ; Test to ensure a loop with multiple loads guarded by runtime-checks (like
7 ; from multiple calls to C++'s std::vector::at) can be vectorized after
8 ; hoisting the runtime checks out of the loop.
10 define i64 @sum_2_at_with_int_conversion(%vec* %A, %vec* %B, i64 %N) {
11 ; CHECK-LABEL: @sum_2_at_with_int_conversion(
12 ; CHECK-NEXT: at_with_int_conversion.exit12.peel:
13 ; CHECK-NEXT: [[GEP_START_I:%.*]] = getelementptr [[VEC:%.*]], %vec* [[A:%.*]], i64 0, i32 0
14 ; CHECK-NEXT: [[START_I:%.*]] = load i64*, i64** [[GEP_START_I]], align 8
15 ; CHECK-NEXT: [[GEP_END_I:%.*]] = getelementptr [[VEC]], %vec* [[A]], i64 0, i32 1
16 ; CHECK-NEXT: [[END_I:%.*]] = load i64*, i64** [[GEP_END_I]], align 8
17 ; CHECK-NEXT: [[START_INT_I:%.*]] = ptrtoint i64* [[START_I]] to i64
18 ; CHECK-NEXT: [[END_INT_I:%.*]] = ptrtoint i64* [[END_I]] to i64
19 ; CHECK-NEXT: [[SUB_I:%.*]] = sub i64 [[END_INT_I]], [[START_INT_I]]
20 ; CHECK-NEXT: [[GEP_END_I3:%.*]] = getelementptr [[VEC]], %vec* [[B:%.*]], i64 0, i32 1
21 ; CHECK-NEXT: [[GEP_START_I1:%.*]] = getelementptr [[VEC]], %vec* [[B]], i64 0, i32 0
22 ; CHECK-NEXT: [[START_I2_PEEL:%.*]] = load i64*, i64** [[GEP_START_I1]], align 8
23 ; CHECK-NEXT: [[END_I4_PEEL:%.*]] = load i64*, i64** [[GEP_END_I3]], align 8
24 ; CHECK-NEXT: [[START_INT_I5_PEEL:%.*]] = ptrtoint i64* [[START_I2_PEEL]] to i64
25 ; CHECK-NEXT: [[END_INT_I6_PEEL:%.*]] = ptrtoint i64* [[END_I4_PEEL]] to i64
26 ; CHECK-NEXT: [[SUB_I7_PEEL:%.*]] = sub i64 [[END_INT_I6_PEEL]], [[START_INT_I5_PEEL]]
27 ; CHECK-NEXT: [[LV_I_PEEL:%.*]] = load i64, i64* [[START_I]], align 4
28 ; CHECK-NEXT: [[LV_I10_PEEL:%.*]] = load i64, i64* [[START_I2_PEEL]], align 4
29 ; CHECK-NEXT: [[SUM_NEXT_PEEL:%.*]] = add i64 [[LV_I_PEEL]], [[LV_I10_PEEL]]
30 ; CHECK-NEXT: [[C_PEEL:%.*]] = icmp sgt i64 [[N:%.*]], 0
31 ; CHECK-NEXT: br i1 [[C_PEEL]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
32 ; CHECK: loop.preheader:
33 ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1
34 ; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB_I7_PEEL]], i64 [[TMP0]])
35 ; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[UMIN]]
36 ; CHECK-NEXT: [[UMIN16:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[SUB_I]])
37 ; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[UMIN16]], 1
38 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 5
39 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[LOOP_PREHEADER21:%.*]], label [[VECTOR_PH:%.*]]
41 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP2]], 3
42 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[N_MOD_VF]], 0
43 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i64 4, i64 [[N_MOD_VF]]
44 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP2]], [[TMP4]]
45 ; CHECK-NEXT: [[IND_END:%.*]] = add i64 [[N_VEC]], 1
46 ; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i64> <i64 poison, i64 0>, i64 [[SUM_NEXT_PEEL]], i64 0
47 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
49 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
50 ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ [[TMP5]], [[VECTOR_PH]] ], [ [[TMP16:%.*]], [[VECTOR_BODY]] ]
51 ; CHECK-NEXT: [[VEC_PHI17:%.*]] = phi <2 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP17:%.*]], [[VECTOR_BODY]] ]
52 ; CHECK-NEXT: [[OFFSET_IDX:%.*]] = or i64 [[INDEX]], 1
53 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[OFFSET_IDX]]
54 ; CHECK-NEXT: [[TMP7:%.*]] = bitcast i64* [[TMP6]] to <2 x i64>*
55 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7]], align 4
56 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, i64* [[TMP6]], i64 2
57 ; CHECK-NEXT: [[TMP9:%.*]] = bitcast i64* [[TMP8]] to <2 x i64>*
58 ; CHECK-NEXT: [[WIDE_LOAD18:%.*]] = load <2 x i64>, <2 x i64>* [[TMP9]], align 4
59 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[OFFSET_IDX]]
60 ; CHECK-NEXT: [[TMP11:%.*]] = bitcast i64* [[TMP10]] to <2 x i64>*
61 ; CHECK-NEXT: [[WIDE_LOAD19:%.*]] = load <2 x i64>, <2 x i64>* [[TMP11]], align 4
62 ; CHECK-NEXT: [[TMP12:%.*]] = getelementptr i64, i64* [[TMP10]], i64 2
63 ; CHECK-NEXT: [[TMP13:%.*]] = bitcast i64* [[TMP12]] to <2 x i64>*
64 ; CHECK-NEXT: [[WIDE_LOAD20:%.*]] = load <2 x i64>, <2 x i64>* [[TMP13]], align 4
65 ; CHECK-NEXT: [[TMP14:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[VEC_PHI]]
66 ; CHECK-NEXT: [[TMP15:%.*]] = add <2 x i64> [[WIDE_LOAD18]], [[VEC_PHI17]]
67 ; CHECK-NEXT: [[TMP16]] = add <2 x i64> [[TMP14]], [[WIDE_LOAD19]]
68 ; CHECK-NEXT: [[TMP17]] = add <2 x i64> [[TMP15]], [[WIDE_LOAD20]]
69 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
70 ; CHECK-NEXT: [[TMP18:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
71 ; CHECK-NEXT: br i1 [[TMP18]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]]
72 ; CHECK: middle.block:
73 ; CHECK-NEXT: [[BIN_RDX:%.*]] = add <2 x i64> [[TMP17]], [[TMP16]]
74 ; CHECK-NEXT: [[TMP19:%.*]] = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> [[BIN_RDX]])
75 ; CHECK-NEXT: br label [[LOOP_PREHEADER21]]
76 ; CHECK: loop.preheader21:
77 ; CHECK-NEXT: [[IV_PH:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ]
78 ; CHECK-NEXT: [[SUM_PH:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[LOOP_PREHEADER]] ], [ [[TMP19]], [[MIDDLE_BLOCK]] ]
79 ; CHECK-NEXT: br label [[LOOP:%.*]]
81 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12:%.*]] ], [ [[IV_PH]], [[LOOP_PREHEADER21]] ]
82 ; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT12]] ], [ [[SUM_PH]], [[LOOP_PREHEADER21]] ]
83 ; CHECK-NEXT: [[INRANGE_I:%.*]] = icmp ult i64 [[SUB_I]], [[IV]]
84 ; CHECK-NEXT: br i1 [[INRANGE_I]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT:%.*]]
86 ; CHECK-NEXT: tail call void @error()
87 ; CHECK-NEXT: unreachable
88 ; CHECK: at_with_int_conversion.exit:
89 ; CHECK-NEXT: [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7_PEEL]], [[IV]]
90 ; CHECK-NEXT: br i1 [[INRANGE_I8]], label [[ERROR_I11:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12]]
92 ; CHECK-NEXT: tail call void @error()
93 ; CHECK-NEXT: unreachable
94 ; CHECK: at_with_int_conversion.exit12:
95 ; CHECK-NEXT: [[GEP_IDX_I:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[IV]]
96 ; CHECK-NEXT: [[LV_I:%.*]] = load i64, i64* [[GEP_IDX_I]], align 4
97 ; CHECK-NEXT: [[GEP_IDX_I9:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[IV]]
98 ; CHECK-NEXT: [[LV_I10:%.*]] = load i64, i64* [[GEP_IDX_I9]], align 4
99 ; CHECK-NEXT: [[ADD:%.*]] = add i64 [[LV_I]], [[SUM]]
100 ; CHECK-NEXT: [[SUM_NEXT]] = add i64 [[ADD]], [[LV_I10]]
101 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
102 ; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[IV]], [[N]]
103 ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT]], !llvm.loop [[LOOP3:![0-9]+]]
105 ; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[AT_WITH_INT_CONVERSION_EXIT12_PEEL:%.*]] ], [ [[SUM_NEXT]], [[AT_WITH_INT_CONVERSION_EXIT12]] ]
106 ; CHECK-NEXT: ret i64 [[SUM_NEXT_LCSSA]]
112 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
113 %sum = phi i64 [ 0, %entry ], [ %sum.next, %loop ]
114 %a = call i64 @at_with_int_conversion(%vec* %A, i64 %iv)
115 %b = call i64 @at_with_int_conversion(%vec* %B, i64 %iv)
116 %add = add i64 %a, %b
117 %sum.next = add i64 %sum, %add
118 %iv.next = add nuw nsw i64 %iv, 1
119 %c = icmp slt i64 %iv, %N
120 br i1 %c, label %loop, label %exit
126 define i64 @sum_3_at_with_int_conversion(%vec* %A, %vec* %B, %vec* %C, i64 %N) {
127 ; CHECK-LABEL: @sum_3_at_with_int_conversion(
128 ; CHECK-NEXT: at_with_int_conversion.exit24.peel:
129 ; CHECK-NEXT: [[GEP_START_I:%.*]] = getelementptr [[VEC:%.*]], %vec* [[A:%.*]], i64 0, i32 0
130 ; CHECK-NEXT: [[START_I:%.*]] = load i64*, i64** [[GEP_START_I]], align 8
131 ; CHECK-NEXT: [[GEP_END_I:%.*]] = getelementptr [[VEC]], %vec* [[A]], i64 0, i32 1
132 ; CHECK-NEXT: [[END_I:%.*]] = load i64*, i64** [[GEP_END_I]], align 8
133 ; CHECK-NEXT: [[START_INT_I:%.*]] = ptrtoint i64* [[START_I]] to i64
134 ; CHECK-NEXT: [[END_INT_I:%.*]] = ptrtoint i64* [[END_I]] to i64
135 ; CHECK-NEXT: [[SUB_I:%.*]] = sub i64 [[END_INT_I]], [[START_INT_I]]
136 ; CHECK-NEXT: [[GEP_START_I13:%.*]] = getelementptr [[VEC]], %vec* [[C:%.*]], i64 0, i32 0
137 ; CHECK-NEXT: [[GEP_END_I15:%.*]] = getelementptr [[VEC]], %vec* [[C]], i64 0, i32 1
138 ; CHECK-NEXT: [[GEP_END_I3:%.*]] = getelementptr [[VEC]], %vec* [[B:%.*]], i64 0, i32 1
139 ; CHECK-NEXT: [[GEP_START_I1:%.*]] = getelementptr [[VEC]], %vec* [[B]], i64 0, i32 0
140 ; CHECK-NEXT: [[LV_I_PEEL:%.*]] = load i64, i64* [[START_I]], align 4
141 ; CHECK-NEXT: [[START_I2_PEEL:%.*]] = load i64*, i64** [[GEP_START_I1]], align 8
142 ; CHECK-NEXT: [[END_I4_PEEL:%.*]] = load i64*, i64** [[GEP_END_I3]], align 8
143 ; CHECK-NEXT: [[START_INT_I5_PEEL:%.*]] = ptrtoint i64* [[START_I2_PEEL]] to i64
144 ; CHECK-NEXT: [[END_I4_PEEL_FR:%.*]] = freeze i64* [[END_I4_PEEL]]
145 ; CHECK-NEXT: [[END_INT_I6_PEEL:%.*]] = ptrtoint i64* [[END_I4_PEEL_FR]] to i64
146 ; CHECK-NEXT: [[SUB_I7_PEEL:%.*]] = sub i64 [[END_INT_I6_PEEL]], [[START_INT_I5_PEEL]]
147 ; CHECK-NEXT: [[START_I14_PEEL:%.*]] = load i64*, i64** [[GEP_START_I13]], align 8
148 ; CHECK-NEXT: [[END_I16_PEEL:%.*]] = load i64*, i64** [[GEP_END_I15]], align 8
149 ; CHECK-NEXT: [[START_INT_I17_PEEL:%.*]] = ptrtoint i64* [[START_I14_PEEL]] to i64
150 ; CHECK-NEXT: [[END_INT_I18_PEEL:%.*]] = ptrtoint i64* [[END_I16_PEEL]] to i64
151 ; CHECK-NEXT: [[SUB_I19_PEEL:%.*]] = sub i64 [[END_INT_I18_PEEL]], [[START_INT_I17_PEEL]]
152 ; CHECK-NEXT: [[LV_I10_PEEL:%.*]] = load i64, i64* [[START_I2_PEEL]], align 4
153 ; CHECK-NEXT: [[LV_I22_PEEL:%.*]] = load i64, i64* [[START_I14_PEEL]], align 4
154 ; CHECK-NEXT: [[ADD_2_PEEL:%.*]] = add i64 [[LV_I_PEEL]], [[LV_I10_PEEL]]
155 ; CHECK-NEXT: [[SUM_NEXT_PEEL:%.*]] = add i64 [[ADD_2_PEEL]], [[LV_I22_PEEL]]
156 ; CHECK-NEXT: [[COND_PEEL:%.*]] = icmp sgt i64 [[N:%.*]], 0
157 ; CHECK-NEXT: br i1 [[COND_PEEL]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
158 ; CHECK: loop.preheader:
159 ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1
160 ; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB_I19_PEEL]], i64 [[TMP0]])
161 ; CHECK-NEXT: [[TMP1:%.*]] = freeze i64 [[UMIN]]
162 ; CHECK-NEXT: [[UMIN28:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[SUB_I7_PEEL]])
163 ; CHECK-NEXT: [[UMIN29:%.*]] = call i64 @llvm.umin.i64(i64 [[UMIN28]], i64 [[SUB_I]])
164 ; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[UMIN29]], 1
165 ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i64 [[TMP2]], 5
166 ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[LOOP_PREHEADER36:%.*]], label [[VECTOR_PH:%.*]]
168 ; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[TMP2]], 3
169 ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[N_MOD_VF]], 0
170 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i64 4, i64 [[N_MOD_VF]]
171 ; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[TMP2]], [[TMP4]]
172 ; CHECK-NEXT: [[IND_END:%.*]] = add i64 [[N_VEC]], 1
173 ; CHECK-NEXT: [[TMP5:%.*]] = insertelement <2 x i64> <i64 poison, i64 0>, i64 [[SUM_NEXT_PEEL]], i64 0
174 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]
175 ; CHECK: vector.body:
176 ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
177 ; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <2 x i64> [ [[TMP5]], [[VECTOR_PH]] ], [ [[TMP22:%.*]], [[VECTOR_BODY]] ]
178 ; CHECK-NEXT: [[VEC_PHI30:%.*]] = phi <2 x i64> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP23:%.*]], [[VECTOR_BODY]] ]
179 ; CHECK-NEXT: [[OFFSET_IDX:%.*]] = or i64 [[INDEX]], 1
180 ; CHECK-NEXT: [[TMP6:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[OFFSET_IDX]]
181 ; CHECK-NEXT: [[TMP7:%.*]] = bitcast i64* [[TMP6]] to <2 x i64>*
182 ; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i64>, <2 x i64>* [[TMP7]], align 4
183 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr i64, i64* [[TMP6]], i64 2
184 ; CHECK-NEXT: [[TMP9:%.*]] = bitcast i64* [[TMP8]] to <2 x i64>*
185 ; CHECK-NEXT: [[WIDE_LOAD31:%.*]] = load <2 x i64>, <2 x i64>* [[TMP9]], align 4
186 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[OFFSET_IDX]]
187 ; CHECK-NEXT: [[TMP11:%.*]] = bitcast i64* [[TMP10]] to <2 x i64>*
188 ; CHECK-NEXT: [[WIDE_LOAD32:%.*]] = load <2 x i64>, <2 x i64>* [[TMP11]], align 4
189 ; CHECK-NEXT: [[TMP12:%.*]] = getelementptr i64, i64* [[TMP10]], i64 2
190 ; CHECK-NEXT: [[TMP13:%.*]] = bitcast i64* [[TMP12]] to <2 x i64>*
191 ; CHECK-NEXT: [[WIDE_LOAD33:%.*]] = load <2 x i64>, <2 x i64>* [[TMP13]], align 4
192 ; CHECK-NEXT: [[TMP14:%.*]] = getelementptr i64, i64* [[START_I14_PEEL]], i64 [[OFFSET_IDX]]
193 ; CHECK-NEXT: [[TMP15:%.*]] = bitcast i64* [[TMP14]] to <2 x i64>*
194 ; CHECK-NEXT: [[WIDE_LOAD34:%.*]] = load <2 x i64>, <2 x i64>* [[TMP15]], align 4
195 ; CHECK-NEXT: [[TMP16:%.*]] = getelementptr i64, i64* [[TMP14]], i64 2
196 ; CHECK-NEXT: [[TMP17:%.*]] = bitcast i64* [[TMP16]] to <2 x i64>*
197 ; CHECK-NEXT: [[WIDE_LOAD35:%.*]] = load <2 x i64>, <2 x i64>* [[TMP17]], align 4
198 ; CHECK-NEXT: [[TMP18:%.*]] = add <2 x i64> [[WIDE_LOAD]], [[VEC_PHI]]
199 ; CHECK-NEXT: [[TMP19:%.*]] = add <2 x i64> [[WIDE_LOAD31]], [[VEC_PHI30]]
200 ; CHECK-NEXT: [[TMP20:%.*]] = add <2 x i64> [[TMP18]], [[WIDE_LOAD32]]
201 ; CHECK-NEXT: [[TMP21:%.*]] = add <2 x i64> [[TMP19]], [[WIDE_LOAD33]]
202 ; CHECK-NEXT: [[TMP22]] = add <2 x i64> [[TMP20]], [[WIDE_LOAD34]]
203 ; CHECK-NEXT: [[TMP23]] = add <2 x i64> [[TMP21]], [[WIDE_LOAD35]]
204 ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
205 ; CHECK-NEXT: [[TMP24:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
206 ; CHECK-NEXT: br i1 [[TMP24]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
207 ; CHECK: middle.block:
208 ; CHECK-NEXT: [[BIN_RDX:%.*]] = add <2 x i64> [[TMP23]], [[TMP22]]
209 ; CHECK-NEXT: [[TMP25:%.*]] = call i64 @llvm.vector.reduce.add.v2i64(<2 x i64> [[BIN_RDX]])
210 ; CHECK-NEXT: br label [[LOOP_PREHEADER36]]
211 ; CHECK: loop.preheader36:
212 ; CHECK-NEXT: [[IV_PH:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[IND_END]], [[MIDDLE_BLOCK]] ]
213 ; CHECK-NEXT: [[SUM_PH:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[LOOP_PREHEADER]] ], [ [[TMP25]], [[MIDDLE_BLOCK]] ]
214 ; CHECK-NEXT: br label [[LOOP:%.*]]
216 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24:%.*]] ], [ [[IV_PH]], [[LOOP_PREHEADER36]] ]
217 ; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ [[SUM_NEXT:%.*]], [[AT_WITH_INT_CONVERSION_EXIT24]] ], [ [[SUM_PH]], [[LOOP_PREHEADER36]] ]
218 ; CHECK-NEXT: [[INRANGE_I:%.*]] = icmp ult i64 [[SUB_I]], [[IV]]
219 ; CHECK-NEXT: br i1 [[INRANGE_I]], label [[ERROR_I:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT:%.*]]
221 ; CHECK-NEXT: tail call void @error()
222 ; CHECK-NEXT: unreachable
223 ; CHECK: at_with_int_conversion.exit:
224 ; CHECK-NEXT: [[GEP_IDX_I:%.*]] = getelementptr i64, i64* [[START_I]], i64 [[IV]]
225 ; CHECK-NEXT: [[LV_I:%.*]] = load i64, i64* [[GEP_IDX_I]], align 4
226 ; CHECK-NEXT: [[INRANGE_I8:%.*]] = icmp ult i64 [[SUB_I7_PEEL]], [[IV]]
227 ; CHECK-NEXT: br i1 [[INRANGE_I8]], label [[ERROR_I11:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT12:%.*]]
229 ; CHECK-NEXT: tail call void @error()
230 ; CHECK-NEXT: unreachable
231 ; CHECK: at_with_int_conversion.exit12:
232 ; CHECK-NEXT: [[INRANGE_I20:%.*]] = icmp ult i64 [[SUB_I19_PEEL]], [[IV]]
233 ; CHECK-NEXT: br i1 [[INRANGE_I20]], label [[ERROR_I23:%.*]], label [[AT_WITH_INT_CONVERSION_EXIT24]]
235 ; CHECK-NEXT: tail call void @error()
236 ; CHECK-NEXT: unreachable
237 ; CHECK: at_with_int_conversion.exit24:
238 ; CHECK-NEXT: [[GEP_IDX_I9:%.*]] = getelementptr i64, i64* [[START_I2_PEEL]], i64 [[IV]]
239 ; CHECK-NEXT: [[LV_I10:%.*]] = load i64, i64* [[GEP_IDX_I9]], align 4
240 ; CHECK-NEXT: [[GEP_IDX_I21:%.*]] = getelementptr i64, i64* [[START_I14_PEEL]], i64 [[IV]]
241 ; CHECK-NEXT: [[LV_I22:%.*]] = load i64, i64* [[GEP_IDX_I21]], align 4
242 ; CHECK-NEXT: [[ADD_1:%.*]] = add i64 [[LV_I]], [[SUM]]
243 ; CHECK-NEXT: [[ADD_2:%.*]] = add i64 [[ADD_1]], [[LV_I10]]
244 ; CHECK-NEXT: [[SUM_NEXT]] = add i64 [[ADD_2]], [[LV_I22]]
245 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
246 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[IV]], [[N]]
247 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT]], !llvm.loop [[LOOP6:![0-9]+]]
249 ; CHECK-NEXT: [[SUM_NEXT_LCSSA:%.*]] = phi i64 [ [[SUM_NEXT_PEEL]], [[AT_WITH_INT_CONVERSION_EXIT24_PEEL:%.*]] ], [ [[SUM_NEXT]], [[AT_WITH_INT_CONVERSION_EXIT24]] ]
250 ; CHECK-NEXT: ret i64 [[SUM_NEXT_LCSSA]]
256 %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
257 %sum = phi i64 [ 0, %entry ], [ %sum.next, %loop ]
258 %a = call i64 @at_with_int_conversion(%vec* %A, i64 %iv)
259 %b = call i64 @at_with_int_conversion(%vec* %B, i64 %iv)
260 %c = call i64 @at_with_int_conversion(%vec* %C, i64 %iv)
261 %add.1 = add i64 %a, %b
262 %add.2 = add i64 %add.1, %c
263 %sum.next = add i64 %sum, %add.2
264 %iv.next = add nuw nsw i64 %iv, 1
265 %cond = icmp slt i64 %iv, %N
266 br i1 %cond, label %loop, label %exit
273 define i64 @at_with_int_conversion(%vec* %ptr, i64 %idx) {
274 ; CHECK-LABEL: @at_with_int_conversion(
275 ; CHECK-NEXT: [[GEP_START:%.*]] = getelementptr [[VEC:%.*]], %vec* [[PTR:%.*]], i64 0, i32 0
276 ; CHECK-NEXT: [[START:%.*]] = load i64*, i64** [[GEP_START]], align 8
277 ; CHECK-NEXT: [[GEP_END:%.*]] = getelementptr [[VEC]], %vec* [[PTR]], i64 0, i32 1
278 ; CHECK-NEXT: [[END:%.*]] = load i64*, i64** [[GEP_END]], align 8
279 ; CHECK-NEXT: [[START_INT:%.*]] = ptrtoint i64* [[START]] to i64
280 ; CHECK-NEXT: [[END_INT:%.*]] = ptrtoint i64* [[END]] to i64
281 ; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[END_INT]], [[START_INT]]
282 ; CHECK-NEXT: [[INRANGE:%.*]] = icmp ult i64 [[SUB]], [[IDX:%.*]]
283 ; CHECK-NEXT: br i1 [[INRANGE]], label [[ERROR:%.*]], label [[EXIT:%.*]]
285 ; CHECK-NEXT: [[GEP_IDX:%.*]] = getelementptr i64, i64* [[START]], i64 [[IDX]]
286 ; CHECK-NEXT: [[LV:%.*]] = load i64, i64* [[GEP_IDX]], align 4
287 ; CHECK-NEXT: ret i64 [[LV]]
289 ; CHECK-NEXT: tail call void @error()
290 ; CHECK-NEXT: unreachable
292 %gep.start = getelementptr %vec, %vec* %ptr, i64 0, i32 0
293 %start = load i64*, i64** %gep.start
294 %gep.end = getelementptr %vec, %vec* %ptr, i64 0, i32 1
295 %end = load i64*, i64** %gep.end
296 %start.int = ptrtoint i64* %start to i64
297 %end.int = ptrtoint i64* %end to i64
298 %sub = sub i64 %end.int, %start.int
299 %inrange = icmp ugt i64 %idx, %sub
300 br i1 %inrange, label %error, label %exit
303 %gep.idx = getelementptr i64, i64* %start, i64 %idx
304 %lv = load i64, i64* %gep.idx
312 declare void @error()