Reorganize the analysis of basic block predication.

2010-05-26  Sebastian Pop  <sebastian.pop@amd.com>

	* tree-if-conv.c (add_to_dst_predicate_list): Do not pass a statemet
	iterator in parameter.  Do not generate code during the analysis.
	(tree_if_convert_cond_stmt): Removed.
	(tree_if_convert_stmt): Removed.
	(predicate_bbs): New.
	(if_convertible_loop_p): Call predicate_bbs.
	(tree_if_conversion): Simplify the top-level logic as predicate_bbs
	now contains all the analysis part.

From-SVN: r159886
This commit is contained in:
Sebastian Pop 2010-05-26 16:46:59 +00:00 committed by Sebastian Pop
parent 76b8477663
commit e1449456c0
2 changed files with 161 additions and 163 deletions

View File

@ -1,3 +1,14 @@
2010-05-26 Sebastian Pop <sebastian.pop@amd.com>
* tree-if-conv.c (add_to_dst_predicate_list): Do not pass a statemet
iterator in parameter. Do not generate code during the analysis.
(tree_if_convert_cond_stmt): Removed.
(tree_if_convert_stmt): Removed.
(predicate_bbs): New.
(if_convertible_loop_p): Call predicate_bbs.
(tree_if_conversion): Simplify the top-level logic as predicate_bbs
now contains all the analysis part.
2010-05-26 Sebastian Pop <sebastian.pop@amd.com>
* tree-if-conv.c (tree_if_convert_cond_stmt): Do not remove

View File

@ -147,15 +147,13 @@ add_to_predicate_list (basic_block bb, tree new_cond)
bb->aux = cond;
}
/* Add the condition COND to the previous condition PREV_COND, and add this
to the predicate list of the destination of edge E. GSI is the
place where the gimplification of the resulting condition should
output code. LOOP is the loop to be if-converted. */
/* Add the condition COND to the previous condition PREV_COND, and add
this to the predicate list of the destination of edge E. LOOP is
the loop to be if-converted. */
static tree
add_to_dst_predicate_list (struct loop *loop, edge e,
tree prev_cond, tree cond,
gimple_stmt_iterator *gsi)
tree prev_cond, tree cond)
{
tree new_cond = NULL_TREE;
@ -166,25 +164,13 @@ add_to_dst_predicate_list (struct loop *loop, edge e,
new_cond = unshare_expr (cond);
else
{
tree tmp;
gimple tmp_stmt = NULL;
prev_cond = force_gimple_operand_gsi (gsi, unshare_expr (prev_cond),
true, NULL, true, GSI_SAME_STMT);
cond = force_gimple_operand_gsi (gsi, unshare_expr (cond),
true, NULL, true, GSI_SAME_STMT);
/* Add the condition COND to the e->aux field. In case the edge
destination is a PHI node, this condition will be added to
the block predicate to construct a complete condition. */
e->aux = cond;
tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
unshare_expr (prev_cond), cond);
tmp_stmt = ifc_temp_var (boolean_type_node, tmp);
gsi_insert_before (gsi, tmp_stmt, GSI_SAME_STMT);
new_cond = gimple_assign_lhs (tmp_stmt);
new_cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
unshare_expr (prev_cond), cond);
}
add_to_predicate_list (e->dest, new_cond);
@ -206,84 +192,6 @@ bb_with_exit_edge_p (struct loop *loop, basic_block bb)
return false;
}
/* STMT is a GIMPLE_COND. Update two destination's predicate list.
Otherwise update the exit condition of LOOP appropriately. GSI
points to the statement STMT. */
static void
tree_if_convert_cond_stmt (struct loop *loop, gimple stmt, tree cond,
gimple_stmt_iterator *gsi)
{
tree c2;
edge true_edge, false_edge;
location_t loc = gimple_location (stmt);
tree c = fold_build2_loc (loc, gimple_cond_code (stmt), boolean_type_node,
gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
extract_true_false_edges_from_block (gimple_bb (stmt),
&true_edge, &false_edge);
/* Add new condition into destination's predicate list. */
/* If C is true, then TRUE_EDGE is taken. */
add_to_dst_predicate_list (loop, true_edge, cond, c, gsi);
/* If C is false, then FALSE_EDGE is taken. */
c2 = invert_truthvalue_loc (loc, unshare_expr (c));
add_to_dst_predicate_list (loop, false_edge, cond, c2, gsi);
}
/* If-convert stmt T which is part of LOOP.
For conditional expressions, add a condition in the destination
basic block's predicate list. GSI points to the statement T. */
static tree
tree_if_convert_stmt (struct loop *loop, gimple t, tree cond,
gimple_stmt_iterator *gsi)
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "------if-convert stmt\n");
print_gimple_stmt (dump_file, t, 0, TDF_SLIM);
print_generic_stmt (dump_file, cond, TDF_SLIM);
}
switch (gimple_code (t))
{
/* Labels are harmless here. */
case GIMPLE_LABEL:
break;
case GIMPLE_DEBUG:
/* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */
if (gimple_debug_bind_p (gsi_stmt (*gsi)))
{
gimple_debug_bind_reset_value (gsi_stmt (*gsi));
update_stmt (gsi_stmt (*gsi));
}
break;
case GIMPLE_ASSIGN:
/* This GIMPLE_ASSIGN is killing previous value of LHS. Appropriate
value will be selected by PHI node based on condition. It is possible
that before this transformation, PHI nodes was selecting default
value and now it will use this new value. This is OK because it does
not change the validity of the program. */
break;
case GIMPLE_COND:
tree_if_convert_cond_stmt (loop, t, cond, gsi);
cond = NULL_TREE;
break;
default:
gcc_unreachable ();
}
return cond;
}
/* Return true when PHI is if-convertible. PHI is part of loop LOOP
and it belongs to basic block BB.
@ -560,6 +468,126 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
return blocks;
}
/* Returns true when the analysis of the predicates for all the basic
blocks in LOOP succeeded.
predicate_bbs first clears the ->aux fields of the edges and basic
blocks. These fields are then initialized with the tree
expressions representing the predicates under which a basic block
is executed in the LOOP. As the loop->header is executed at each
iteration, it has the "true" predicate. Other statements executed
under a condition are predicated with that condition, for example
| if (x)
| S1;
| else
| S2;
S1 will be predicated with "x", and S2 will be predicated with
"!x". */
static bool
predicate_bbs (loop_p loop)
{
unsigned int i;
for (i = 0; i < loop->num_nodes; i++)
{
edge e;
edge_iterator ei;
basic_block bb = ifc_bbs [i];
gimple_stmt_iterator itr = gsi_start_phis (bb);
if (!gsi_end_p (itr))
FOR_EACH_EDGE (e, ei, bb->preds)
e->aux = NULL;
bb->aux = NULL;
}
for (i = 0; i < loop->num_nodes; i++)
{
basic_block bb = ifc_bbs [i];
tree cond = (tree) bb->aux;
gimple_stmt_iterator itr;
for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr))
{
gimple stmt = gsi_stmt (itr);
switch (gimple_code (stmt))
{
case GIMPLE_LABEL:
case GIMPLE_ASSIGN:
case GIMPLE_CALL:
break;
case GIMPLE_DEBUG:
/* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */
if (gimple_debug_bind_p (gsi_stmt (itr)))
{
gimple_debug_bind_reset_value (gsi_stmt (itr));
update_stmt (gsi_stmt (itr));
}
break;
case GIMPLE_COND:
{
tree c2;
edge true_edge, false_edge;
location_t loc = gimple_location (stmt);
tree c = fold_build2_loc (loc, gimple_cond_code (stmt),
boolean_type_node,
gimple_cond_lhs (stmt),
gimple_cond_rhs (stmt));
extract_true_false_edges_from_block (gimple_bb (stmt),
&true_edge, &false_edge);
/* Add new condition into destination's predicate list. */
/* If C is true, then TRUE_EDGE is taken. */
add_to_dst_predicate_list (loop, true_edge, cond, c);
/* If C is false, then FALSE_EDGE is taken. */
c2 = invert_truthvalue_loc (loc, unshare_expr (c));
add_to_dst_predicate_list (loop, false_edge, cond, c2);
cond = NULL_TREE;
break;
}
case GIMPLE_SWITCH:
/* Not handled yet in if-conversion. */
return false;
default:
gcc_unreachable ();
}
}
/* If current bb has only one successor, then consider it as an
unconditional goto. */
if (single_succ_p (bb))
{
basic_block bb_n = single_succ (bb);
/* The successor bb inherits the predicate of its
predecessor. If there is no predicate in the predecessor
bb, then consider the successor bb as always executed. */
if (cond == NULL_TREE)
cond = boolean_true_node;
add_to_predicate_list (bb_n, cond);
}
}
/* The loop header is always executed. */
loop->header->aux = boolean_true_node;
return true;
}
/* Return true when LOOP is if-convertible.
LOOP is if-convertible if:
- it is innermost,
@ -571,8 +599,6 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
static bool
if_convertible_loop_p (struct loop *loop)
{
basic_block bb;
gimple_stmt_iterator itr;
unsigned int i;
edge e;
edge_iterator ei;
@ -639,27 +665,30 @@ if_convertible_loop_p (struct loop *loop)
for (i = 0; i < loop->num_nodes; i++)
{
bb = ifc_bbs[i];
basic_block bb = ifc_bbs[i];
if (!if_convertible_bb_p (loop, bb, exit_bb))
return false;
if (bb_with_exit_edge_p (loop, bb))
exit_bb = bb;
}
if (!predicate_bbs (loop))
return false;
for (i = 0; i < loop->num_nodes; i++)
{
basic_block bb = ifc_bbs[i];
gimple_stmt_iterator itr;
for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr))
if (!if_convertible_stmt_p (loop, bb, gsi_stmt (itr)))
return false;
itr = gsi_start_phis (bb);
if (!gsi_end_p (itr))
FOR_EACH_EDGE (e, ei, bb->preds)
e->aux = NULL;
for (; !gsi_end_p (itr); gsi_next (&itr))
for (itr = gsi_start_phis (bb); !gsi_end_p (itr); gsi_next (&itr))
if (!if_convertible_phi_p (loop, bb, gsi_stmt (itr)))
return false;
if (bb_with_exit_edge_p (loop, bb))
exit_bb = bb;
}
if (dump_file)
@ -1030,65 +1059,23 @@ combine_blocks (struct loop *loop)
static void
tree_if_conversion (struct loop *loop)
{
gimple_stmt_iterator itr;
unsigned int i;
ifc_bbs = NULL;
/* If-conversion is not appropriate for all loops. First, check if
the loop is if-convertible. */
if (!if_convertible_loop_p (loop))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "-------------------------\n");
if (ifc_bbs)
{
free (ifc_bbs);
ifc_bbs = NULL;
}
return;
}
goto cleanup;
for (i = 0; i < loop->num_nodes; i++)
{
basic_block bb = ifc_bbs [i];
tree cond = (tree) bb->aux;
/* Predicate basic block(s) with the condition expressions
leading to their execution. */
for (itr = gsi_start_bb (bb); !gsi_end_p (itr); /* empty */)
{
gimple t = gsi_stmt (itr);
cond = tree_if_convert_stmt (loop, t, cond, &itr);
if (!gsi_end_p (itr))
gsi_next (&itr);
}
/* If current bb has only one successor, then consider it as an
unconditional goto. */
if (single_succ_p (bb))
{
basic_block bb_n = single_succ (bb);
/* The successor bb inherits the predicate of its
predecessor. If there is no predicate in the predecessor
bb, then consider the successor bb as always executed. */
if (cond == NULL_TREE)
cond = boolean_true_node;
add_to_predicate_list (bb_n, cond);
}
}
/* Now, all statements are if-converted and basic blocks are
annotated appropriately. Combine all the basic blocks into one
huge basic block. */
/* Now all statements are if-convertible. Combine all the basic
blocks into one huge basic block doing the if-conversion
on-the-fly. */
combine_blocks (loop);
/* clean up */
cleanup:
clean_predicate_lists (loop);
free (ifc_bbs);
ifc_bbs = NULL;
if (ifc_bbs)
{
free (ifc_bbs);
ifc_bbs = NULL;
}
}
/* Tree if-conversion pass management. */