diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2008-03-05 17:20:26 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2008-03-05 17:20:26 +0000 |
commit | ea7e6d5ae0e3b5d14740bd33d55302a73f6d2b32 (patch) | |
tree | 581bbd0f679ef1aaf0ad42e7d8f0b56620d3e34a /gcc/tree-ssa.c | |
parent | a7d95bfef5d2b7515ca51bfaba63b3ef70452adf (diff) | |
download | gcc-ea7e6d5ae0e3b5d14740bd33d55302a73f6d2b32.zip gcc-ea7e6d5ae0e3b5d14740bd33d55302a73f6d2b32.tar.gz gcc-ea7e6d5ae0e3b5d14740bd33d55302a73f6d2b32.tar.bz2 |
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
Diffstat (limited to 'gcc/tree-ssa.c')
-rw-r--r-- | gcc/tree-ssa.c | 156 |
1 files changed, 139 insertions, 17 deletions
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 6c06df0..a036346 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -45,32 +45,147 @@ along with GCC; see the file COPYING3. If not see #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; } @@ -81,20 +196,24 @@ ssa_redirect_edge (edge e, basic_block dest) 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. @@ -920,6 +1039,9 @@ delete_tree_ssa (void) 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. */ |