@@ -585,6 +585,89 @@ struct RangeOps
585585 result.uLimit = Limit (Limit::keConstant, -lo);
586586 return result;
587587 }
588+
589+ enum class RelationKind
590+ {
591+ AlwaysTrue,
592+ AlwaysFalse,
593+ Unknown
594+ };
595+
596+ // ------------------------------------------------------------------------
597+ // EvalRelop: Evaluate the relation between two ranges for the given relop
598+ // Example: "x >= y" is AlwaysTrue when "x.LowerLimit() >= y.UpperLimit()"
599+ //
600+ // Arguments:
601+ // relop - The relational operator (LE,LT,GE,GT,EQ,NE)
602+ // isUnsigned - True if the comparison is unsigned
603+ // x - The left range
604+ // y - The right range
605+ //
606+ // Returns:
607+ // AlwaysTrue when the given relop always evaluates to true for the given ranges
608+ // AlwaysFalse when the given relop always evaluates to false for the given ranges
609+ // Otherwise Unknown
610+ //
611+ static RelationKind EvalRelop (const genTreeOps relop, bool isUnsigned, const Range& x, const Range& y)
612+ {
613+ const Limit& xLower = x.LowerLimit ();
614+ const Limit& yLower = y.LowerLimit ();
615+ const Limit& xUpper = x.UpperLimit ();
616+ const Limit& yUpper = y.UpperLimit ();
617+
618+ // For unsigned comparisons, we only support non-negative ranges.
619+ if (isUnsigned)
620+ {
621+ if (!xLower.IsConstant () || !yUpper.IsConstant () || (xLower.GetConstant () < 0 ) ||
622+ (yLower.GetConstant () < 0 ))
623+ {
624+ return RelationKind::Unknown;
625+ }
626+ }
627+
628+ switch (relop)
629+ {
630+ case GT_GE:
631+ case GT_LT:
632+ if (xLower.IsConstant () && yUpper.IsConstant () && (xLower.GetConstant () >= yUpper.GetConstant ()))
633+ {
634+ return relop == GT_GE ? RelationKind::AlwaysTrue : RelationKind::AlwaysFalse;
635+ }
636+
637+ if (xUpper.IsConstant () && yLower.IsConstant () && (xUpper.GetConstant () < yLower.GetConstant ()))
638+ {
639+ return relop == GT_GE ? RelationKind::AlwaysFalse : RelationKind::AlwaysTrue;
640+ }
641+ break ;
642+
643+ case GT_GT:
644+ case GT_LE:
645+ if (xLower.IsConstant () && yUpper.IsConstant () && (xLower.GetConstant () > yUpper.GetConstant ()))
646+ {
647+ return relop == GT_GT ? RelationKind::AlwaysTrue : RelationKind::AlwaysFalse;
648+ }
649+
650+ if (xUpper.IsConstant () && yLower.IsConstant () && (xUpper.GetConstant () <= yLower.GetConstant ()))
651+ {
652+ return relop == GT_GT ? RelationKind::AlwaysFalse : RelationKind::AlwaysTrue;
653+ }
654+ break ;
655+
656+ case GT_EQ:
657+ case GT_NE:
658+ if ((xLower.IsConstant () && yUpper.IsConstant () && (xLower.GetConstant () > yUpper.GetConstant ())) ||
659+ (xUpper.IsConstant () && yLower.IsConstant () && (xUpper.GetConstant () < yLower.GetConstant ())))
660+ {
661+ return relop == GT_EQ ? RelationKind::AlwaysFalse : RelationKind::AlwaysTrue;
662+ }
663+ break ;
664+
665+ default :
666+ assert (!" unknown comparison operator" );
667+ break ;
668+ }
669+ return RelationKind::Unknown;
670+ }
588671};
589672
590673class RangeCheck
0 commit comments