llvm.org GIT mirror llvm / 995a17c
[Tests] Add a few more tests for LoopPredication w/invariant loads Making sure to cover an important legality cornercase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358439 91177308-0d34-0410-b5e6-96231b3b80d8 Philip Reames 5 months ago
1 changed file(s) with 127 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
6464 ret i32 %result
6565 }
6666
67 define i32 @invariant_load(i32* %array, i32* %length, i32 %n) {
68 ; CHECK-LABEL: @invariant_load(
67 define i32 @invariant_load_guard_limit(i32* %array, i32* %length, i32 %n) {
68 ; CHECK-LABEL: @invariant_load_guard_limit(
6969 ; CHECK-NEXT: entry:
7070 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
7171 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
123123 ret i32 %result
124124 }
125125
126 ; This is a case where moving the load which provides the limit for the latch
127 ; would be invalid, so we can't preform the tempting transform. Loading the
128 ; latch limit may fault since we could always fail the guard.
129 define i32 @neg_invariant_load_latch_limit(i32* %array, i32* %length, i32 %n) {
130 ; CHECK-LABEL: @neg_invariant_load_latch_limit(
131 ; CHECK-NEXT: entry:
132 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
133 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
134 ; CHECK: loop.preheader:
135 ; CHECK-NEXT: br label [[LOOP:%.*]]
136 ; CHECK: loop:
137 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
138 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
139 ; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
140 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
141 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]]
142 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
143 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
144 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
145 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
146 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
147 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
148 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0
149 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]]
150 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
151 ; CHECK: exit.loopexit:
152 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
153 ; CHECK-NEXT: br label [[EXIT]]
154 ; CHECK: exit:
155 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
156 ; CHECK-NEXT: ret i32 [[RESULT]]
157 ;
158 entry:
159 %tmp5 = icmp eq i32 %n, 0
160 br i1 %tmp5, label %exit, label %loop.preheader
161
162 loop.preheader:
163 br label %loop
164
165 loop:
166 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
167 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
168 %unknown = load volatile i1, i1* @UNKNOWN
169 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
170 %within.bounds = icmp ult i32 %i, %n
171 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
172
173 %i.i64 = zext i32 %i to i64
174 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
175 %array.i = load i32, i32* %array.i.ptr, align 4
176 %loop.acc.next = add i32 %loop.acc, %array.i
177
178 %i.next = add nuw i32 %i, 1
179 %len = load i32, i32* %length, align 4, !invariant.load !{}
180 %continue = icmp ult i32 %i.next, %len
181 br i1 %continue, label %loop, label %exit
182
183 exit:
184 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
185 ret i32 %result
186 }
187
188 define i32 @invariant_load_latch_limit(i32* %array,
189 ; CHECK-LABEL: @invariant_load_latch_limit(
190 ; CHECK-NEXT: entry:
191 ; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
192 ; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
193 ; CHECK: loop.preheader:
194 ; CHECK-NEXT: br label [[LOOP:%.*]]
195 ; CHECK: loop:
196 ; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
197 ; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
198 ; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN
199 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ]
200 ; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]]
201 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ]
202 ; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64
203 ; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
204 ; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
205 ; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
206 ; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1
207 ; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0
208 ; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]]
209 ; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
210 ; CHECK: exit.loopexit:
211 ; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ]
212 ; CHECK-NEXT: br label [[EXIT]]
213 ; CHECK: exit:
214 ; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
215 ; CHECK-NEXT: ret i32 [[RESULT]]
216 ;
217 i32* dereferenceable(4) %length,
218 i32 %n) {
219 entry:
220 %tmp5 = icmp eq i32 %n, 0
221 br i1 %tmp5, label %exit, label %loop.preheader
222
223 loop.preheader:
224 br label %loop
225
226 loop:
227 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ]
228 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ]
229 %unknown = load volatile i1, i1* @UNKNOWN
230 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ]
231 %within.bounds = icmp ult i32 %i, %n
232 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ]
233
234 %i.i64 = zext i32 %i to i64
235 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
236 %array.i = load i32, i32* %array.i.ptr, align 4
237 %loop.acc.next = add i32 %loop.acc, %array.i
238
239 %i.next = add nuw i32 %i, 1
240 %len = load i32, i32* %length, align 4, !invariant.load !{}
241 %continue = icmp ult i32 %i.next, %len
242 br i1 %continue, label %loop, label %exit
243
244 exit:
245 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ]
246 ret i32 %result
247 }
248
249
250
126251 @Length = external constant i32
127252
128253 define i32 @constant_memory(i32* %array, i32 %n) {