blob: c380f4159d57f645c3b6da30589e0ccea86903d8 [file] [log] [blame]
Nikita Popovd89de3f2019-04-20 12:05:53 +00001; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
Eric Christophercee313d2019-04-17 04:52:47 +00002; RUN: opt < %s -indvars -S | FileCheck %s
Nikita Popovd89de3f2019-04-20 12:05:53 +00003
Eric Christophercee313d2019-04-17 04:52:47 +00004; Make sure that indvars can perform LFTR without a canonical IV.
5
6target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
7
8; Perform LFTR using the original pointer-type IV.
9
10declare void @use(double %x)
11
12; for(char* p = base; p < base + n; ++p) {
13; *p = p-base;
14; }
15define void @ptriv(i8* %base, i32 %n) nounwind {
Nikita Popovd89de3f2019-04-20 12:05:53 +000016; CHECK-LABEL: @ptriv(
17; CHECK-NEXT: entry:
18; CHECK-NEXT: [[IDX_EXT:%.*]] = sext i32 [[N:%.*]] to i64
19; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[BASE:%.*]], i64 [[IDX_EXT]]
20; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8* [[BASE]], [[ADD_PTR]]
21; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]
22; CHECK: for.body.preheader:
23; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* [[BASE]], i64 [[IDX_EXT]]
24; CHECK-NEXT: br label [[FOR_BODY:%.*]]
25; CHECK: for.body:
26; CHECK-NEXT: [[P_02:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[FOR_BODY]] ], [ [[BASE]], [[FOR_BODY_PREHEADER]] ]
27; CHECK-NEXT: [[SUB_PTR_LHS_CAST:%.*]] = ptrtoint i8* [[P_02]] to i64
28; CHECK-NEXT: [[SUB_PTR_RHS_CAST:%.*]] = ptrtoint i8* [[BASE]] to i64
29; CHECK-NEXT: [[SUB_PTR_SUB:%.*]] = sub i64 [[SUB_PTR_LHS_CAST]], [[SUB_PTR_RHS_CAST]]
30; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[SUB_PTR_SUB]] to i8
31; CHECK-NEXT: store i8 [[CONV]], i8* [[P_02]]
32; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[P_02]], i32 1
33; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[LFTR_LIMIT]]
34; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
35; CHECK: for.end.loopexit:
36; CHECK-NEXT: br label [[FOR_END]]
37; CHECK: for.end:
38; CHECK-NEXT: ret void
39;
Eric Christophercee313d2019-04-17 04:52:47 +000040entry:
41 %idx.ext = sext i32 %n to i64
42 %add.ptr = getelementptr inbounds i8, i8* %base, i64 %idx.ext
43 %cmp1 = icmp ult i8* %base, %add.ptr
44 br i1 %cmp1, label %for.body, label %for.end
45
Eric Christophercee313d2019-04-17 04:52:47 +000046for.body:
47 %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ]
48 ; cruft to make the IV useful
49 %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64
50 %sub.ptr.rhs.cast = ptrtoint i8* %base to i64
51 %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
52 %conv = trunc i64 %sub.ptr.sub to i8
53 store i8 %conv, i8* %p.02
54 %incdec.ptr = getelementptr inbounds i8, i8* %p.02, i32 1
55 %cmp = icmp ult i8* %incdec.ptr, %add.ptr
56 br i1 %cmp, label %for.body, label %for.end
57
58for.end:
59 ret void
60}
61
62; This test checks that SCEVExpander can handle an outer loop that has been
63; simplified, and as a result the inner loop's exit test will be rewritten.
64define void @expandOuterRecurrence(i32 %arg) nounwind {
Nikita Popovd89de3f2019-04-20 12:05:53 +000065; CHECK-LABEL: @expandOuterRecurrence(
66; CHECK-NEXT: entry:
67; CHECK-NEXT: [[SUB1:%.*]] = sub nsw i32 [[ARG:%.*]], 1
68; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 0, [[SUB1]]
69; CHECK-NEXT: br i1 [[CMP1]], label [[OUTER_PREHEADER:%.*]], label [[EXIT:%.*]]
70; CHECK: outer.preheader:
71; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[ARG]], -1
72; CHECK-NEXT: br label [[OUTER:%.*]]
73; CHECK: outer:
74; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[TMP0]], [[OUTER_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[OUTER_INC:%.*]] ]
75; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_INC:%.*]], [[OUTER_INC]] ], [ 0, [[OUTER_PREHEADER]] ]
76; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i32 [[ARG]], [[I]]
77; CHECK-NEXT: [[SUB3:%.*]] = sub nsw i32 [[SUB2]], 1
78; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[SUB3]]
79; CHECK-NEXT: br i1 [[CMP2]], label [[INNER_PH:%.*]], label [[OUTER_INC]]
80; CHECK: inner.ph:
81; CHECK-NEXT: br label [[INNER:%.*]]
82; CHECK: inner:
83; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[INNER_PH]] ], [ [[J_INC:%.*]], [[INNER]] ]
84; CHECK-NEXT: [[J_INC]] = add nuw nsw i32 [[J]], 1
85; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[J_INC]], [[INDVARS_IV]]
86; CHECK-NEXT: br i1 [[EXITCOND]], label [[INNER]], label [[OUTER_INC_LOOPEXIT:%.*]]
87; CHECK: outer.inc.loopexit:
88; CHECK-NEXT: br label [[OUTER_INC]]
89; CHECK: outer.inc:
90; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[I]], 1
91; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i32 [[INDVARS_IV]], -1
92; CHECK-NEXT: [[EXITCOND1:%.*]] = icmp ne i32 [[I_INC]], [[TMP0]]
93; CHECK-NEXT: br i1 [[EXITCOND1]], label [[OUTER]], label [[EXIT_LOOPEXIT:%.*]]
94; CHECK: exit.loopexit:
95; CHECK-NEXT: br label [[EXIT]]
96; CHECK: exit:
97; CHECK-NEXT: ret void
98;
Eric Christophercee313d2019-04-17 04:52:47 +000099entry:
100 %sub1 = sub nsw i32 %arg, 1
101 %cmp1 = icmp slt i32 0, %sub1
102 br i1 %cmp1, label %outer, label %exit
103
Eric Christophercee313d2019-04-17 04:52:47 +0000104outer:
105 %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
106 %sub2 = sub nsw i32 %arg, %i
107 %sub3 = sub nsw i32 %sub2, 1
108 %cmp2 = icmp slt i32 0, %sub3
109 br i1 %cmp2, label %inner.ph, label %outer.inc
110
111inner.ph:
112 br label %inner
113
Eric Christophercee313d2019-04-17 04:52:47 +0000114inner:
115 %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
116 %j.inc = add nsw i32 %j, 1
117 %cmp3 = icmp slt i32 %j.inc, %sub3
118 br i1 %cmp3, label %inner, label %outer.inc
119
Eric Christophercee313d2019-04-17 04:52:47 +0000120outer.inc:
121 %i.inc = add nsw i32 %i, 1
122 %cmp4 = icmp slt i32 %i.inc, %sub1
123 br i1 %cmp4, label %outer, label %exit
124
125exit:
126 ret void
127}
128
129; Force SCEVExpander to look for an existing well-formed phi.
130; Perform LFTR without generating extra preheader code.
131define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector,
Nikita Popovd89de3f2019-04-20 12:05:53 +0000132; CHECK-LABEL: @guardedloop(
133; CHECK-NEXT: entry:
134; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 1, [[IROW:%.*]]
135; CHECK-NEXT: br i1 [[CMP]], label [[LOOP_PREHEADER:%.*]], label [[RETURN:%.*]]
136; CHECK: loop.preheader:
137; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[ILEAD:%.*]] to i64
138; CHECK-NEXT: br label [[LOOP:%.*]]
139; CHECK: loop:
140; CHECK-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ 0, [[LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT3:%.*]], [[LOOP]] ]
141; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[LOOP_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ]
142; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], [[INDVARS_IV2]]
143; CHECK-NEXT: [[MATRIXP:%.*]] = getelementptr inbounds [0 x double], [0 x double]* [[MATRIX:%.*]], i32 0, i64 [[TMP1]]
144; CHECK-NEXT: [[V1:%.*]] = load double, double* [[MATRIXP]]
145; CHECK-NEXT: call void @use(double [[V1]])
146; CHECK-NEXT: [[VECTORP:%.*]] = getelementptr inbounds [0 x double], [0 x double]* [[VECTOR:%.*]], i32 0, i64 [[INDVARS_IV2]]
147; CHECK-NEXT: [[V2:%.*]] = load double, double* [[VECTORP]]
148; CHECK-NEXT: call void @use(double [[V2]])
149; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[TMP0]]
150; CHECK-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
151; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[IROW]] to i64
152; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT3]], [[WIDE_TRIP_COUNT]]
153; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[RETURN_LOOPEXIT:%.*]]
154; CHECK: return.loopexit:
155; CHECK-NEXT: br label [[RETURN]]
156; CHECK: return:
157; CHECK-NEXT: ret void
158;
159 i32 %irow, i32 %ilead) nounwind {
Eric Christophercee313d2019-04-17 04:52:47 +0000160entry:
161 %cmp = icmp slt i32 1, %irow
162 br i1 %cmp, label %loop, label %return
163
164loop:
165 %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
166 %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
167 %diagidx = add nsw i32 %rowidx, %i
168 %diagidxw = sext i32 %diagidx to i64
169 %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw
170 %v1 = load double, double* %matrixp
171 call void @use(double %v1)
172 %iw = sext i32 %i to i64
173 %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw
174 %v2 = load double, double* %vectorp
175 call void @use(double %v2)
176 %row.inc = add nsw i32 %rowidx, %ilead
177 %i.inc = add nsw i32 %i, 1
178 %cmp196 = icmp slt i32 %i.inc, %irow
179 br i1 %cmp196, label %loop, label %return
180
181return:
182 ret void
183}
184
185; Avoid generating extra code to materialize a trip count. Skip LFTR.
186define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
Nikita Popovd89de3f2019-04-20 12:05:53 +0000187; CHECK-LABEL: @unguardedloop(
188; CHECK-NEXT: entry:
189; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[IROW:%.*]] to i64
190; CHECK-NEXT: br label [[LOOP:%.*]]
191; CHECK: loop:
192; CHECK-NEXT: [[INDVARS_IV2:%.*]] = phi i64 [ [[INDVARS_IV_NEXT3:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
193; CHECK-NEXT: [[INDVARS_IV_NEXT3]] = add nuw nsw i64 [[INDVARS_IV2]], 1
194; CHECK-NEXT: [[CMP196:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT3]], [[TMP0]]
195; CHECK-NEXT: br i1 [[CMP196]], label [[LOOP]], label [[RETURN:%.*]]
196; CHECK: return:
197; CHECK-NEXT: ret void
198;
199 i32 %irow, i32 %ilead) nounwind {
Eric Christophercee313d2019-04-17 04:52:47 +0000200entry:
201 br label %loop
202
Eric Christophercee313d2019-04-17 04:52:47 +0000203loop:
204 %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
205 %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
206 %diagidx = add nsw i32 %rowidx, %i
207 %diagidxw = sext i32 %diagidx to i64
208 %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw
209 %v1 = load double, double* %matrixp
210 %iw = sext i32 %i to i64
211 %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw
212 %v2 = load double, double* %vectorp
213 %row.inc = add nsw i32 %rowidx, %ilead
214 %i.inc = add nsw i32 %i, 1
215 %cmp196 = icmp slt i32 %i.inc, %irow
216 br i1 %cmp196, label %loop, label %return
217
218return:
219 ret void
220}
221
222; Remove %i which is only used by the exit test.
223; Verify that SCEV can still compute a backedge count from the sign
224; extended %n, used for pointer comparison by LFTR.
225;
226; TODO: Fix for PR13371 currently makes this impossible. See
227; IndVarSimplify.cpp hasConcreteDef(). We may want to change to undef rules.
228define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind {
Nikita Popovd89de3f2019-04-20 12:05:53 +0000229; CHECK-LABEL: @geplftr(
230; CHECK-NEXT: entry:
231; CHECK-NEXT: [[X_EXT:%.*]] = sext i32 [[X:%.*]] to i64
232; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[BASE:%.*]], i64 [[X_EXT]]
233; CHECK-NEXT: [[Y_EXT:%.*]] = sext i32 [[Y:%.*]] to i64
234; CHECK-NEXT: [[ADD_PTR10:%.*]] = getelementptr inbounds i8, i8* [[ADD_PTR]], i64 [[Y_EXT]]
235; CHECK-NEXT: [[LIM:%.*]] = add i32 [[X]], [[N:%.*]]
236; CHECK-NEXT: [[CMP_PH:%.*]] = icmp ult i32 [[X]], [[LIM]]
237; CHECK-NEXT: br i1 [[CMP_PH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
238; CHECK: loop.preheader:
239; CHECK-NEXT: br label [[LOOP:%.*]]
240; CHECK: loop:
241; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[INC:%.*]], [[LOOP]] ], [ [[X]], [[LOOP_PREHEADER]] ]
242; CHECK-NEXT: [[APTR:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[LOOP]] ], [ [[ADD_PTR10]], [[LOOP_PREHEADER]] ]
243; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[APTR]], i32 1
244; CHECK-NEXT: store i8 3, i8* [[APTR]]
245; CHECK-NEXT: [[INC]] = add nuw i32 [[I]], 1
246; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i32 [[INC]], [[LIM]]
247; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
248; CHECK: exit.loopexit:
249; CHECK-NEXT: br label [[EXIT]]
250; CHECK: exit:
251; CHECK-NEXT: ret void
252;
Eric Christophercee313d2019-04-17 04:52:47 +0000253entry:
254 %x.ext = sext i32 %x to i64
255 %add.ptr = getelementptr inbounds i8, i8* %base, i64 %x.ext
256 %y.ext = sext i32 %y to i64
257 %add.ptr10 = getelementptr inbounds i8, i8* %add.ptr, i64 %y.ext
258 %lim = add i32 %x, %n
259 %cmp.ph = icmp ult i32 %x, %lim
260 br i1 %cmp.ph, label %loop, label %exit
Eric Christophercee313d2019-04-17 04:52:47 +0000261loop:
262 %i = phi i32 [ %x, %entry ], [ %inc, %loop ]
263 %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ]
264 %incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1
265 store i8 3, i8* %aptr
266 %inc = add i32 %i, 1
267 %cmp = icmp ult i32 %inc, %lim
268 br i1 %cmp, label %loop, label %exit
269
270exit:
271 ret void
272}
273
274; Exercise backedge taken count verification with a never-taken loop.
275define void @nevertaken() nounwind uwtable ssp {
Nikita Popovd89de3f2019-04-20 12:05:53 +0000276; CHECK-LABEL: @nevertaken(
277; CHECK-NEXT: entry:
278; CHECK-NEXT: br label [[LOOP:%.*]]
279; CHECK: loop:
280; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
281; CHECK: exit:
282; CHECK-NEXT: ret void
283;
Eric Christophercee313d2019-04-17 04:52:47 +0000284entry:
285 br label %loop
Eric Christophercee313d2019-04-17 04:52:47 +0000286loop:
287 %i = phi i32 [ 0, %entry ], [ %inc, %loop ]
288 %inc = add nsw i32 %i, 1
289 %cmp = icmp sle i32 %inc, 0
290 br i1 %cmp, label %loop, label %exit
291
292exit:
293 ret void
294}
295
296; Test LFTR on an IV whose recurrence start is a non-unit pointer type.
297define void @aryptriv([256 x i8]* %base, i32 %n) nounwind {
Nikita Popovd89de3f2019-04-20 12:05:53 +0000298; CHECK-LABEL: @aryptriv(
299; CHECK-NEXT: entry:
300; CHECK-NEXT: [[IVSTART:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[BASE:%.*]], i32 0, i32 0
301; CHECK-NEXT: [[IVEND:%.*]] = getelementptr inbounds [256 x i8], [256 x i8]* [[BASE]], i32 0, i32 [[N:%.*]]
302; CHECK-NEXT: [[CMP_PH:%.*]] = icmp ult i8* [[IVSTART]], [[IVEND]]
303; CHECK-NEXT: br i1 [[CMP_PH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
304; CHECK: loop.preheader:
305; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[N]] to i64
306; CHECK-NEXT: [[LFTR_LIMIT:%.*]] = getelementptr i8, i8* [[IVSTART]], i64 [[TMP0]]
307; CHECK-NEXT: br label [[LOOP:%.*]]
308; CHECK: loop:
309; CHECK-NEXT: [[APTR:%.*]] = phi i8* [ [[INCDEC_PTR:%.*]], [[LOOP]] ], [ [[IVSTART]], [[LOOP_PREHEADER]] ]
310; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i8, i8* [[APTR]], i32 1
311; CHECK-NEXT: store i8 3, i8* [[APTR]]
312; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i8* [[INCDEC_PTR]], [[LFTR_LIMIT]]
313; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
314; CHECK: exit.loopexit:
315; CHECK-NEXT: br label [[EXIT]]
316; CHECK: exit:
317; CHECK-NEXT: ret void
318;
Eric Christophercee313d2019-04-17 04:52:47 +0000319entry:
320 %ivstart = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 0
321 %ivend = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 %n
322 %cmp.ph = icmp ult i8* %ivstart, %ivend
323 br i1 %cmp.ph, label %loop, label %exit
324
Eric Christophercee313d2019-04-17 04:52:47 +0000325loop:
326 %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ]
327 %incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1
328 store i8 3, i8* %aptr
329 %cmp = icmp ult i8* %incdec.ptr, %ivend
330 br i1 %cmp, label %loop, label %exit
331
332exit:
333 ret void
334}