1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=indvars -S | FileCheck %s
4 ; This tests that the IV is recomputed outside of the loop even when it is known
5 ; to be computed by the loop and used in the loop any way, if it is cheap to do
6 ; so. In the example below the value can be computed outside of the loop,
7 ; and we should do so because after that IV is no longer used outside of
8 ; the loop, which is likely beneficial for vectorization.
10 ; extern void func(unsigned val);
12 ; void test(unsigned m)
16 ; for (int i=0; i<186; i++) {
24 declare void @func(i32)
26 define void @test(i32 %m) nounwind uwtable {
29 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
31 ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
32 ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
33 ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
34 ; CHECK-NEXT: tail call void @func(i32 [[ADD]])
35 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
36 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
37 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
39 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
40 ; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
41 ; CHECK-NEXT: ret void
46 for.body: ; preds = %for.body, %entry
47 %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
48 %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
49 %add = add i32 %a.05, %m
50 tail call void @func(i32 %add)
51 %inc = add nsw i32 %i.06, 1
52 %exitcond = icmp eq i32 %inc, 186
53 br i1 %exitcond, label %for.end, label %for.body
55 for.end: ; preds = %for.body
56 tail call void @func(i32 %add)
60 define i32 @test2(i32 %m) nounwind uwtable {
61 ; CHECK-LABEL: @test2(
63 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
65 ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
66 ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
67 ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
68 ; CHECK-NEXT: tail call void @func(i32 [[ADD]])
69 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
70 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
71 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
73 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
74 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
79 for.body: ; preds = %for.body, %entry
80 %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
81 %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
82 %add = add i32 %a.05, %m
83 tail call void @func(i32 %add)
84 %inc = add nsw i32 %i.06, 1
85 %exitcond = icmp eq i32 %inc, 186
86 br i1 %exitcond, label %for.end, label %for.body
88 for.end: ; preds = %for.body
92 define void @test3(i32 %m) nounwind uwtable {
93 ; CHECK-LABEL: @test3(
95 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
97 ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
98 ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
99 ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
100 ; CHECK-NEXT: tail call void @func(i32 [[ADD]])
101 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
102 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
103 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
105 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
106 ; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
107 ; CHECK-NEXT: ret void
112 for.body: ; preds = %for.body, %entry
113 %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
114 %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
115 %add = add i32 %a.05, %m
122 tail call void @func(i32 %add)
123 %inc = add nsw i32 %i.06, 1
124 %exitcond = icmp eq i32 %inc, 186
125 br i1 %exitcond, label %for.end, label %for.body
127 for.end: ; preds = %for.body
128 tail call void @func(i32 %add)
132 define void @test4(i32 %m) nounwind uwtable {
133 ; CHECK-LABEL: @test4(
135 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
137 ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
138 ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
139 ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
140 ; CHECK-NEXT: tail call void @func(i32 [[ADD]])
141 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
142 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
143 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
145 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
146 ; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD_LCSSA]], 123
147 ; CHECK-NEXT: tail call void @func(i32 [[SOFT_USE]])
148 ; CHECK-NEXT: ret void
153 for.body: ; preds = %for.body, %entry
154 %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
155 %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
156 %add = add i32 %a.05, %m
157 tail call void @func(i32 %add)
158 %inc = add nsw i32 %i.06, 1
159 %exitcond = icmp eq i32 %inc, 186
160 br i1 %exitcond, label %for.end, label %for.body
162 for.end: ; preds = %for.body
163 %soft_use = add i32 %add, 123
164 tail call void @func(i32 %soft_use)
168 define void @test5(i32 %m) nounwind uwtable {
169 ; CHECK-LABEL: @test5(
171 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
173 ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
174 ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
175 ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
176 ; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD]], 123
177 ; CHECK-NEXT: tail call void @func(i32 [[SOFT_USE]])
178 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
179 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
180 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
182 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
183 ; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
184 ; CHECK-NEXT: ret void
189 for.body: ; preds = %for.body, %entry
190 %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
191 %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
192 %add = add i32 %a.05, %m
193 %soft_use = add i32 %add, 123
194 tail call void @func(i32 %soft_use)
195 %inc = add nsw i32 %i.06, 1
196 %exitcond = icmp eq i32 %inc, 186
197 br i1 %exitcond, label %for.end, label %for.body
199 for.end: ; preds = %for.body
200 tail call void @func(i32 %add)
204 define void @test6(i32 %m, ptr %p) nounwind uwtable {
205 ; CHECK-LABEL: @test6(
207 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
209 ; CHECK-NEXT: [[I_06:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
210 ; CHECK-NEXT: [[A_05:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ]
211 ; CHECK-NEXT: [[ADD]] = add i32 [[A_05]], [[M:%.*]]
212 ; CHECK-NEXT: [[SOFT_USE:%.*]] = add i32 [[ADD]], 123
213 ; CHECK-NEXT: [[PIDX:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 [[ADD]]
214 ; CHECK-NEXT: store i32 [[SOFT_USE]], ptr [[PIDX]]
215 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_06]], 1
216 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 186
217 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END:%.*]], label [[FOR_BODY]]
219 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ]
220 ; CHECK-NEXT: tail call void @func(i32 [[ADD_LCSSA]])
221 ; CHECK-NEXT: ret void
226 for.body: ; preds = %for.body, %entry
227 %i.06 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
228 %a.05 = phi i32 [ 0, %entry ], [ %add, %for.body ]
229 %add = add i32 %a.05, %m
230 %soft_use = add i32 %add, 123
231 %pidx = getelementptr i32, ptr %p, i32 %add
232 store i32 %soft_use, ptr %pidx
233 %inc = add nsw i32 %i.06, 1
234 %exitcond = icmp eq i32 %inc, 186
235 br i1 %exitcond, label %for.end, label %for.body
237 for.end: ; preds = %for.body
238 tail call void @func(i32 %add)