Commit ea7e6d5a by Aldy Hernandez Committed by Aldy Hernandez

cfg.c: Include tree-flow.h.

        * cfg.c: Include tree-flow.h.
        (remove_edge_raw): Call redirect_edge_var_map_clear.
        (redirect_edge_succ_nodup): Call redirect_edge_var_map_dup.
        * tree-flow-inline.h (redirect_edge_var_map_def): New.
        (redirect_edge_var_map_result): New.
        * tree-cfgcleanup.c (remove_forwarder_block_with_phi): Replace
        PENDING_STMT use with redirect_edge_var_map_*.
        * tree-ssa.c (edge_var_maps): New definition.
        (redirect_edge_var_map_add): New.
        (redirect_edge_var_map_clear): New.
        (redirect_edge_var_map_dup): New.
        (redirect_edge_var_map_vector): New.
        (redirect_edge_var_map_destroy): New.
        (ssa_redirect_edge): Replace PENDING_STMT use with
        redirect_edge_var_map_*.
        (flush_pending_stmts): Same.
        (delete_tree_ssa): Destroy edge var map.
        * tree-flow.h (struct _edge_var_map): New.
        Define edge_var_map vector type.
        Declare redirect_edge_var_map_* prototypes.
        * Makefile.in (cfg.o): Depend on TREE_FLOW_H.
        * tree-cfg.c (reinstall_phi_args): Replace
        PENDING_STMT use with redirect_edge_var_map_*.

From-SVN: r132903
parent a7d95bfe
2008-03-05 Aldy Hernandez <aldyh@redhat.com>
* cfg.c: Include tree-flow.h.
(remove_edge_raw): Call redirect_edge_var_map_clear.
(redirect_edge_succ_nodup): Call redirect_edge_var_map_dup.
* tree-flow-inline.h (redirect_edge_var_map_def): New.
(redirect_edge_var_map_result): New.
* tree-cfgcleanup.c (remove_forwarder_block_with_phi): Replace
PENDING_STMT use with redirect_edge_var_map_*.
* tree-ssa.c (edge_var_maps): New definition.
(redirect_edge_var_map_add): New.
(redirect_edge_var_map_clear): New.
(redirect_edge_var_map_dup): New.
(redirect_edge_var_map_vector): New.
(redirect_edge_var_map_destroy): New.
(ssa_redirect_edge): Replace PENDING_STMT use with
redirect_edge_var_map_*.
(flush_pending_stmts): Same.
(delete_tree_ssa): Destroy edge var map.
* tree-flow.h (struct _edge_var_map): New.
Define edge_var_map vector type.
Declare redirect_edge_var_map_* prototypes.
* Makefile.in (cfg.o): Depend on TREE_FLOW_H.
* tree-cfg.c (reinstall_phi_args): Replace
PENDING_STMT use with redirect_edge_var_map_*.
2008-03-05 Richard Guenther <rguenther@suse.de> 2008-03-05 Richard Guenther <rguenther@suse.de>
PR tree-optimization/35472 PR tree-optimization/35472
......
...@@ -2643,7 +2643,7 @@ auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ ...@@ -2643,7 +2643,7 @@ auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \ cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \
$(REGS_H) hard-reg-set.h output.h toplev.h $(FUNCTION_H) except.h $(GGC_H) \ $(REGS_H) hard-reg-set.h output.h toplev.h $(FUNCTION_H) except.h $(GGC_H) \
$(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h \ $(TM_P_H) $(TIMEVAR_H) $(OBSTACK_H) $(TREE_H) alloc-pool.h \
$(HASHTAB_H) $(DF_H) $(CFGLOOP_H) $(HASHTAB_H) $(DF_H) $(CFGLOOP_H) $(TREE_FLOW_H)
cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(CFGLOOP_H) $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(CFGLOOP_H)
cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
......
...@@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see
#include "alloc-pool.h" #include "alloc-pool.h"
#include "df.h" #include "df.h"
#include "cfgloop.h" #include "cfgloop.h"
#include "tree-flow.h"
/* The obstack on which the flow graph components are allocated. */ /* The obstack on which the flow graph components are allocated. */
...@@ -359,6 +360,9 @@ remove_edge_raw (edge e) ...@@ -359,6 +360,9 @@ remove_edge_raw (edge e)
disconnect_src (e); disconnect_src (e);
disconnect_dest (e); disconnect_dest (e);
/* This is probably not needed, but it doesn't hurt. */
redirect_edge_var_map_clear (e);
free_edge (e); free_edge (e);
} }
...@@ -395,6 +399,7 @@ redirect_edge_succ_nodup (edge e, basic_block new_succ) ...@@ -395,6 +399,7 @@ redirect_edge_succ_nodup (edge e, basic_block new_succ)
s->probability = REG_BR_PROB_BASE; s->probability = REG_BR_PROB_BASE;
s->count += e->count; s->count += e->count;
remove_edge (e); remove_edge (e);
redirect_edge_var_map_dup (s, e);
e = s; e = s;
} }
else else
......
...@@ -3031,24 +3031,28 @@ bsi_insert_on_edge_immediate (edge e, tree stmt) ...@@ -3031,24 +3031,28 @@ bsi_insert_on_edge_immediate (edge e, tree stmt)
static void static void
reinstall_phi_args (edge new_edge, edge old_edge) reinstall_phi_args (edge new_edge, edge old_edge)
{ {
tree var, phi; tree phi;
edge_var_map_vector v;
edge_var_map *vm;
int i;
if (!PENDING_STMT (old_edge)) v = redirect_edge_var_map_vector (old_edge);
if (!v)
return; return;
for (var = PENDING_STMT (old_edge), phi = phi_nodes (new_edge->dest); for (i = 0, phi = phi_nodes (new_edge->dest);
var && phi; VEC_iterate (edge_var_map, v, i, vm) && phi;
var = TREE_CHAIN (var), phi = PHI_CHAIN (phi)) i++, phi = PHI_CHAIN (phi))
{ {
tree result = TREE_PURPOSE (var); tree result = redirect_edge_var_map_result (vm);
tree arg = TREE_VALUE (var); tree arg = redirect_edge_var_map_def (vm);
gcc_assert (result == PHI_RESULT (phi)); gcc_assert (result == PHI_RESULT (phi));
add_phi_arg (phi, arg, new_edge); add_phi_arg (phi, arg, new_edge);
} }
PENDING_STMT (old_edge) = NULL; redirect_edge_var_map_clear (old_edge);
} }
/* Returns the basic block after which the new basic block created /* Returns the basic block after which the new basic block created
......
...@@ -748,7 +748,7 @@ remove_forwarder_block_with_phi (basic_block bb) ...@@ -748,7 +748,7 @@ remove_forwarder_block_with_phi (basic_block bb)
if (phi_alternatives_equal (dest, s, succ)) if (phi_alternatives_equal (dest, s, succ))
{ {
e = redirect_edge_and_branch (e, dest); e = redirect_edge_and_branch (e, dest);
PENDING_STMT (e) = NULL_TREE; redirect_edge_var_map_clear (e);
continue; continue;
} }
...@@ -771,15 +771,18 @@ remove_forwarder_block_with_phi (basic_block bb) ...@@ -771,15 +771,18 @@ remove_forwarder_block_with_phi (basic_block bb)
if (TREE_CODE (def) == SSA_NAME) if (TREE_CODE (def) == SSA_NAME)
{ {
tree var; edge_var_map_vector head;
edge_var_map *vm;
size_t i;
/* If DEF is one of the results of PHI nodes removed during /* If DEF is one of the results of PHI nodes removed during
redirection, replace it with the PHI argument that used redirection, replace it with the PHI argument that used
to be on E. */ to be on E. */
for (var = PENDING_STMT (e); var; var = TREE_CHAIN (var)) head = redirect_edge_var_map_vector (e);
for (i = 0; VEC_iterate (edge_var_map, head, i, vm); ++i)
{ {
tree old_arg = TREE_PURPOSE (var); tree old_arg = redirect_edge_var_map_result (vm);
tree new_arg = TREE_VALUE (var); tree new_arg = redirect_edge_var_map_def (vm);
if (def == old_arg) if (def == old_arg)
{ {
...@@ -792,7 +795,7 @@ remove_forwarder_block_with_phi (basic_block bb) ...@@ -792,7 +795,7 @@ remove_forwarder_block_with_phi (basic_block bb)
add_phi_arg (phi, def, s); add_phi_arg (phi, def, s);
} }
PENDING_STMT (e) = NULL; redirect_edge_var_map_clear (e);
} }
/* Update the dominators. */ /* Update the dominators. */
......
...@@ -1842,4 +1842,20 @@ gimple_mem_ref_stats (const struct function *fn) ...@@ -1842,4 +1842,20 @@ gimple_mem_ref_stats (const struct function *fn)
{ {
return &fn->gimple_df->mem_ref_stats; return &fn->gimple_df->mem_ref_stats;
} }
/* Given an edge_var_map V, return the PHI arg definition. */
static inline tree
redirect_edge_var_map_def (edge_var_map *v)
{
return v->def;
}
/* Given an edge_var_map V, return the PHI result. */
static inline tree
redirect_edge_var_map_result (edge_var_map *v)
{
return v->result;
}
#endif /* _TREE_FLOW_INLINE_H */ #endif /* _TREE_FLOW_INLINE_H */
...@@ -879,7 +879,30 @@ typedef bool (*walk_use_def_chains_fn) (tree, tree, void *); ...@@ -879,7 +879,30 @@ typedef bool (*walk_use_def_chains_fn) (tree, tree, void *);
/* In tree-ssa-alias-warnings.c */ /* In tree-ssa-alias-warnings.c */
extern void strict_aliasing_warning_backend (void); extern void strict_aliasing_warning_backend (void);
/* In tree-ssa.c */ /* In tree-ssa.c */
/* Mapping for redirected edges. */
struct _edge_var_map GTY(())
{
tree result; /* PHI result. */
tree def; /* PHI arg definition. */
};
typedef struct _edge_var_map edge_var_map;
DEF_VEC_O(edge_var_map);
DEF_VEC_ALLOC_O(edge_var_map, heap);
/* A vector of var maps. */
typedef VEC(edge_var_map, heap) *edge_var_map_vector;
extern void redirect_edge_var_map_add (edge, tree, tree);
extern void redirect_edge_var_map_clear (edge);
extern void redirect_edge_var_map_dup (edge, edge);
extern edge_var_map_vector redirect_edge_var_map_vector (edge);
extern void redirect_edge_var_map_destroy (void);
extern void init_tree_ssa (void); extern void init_tree_ssa (void);
extern edge ssa_redirect_edge (edge, basic_block); extern edge ssa_redirect_edge (edge, basic_block);
extern void flush_pending_stmts (edge); extern void flush_pending_stmts (edge);
...@@ -892,6 +915,7 @@ extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool); ...@@ -892,6 +915,7 @@ extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
extern bool stmt_references_memory_p (tree); extern bool stmt_references_memory_p (tree);
extern bool ssa_undefined_value_p (tree); extern bool ssa_undefined_value_p (tree);
/* In tree-into-ssa.c */ /* In tree-into-ssa.c */
void update_ssa (unsigned); void update_ssa (unsigned);
void delete_update_ssa (void); void delete_update_ssa (void);
......
...@@ -45,32 +45,147 @@ along with GCC; see the file COPYING3. If not see ...@@ -45,32 +45,147 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h" #include "tree-pass.h"
#include "toplev.h" #include "toplev.h"
/* Pointer map of variable mappings, keyed by edge. */
static struct pointer_map_t *edge_var_maps;
/* Add a mapping with PHI RESULT and PHI DEF associated with edge E. */
void
redirect_edge_var_map_add (edge e, tree result, tree def)
{
void **slot;
edge_var_map_vector old_head, head;
edge_var_map new_node;
if (edge_var_maps == NULL)
edge_var_maps = pointer_map_create ();
slot = pointer_map_insert (edge_var_maps, e);
old_head = head = *slot;
if (!head)
{
head = VEC_alloc (edge_var_map, heap, 5);
*slot = head;
}
new_node.def = def;
new_node.result = result;
VEC_safe_push (edge_var_map, heap, head, &new_node);
if (old_head != head)
{
/* The push did some reallocation. Update the pointer map. */
*slot = head;
}
}
/* Clear the var mappings in edge E. */
void
redirect_edge_var_map_clear (edge e)
{
void **slot;
edge_var_map_vector head;
if (!edge_var_maps)
return;
slot = pointer_map_contains (edge_var_maps, e);
if (slot)
{
head = *slot;
VEC_free (edge_var_map, heap, head);
*slot = NULL;
}
}
/* Duplicate the redirected var mappings in OLDE in NEWE.
Since we can't remove a mapping, let's just duplicate it. This assumes a
pointer_map can have multiple edges mapping to the same var_map (many to
one mapping), since we don't remove the previous mappings. */
void
redirect_edge_var_map_dup (edge newe, edge olde)
{
void **new_slot, **old_slot; edge_var_map_vector head;
if (!edge_var_maps)
return;
new_slot = pointer_map_insert (edge_var_maps, newe);
old_slot = pointer_map_contains (edge_var_maps, olde);
if (!old_slot)
return;
head = *old_slot;
if (head)
*new_slot = VEC_copy (edge_var_map, heap, head);
else
*new_slot = VEC_alloc (edge_var_map, heap, 5);
}
/* Return the varable mappings for a given edge. If there is none, return
NULL. */
edge_var_map_vector
redirect_edge_var_map_vector (edge e)
{
void **slot;
/* Hey, what kind of idiot would... you'd be surprised. */
if (!edge_var_maps)
return NULL;
slot = pointer_map_contains (edge_var_maps, e);
if (!slot)
return NULL;
return (edge_var_map_vector) *slot;
}
/* Clear the edge variable mappings. */
void
redirect_edge_var_map_destroy (void)
{
if (edge_var_maps)
{
pointer_map_destroy (edge_var_maps);
edge_var_maps = NULL;
}
}
/* Remove the corresponding arguments from the PHI nodes in E's /* Remove the corresponding arguments from the PHI nodes in E's
destination block and redirect it to DEST. Return redirected edge. destination block and redirect it to DEST. Return redirected edge.
The list of removed arguments is stored in PENDING_STMT (e). */ The list of removed arguments is stored in a vector accessed
through edge_var_maps. */
edge edge
ssa_redirect_edge (edge e, basic_block dest) ssa_redirect_edge (edge e, basic_block dest)
{ {
tree phi; tree phi;
tree list = NULL, *last = &list;
tree src, dst, node; redirect_edge_var_map_clear (e);
/* Remove the appropriate PHI arguments in E's destination block. */ /* Remove the appropriate PHI arguments in E's destination block. */
for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi)) for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
{ {
if (PHI_ARG_DEF (phi, e->dest_idx) == NULL_TREE) tree def = PHI_ARG_DEF (phi, e->dest_idx);
if (def == NULL_TREE)
continue; continue;
src = PHI_ARG_DEF (phi, e->dest_idx); redirect_edge_var_map_add (e, PHI_RESULT (phi), def);
dst = PHI_RESULT (phi);
node = build_tree_list (dst, src);
*last = node;
last = &TREE_CHAIN (node);
} }
e = redirect_edge_succ_nodup (e, dest); e = redirect_edge_succ_nodup (e, dest);
PENDING_STMT (e) = list;
return e; return e;
} }
...@@ -81,20 +196,24 @@ ssa_redirect_edge (edge e, basic_block dest) ...@@ -81,20 +196,24 @@ ssa_redirect_edge (edge e, basic_block dest)
void void
flush_pending_stmts (edge e) flush_pending_stmts (edge e)
{ {
tree phi, arg; tree phi;
edge_var_map_vector v;
edge_var_map *vm;
int i;
if (!PENDING_STMT (e)) v = redirect_edge_var_map_vector (e);
if (!v)
return; return;
for (phi = phi_nodes (e->dest), arg = PENDING_STMT (e); for (phi = phi_nodes (e->dest), i = 0;
phi; phi && VEC_iterate (edge_var_map, v, i, vm);
phi = PHI_CHAIN (phi), arg = TREE_CHAIN (arg)) phi = PHI_CHAIN (phi), i++)
{ {
tree def = TREE_VALUE (arg); tree def = redirect_edge_var_map_def (vm);
add_phi_arg (phi, def, e); add_phi_arg (phi, def, e);
} }
PENDING_STMT (e) = NULL; redirect_edge_var_map_clear (e);
} }
/* Return true if SSA_NAME is malformed and mark it visited. /* Return true if SSA_NAME is malformed and mark it visited.
...@@ -920,6 +1039,9 @@ delete_tree_ssa (void) ...@@ -920,6 +1039,9 @@ delete_tree_ssa (void)
delete_mem_ref_stats (cfun); delete_mem_ref_stats (cfun);
cfun->gimple_df = NULL; cfun->gimple_df = NULL;
/* We no longer need the edge variable maps. */
redirect_edge_var_map_destroy ();
} }
/* Helper function for useless_type_conversion_p. */ /* Helper function for useless_type_conversion_p. */
......
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