@@ -524,14 +524,49 @@ struct RangeOps
524524 {
525525 result.uLimit = r1hi;
526526 }
527+
528+ // <$bnd + cns1, ...> U <cns2, ...> = <min(cns1, cns2), ...> when cns1 <= 0
529+ // where "cns1 <= 0" to avoid masking possible overflow.
530+ // We rely on the fact that $bnd is always >= 0.
531+ //
532+ // Example: <$bnd - 3, ...> U <0, ...> = <-3, ...>
533+ if (r1lo.IsBinOpArray () && r2lo.IsConstant () && (r1lo.cns <= 0 ))
534+ {
535+ result.lLimit = Limit (Limit::keConstant, min (r1lo.cns , r2lo.cns ));
536+ }
537+ if (r2lo.IsBinOpArray () && r1lo.IsConstant () && (r2lo.cns <= 0 ))
538+ {
539+ result.lLimit = Limit (Limit::keConstant, min (r2lo.cns , r1lo.cns ));
540+ }
541+
542+ // <$bnd + cns1, ...> U <cns2, ...> = <$bnd + cns1, ...> when cns1 >= cns2
543+ // Possible overflow is preserved in the result.
544+ // We rely on the fact that $bnd is always >= 0.
545+ //
546+ // Example: <$bnd + 10, ...> U <1, ...> = <$bnd + 10, ...>
547+ if (r1lo.IsBinOpArray () && r2lo.IsConstant () && (r1lo.cns >= r2lo.cns ))
548+ {
549+ result.lLimit = r1lo;
550+ }
551+ if (r2lo.IsBinOpArray () && r1lo.IsConstant () && (r2lo.cns >= r1lo.cns ))
552+ {
553+ result.lLimit = r2lo;
554+ }
555+
556+ // <..., $bnd + cns1> U <..., $bnd + cns2> = <..., $bnd + max(cns1, cns2)>
557+ //
558+ // Example: <..., $bnd + 10> U <..., $bnd + 20> = <..., $bnd + 20>
527559 if (r1hi.IsBinOpArray () && r2hi.IsBinOpArray () && r1hi.vn == r2hi.vn )
528560 {
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- }
561+ result.uLimit .cns = max (r1hi.cns , r2hi.cns );
562+ }
563+
564+ // <$bnd + cns1, ...> U <$bnd + cns2, ...> = <$bnd + min(cns1, cns2), ...>
565+ //
566+ // Example: <$bnd + 10, ...> U <$bnd + 20, ...> = <$bnd + 10, ...>
567+ if (r1lo.IsBinOpArray () && r2lo.IsBinOpArray () && r1lo.vn == r2lo.vn )
568+ {
569+ result.lLimit .cns = min (r1lo.cns , r2lo.cns );
535570 }
536571 return result;
537572 }
0 commit comments