@@ -232,6 +232,7 @@ static SILInstruction *constantFoldCompare(BuiltinInst *BI,
232
232
return B.createIntegerLiteral (BI->getLoc (), BI->getType (), Res);
233
233
}
234
234
235
+ // Comparisons of an unsigned value with 0.
235
236
SILValue Other;
236
237
auto MatchNonNegative =
237
238
m_BuiltinInst (BuiltinValueKind::AssumeNonNegative, m_ValueBase ());
@@ -259,6 +260,132 @@ static SILInstruction *constantFoldCompare(BuiltinInst *BI,
259
260
return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt (1 , 1 ));
260
261
}
261
262
263
+ // Comparisons with Int.Max.
264
+ IntegerLiteralInst *IntMax;
265
+
266
+ // Check signed comparisons.
267
+ if (match (BI,
268
+ m_CombineOr (
269
+ // Int.max < x
270
+ m_BuiltinInst (BuiltinValueKind::ICMP_SLT,
271
+ m_IntegerLiteralInst (IntMax), m_SILValue (Other)),
272
+ // x > Int.max
273
+ m_BuiltinInst (BuiltinValueKind::ICMP_SGT, m_SILValue (Other),
274
+ m_IntegerLiteralInst (IntMax)))) &&
275
+ IntMax->getValue ().isMaxSignedValue ()) {
276
+ // Any signed number should be <= then IntMax.
277
+ SILBuilderWithScope B (BI);
278
+ return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt ());
279
+ }
280
+
281
+ if (match (BI,
282
+ m_CombineOr (
283
+ m_BuiltinInst (BuiltinValueKind::ICMP_SGE,
284
+ m_IntegerLiteralInst (IntMax), m_SILValue (Other)),
285
+ m_BuiltinInst (BuiltinValueKind::ICMP_SLE, m_SILValue (Other),
286
+ m_IntegerLiteralInst (IntMax)))) &&
287
+ IntMax->getValue ().isMaxSignedValue ()) {
288
+ // Any signed number should be <= then IntMax.
289
+ SILBuilderWithScope B (BI);
290
+ return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt (1 , 1 ));
291
+ }
292
+
293
+ // For any x of the same size as Int.max and n>=1 , (x>>n) is always <= Int.max,
294
+ // that is (x>>n) <= Int.max and Int.max >= (x>>n) are true.
295
+ if (match (BI,
296
+ m_CombineOr (
297
+ // Int.max >= x
298
+ m_BuiltinInst (BuiltinValueKind::ICMP_UGE,
299
+ m_IntegerLiteralInst (IntMax), m_SILValue (Other)),
300
+ // x <= Int.max
301
+ m_BuiltinInst (BuiltinValueKind::ICMP_ULE, m_SILValue (Other),
302
+ m_IntegerLiteralInst (IntMax)),
303
+ // Int.max >= x
304
+ m_BuiltinInst (BuiltinValueKind::ICMP_SGE,
305
+ m_IntegerLiteralInst (IntMax), m_SILValue (Other)),
306
+ // x <= Int.max
307
+ m_BuiltinInst (BuiltinValueKind::ICMP_SLE, m_SILValue (Other),
308
+ m_IntegerLiteralInst (IntMax)))) &&
309
+ IntMax->getValue ().isMaxSignedValue ()) {
310
+ // Check if other is a result of a logical shift right by a strictly
311
+ // positive number of bits.
312
+ IntegerLiteralInst *ShiftCount;
313
+ if (match (Other, m_BuiltinInst (BuiltinValueKind::LShr, m_ValueBase (),
314
+ m_IntegerLiteralInst (ShiftCount))) &&
315
+ ShiftCount->getValue ().isStrictlyPositive ()) {
316
+ SILBuilderWithScope B (BI);
317
+ return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt (1 , 1 ));
318
+ }
319
+ }
320
+
321
+ // At the same time (x>>n) > Int.max and Int.max < (x>>n) is false.
322
+ if (match (BI,
323
+ m_CombineOr (
324
+ // Int.max < x
325
+ m_BuiltinInst (BuiltinValueKind::ICMP_ULT,
326
+ m_IntegerLiteralInst (IntMax), m_SILValue (Other)),
327
+ // x > Int.max
328
+ m_BuiltinInst (BuiltinValueKind::ICMP_UGT, m_SILValue (Other),
329
+ m_IntegerLiteralInst (IntMax)),
330
+ // Int.max < x
331
+ m_BuiltinInst (BuiltinValueKind::ICMP_SLT,
332
+ m_IntegerLiteralInst (IntMax), m_SILValue (Other)),
333
+ // x > Int.max
334
+ m_BuiltinInst (BuiltinValueKind::ICMP_SGT, m_SILValue (Other),
335
+ m_IntegerLiteralInst (IntMax)))) &&
336
+ IntMax->getValue ().isMaxSignedValue ()) {
337
+ // Check if other is a result of a logical shift right by a strictly
338
+ // positive number of bits.
339
+ IntegerLiteralInst *ShiftCount;
340
+ if (match (Other, m_BuiltinInst (BuiltinValueKind::LShr, m_ValueBase (),
341
+ m_IntegerLiteralInst (ShiftCount))) &&
342
+ ShiftCount->getValue ().isStrictlyPositive ()) {
343
+ SILBuilderWithScope B (BI);
344
+ return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt ());
345
+ }
346
+ }
347
+
348
+ // Fold x < 0 into false, if x is known to be a result of an unsigned
349
+ // operation with overflow checks enabled.
350
+ BuiltinInst *BIOp;
351
+ if (match (BI, m_BuiltinInst (BuiltinValueKind::ICMP_SLT,
352
+ m_TupleExtractInst (m_BuiltinInst (BIOp), 0 ),
353
+ m_Zero ()))) {
354
+ // Check if Other is a result of an unsigned operation with overflow.
355
+ switch (BIOp->getBuiltinInfo ().ID ) {
356
+ default :
357
+ break ;
358
+ case BuiltinValueKind::UAddOver:
359
+ case BuiltinValueKind::USubOver:
360
+ case BuiltinValueKind::UMulOver:
361
+ // Was it an operation with an overflow check?
362
+ if (match (BIOp->getOperand (2 ), m_One ())) {
363
+ SILBuilderWithScope B (BI);
364
+ return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt ());
365
+ }
366
+ }
367
+ }
368
+
369
+ // Fold x >= 0 into true, if x is known to be a result of an unsigned
370
+ // operation with overflow checks enabled.
371
+ if (match (BI, m_BuiltinInst (BuiltinValueKind::ICMP_SGE,
372
+ m_TupleExtractInst (m_BuiltinInst (BIOp), 0 ),
373
+ m_Zero ()))) {
374
+ // Check if Other is a result of an unsigned operation with overflow.
375
+ switch (BIOp->getBuiltinInfo ().ID ) {
376
+ default :
377
+ break ;
378
+ case BuiltinValueKind::UAddOver:
379
+ case BuiltinValueKind::USubOver:
380
+ case BuiltinValueKind::UMulOver:
381
+ // Was it an operation with an overflow check?
382
+ if (match (BIOp->getOperand (2 ), m_One ())) {
383
+ SILBuilderWithScope B (BI);
384
+ return B.createIntegerLiteral (BI->getLoc (), BI->getType (), APInt (1 , 1 ));
385
+ }
386
+ }
387
+ }
388
+
262
389
return nullptr ;
263
390
}
264
391
0 commit comments