llvm.org GIT mirror llvm / 861388b
[LVI] Make LVI smarter about comparisons with non-constants Make LVI smarter about comparisons with a non-constant. For example, a s< b constraints a to be in [INT_MIN, INT_MAX) range. This is a part of https://llvm.org/bugs/show_bug.cgi?id=28620 fix. Reviewed By: sanjoy Differential Revision: https://reviews.llvm.org/D23205 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278122 91177308-0d34-0410-b5e6-96231b3b80d8 Artur Pilipenko 3 years ago
2 changed file(s) with 153 addition(s) and 24 deletion(s). Raw diff Collapse all Expand all
11961196 Result = LVILatticeVal::getNot(cast(RHS));
11971197 return true;
11981198 }
1199
1200 // Recognize the range checking idiom that InstCombine produces.
1201 // (X+C1) u< C2 --> [-C1, C2-C1)
1202 ConstantInt *Offset = nullptr;
1203 if (Predicate == ICmpInst::ICMP_ULT)
1204 match(LHS, m_Add(m_Specific(Val), m_ConstantInt(Offset)));
1205
1206 ConstantInt *CI = dyn_cast(RHS);
1207 if (CI && (LHS == Val || Offset)) {
1208 // Calculate the range of values that are allowed by the comparison
1209 ConstantRange CmpRange(CI->getValue());
1210
1211 // If we're interested in the false dest, invert the condition
1212 CmpInst::Predicate Pred =
1213 isTrueDest ? Predicate : CmpInst::getInversePredicate(Predicate);
1214 ConstantRange TrueValues =
1215 ConstantRange::makeAllowedICmpRegion(Pred, CmpRange);
1216
1217 if (Offset) // Apply the offset from above.
1218 TrueValues = TrueValues.subtract(Offset->getValue());
1219
1220 Result = LVILatticeVal::getRange(std::move(TrueValues));
1221 return true;
1222 }
1199 }
1200
1201 if (!Val->getType()->isIntegerTy())
1202 return false;
1203
1204 // Use ConstantRange::makeAllowedICmpRegion in order to determine the possible
1205 // range of Val guaranteed by the condition. Recognize comparisons in the from
1206 // of:
1207 // icmp Val, ...
1208 // icmp ult (add Val, Offset), ...
1209 // The latter is the range checking idiom that InstCombine produces. Subtract
1210 // the offset from the allowed range for RHS in this case.
1211
1212 // Val or (add Val, Offset) can be on either hand of the comparison
1213 if (LHS != Val && !match(LHS, m_Add(m_Specific(Val), m_ConstantInt()))) {
1214 std::swap(LHS, RHS);
1215 Predicate = CmpInst::getSwappedPredicate(Predicate);
1216 }
1217
1218 ConstantInt *Offset = nullptr;
1219 if (Predicate == ICmpInst::ICMP_ULT)
1220 match(LHS, m_Add(m_Specific(Val), m_ConstantInt(Offset)));
1221
1222 if (LHS == Val || Offset) {
1223 // Calculate the range of values that are allowed by the comparison
1224 ConstantRange RHSRange(RHS->getType()->getIntegerBitWidth(),
1225 /*isFullSet=*/true);
1226 if (ConstantInt *CI = dyn_cast(RHS))
1227 RHSRange = ConstantRange(CI->getValue());
1228
1229 // If we're interested in the false dest, invert the condition
1230 CmpInst::Predicate Pred =
1231 isTrueDest ? Predicate : CmpInst::getInversePredicate(Predicate);
1232 ConstantRange TrueValues =
1233 ConstantRange::makeAllowedICmpRegion(Pred, RHSRange);
1234
1235 if (Offset) // Apply the offset from above.
1236 TrueValues = TrueValues.subtract(Offset->getValue());
1237
1238 Result = LVILatticeVal::getRange(std::move(TrueValues));
1239 return true;
12231240 }
12241241
12251242 return false;
202202 next:
203203 ret i1 %test
204204 }
205
206 define i32 @test12(i32 %a, i32 %b) {
207 ; CHECK-LABEL: @test12(
208 ; CHECK: then:
209 ; CHECK-NEXT: br i1 false, label %end, label %else
210 %cmp = icmp ult i32 %a, %b
211 br i1 %cmp, label %then, label %else
212
213 then:
214 %dead = icmp eq i32 %a, -1
215 br i1 %dead, label %end, label %else
216
217 else:
218 ret i32 1
219
220 end:
221 ret i32 2
222 }
223
224 define i32 @test12_swap(i32 %a, i32 %b) {
225 ; CHECK-LABEL: @test12_swap(
226 ; CHECK: then:
227 ; CHECK-NEXT: br i1 false, label %end, label %else
228 %cmp = icmp ugt i32 %b, %a
229 br i1 %cmp, label %then, label %else
230
231 then:
232 %dead = icmp eq i32 %a, -1
233 br i1 %dead, label %end, label %else
234
235 else:
236 ret i32 1
237
238 end:
239 ret i32 2
240 }
241
242 define i32 @test12_neg(i32 %a, i32 %b) {
243 ; The same as @test12 but the second check is on the false path
244 ; CHECK-LABEL: @test12_neg(
245 ; CHECK: else:
246 ; CHECK-NEXT: %alive = icmp eq i32 %a, -1
247 %cmp = icmp ult i32 %a, %b
248 br i1 %cmp, label %then, label %else
249
250 else:
251 %alive = icmp eq i32 %a, -1
252 br i1 %alive, label %end, label %then
253
254 then:
255 ret i32 1
256
257 end:
258 ret i32 2
259 }
260
261 define i32 @test12_signed(i32 %a, i32 %b) {
262 ; The same as @test12 but with signed comparison
263 ; CHECK-LABEL: @test12_signed(
264 ; CHECK: then:
265 ; CHECK-NEXT: br i1 false, label %end, label %else
266 %cmp = icmp slt i32 %a, %b
267 br i1 %cmp, label %then, label %else
268
269 then:
270 %dead = icmp eq i32 %a, 2147483647
271 br i1 %dead, label %end, label %else
272
273 else:
274 ret i32 1
275
276 end:
277 ret i32 2
278 }
279
280 define i32 @test13(i32 %a, i32 %b) {
281 ; CHECK-LABEL: @test13(
282 ; CHECK: then:
283 ; CHECK-NEXT: br i1 false, label %end, label %else
284 %a.off = add i32 %a, -8
285 %cmp = icmp ult i32 %a.off, %b
286 br i1 %cmp, label %then, label %else
287
288 then:
289 %dead = icmp eq i32 %a, 7
290 br i1 %dead, label %end, label %else
291
292 else:
293 ret i32 1
294
295 end:
296 ret i32 2
297 }
298
299 define i32 @test13_swap(i32 %a, i32 %b) {
300 ; CHECK-LABEL: @test13_swap(
301 ; CHECK: then:
302 ; CHECK-NEXT: br i1 false, label %end, label %else
303 %a.off = add i32 %a, -8
304 %cmp = icmp ugt i32 %b, %a.off
305 br i1 %cmp, label %then, label %else
306
307 then:
308 %dead = icmp eq i32 %a, 7
309 br i1 %dead, label %end, label %else
310
311 else:
312 ret i32 1
313
314 end:
315 ret i32 2
316 }