Commit 361b51c0 by Jeff Law Committed by Jeff Law

tree-ssa-threadupdate.c (struct redirection_data): New field intermediate_edge.


	* tree-ssa-threadupdate.c (struct redirection_data): New field
	intermediate_edge.
	(THREAD_TARGET2): Define.
	(redirection_data_eq): Also check that the intermediate edge is
	equal.
	(lookup_redirection_data): Drop useless argument.  Extract the
	outgoing_edge and intermediate edge from E.  Callers updated.
	(copy_phi_args, update_destination_phis): New functions.
	(fix_duplicate_block_edges): Likewise.
	(create_edge_and_update_destination_phis): Duplicate all the edges
	hung off e->aux.  Use copy_phi_args.
	(create_duplicates): Use fix_duplicate_block_edges.
	(fixup_template_block): Likewise.
	(redirect_edges): If necessary, redirect the joiner block's incoming
	edge to the duplicate of the joiner block.
	(thread_block): Don't muck up loops when threading through a joiner
	block.
	(thread_through_loop_header): Handle threading through a joiner
	block.
	(mark_threaded_blocks, register_jump_thread): Likewise.
	* tree-flow.h (register_jump_thread): Add new argument.  Callers
	updated.
	* tree-ssa-threadedge.c (phi_args_equal_on_edges): New function.
	(thread_across_edge): Handle threading through a joiner block.
	

	
	* gcc.dg/builtin-object-size-1.c: Update to handle changes from
	improved jump threading.
	* gcc.dg/builtin-object-size-2.c: Likewise.
	* gcc.dg/tree-ssa/20030728-1.c: Likewise.

From-SVN: r175114
parent 67a7c837
2011-06-16 Jeff Law <law@redhat.com>
* tree-ssa-threadupdate.c (struct redirection_data): New field
intermediate_edge.
(THREAD_TARGET2): Define.
(redirection_data_eq): Also check that the intermediate edge is
equal.
(lookup_redirection_data): Drop useless argument. Extract the
outgoing_edge and intermediate edge from E. Callers updated.
(copy_phi_args, update_destination_phis): New functions.
(fix_duplicate_block_edges): Likewise.
(create_edge_and_update_destination_phis): Duplicate all the edges
hung off e->aux. Use copy_phi_args.
(create_duplicates): Use fix_duplicate_block_edges.
(fixup_template_block): Likewise.
(redirect_edges): If necessary, redirect the joiner block's incoming
edge to the duplicate of the joiner block.
(thread_block): Don't muck up loops when threading through a joiner
block.
(thread_through_loop_header): Handle threading through a joiner
block.
(mark_threaded_blocks, register_jump_thread): Likewise.
* tree-flow.h (register_jump_thread): Add new argument. Callers
updated.
* tree-ssa-threadedge.c (phi_args_equal_on_edges): New function.
(thread_across_edge): Handle threading through a joiner block.
2011-06-16 Martin Jambor <mjambor@suse.cz>
PR tree-optimization/49343
......@@ -320,7 +347,7 @@
* ddg.c (add_intra_loop_mem_dep): New function.
(build_intra_loop_deps): Call it.
2011-05-06 Jeff Law <law@redhat.com>
2011-06-13 Jeff Law <law@redhat.com>
* df-problems.c (df_lr_local_compute): Manually CSE
PIC_OFFSET_TABLE_REGNUM.
......
2011-06-16 Jeff Law <law@redhat.com>
* gcc.dg/builtin-object-size-1.c: Update to handle chances from
improved jump threading.
* gcc.dg/builtin-object-size-2.c: Likewise.
* gcc.dg/tree-ssa/20030728-1.c: Likewise.
2011-06-16 Janus Weil <janus@gcc.gnu.org>
PR fortran/49074
......
......@@ -64,7 +64,11 @@ test1 (void *q, int x)
r = malloc (30);
else
r = calloc (2, 16);
if (__builtin_object_size (r, 0) != 2 * 16)
/* We may duplicate this test onto the two exit paths. On one path
the size will be 32, the other it will be 30. If we don't duplicate
this test, then the size will be 32. */
if (__builtin_object_size (r, 0) != 2 * 16
&& __builtin_object_size (r, 0) != 30)
abort ();
if (x < 20)
r = malloc (30);
......
......@@ -60,7 +60,11 @@ test1 (void *q, int x)
r = malloc (30);
else
r = calloc (2, 16);
if (__builtin_object_size (r, 1) != 2 * 16)
/* We may duplicate this test onto the two exit paths. On one path
the size will be 32, the other it will be 30. If we don't duplicate
this test, then the size will be 32. */
if (__builtin_object_size (r, 1) != 2 * 16
&& __builtin_object_size (r, 1) != 30)
abort ();
if (x < 20)
r = malloc (30);
......
......@@ -41,7 +41,9 @@ objects_must_conflict_p (t1, t2)
return foo (t2 ? get_alias_set (t2) : 0);
}
/* There should be two assignments of variables to the value zero. */
/* { dg-final { scan-rtl-dump-times "PART.. = 0" 2 "expand"} } */
/* There should be one assignment of variables to the value zero. There
used to be two assignments, but improvements in threading allowed the
second to be propagated into all its uses and eliminated. */
/* { dg-final { scan-rtl-dump-times "PART.. = 0" 1 "expand"} } */
/* { dg-final { cleanup-rtl-dump "expand" } } */
......@@ -808,7 +808,7 @@ bool may_be_nonaddressable_p (tree expr);
/* In tree-ssa-threadupdate.c. */
extern bool thread_through_all_blocks (bool);
extern void register_jump_thread (edge, edge);
extern void register_jump_thread (edge, edge, edge);
/* In gimplify.c */
tree force_gimple_operand_1 (tree, gimple_seq *, gimple_predicate, tree);
......
/* SSA Jump Threading
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Jeff Law <law@redhat.com>
......@@ -652,6 +652,27 @@ thread_around_empty_block (edge taken_edge,
return NULL;
}
/* 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
jump which has a known value when reached via E.
......@@ -770,11 +791,73 @@ thread_across_edge (gimple dummy_cond,
}
remove_temporary_equivalences (stack);
register_jump_thread (e, taken_edge);
register_jump_thread (e, taken_edge, NULL);
return;
}
}
/* We were unable to determine what out edge from E->dest is taken. However,
we might still be able to thread through successors of E->dest. This
often occurs when E->dest is a joiner block which then fans back out
based on redundant tests.
If so, we'll copy E->dest and redirect the appropriate predecessor to
the copy. Within the copy of E->dest, we'll thread one or more edges
to points deeper in the CFG.
This is a stopgap until we have a more structured approach to path
isolation. */
{
edge e2, e3, taken_edge;
edge_iterator ei;
bool found = false;
bitmap visited = BITMAP_ALLOC (NULL);
/* Look at each successor of E->dest to see if we can thread through it. */
FOR_EACH_EDGE (taken_edge, ei, e->dest->succs)
{
/* Avoid threading to any block we have already visited. */
bitmap_clear (visited);
bitmap_set_bit (visited, taken_edge->dest->index);
bitmap_set_bit (visited, e->dest->index);
/* Record whether or not we were able to thread through a successor
of E->dest. */
found = false;
e3 = taken_edge;
do
{
e2 = thread_around_empty_block (e3,
dummy_cond,
handle_dominating_asserts,
simplify,
visited);
if (e2)
{
e3 = e2;
found = true;
}
}
while (e2);
/* If we were able to thread through a successor of E->dest, then
record the jump threading opportunity. */
if (found)
{
edge tmp;
/* If there is already an edge from the block to be duplicated
(E2->src) to the final target (E3->dest), then make sure that
the PHI args associated with the edges E2 and E3 are the
same. */
tmp = find_edge (taken_edge->src, e3->dest);
if (!tmp || phi_args_equal_on_edges (tmp, e3))
register_jump_thread (e, taken_edge, e3);
}
}
BITMAP_FREE (visited);
}
fail:
remove_temporary_equivalences (stack);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment