@@ -510,10 +510,15 @@ struct RangeOps
510
510
{
511
511
result.lLimit = r1lo;
512
512
}
513
- // Widen Upper Limit => Max(k, (a.len + n)) yields (a.len + n),
514
- // This is correct if k >= 0 and n >= k, since a.len always >= 0
515
- // (a.len + n) could overflow, but the result (a.len + n) also
513
+
514
+ // NOTE: in some of the calculations below, we assume that $bnd is never negative
515
+ // and we have to be careful by not masking possible overflows.
516
+
517
+ // Widen Upper Limit => Max(k, ($bnd + n)) yields ($bnd + n),
518
+ // This is correct if k >= 0 and n >= k, since $bnd always >= 0
519
+ // ($bnd + n) could overflow, but the result ($bnd + n) also
516
520
// preserves the overflow.
521
+ //
517
522
if (r1hi.IsConstant () && r1hi.GetConstant () >= 0 && r2hi.IsBinOpArray () &&
518
523
r2hi.GetConstant () >= r1hi.GetConstant ())
519
524
{
@@ -524,14 +529,38 @@ struct RangeOps
524
529
{
525
530
result.uLimit = r1hi;
526
531
}
532
+
533
+ // Rule: <$bnd + cns1, ...> U <cns2, ...> = <min(cns1, cns2), ...> when cns1 <= 0
534
+ //
535
+ // Example: <$bnd - 3, ...> U <0, ...> = <-3, ...>
536
+ //
537
+ if (r1lo.IsBinOpArray () && r2lo.IsConstant () && (r1lo.cns <= 0 ))
538
+ {
539
+ result.lLimit = Limit (Limit::keConstant, min (r1lo.cns , r2lo.cns ));
540
+ }
541
+ if (r2lo.IsBinOpArray () && r1lo.IsConstant () && (r2lo.cns <= 0 ))
542
+ {
543
+ result.lLimit = Limit (Limit::keConstant, min (r2lo.cns , r1lo.cns ));
544
+ }
545
+
546
+ // Rule: <..., $bnd + cns1> U <..., $bnd + cns2> = <..., $bnd + max(cns1, cns2)>
547
+ //
548
+ // Example: <..., $bnd + 10> U <..., $bnd + 20> = <..., $bnd + 20>
549
+ //
527
550
if (r1hi.IsBinOpArray () && r2hi.IsBinOpArray () && r1hi.vn == r2hi.vn )
528
551
{
529
- result.uLimit = r1hi;
530
- // Widen the upper bound if the other constant is greater.
531
- if (r2hi.GetConstant () > r1hi.GetConstant ())
532
- {
533
- result.uLimit = r2hi;
534
- }
552
+ result.uLimit = r1hi; // copy $bnd and kind info
553
+ result.uLimit .cns = max (r1hi.cns , r2hi.cns );
554
+ }
555
+
556
+ // Rule: <$bnd + cns1, ...> U <$bnd + cns2, ...> = <$bnd + min(cns1, cns2), ...>
557
+ //
558
+ // Example: <$bnd + 10, ...> U <$bnd + 20, ...> = <$bnd + 10, ...>
559
+ //
560
+ if (r1lo.IsBinOpArray () && r2lo.IsBinOpArray () && r1lo.vn == r2lo.vn )
561
+ {
562
+ result.lLimit = r1lo; // copy $bnd and kind info
563
+ result.lLimit .cns = min (r1lo.cns , r2lo.cns );
535
564
}
536
565
return result;
537
566
}
0 commit comments