1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=loop-vectorize -force-vector-width=2 -S %s | FileCheck %s
3
4; Tests where the indices of some accesses are clamped to a small range.
5
6; FIXME: At the moment, the runtime checks require that the indices do not wrap
7;        and runtime checks are emitted to ensure that. The clamped indices do
8;        wrap, so the vector loops are dead at the moment. But it is still
9;        possible to compute the bounds of the accesses and generate proper
10;        runtime checks.
11
12; The relevant bounds for %gep.A are [%A, %A+4).
13define void @load_clamped_index(i32* %A, i32* %B, i32 %N) {
14; CHECK-LABEL: @load_clamped_index(
15; CHECK-NEXT:  entry:
16; CHECK-NEXT:    [[A2:%.*]] = ptrtoint i32* [[A:%.*]] to i64
17; CHECK-NEXT:    [[B1:%.*]] = ptrtoint i32* [[B:%.*]] to i64
18; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N:%.*]], 2
19; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
20; CHECK:       vector.scevcheck:
21; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
22; CHECK-NEXT:    [[TMP7:%.*]] = icmp ugt i32 [[TMP0]], 3
23; CHECK-NEXT:    br i1 [[TMP7]], label [[SCALAR_PH]], label [[VECTOR_MEMCHECK:%.*]]
24; CHECK:       vector.memcheck:
25; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 [[B1]], [[A2]]
26; CHECK-NEXT:    [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP2]], 8
27; CHECK-NEXT:    br i1 [[DIFF_CHECK]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
28; CHECK:       vector.ph:
29; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i32 [[N]], 2
30; CHECK-NEXT:    [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]]
31; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
32; CHECK:       vector.body:
33; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
34; CHECK-NEXT:    [[TMP13:%.*]] = add i32 [[INDEX]], 0
35; CHECK-NEXT:    [[TMP14:%.*]] = urem i32 [[TMP13]], 4
36; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[TMP14]]
37; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, i32* [[TMP15]], i32 0
38; CHECK-NEXT:    [[TMP17:%.*]] = bitcast i32* [[TMP16]] to <2 x i32>*
39; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, <2 x i32>* [[TMP17]], align 4
40; CHECK-NEXT:    [[TMP18:%.*]] = add <2 x i32> [[WIDE_LOAD]], <i32 10, i32 10>
41; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[B]], i32 [[TMP13]]
42; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds i32, i32* [[TMP19]], i32 0
43; CHECK-NEXT:    [[TMP21:%.*]] = bitcast i32* [[TMP20]] to <2 x i32>*
44; CHECK-NEXT:    store <2 x i32> [[TMP18]], <2 x i32>* [[TMP21]], align 4
45; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
46; CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
47; CHECK-NEXT:    br i1 [[TMP22]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP5:![0-9]+]]
48; CHECK:       middle.block:
49; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]]
50; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
51; CHECK:       scalar.ph:
52; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_SCEVCHECK]] ], [ 0, [[VECTOR_MEMCHECK]] ]
53; CHECK-NEXT:    br label [[LOOP:%.*]]
54; CHECK:       loop:
55; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
56; CHECK-NEXT:    [[CLAMPED_INDEX:%.*]] = urem i32 [[IV]], 4
57; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[CLAMPED_INDEX]]
58; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[GEP_A]], align 4
59; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LV]], 10
60; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, i32* [[B]], i32 [[IV]]
61; CHECK-NEXT:    store i32 [[ADD]], i32* [[GEP_B]], align 4
62; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
63; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N]]
64; CHECK-NEXT:    br i1 [[COND]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP7:![0-9]+]]
65; CHECK:       exit:
66; CHECK-NEXT:    ret void
67;
68entry:
69  br label %loop
70
71loop:
72  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
73  %clamped.index = urem i32 %iv, 4
74  %gep.A = getelementptr inbounds i32, i32* %A, i32 %clamped.index
75  %lv = load i32, i32* %gep.A
76  %add = add i32 %lv, 10
77  %gep.B = getelementptr inbounds i32, i32* %B, i32 %iv
78  store i32 %add, i32* %gep.B
79  %iv.next = add nuw nsw i32 %iv, 1
80  %cond = icmp eq i32 %iv.next, %N
81  br i1 %cond, label %exit, label %loop
82
83exit:
84  ret void
85}
86
87; The relevant bounds for %gep.A are [%A, %A+4).
88define void @store_clamped_index(i32* %A, i32* %B, i32 %N) {
89; CHECK-LABEL: @store_clamped_index(
90; CHECK-NEXT:  entry:
91; CHECK-NEXT:    [[B2:%.*]] = ptrtoint i32* [[B:%.*]] to i64
92; CHECK-NEXT:    [[A1:%.*]] = ptrtoint i32* [[A:%.*]] to i64
93; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N:%.*]], 2
94; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
95; CHECK:       vector.scevcheck:
96; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
97; CHECK-NEXT:    [[TMP7:%.*]] = icmp ugt i32 [[TMP0]], 3
98; CHECK-NEXT:    br i1 [[TMP7]], label [[SCALAR_PH]], label [[VECTOR_MEMCHECK:%.*]]
99; CHECK:       vector.memcheck:
100; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 [[A1]], [[B2]]
101; CHECK-NEXT:    [[DIFF_CHECK:%.*]] = icmp ult i64 [[TMP2]], 8
102; CHECK-NEXT:    br i1 [[DIFF_CHECK]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
103; CHECK:       vector.ph:
104; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i32 [[N]], 2
105; CHECK-NEXT:    [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]]
106; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
107; CHECK:       vector.body:
108; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
109; CHECK-NEXT:    [[TMP13:%.*]] = add i32 [[INDEX]], 0
110; CHECK-NEXT:    [[TMP14:%.*]] = urem i32 [[TMP13]], 4
111; CHECK-NEXT:    [[TMP15:%.*]] = getelementptr inbounds i32, i32* [[B]], i32 [[TMP13]]
112; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32, i32* [[TMP15]], i32 0
113; CHECK-NEXT:    [[TMP17:%.*]] = bitcast i32* [[TMP16]] to <2 x i32>*
114; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, <2 x i32>* [[TMP17]], align 4
115; CHECK-NEXT:    [[TMP18:%.*]] = add <2 x i32> [[WIDE_LOAD]], <i32 10, i32 10>
116; CHECK-NEXT:    [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[TMP14]]
117; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds i32, i32* [[TMP19]], i32 0
118; CHECK-NEXT:    [[TMP21:%.*]] = bitcast i32* [[TMP20]] to <2 x i32>*
119; CHECK-NEXT:    store <2 x i32> [[TMP18]], <2 x i32>* [[TMP21]], align 4
120; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
121; CHECK-NEXT:    [[TMP22:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
122; CHECK-NEXT:    br i1 [[TMP22]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP13:![0-9]+]]
123; CHECK:       middle.block:
124; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]]
125; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
126; CHECK:       scalar.ph:
127; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_SCEVCHECK]] ], [ 0, [[VECTOR_MEMCHECK]] ]
128; CHECK-NEXT:    br label [[LOOP:%.*]]
129; CHECK:       loop:
130; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
131; CHECK-NEXT:    [[CLAMPED_INDEX:%.*]] = urem i32 [[IV]], 4
132; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, i32* [[B]], i32 [[IV]]
133; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[GEP_B]], align 4
134; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LV]], 10
135; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[CLAMPED_INDEX]]
136; CHECK-NEXT:    store i32 [[ADD]], i32* [[GEP_A]], align 4
137; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
138; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N]]
139; CHECK-NEXT:    br i1 [[COND]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP14:![0-9]+]]
140; CHECK:       exit:
141; CHECK-NEXT:    ret void
142;
143entry:
144  br label %loop
145
146loop:
147  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
148  %clamped.index = urem i32 %iv, 4
149  %gep.B = getelementptr inbounds i32, i32* %B, i32 %iv
150  %lv = load i32, i32* %gep.B
151  %add = add i32 %lv, 10
152  %gep.A = getelementptr inbounds i32, i32* %A, i32 %clamped.index
153  store i32 %add, i32* %gep.A
154  %iv.next = add nuw nsw i32 %iv, 1
155  %cond = icmp eq i32 %iv.next, %N
156  br i1 %cond, label %exit, label %loop
157
158exit:
159  ret void
160}
161
162define void @clamped_index_dependence_non_clamped(i32* %A, i32* %B, i32 %N) {
163; CHECK-LABEL: @clamped_index_dependence_non_clamped(
164; CHECK-NEXT:  entry:
165; CHECK-NEXT:    br label [[LOOP:%.*]]
166; CHECK:       loop:
167; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
168; CHECK-NEXT:    [[GEP_B:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i32 [[IV]]
169; CHECK-NEXT:    [[LV:%.*]] = load i32, i32* [[GEP_B]], align 4
170; CHECK-NEXT:    [[GEP_A_1:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[IV]]
171; CHECK-NEXT:    [[LV_A:%.*]] = load i32, i32* [[GEP_A_1]], align 4
172; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LV]], [[LV_A]]
173; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
174; CHECK-NEXT:    [[CLAMPED_INDEX:%.*]] = urem i32 [[IV_NEXT]], 4
175; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[CLAMPED_INDEX]]
176; CHECK-NEXT:    store i32 [[ADD]], i32* [[GEP_A]], align 4
177; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]
178; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
179; CHECK:       exit:
180; CHECK-NEXT:    ret void
181;
182entry:
183  br label %loop
184
185loop:
186  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
187  %gep.B = getelementptr inbounds i32, i32* %B, i32 %iv
188  %lv = load i32, i32* %gep.B
189  %gep.A.1 = getelementptr inbounds i32, i32* %A, i32 %iv
190  %lv.A = load i32, i32* %gep.A.1
191  %add = add i32 %lv, %lv.A
192
193  %iv.next = add nuw nsw i32 %iv, 1
194  %clamped.index = urem i32 %iv.next, 4
195  %gep.A = getelementptr inbounds i32, i32* %A, i32 %clamped.index
196  store i32 %add, i32* %gep.A
197  %cond = icmp eq i32 %iv.next, %N
198  br i1 %cond, label %exit, label %loop
199
200exit:
201  ret void
202}
203
204define void @clamped_index_dependence_clamped_index(i32* %A, i32* %B, i32 %N) {
205; CHECK-LABEL: @clamped_index_dependence_clamped_index(
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    br label [[LOOP:%.*]]
208; CHECK:       loop:
209; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
210; CHECK-NEXT:    [[CLAMPED_INDEX_1:%.*]] = urem i32 [[IV]], 4
211; CHECK-NEXT:    [[GEP_A_1:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[CLAMPED_INDEX_1]]
212; CHECK-NEXT:    [[LV_A:%.*]] = load i32, i32* [[GEP_A_1]], align 4
213; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LV_A]], 10
214; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
215; CHECK-NEXT:    [[CLAMPED_INDEX:%.*]] = urem i32 [[IV_NEXT]], 4
216; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[CLAMPED_INDEX]]
217; CHECK-NEXT:    store i32 [[ADD]], i32* [[GEP_A]], align 4
218; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N:%.*]]
219; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
220; CHECK:       exit:
221; CHECK-NEXT:    ret void
222;
223entry:
224  br label %loop
225
226loop:
227  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
228  %clamped.index.1 = urem i32 %iv, 4
229  %gep.A.1 = getelementptr inbounds i32, i32* %A, i32 %clamped.index.1
230  %lv.A = load i32, i32* %gep.A.1
231  %add = add i32 %lv.A, 10
232
233  %iv.next = add nuw nsw i32 %iv, 1
234  %clamped.index = urem i32 %iv.next, 4
235  %gep.A = getelementptr inbounds i32, i32* %A, i32 %clamped.index
236  store i32 %add, i32* %gep.A
237  %cond = icmp eq i32 %iv.next, %N
238  br i1 %cond, label %exit, label %loop
239
240exit:
241  ret void
242}
243
244define void @clamped_index_equal_dependence(i32* %A, i32* %B, i32 %N) {
245; CHECK-LABEL: @clamped_index_equal_dependence(
246; CHECK-NEXT:  entry:
247; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N:%.*]], 2
248; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_SCEVCHECK:%.*]]
249; CHECK:       vector.scevcheck:
250; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N]], -1
251; CHECK-NEXT:    [[TMP7:%.*]] = icmp ugt i32 [[TMP0]], 3
252; CHECK-NEXT:    br i1 [[TMP7]], label [[SCALAR_PH]], label [[VECTOR_PH:%.*]]
253; CHECK:       vector.ph:
254; CHECK-NEXT:    [[N_MOD_VF:%.*]] = urem i32 [[N]], 2
255; CHECK-NEXT:    [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]]
256; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
257; CHECK:       vector.body:
258; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
259; CHECK-NEXT:    [[TMP10:%.*]] = add i32 [[INDEX]], 0
260; CHECK-NEXT:    [[TMP11:%.*]] = urem i32 [[TMP10]], 4
261; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i32 [[TMP11]]
262; CHECK-NEXT:    [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[TMP12]], i32 0
263; CHECK-NEXT:    [[TMP14:%.*]] = bitcast i32* [[TMP13]] to <2 x i32>*
264; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x i32>, <2 x i32>* [[TMP14]], align 4
265; CHECK-NEXT:    [[TMP15:%.*]] = add <2 x i32> [[WIDE_LOAD]], <i32 10, i32 10>
266; CHECK-NEXT:    [[TMP16:%.*]] = bitcast i32* [[TMP13]] to <2 x i32>*
267; CHECK-NEXT:    store <2 x i32> [[TMP15]], <2 x i32>* [[TMP16]], align 4
268; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 2
269; CHECK-NEXT:    [[TMP17:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
270; CHECK-NEXT:    br i1 [[TMP17]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP15:![0-9]+]]
271; CHECK:       middle.block:
272; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]]
273; CHECK-NEXT:    br i1 [[CMP_N]], label [[EXIT:%.*]], label [[SCALAR_PH]]
274; CHECK:       scalar.ph:
275; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[VECTOR_SCEVCHECK]] ]
276; CHECK-NEXT:    br label [[LOOP:%.*]]
277; CHECK:       loop:
278; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
279; CHECK-NEXT:    [[CLAMPED_INDEX:%.*]] = urem i32 [[IV]], 4
280; CHECK-NEXT:    [[GEP_A:%.*]] = getelementptr inbounds i32, i32* [[A]], i32 [[CLAMPED_INDEX]]
281; CHECK-NEXT:    [[LV_A:%.*]] = load i32, i32* [[GEP_A]], align 4
282; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[LV_A]], 10
283; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
284; CHECK-NEXT:    store i32 [[ADD]], i32* [[GEP_A]], align 4
285; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV_NEXT]], [[N]]
286; CHECK-NEXT:    br i1 [[COND]], label [[EXIT]], label [[LOOP]], !llvm.loop [[LOOP16:![0-9]+]]
287; CHECK:       exit:
288; CHECK-NEXT:    ret void
289;
290entry:
291  br label %loop
292
293loop:
294  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
295  %clamped.index = urem i32 %iv, 4
296  %gep.A = getelementptr inbounds i32, i32* %A, i32 %clamped.index
297  %lv.A = load i32, i32* %gep.A
298  %add = add i32 %lv.A, 10
299
300  %iv.next = add nuw nsw i32 %iv, 1
301  store i32 %add, i32* %gep.A
302  %cond = icmp eq i32 %iv.next, %N
303  br i1 %cond, label %exit, label %loop
304
305exit:
306  ret void
307}
308