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:
Bill Schmidt 2016-11-16 22:17:10 +00:00 committed by William Schmidt
parent a2ea37fb4c
commit 9e16e65681
2 changed files with 59 additions and 4 deletions

View File

@ -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>
* gcc/bb-reorder.c: Remove 'toplev.h' include.

View File

@ -2533,6 +2533,7 @@ version_loop_for_if_conversion (struct loop *loop)
struct loop *new_loop;
gimple *g;
gimple_stmt_iterator gsi;
unsigned int save_length;
g = gimple_build_call_internal (IFN_LOOP_VECTORIZED, 2,
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);
/* Save BB->aux around loop_version as that uses the same field. */
void **saved_preds = XALLOCAVEC (void *, loop->num_nodes);
for (unsigned i = 0; i < loop->num_nodes; i++)
save_length = loop->inner ? loop->inner->num_nodes : loop->num_nodes;
void **saved_preds = XALLOCAVEC (void *, save_length);
for (unsigned i = 0; i < save_length; i++)
saved_preds[i] = ifc_bbs[i]->aux;
initialize_original_copy_tables ();
@ -2550,7 +2552,7 @@ version_loop_for_if_conversion (struct loop *loop)
REG_BR_PROB_BASE, true);
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];
if (new_loop == NULL)
@ -2565,6 +2567,40 @@ version_loop_for_if_conversion (struct loop *loop)
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
if LOOP will not be converted because:
@ -2767,8 +2803,16 @@ tree_if_conversion (struct loop *loop)
|| loop->dont_vectorize))
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)
&& !version_loop_for_if_conversion (loop))
&& !version_loop_for_if_conversion
(versionable_outer_loop_p (loop_outer (loop))
? loop_outer (loop) : loop))
goto cleanup;
/* Now all statements are if-convertible. Combine all the basic