@@ -1556,9 +1556,63 @@ loop_version (struct loop *loop,
Note down new head as second_head. */
second_head = entry->dest;
- /* Split loop entry edge and insert new block with cond expr. */
- cond_bb = lv_adjust_loop_entry_edge (first_head, second_head,
- entry, cond_expr, then_prob);
+ /* On rtl level support multiple conditions (with logical conjunction
+ between them) organized as an expr_list. */
+ if (current_ir_type () != IR_GIMPLE
+ && GET_CODE ((rtx)cond_expr) == EXPR_LIST)
+ {
+ edge curr_edge;
+ basic_block bb;
+ int num_cond = 0;
+ rtx curr_cond, backward, other_cond;
+
+ /* Reverse condition list. */
+ backward = NULL_RTX;
+ other_cond = (rtx)cond_expr;
+ while (other_cond != NULL_RTX)
+ {
+ backward = gen_rtx_EXPR_LIST (VOIDmode,
+ XEXP (other_cond, 0), backward);
+ other_cond = XEXP (other_cond, 1);
+ num_cond++;
+ }
+ gcc_assert (num_cond > 1);
+
+ /* Create new block to prevent many preheaders. */
+ second_head = split_edge (entry);
+ entry = find_edge (entry->src, second_head);
+
+ /* Starting multi split using the last condition
+ which is first in a reversed list. */
+ cond_bb = lv_adjust_loop_entry_edge (first_head, second_head, entry,
+ XEXP (backward, 0), then_prob);
+ other_cond = XEXP (backward, 1);
+ bb = cond_bb;
+ /* Find edge entering the created bb. */
+ curr_edge = find_edge (entry->src, bb);
+ while (other_cond != NULL_RTX)
+ {
+ curr_cond = XEXP (other_cond, 0);
+ other_cond = XEXP (other_cond, 1);
+ /* Redirect the edge to make it possible to use
+ lv_adjust_loop_entry_edge. */
+ curr_edge = redirect_edge_and_branch (curr_edge, second_head);
+ gcc_assert (curr_edge && curr_edge->src == entry->src);
+
+ /* Split using the next condition is the reversed list.
+ Set 100% probability in all conditions except last. */
+ bb = lv_adjust_loop_entry_edge (bb, second_head, curr_edge,
+ curr_cond, REG_BR_PROB_BASE);
+ /* The next edge to process - to new condition bb. */
+ curr_edge = find_edge (curr_edge->src, bb);
+ gcc_assert (curr_edge && curr_edge->src == entry->src);
+ }
+ }
+ else
+ /* Simply split loop entry edge and insert new block with cond expr. */
+ cond_bb = lv_adjust_loop_entry_edge (first_head, second_head,
+ entry, cond_expr, then_prob);
+
if (condition_bb)
*condition_bb = cond_bb;
@@ -1437,6 +1437,10 @@ fmodulo-sched-allow-regmoves
Common Report Var(flag_modulo_sched_allow_regmoves)
Perform SMS based modulo scheduling with register moves allowed
+fmodulo-sched-insert-infinite-checks
+Common Report Var(flag_modulo_sched_insert_infinite_checks)
+Insert expensive checks for infinite amount of loop iterations while SMS
+
fmove-loop-invariants
Common Report Var(flag_move_loop_invariants) Init(1) Optimization
Move loop invariant computations out of loops
@@ -1994,8 +1994,12 @@ sms_schedule (void)
We want doloops to be scheduled even if analyzis shows they are
nonsimple (backward compatibility). */
nonsimple_loop = !desc->simple_p;
- /* We allow scheduling loop with some assumptions or infinite condition
- only when unsafe_loop_optimizations flag is enabled. */
+ /* Infinite number of iterations condition can be checked at runtime
+ to execute the right version of a loop. But this checks can
+ slow down the program when the loop is inside an outer one.
+ So, we add this checks only when an option is enabled, and allow
+ scheduling loop without adding checks when unsafe_loop_optimizations
+ flag is enabled. */
if (flag_unsafe_loop_optimizations)
{
desc->infinite = NULL_RTX;
@@ -2003,8 +2007,20 @@ sms_schedule (void)
desc->noloop_assumptions = NULL_RTX;
}
nonsimple_loop = nonsimple_loop || (desc->assumptions != NULL_RTX)
- || (desc->noloop_assumptions != NULL_RTX)
- || (desc->infinite != NULL_RTX);
+ || (desc->noloop_assumptions != NULL_RTX);
+ if (!flag_modulo_sched_insert_infinite_checks)
+ nonsimple_loop = nonsimple_loop || (desc->infinite != NULL_RTX);
+ /* Check the form of the infinite condition. */
+ if (!nonsimple_loop && desc->infinite)
+ {
+ rtx r = desc->infinite;
+ while (r && COMPARISON_P (XEXP (r, 0)))
+ {
+ gcc_assert (GET_CODE (r) == EXPR_LIST);
+ r = XEXP (r, 1);
+ }
+ nonsimple_loop = (r != NULL);
+ }
/* Only doloops can be nonsimple_loops for SMS. */
if (nonsimple_loop && !doloop_p)
{
@@ -2142,9 +2158,37 @@ sms_schedule (void)
/* Loop versioning if the number of iterations is unknown. */
unsigned prob;
rtx vers_cond;
- vers_cond = gen_rtx_fmt_ee (GT, VOIDmode, nonsimple_loop ?
- count_reg : desc->niter_expr,
- GEN_INT (stage_count));
+
+ if (desc->infinite)
+ {
+ /* We have to check the number of iterations is non-infinite
+ before comparing it with the number of stages. So, each
+ condition in a desc->infinite expr list (with logical OR)
+ is reversed and add to a new expr list (with logical AND). */
+ rtx r, temp;
+ vers_cond = copy_rtx (desc->infinite);
+ gcc_assert (desc->niter_expr);
+ r = vers_cond;
+ temp = reversed_condition (XEXP(r, 0));
+ gcc_assert(temp);
+ XEXP (r, 0) = temp;
+ while (XEXP (r, 1))
+ {
+ temp = reversed_condition (XEXP(r, 0));
+ gcc_assert(temp);
+ XEXP (r, 0) = temp;
+ r = XEXP (r, 1);
+ }
+ XEXP (r, 1) = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_fmt_ee (GT, VOIDmode,
+ desc->niter_expr,
+ GEN_INT (stage_count)),
+ NULL_RTX);
+ }
+ else /* Condition = (number of iters > number of stages). */
+ vers_cond = gen_rtx_fmt_ee (GT, VOIDmode, nonsimple_loop ?
+ count_reg : desc->niter_expr,
+ GEN_INT (stage_count));
if (dump_file)
{
fprintf (dump_file, "\nLoop versioning condition:\n");