+ /* Only handle relational comparisons, for equality and non-equality
+ we'd have to split the loop into two loops and a middle statement. */
+ switch (code)
+ {
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ break;
+ case NE_EXPR:
+ case EQ_EXPR:
+ /* If the test check for first iteration, we can handle NE/EQ
+ with only one split loop. */
+ if (operand_equal_p (iv->base, iv2.base, 0))
+ {
+ if (code == EQ_EXPR)
+ code = !tree_int_cst_sign_bit (iv->step) ? LE_EXPR : GE_EXPR;
+ else
+ code = !tree_int_cst_sign_bit (iv->step) ? GT_EXPR : LT_EXPR;
+ break;
+ }
+ /* Similarly when the test checks for minimal or maximal
+ value range. */
+ else
+ {
+ int_range<2> r;
+ get_global_range_query ()->range_of_expr (r, op0, stmt);
+ if (!r.varying_p () && !r.undefined_p ()
+ && TREE_CODE (op1) == INTEGER_CST)
+ {
+ wide_int val = wi::to_wide (op1);
+ if (known_eq (val, r.lower_bound ()))
+ {
+ code = (code == EQ_EXPR) ? LE_EXPR : GT_EXPR;
+ break;
+ }
+ else if (known_eq (val, r.upper_bound ()))
+ {
+ code = (code == EQ_EXPR) ? GE_EXPR : LT_EXPR;
+ break;
+ }
+ }
+ }
+ /* TODO: We can compare with exit condition; it seems that testing for
+ last iteration is common case. */
+ return NULL_TREE;
+ default:
+ return NULL_TREE;
+ }
+