pr58387.c: New test.

* gcc.c-torture/execute/pr58387.c: New test.

	* tree-ssa-dom.c (cprop_into_successor_phis): Also propagate
	edge implied equivalences into successor phis.
	* tree-ssa-threadupdate.c (phi_args_equal_on_edges): Moved into
	here from tree-ssa-threadedge.c.
	(mark_threaded_blocks): When threading through a joiner, if both
	successors of the joiner's clone reach the same block, verify the
	PHI arguments are equal.  If not, cancel the jump threading request.
	* tree-ssa-threadedge.c (phi_args_equal_on_edges): Moved into
	tree-ssa-threadupdate.c
	(thread_across_edge): Don't check PHI argument equality when
	threading through joiner block here.

From-SVN: r202660
This commit is contained in:
Jeff Law 2013-09-17 11:27:41 -06:00 committed by Jeff Law
parent c152901f5e
commit 8d34e421a5
6 changed files with 119 additions and 35 deletions

View File

@ -1,3 +1,17 @@
2013-09-17 Jeff Law <law@redhat.com>
* tree-ssa-dom.c (cprop_into_successor_phis): Also propagate
edge implied equivalences into successor phis.
* tree-ssa-threadupdate.c (phi_args_equal_on_edges): Moved into
here from tree-ssa-threadedge.c.
(mark_threaded_blocks): When threading through a joiner, if both
successors of the joiner's clone reach the same block, verify the
PHI arguments are equal. If not, cancel the jump threading request.
* tree-ssa-threadedge.c (phi_args_equal_on_edges): Moved into
tree-ssa-threadupdate.c
(thread_across_edge): Don't check PHI argument equality when
threading through joiner block here.
2013-09-17 Andrew MacLeod <amacleod@redhat.com> 2013-09-17 Andrew MacLeod <amacleod@redhat.com>
* tree-flow.h (ssa_undefined_value_p): Remove prototype. * tree-flow.h (ssa_undefined_value_p): Remove prototype.

View File

@ -1,3 +1,7 @@
2013-09-17 Jeff Law <law@redhat.com>
* gcc.c-torture/execute/pr58387.c: New test.
2013-09-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com> 2013-09-17 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR tree-optimization/58088 PR tree-optimization/58088

View File

@ -0,0 +1,11 @@
extern void abort(void);
int a = -1;
int main ()
{
int b = a == 0 ? 0 : -a;
if (b < 1)
abort ();
return 0;
}

View File

@ -1235,7 +1235,7 @@ record_equivalences_from_incoming_edge (basic_block bb)
/* If the conversion widens the original value and /* If the conversion widens the original value and
the constant is in the range of the type of OLD_RHS, the constant is in the range of the type of OLD_RHS,
then convert the constant and record the equivalence. then convert the constant and record the equivalence.
Note that int_fits_type_p does not check the precision Note that int_fits_type_p does not check the precision
if the upper and lower bounds are OK. */ if the upper and lower bounds are OK. */
@ -1642,6 +1642,28 @@ cprop_into_successor_phis (basic_block bb)
if (gsi_end_p (gsi)) if (gsi_end_p (gsi))
continue; continue;
/* We may have an equivalence associated with this edge. While
we can not propagate it into non-dominated blocks, we can
propagate them into PHIs in non-dominated blocks. */
/* Push the unwind marker so we can reset the const and copies
table back to its original state after processing this edge. */
const_and_copies_stack.safe_push (NULL_TREE);
/* Extract and record any simple NAME = VALUE equivalences.
Don't bother with [01] = COND equivalences, they're not useful
here. */
struct edge_info *edge_info = (struct edge_info *) e->aux;
if (edge_info)
{
tree lhs = edge_info->lhs;
tree rhs = edge_info->rhs;
if (lhs && TREE_CODE (lhs) == SSA_NAME)
record_const_or_copy (lhs, rhs);
}
indx = e->dest_idx; indx = e->dest_idx;
for ( ; !gsi_end_p (gsi); gsi_next (&gsi)) for ( ; !gsi_end_p (gsi); gsi_next (&gsi))
{ {
@ -1667,6 +1689,8 @@ cprop_into_successor_phis (basic_block bb)
&& may_propagate_copy (orig_val, new_val)) && may_propagate_copy (orig_val, new_val))
propagate_value (orig_p, new_val); propagate_value (orig_p, new_val);
} }
restore_vars_to_original_value ();
} }
} }

View File

@ -841,28 +841,6 @@ thread_around_empty_blocks (edge taken_edge,
return false; return false;
} }
/* E1 and E2 are edges into the same basic block. Return TRUE if the
PHI arguments associated with those edges are equal or there are no
PHI arguments, otherwise return FALSE. */
static bool
phi_args_equal_on_edges (edge e1, edge e2)
{
gimple_stmt_iterator gsi;
int indx1 = e1->dest_idx;
int indx2 = e2->dest_idx;
for (gsi = gsi_start_phis (e1->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
if (!operand_equal_p (gimple_phi_arg_def (phi, indx1),
gimple_phi_arg_def (phi, indx2), 0))
return false;
}
return true;
}
/* We are exiting E->src, see if E->dest ends with a conditional /* We are exiting E->src, see if E->dest ends with a conditional
jump which has a known value when reached via E. jump which has a known value when reached via E.
@ -1021,18 +999,9 @@ thread_across_edge (gimple dummy_cond,
record the jump threading opportunity. */ record the jump threading opportunity. */
if (found) if (found)
{ {
edge tmp; propagate_threaded_block_debug_into (path[path.length () - 1]->dest,
/* If there is already an edge from the block to be duplicated taken_edge->dest);
(E2->src) to the final target (E3->dest), then make sure that register_jump_thread (path, true);
the PHI args associated with the edges E2 and E3 are the
same. */
tmp = find_edge (taken_edge->src, path[path.length () - 1]->dest);
if (!tmp || phi_args_equal_on_edges (tmp, path[path.length () - 1]))
{
propagate_threaded_block_debug_into (path[path.length () - 1]->dest,
taken_edge->dest);
register_jump_thread (path, true);
}
} }
path.release(); path.release();

View File

@ -1147,6 +1147,28 @@ fail:
return false; return false;
} }
/* E1 and E2 are edges into the same basic block. Return TRUE if the
PHI arguments associated with those edges are equal or there are no
PHI arguments, otherwise return FALSE. */
static bool
phi_args_equal_on_edges (edge e1, edge e2)
{
gimple_stmt_iterator gsi;
int indx1 = e1->dest_idx;
int indx2 = e2->dest_idx;
for (gsi = gsi_start_phis (e1->dest); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple phi = gsi_stmt (gsi);
if (!operand_equal_p (gimple_phi_arg_def (phi, indx1),
gimple_phi_arg_def (phi, indx2), 0))
return false;
}
return true;
}
/* Walk through the registered jump threads and convert them into a /* Walk through the registered jump threads and convert them into a
form convenient for this pass. form convenient for this pass.
@ -1219,6 +1241,46 @@ mark_threaded_blocks (bitmap threaded_blocks)
} }
} }
/* If we have a joiner block (J) which has two successors S1 and S2 and
we are threading though S1 and the final destination of the thread
is S2, then we must verify that any PHI nodes in S2 have the same
PHI arguments for the edge J->S2 and J->S1->...->S2.
We used to detect this prior to registering the jump thread, but
that prohibits propagation of edge equivalences into non-dominated
PHI nodes as the equivalency test might occur before propagation.
This works for now, but will need improvement as part of the FSA
optimization.
Note since we've moved the thread request data to the edges,
we have to iterate on those rather than the threaded_edges vector. */
EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
{
bb = BASIC_BLOCK (i);
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->aux)
{
bool have_joiner = THREAD_TARGET2 (e) != NULL;
if (have_joiner)
{
basic_block joiner = e->dest;
edge final_edge = THREAD_TARGET2 (e);
basic_block final_dest = final_edge->dest;
edge e2 = find_edge (joiner, final_dest);
if (e2 && !phi_args_equal_on_edges (e2, final_edge))
{
free (e->aux);
e->aux = NULL;
}
}
}
}
}
/* If optimizing for size, only thread through block if we don't have /* If optimizing for size, only thread through block if we don't have
to duplicate it or it's an otherwise empty redirection block. */ to duplicate it or it's an otherwise empty redirection block. */