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:
parent
c152901f5e
commit
8d34e421a5
@ -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.
|
||||||
|
@ -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
|
||||||
|
11
gcc/testsuite/gcc.c-torture/execute/pr58387.c
Normal file
11
gcc/testsuite/gcc.c-torture/execute/pr58387.c
Normal 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;
|
||||||
|
}
|
@ -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 ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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. */
|
||||||
|
Loading…
Reference in New Issue
Block a user