mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-28 14:24:43 +08:00
tree-cfg.c (thread_jumps): Use a do-while loop instead of a loop with goto.
* tree-cfg.c (thread_jumps): Use a do-while loop instead of a loop with goto. From-SVN: r89276
This commit is contained in:
parent
e836a5a26a
commit
e61d7b781e
@ -1,3 +1,8 @@
|
||||
2004-10-19 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* tree-cfg.c (thread_jumps): Use a do-while loop instead of a
|
||||
loop with goto.
|
||||
|
||||
2004-10-19 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* expr.c (expand_assignment): Remove the last argument.
|
||||
|
284
gcc/tree-cfg.c
284
gcc/tree-cfg.c
@ -3781,173 +3781,179 @@ thread_jumps (void)
|
||||
FOR_EACH_BB (bb)
|
||||
bb_ann (bb)->forwardable = tree_forwarder_block_p (bb);
|
||||
|
||||
restart:
|
||||
rerun = false;
|
||||
FOR_EACH_BB (bb)
|
||||
do
|
||||
{
|
||||
edge_iterator ei;
|
||||
bool this_jump_threaded = false;
|
||||
|
||||
/* Don't waste time on forwarders. */
|
||||
if (bb_ann (bb)->forwardable)
|
||||
continue;
|
||||
|
||||
/* Examine each of our block's successors to see if it is
|
||||
forwardable. */
|
||||
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
|
||||
rerun = false;
|
||||
FOR_EACH_BB (bb)
|
||||
{
|
||||
int freq;
|
||||
gcov_type count;
|
||||
edge_iterator ei;
|
||||
bool this_jump_threaded = false;
|
||||
|
||||
/* If the edge is abnormal or its destination is not
|
||||
forwardable, then there's nothing to do. */
|
||||
if ((e->flags & EDGE_ABNORMAL)
|
||||
|| !bb_ann (e->dest)->forwardable)
|
||||
/* Don't waste time on forwarders. */
|
||||
if (bb_ann (bb)->forwardable)
|
||||
continue;
|
||||
|
||||
/* Examine each of our block's successors to see if it is
|
||||
forwardable. */
|
||||
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
}
|
||||
int freq;
|
||||
gcov_type count;
|
||||
|
||||
count = e->count;
|
||||
freq = EDGE_FREQUENCY (e);
|
||||
/* If the edge is abnormal or its destination is not
|
||||
forwardable, then there's nothing to do. */
|
||||
if ((e->flags & EDGE_ABNORMAL)
|
||||
|| !bb_ann (e->dest)->forwardable)
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now walk through as many forwarder blocks as possible to
|
||||
find the ultimate destination we want to thread our jump
|
||||
to. */
|
||||
last = EDGE_SUCC (e->dest, 0);
|
||||
bb_ann (e->dest)->forwardable = 0;
|
||||
for (dest = EDGE_SUCC (e->dest, 0)->dest;
|
||||
bb_ann (dest)->forwardable;
|
||||
last = EDGE_SUCC (dest, 0),
|
||||
dest = EDGE_SUCC (dest, 0)->dest)
|
||||
bb_ann (dest)->forwardable = 0;
|
||||
count = e->count;
|
||||
freq = EDGE_FREQUENCY (e);
|
||||
|
||||
/* Reset the forwardable marks to 1. */
|
||||
for (tmp = e->dest;
|
||||
tmp != dest;
|
||||
tmp = EDGE_SUCC (tmp, 0)->dest)
|
||||
bb_ann (tmp)->forwardable = 1;
|
||||
/* Now walk through as many forwarder blocks as possible to
|
||||
find the ultimate destination we want to thread our jump
|
||||
to. */
|
||||
last = EDGE_SUCC (e->dest, 0);
|
||||
bb_ann (e->dest)->forwardable = 0;
|
||||
for (dest = EDGE_SUCC (e->dest, 0)->dest;
|
||||
bb_ann (dest)->forwardable;
|
||||
last = EDGE_SUCC (dest, 0),
|
||||
dest = EDGE_SUCC (dest, 0)->dest)
|
||||
bb_ann (dest)->forwardable = 0;
|
||||
|
||||
if (dest == e->dest)
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
}
|
||||
/* Reset the forwardable marks to 1. */
|
||||
for (tmp = e->dest;
|
||||
tmp != dest;
|
||||
tmp = EDGE_SUCC (tmp, 0)->dest)
|
||||
bb_ann (tmp)->forwardable = 1;
|
||||
|
||||
if (dest == e->dest)
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
}
|
||||
|
||||
old = find_edge (bb, dest);
|
||||
if (old)
|
||||
{
|
||||
/* If there already is an edge, check whether the values
|
||||
in phi nodes differ. */
|
||||
if (!phi_alternatives_equal (dest, last, old))
|
||||
old = find_edge (bb, dest);
|
||||
if (old)
|
||||
{
|
||||
/* The previous block is forwarder. Redirect our jump
|
||||
to that target instead since we know it has no PHI
|
||||
nodes that will need updating. */
|
||||
dest = last->src;
|
||||
|
||||
/* That might mean that no forwarding at all is possible. */
|
||||
if (dest == e->dest)
|
||||
/* If there already is an edge, check whether the values
|
||||
in phi nodes differ. */
|
||||
if (!phi_alternatives_equal (dest, last, old))
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
/* The previous block is forwarder. Redirect our jump
|
||||
to that target instead since we know it has no PHI
|
||||
nodes that will need updating. */
|
||||
dest = last->src;
|
||||
|
||||
/* That might mean that no forwarding at all is
|
||||
possible. */
|
||||
if (dest == e->dest)
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
}
|
||||
|
||||
old = find_edge (bb, dest);
|
||||
}
|
||||
|
||||
old = find_edge (bb, dest);
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform the redirection. */
|
||||
retval = this_jump_threaded = true;
|
||||
old_dest = e->dest;
|
||||
e = redirect_edge_and_branch (e, dest);
|
||||
/* Perform the redirection. */
|
||||
retval = this_jump_threaded = true;
|
||||
old_dest = e->dest;
|
||||
e = redirect_edge_and_branch (e, dest);
|
||||
|
||||
/* Update the profile. */
|
||||
if (profile_status != PROFILE_ABSENT)
|
||||
for (curr = old_dest; curr != dest; curr = EDGE_SUCC (curr, 0)->dest)
|
||||
{
|
||||
curr->frequency -= freq;
|
||||
if (curr->frequency < 0)
|
||||
curr->frequency = 0;
|
||||
curr->count -= count;
|
||||
if (curr->count < 0)
|
||||
curr->count = 0;
|
||||
EDGE_SUCC (curr, 0)->count -= count;
|
||||
if (EDGE_SUCC (curr, 0)->count < 0)
|
||||
EDGE_SUCC (curr, 0)->count = 0;
|
||||
}
|
||||
/* Update the profile. */
|
||||
if (profile_status != PROFILE_ABSENT)
|
||||
for (curr = old_dest;
|
||||
curr != dest;
|
||||
curr = EDGE_SUCC (curr, 0)->dest)
|
||||
{
|
||||
curr->frequency -= freq;
|
||||
if (curr->frequency < 0)
|
||||
curr->frequency = 0;
|
||||
curr->count -= count;
|
||||
if (curr->count < 0)
|
||||
curr->count = 0;
|
||||
EDGE_SUCC (curr, 0)->count -= count;
|
||||
if (EDGE_SUCC (curr, 0)->count < 0)
|
||||
EDGE_SUCC (curr, 0)->count = 0;
|
||||
}
|
||||
|
||||
if (!old)
|
||||
{
|
||||
/* Update PHI nodes. We know that the new argument should
|
||||
have the same value as the argument associated with LAST.
|
||||
Otherwise we would have changed our target block above. */
|
||||
for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
|
||||
if (!old)
|
||||
{
|
||||
arg = phi_arg_from_edge (phi, last);
|
||||
gcc_assert (arg >= 0);
|
||||
add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
|
||||
/* Update PHI nodes. We know that the new argument
|
||||
should have the same value as the argument
|
||||
associated with LAST. Otherwise we would have
|
||||
changed our target block above. */
|
||||
for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
|
||||
{
|
||||
arg = phi_arg_from_edge (phi, last);
|
||||
gcc_assert (arg >= 0);
|
||||
add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the unreachable blocks (observe that if all blocks
|
||||
were reachable before, only those in the path we threaded
|
||||
over and did not have any predecessor outside of the path
|
||||
become unreachable). */
|
||||
for (; old_dest != dest; old_dest = tmp)
|
||||
{
|
||||
tmp = EDGE_SUCC (old_dest, 0)->dest;
|
||||
|
||||
if (EDGE_COUNT (old_dest->preds) > 0)
|
||||
break;
|
||||
|
||||
delete_basic_block (old_dest);
|
||||
}
|
||||
|
||||
/* Update the dominators. */
|
||||
if (dom_info_available_p (CDI_DOMINATORS))
|
||||
{
|
||||
/* If the dominator of the destination was in the path, set its
|
||||
dominator to the start of the redirected edge. */
|
||||
if (get_immediate_dominator (CDI_DOMINATORS, old_dest) == NULL)
|
||||
set_immediate_dominator (CDI_DOMINATORS, old_dest, bb);
|
||||
|
||||
/* Now proceed like if we forwarded just over one edge at a time.
|
||||
Algorithm for forwarding edge S --> A over edge A --> B then
|
||||
is
|
||||
|
||||
if (idom (B) == A
|
||||
&& !dominated_by (S, B))
|
||||
idom (B) = idom (A);
|
||||
recount_idom (A); */
|
||||
|
||||
/* Remove the unreachable blocks (observe that if all blocks
|
||||
were reachable before, only those in the path we threaded
|
||||
over and did not have any predecessor outside of the path
|
||||
become unreachable). */
|
||||
for (; old_dest != dest; old_dest = tmp)
|
||||
{
|
||||
tmp = EDGE_SUCC (old_dest, 0)->dest;
|
||||
|
||||
if (get_immediate_dominator (CDI_DOMINATORS, tmp) == old_dest
|
||||
&& !dominated_by_p (CDI_DOMINATORS, bb, tmp))
|
||||
{
|
||||
dom = get_immediate_dominator (CDI_DOMINATORS, old_dest);
|
||||
set_immediate_dominator (CDI_DOMINATORS, tmp, dom);
|
||||
}
|
||||
if (EDGE_COUNT (old_dest->preds) > 0)
|
||||
break;
|
||||
|
||||
dom = recount_dominator (CDI_DOMINATORS, old_dest);
|
||||
set_immediate_dominator (CDI_DOMINATORS, old_dest, dom);
|
||||
delete_basic_block (old_dest);
|
||||
}
|
||||
|
||||
/* Update the dominators. */
|
||||
if (dom_info_available_p (CDI_DOMINATORS))
|
||||
{
|
||||
/* If the dominator of the destination was in the
|
||||
path, set its dominator to the start of the
|
||||
redirected edge. */
|
||||
if (get_immediate_dominator (CDI_DOMINATORS, old_dest) == NULL)
|
||||
set_immediate_dominator (CDI_DOMINATORS, old_dest, bb);
|
||||
|
||||
/* Now proceed like if we forwarded just over one
|
||||
edge at a time. Algorithm for forwarding edge
|
||||
S --> A over edge A --> B then is
|
||||
|
||||
if (idom (B) == A
|
||||
&& !dominated_by (S, B))
|
||||
idom (B) = idom (A);
|
||||
recount_idom (A); */
|
||||
|
||||
for (; old_dest != dest; old_dest = tmp)
|
||||
{
|
||||
tmp = EDGE_SUCC (old_dest, 0)->dest;
|
||||
|
||||
if (get_immediate_dominator (CDI_DOMINATORS, tmp) == old_dest
|
||||
&& !dominated_by_p (CDI_DOMINATORS, bb, tmp))
|
||||
{
|
||||
dom = get_immediate_dominator (CDI_DOMINATORS, old_dest);
|
||||
set_immediate_dominator (CDI_DOMINATORS, tmp, dom);
|
||||
}
|
||||
|
||||
dom = recount_dominator (CDI_DOMINATORS, old_dest);
|
||||
set_immediate_dominator (CDI_DOMINATORS, old_dest, dom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we succeeded in threading a jump at BB, update the
|
||||
forwardable mark as BB may have become a new forwarder block.
|
||||
This could happen if we have a useless "if" statement whose
|
||||
two arms eventually merge without any intervening
|
||||
statements. */
|
||||
if (this_jump_threaded && tree_forwarder_block_p (bb))
|
||||
bb_ann (bb)->forwardable = rerun = true;
|
||||
/* If we succeeded in threading a jump at BB, update the
|
||||
forwardable mark as BB may have become a new forwarder
|
||||
block. This could happen if we have a useless "if"
|
||||
statement whose two arms eventually merge without any
|
||||
intervening statements. */
|
||||
if (this_jump_threaded && tree_forwarder_block_p (bb))
|
||||
bb_ann (bb)->forwardable = rerun = true;
|
||||
}
|
||||
}
|
||||
if (rerun)
|
||||
goto restart;
|
||||
while (rerun);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user