re PR tree-optimization/77848 (Gimple if-conversion results in redundant comparisons)
2016-11-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com> PR tree-optimization/77848 * tree-if-conv.c (version_loop_for_if_conversion): When versioning an outer loop, only save basic block aux information for the inner loop. (versionable_outer_loop_p): New function. (tree_if_conversion): Version the outer loop instead of the inner one if the pattern will be recognized for outer-loop vectorization. From-SVN: r242520
This commit is contained in:
parent
a2ea37fb4c
commit
9e16e65681
|
@ -1,3 +1,14 @@
|
||||||
|
2016-11-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
PR tree-optimization/77848
|
||||||
|
* tree-if-conv.c (version_loop_for_if_conversion): When versioning
|
||||||
|
an outer loop, only save basic block aux information for the inner
|
||||||
|
loop.
|
||||||
|
(versionable_outer_loop_p): New function.
|
||||||
|
(tree_if_conversion): Version the outer loop instead of the inner
|
||||||
|
one if the pattern will be recognized for outer-loop
|
||||||
|
vectorization.
|
||||||
|
|
||||||
2016-11-16 Andrew Burgess <andrew.burgess@embecosm.com>
|
2016-11-16 Andrew Burgess <andrew.burgess@embecosm.com>
|
||||||
|
|
||||||
* gcc/bb-reorder.c: Remove 'toplev.h' include.
|
* gcc/bb-reorder.c: Remove 'toplev.h' include.
|
||||||
|
|
|
@ -2533,6 +2533,7 @@ version_loop_for_if_conversion (struct loop *loop)
|
||||||
struct loop *new_loop;
|
struct loop *new_loop;
|
||||||
gimple *g;
|
gimple *g;
|
||||||
gimple_stmt_iterator gsi;
|
gimple_stmt_iterator gsi;
|
||||||
|
unsigned int save_length;
|
||||||
|
|
||||||
g = gimple_build_call_internal (IFN_LOOP_VECTORIZED, 2,
|
g = gimple_build_call_internal (IFN_LOOP_VECTORIZED, 2,
|
||||||
build_int_cst (integer_type_node, loop->num),
|
build_int_cst (integer_type_node, loop->num),
|
||||||
|
@ -2540,8 +2541,9 @@ version_loop_for_if_conversion (struct loop *loop)
|
||||||
gimple_call_set_lhs (g, cond);
|
gimple_call_set_lhs (g, cond);
|
||||||
|
|
||||||
/* Save BB->aux around loop_version as that uses the same field. */
|
/* Save BB->aux around loop_version as that uses the same field. */
|
||||||
void **saved_preds = XALLOCAVEC (void *, loop->num_nodes);
|
save_length = loop->inner ? loop->inner->num_nodes : loop->num_nodes;
|
||||||
for (unsigned i = 0; i < loop->num_nodes; i++)
|
void **saved_preds = XALLOCAVEC (void *, save_length);
|
||||||
|
for (unsigned i = 0; i < save_length; i++)
|
||||||
saved_preds[i] = ifc_bbs[i]->aux;
|
saved_preds[i] = ifc_bbs[i]->aux;
|
||||||
|
|
||||||
initialize_original_copy_tables ();
|
initialize_original_copy_tables ();
|
||||||
|
@ -2550,7 +2552,7 @@ version_loop_for_if_conversion (struct loop *loop)
|
||||||
REG_BR_PROB_BASE, true);
|
REG_BR_PROB_BASE, true);
|
||||||
free_original_copy_tables ();
|
free_original_copy_tables ();
|
||||||
|
|
||||||
for (unsigned i = 0; i < loop->num_nodes; i++)
|
for (unsigned i = 0; i < save_length; i++)
|
||||||
ifc_bbs[i]->aux = saved_preds[i];
|
ifc_bbs[i]->aux = saved_preds[i];
|
||||||
|
|
||||||
if (new_loop == NULL)
|
if (new_loop == NULL)
|
||||||
|
@ -2565,6 +2567,40 @@ version_loop_for_if_conversion (struct loop *loop)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true when LOOP satisfies the follow conditions that will
|
||||||
|
allow it to be recognized by the vectorizer for outer-loop
|
||||||
|
vectorization:
|
||||||
|
- The loop is not the root node of the loop tree.
|
||||||
|
- The loop has exactly one inner loop.
|
||||||
|
- The loop has a single exit.
|
||||||
|
- The loop header has a single successor, which is the inner
|
||||||
|
loop header.
|
||||||
|
- The loop exit block has a single predecessor, which is the
|
||||||
|
inner loop's exit block. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
versionable_outer_loop_p (struct loop *loop)
|
||||||
|
{
|
||||||
|
if (!loop_outer (loop)
|
||||||
|
|| !loop->inner
|
||||||
|
|| loop->inner->next
|
||||||
|
|| !single_exit (loop)
|
||||||
|
|| !single_succ_p (loop->header)
|
||||||
|
|| single_succ (loop->header) != loop->inner->header)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
basic_block outer_exit = single_pred (loop->latch);
|
||||||
|
basic_block inner_exit = single_pred (loop->inner->latch);
|
||||||
|
|
||||||
|
if (!single_pred_p (outer_exit) || single_pred (outer_exit) != inner_exit)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (dump_file)
|
||||||
|
fprintf (dump_file, "Found vectorizable outer loop for versioning\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Performs splitting of critical edges. Skip splitting and return false
|
/* Performs splitting of critical edges. Skip splitting and return false
|
||||||
if LOOP will not be converted because:
|
if LOOP will not be converted because:
|
||||||
|
|
||||||
|
@ -2767,8 +2803,16 @@ tree_if_conversion (struct loop *loop)
|
||||||
|| loop->dont_vectorize))
|
|| loop->dont_vectorize))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Since we have no cost model, always version loops if vectorization
|
||||||
|
is enabled. Either version this loop, or if the pattern is right
|
||||||
|
for outer-loop vectorization, version the outer loop. In the
|
||||||
|
latter case we will still if-convert the original inner loop. */
|
||||||
|
/* FIXME: When SLP vectorization can handle if-conversion on its own,
|
||||||
|
predicate all of if-conversion on flag_tree_loop_vectorize. */
|
||||||
if ((any_pred_load_store || any_complicated_phi)
|
if ((any_pred_load_store || any_complicated_phi)
|
||||||
&& !version_loop_for_if_conversion (loop))
|
&& !version_loop_for_if_conversion
|
||||||
|
(versionable_outer_loop_p (loop_outer (loop))
|
||||||
|
? loop_outer (loop) : loop))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Now all statements are if-convertible. Combine all the basic
|
/* Now all statements are if-convertible. Combine all the basic
|
||||||
|
|
Loading…
Reference in New Issue