(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_*.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@132903
138bc75d-0d04-0410-961f-
82ee72b054a4
+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>
PR tree-optimization/35472
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) \
$(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) \
$(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) \
#include "alloc-pool.h"
#include "df.h"
#include "cfgloop.h"
+#include "tree-flow.h"
/* The obstack on which the flow graph components are allocated. */
disconnect_src (e);
disconnect_dest (e);
+ /* This is probably not needed, but it doesn't hurt. */
+ redirect_edge_var_map_clear (e);
+
free_edge (e);
}
s->probability = REG_BR_PROB_BASE;
s->count += e->count;
remove_edge (e);
+ redirect_edge_var_map_dup (s, e);
e = s;
}
else
static void
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;
- for (var = PENDING_STMT (old_edge), phi = phi_nodes (new_edge->dest);
- var && phi;
- var = TREE_CHAIN (var), phi = PHI_CHAIN (phi))
+ for (i = 0, phi = phi_nodes (new_edge->dest);
+ VEC_iterate (edge_var_map, v, i, vm) && phi;
+ i++, phi = PHI_CHAIN (phi))
{
- tree result = TREE_PURPOSE (var);
- tree arg = TREE_VALUE (var);
+ tree result = redirect_edge_var_map_result (vm);
+ tree arg = redirect_edge_var_map_def (vm);
gcc_assert (result == PHI_RESULT (phi));
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
if (phi_alternatives_equal (dest, s, succ))
{
e = redirect_edge_and_branch (e, dest);
- PENDING_STMT (e) = NULL_TREE;
+ redirect_edge_var_map_clear (e);
continue;
}
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
redirection, replace it with the PHI argument that used
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 new_arg = TREE_VALUE (var);
+ tree old_arg = redirect_edge_var_map_result (vm);
+ tree new_arg = redirect_edge_var_map_def (vm);
if (def == old_arg)
{
add_phi_arg (phi, def, s);
}
- PENDING_STMT (e) = NULL;
+ redirect_edge_var_map_clear (e);
}
/* Update the dominators. */
{
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 */
/* In tree-ssa-alias-warnings.c */
extern void strict_aliasing_warning_backend (void);
+
/* 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 edge ssa_redirect_edge (edge, basic_block);
extern void flush_pending_stmts (edge);
extern bool stmt_references_memory_p (tree);
extern bool ssa_undefined_value_p (tree);
+
/* In tree-into-ssa.c */
void update_ssa (unsigned);
void delete_update_ssa (void);
#include "tree-pass.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
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
ssa_redirect_edge (edge e, basic_block dest)
{
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. */
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;
- src = PHI_ARG_DEF (phi, e->dest_idx);
- dst = PHI_RESULT (phi);
- node = build_tree_list (dst, src);
- *last = node;
- last = &TREE_CHAIN (node);
+ redirect_edge_var_map_add (e, PHI_RESULT (phi), def);
}
e = redirect_edge_succ_nodup (e, dest);
- PENDING_STMT (e) = list;
return e;
}
void
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;
- for (phi = phi_nodes (e->dest), arg = PENDING_STMT (e);
- phi;
- phi = PHI_CHAIN (phi), arg = TREE_CHAIN (arg))
+ for (phi = phi_nodes (e->dest), i = 0;
+ phi && VEC_iterate (edge_var_map, v, i, vm);
+ phi = PHI_CHAIN (phi), i++)
{
- tree def = TREE_VALUE (arg);
+ tree def = redirect_edge_var_map_def (vm);
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.
delete_mem_ref_stats (cfun);
cfun->gimple_df = NULL;
+
+ /* We no longer need the edge variable maps. */
+ redirect_edge_var_map_destroy ();
}
/* Helper function for useless_type_conversion_p. */