1; RUN: opt < %s -indvars -S | FileCheck %s
2;
3; Make sure that indvars can perform LFTR without a canonical IV.
4
5target 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"
6
7; Perform LFTR using the original pointer-type IV.
8
9;  for(char* p = base; p < base + n; ++p) {
10;    *p = p-base;
11;  }
12define void @ptriv(i8* %base, i32 %n) nounwind {
13entry:
14  %idx.ext = sext i32 %n to i64
15  %add.ptr = getelementptr inbounds i8, i8* %base, i64 %idx.ext
16  %cmp1 = icmp ult i8* %base, %add.ptr
17  br i1 %cmp1, label %for.body, label %for.end
18
19; CHECK: for.body:
20; CHECK: phi i8*
21; CHECK-NOT: phi
22; CHECK-NOT: add
23; CHECK: icmp ne i8*
24; CHECK: br i1
25for.body:
26  %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ]
27  ; cruft to make the IV useful
28  %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64
29  %sub.ptr.rhs.cast = ptrtoint i8* %base to i64
30  %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast
31  %conv = trunc i64 %sub.ptr.sub to i8
32  store i8 %conv, i8* %p.02
33  %incdec.ptr = getelementptr inbounds i8, i8* %p.02, i32 1
34  %cmp = icmp ult i8* %incdec.ptr, %add.ptr
35  br i1 %cmp, label %for.body, label %for.end
36
37for.end:
38  ret void
39}
40
41; This test checks that SCEVExpander can handle an outer loop that has been
42; simplified, and as a result the inner loop's exit test will be rewritten.
43define void @expandOuterRecurrence(i32 %arg) nounwind {
44entry:
45  %sub1 = sub nsw i32 %arg, 1
46  %cmp1 = icmp slt i32 0, %sub1
47  br i1 %cmp1, label %outer, label %exit
48
49; CHECK: outer:
50; CHECK: icmp slt
51outer:
52  %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ]
53  %sub2 = sub nsw i32 %arg, %i
54  %sub3 = sub nsw i32 %sub2, 1
55  %cmp2 = icmp slt i32 0, %sub3
56  br i1 %cmp2, label %inner.ph, label %outer.inc
57
58inner.ph:
59  br label %inner
60
61; CHECK: inner:
62; CHECK: br i1
63inner:
64  %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ]
65  %j.inc = add nsw i32 %j, 1
66  %cmp3 = icmp slt i32 %j.inc, %sub3
67  br i1 %cmp3, label %inner, label %outer.inc
68
69; CHECK: outer.inc:
70; CHECK: icmp ne
71; CHECK: br i1
72outer.inc:
73  %i.inc = add nsw i32 %i, 1
74  %cmp4 = icmp slt i32 %i.inc, %sub1
75  br i1 %cmp4, label %outer, label %exit
76
77exit:
78  ret void
79}
80
81; Force SCEVExpander to look for an existing well-formed phi.
82; Perform LFTR without generating extra preheader code.
83define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector,
84                         i32 %irow, i32 %ilead) nounwind {
85; CHECK: entry:
86; CHECK-NOT: zext
87; CHECK-NOT: add
88; CHECK: loop:
89; CHECK: phi i64
90; CHECK: phi i64
91; CHECK-NOT: phi
92; CHECK: icmp ne
93; CHECK: br i1
94entry:
95  %cmp = icmp slt i32 1, %irow
96  br i1 %cmp, label %loop, label %return
97
98loop:
99  %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
100  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
101  %diagidx = add nsw i32 %rowidx, %i
102  %diagidxw = sext i32 %diagidx to i64
103  %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw
104  %v1 = load double, double* %matrixp
105  %iw = sext i32 %i to i64
106  %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw
107  %v2 = load double, double* %vectorp
108  %row.inc = add nsw i32 %rowidx, %ilead
109  %i.inc = add nsw i32 %i, 1
110  %cmp196 = icmp slt i32 %i.inc, %irow
111  br i1 %cmp196, label %loop, label %return
112
113return:
114  ret void
115}
116
117; Avoid generating extra code to materialize a trip count. Skip LFTR.
118define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector,
119                           i32 %irow, i32 %ilead) nounwind {
120entry:
121  br label %loop
122
123; CHECK: entry:
124; CHECK-NOT: zext
125; CHECK-NOT: add
126; CHECK: loop:
127; CHECK: phi i64
128; CHECK: phi i64
129; CHECK-NOT: phi
130; CHECK: icmp slt
131; CHECK: br i1
132loop:
133  %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ]
134  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ]
135  %diagidx = add nsw i32 %rowidx, %i
136  %diagidxw = sext i32 %diagidx to i64
137  %matrixp = getelementptr inbounds [0 x double], [0 x double]* %matrix, i32 0, i64 %diagidxw
138  %v1 = load double, double* %matrixp
139  %iw = sext i32 %i to i64
140  %vectorp = getelementptr inbounds [0 x double], [0 x double]* %vector, i32 0, i64 %iw
141  %v2 = load double, double* %vectorp
142  %row.inc = add nsw i32 %rowidx, %ilead
143  %i.inc = add nsw i32 %i, 1
144  %cmp196 = icmp slt i32 %i.inc, %irow
145  br i1 %cmp196, label %loop, label %return
146
147return:
148  ret void
149}
150
151; Remove %i which is only used by the exit test.
152; Verify that SCEV can still compute a backedge count from the sign
153; extended %n, used for pointer comparison by LFTR.
154;
155; TODO: Fix for PR13371 currently makes this impossible. See
156; IndVarSimplify.cpp hasConcreteDef(). We may want to change to undef rules.
157define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind {
158entry:
159  %x.ext = sext i32 %x to i64
160  %add.ptr = getelementptr inbounds i8, i8* %base, i64 %x.ext
161  %y.ext = sext i32 %y to i64
162  %add.ptr10 = getelementptr inbounds i8, i8* %add.ptr, i64 %y.ext
163  %lim = add i32 %x, %n
164  %cmp.ph = icmp ult i32 %x, %lim
165  br i1 %cmp.ph, label %loop, label %exit
166; CHECK-LABEL: @geplftr(
167; CHECK: loop:
168; CHECK: phi i8*
169; DISABLE-NOT: phi      // This check is currently disabled
170; CHECK: getelementptr
171; CHECK: store
172; DISABLE: icmp ne i8*  // This check is currently disabled
173; CHECK: br i1
174loop:
175  %i = phi i32 [ %x, %entry ], [ %inc, %loop ]
176  %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ]
177  %incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1
178  store i8 3, i8* %aptr
179  %inc = add i32 %i, 1
180  %cmp = icmp ult i32 %inc, %lim
181  br i1 %cmp, label %loop, label %exit
182
183exit:
184  ret void
185}
186
187; Exercise backedge taken count verification with a never-taken loop.
188define void @nevertaken() nounwind uwtable ssp {
189entry:
190  br label %loop
191; CHECK-LABEL: @nevertaken(
192; CHECK: loop:
193; CHECK-NOT: phi
194; CHECK-NOT: add
195; CHECK-NOT: icmp
196; CHECK: exit:
197loop:
198  %i = phi i32 [ 0, %entry ], [ %inc, %loop ]
199  %inc = add nsw i32 %i, 1
200  %cmp = icmp sle i32 %inc, 0
201  br i1 %cmp, label %loop, label %exit
202
203exit:
204  ret void
205}
206
207; Test LFTR on an IV whose recurrence start is a non-unit pointer type.
208define void @aryptriv([256 x i8]* %base, i32 %n) nounwind {
209entry:
210  %ivstart = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 0
211  %ivend = getelementptr inbounds [256 x i8], [256 x i8]* %base, i32 0, i32 %n
212  %cmp.ph = icmp ult i8* %ivstart, %ivend
213  br i1 %cmp.ph, label %loop, label %exit
214
215; CHECK: loop:
216; CHECK: phi i8*
217; CHECK-NOT: phi
218; CHECK: getelementptr
219; CHECK: store
220; CHECK: icmp ne i8*
221; CHECK: br i1
222loop:
223  %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ]
224  %incdec.ptr = getelementptr inbounds i8, i8* %aptr, i32 1
225  store i8 3, i8* %aptr
226  %cmp = icmp ult i8* %incdec.ptr, %ivend
227  br i1 %cmp, label %loop, label %exit
228
229exit:
230  ret void
231}
232