}
}
+/* Given exit condition IV0 CODE IV1 in TYPE, this function adjusts
+ the condition for loop-until-wrap cases. For example:
+ (unsigned){8, -1}_loop < 10 => {0, 1} != 9
+ 10 < (unsigned){0, max - 7}_loop => {0, 1} != 8
+ Return true if condition is successfully adjusted. */
+
+static bool
+adjust_cond_for_loop_until_wrap (tree type, affine_iv *iv0, tree_code *code,
+ affine_iv *iv1)
+{
+ /* Only support simple cases for the moment. */
+ if (TREE_CODE (iv0->base) != INTEGER_CST
+ || TREE_CODE (iv1->base) != INTEGER_CST)
+ return false;
+
+ tree niter_type = unsigned_type_for (type), high, low;
+ /* Case: i-- < 10. */
+ if (integer_zerop (iv1->step))
+ {
+ /* TODO: Should handle case in which abs(step) != 1. */
+ if (!integer_minus_onep (iv0->step))
+ return false;
+ /* Give up on infinite loop. */
+ if (*code == LE_EXPR
+ && tree_int_cst_equal (iv1->base, TYPE_MAX_VALUE (type)))
+ return false;
+ high = fold_build2 (PLUS_EXPR, niter_type,
+ fold_convert (niter_type, iv0->base),
+ build_int_cst (niter_type, 1));
+ low = fold_convert (niter_type, TYPE_MIN_VALUE (type));
+ }
+ else if (integer_zerop (iv0->step))
+ {
+ /* TODO: Should handle case in which abs(step) != 1. */
+ if (!integer_onep (iv1->step))
+ return false;
+ /* Give up on infinite loop. */
+ if (*code == LE_EXPR
+ && tree_int_cst_equal (iv0->base, TYPE_MIN_VALUE (type)))
+ return false;
+ high = fold_convert (niter_type, TYPE_MAX_VALUE (type));
+ low = fold_build2 (MINUS_EXPR, niter_type,
+ fold_convert (niter_type, iv1->base),
+ build_int_cst (niter_type, 1));
+ }
+ else
+ gcc_unreachable ();
+
+ iv0->base = low;
+ iv0->step = fold_convert (niter_type, integer_one_node);
+ iv1->base = high;
+ iv1->step = build_int_cst (niter_type, 0);
+ *code = NE_EXPR;
+ return true;
+}
+
/* Determine the number of iterations according to condition (for staying
inside loop) which compares two induction variables using comparison
operator CODE. The induction variable on left side of the comparison
if (integer_zerop (iv0->step) && integer_zerop (iv1->step))
return false;
- /* Ignore loops of while (i-- < 10) type. */
- if (code != NE_EXPR)
- {
- if (iv0->step && tree_int_cst_sign_bit (iv0->step))
- return false;
-
- if (!integer_zerop (iv1->step) && !tree_int_cst_sign_bit (iv1->step))
- return false;
- }
-
/* If the loop exits immediately, there is nothing to do. */
tree tem = fold_binary (code, boolean_type_node, iv0->base, iv1->base);
if (tem && integer_zerop (tem))
return true;
}
+ /* Handle special case loops: while (i-- < 10) and while (10 < i++) by
+ adjusting iv0, iv1 and code. */
+ if (code != NE_EXPR
+ && (tree_int_cst_sign_bit (iv0->step)
+ || (!integer_zerop (iv1->step)
+ && !tree_int_cst_sign_bit (iv1->step)))
+ && !adjust_cond_for_loop_until_wrap (type, iv0, &code, iv1))
+ return false;
+
/* OK, now we know we have a senseful loop. Handle several cases, depending
on what comparison operator is used. */
bound_difference (loop, iv1->base, iv0->base, &bnds);