This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Tree-SSA self checking infrastructure
- From: Andrew MacLeod <amacleod at redhat dot com>
- To: Jeff Law <law at redhat dot com>
- Cc: Jan Hubicka <hubicka at ucw dot cz>, Jan Hubicka <jh at suse dot cz>, gcc mailing list <gcc at gcc dot gnu dot org>
- Date: 19 Nov 2003 14:39:21 -0500
- Subject: Re: Tree-SSA self checking infrastructure
- References: <200311191913.hAJJD6Pa010763@speedy.slc.redhat.com>
On Wed, 2003-11-19 at 14:13, law@redhat.com wrote:
> In message <20031119190649.GQ16923@atrey.karlin.mff.cuni.cz>, Jan Hubicka write
> s:
> >This brings me into questions about my tail call updating code.
> >Perhaps I need to re-do SSA form on call cobbered variables after
> >removing the call?
> Are you changing the CFG? Are you changing the dominator tree? Those
> are the key questions.
>
> >> The exception is the dominator based jump threader where we do rerewrite
> >> existing SSA_NAMEs. In that case we know there are no overlaps as we have
> >> done no optimizations which could have created an overlap.
> >
> >I see. It would be nice to drop a comment somewhere in tree-optimize.c
> >clarifying what can be renamed when.
> Err, I thought there was a comment regarding this issue in the code.
> Regardless, from discussions with Andrew we may have the ability to
> un-ssa specific variables, which would make this a non-issue.
If you want to hack around with it, the following *ought* to get you
what you are looking for. If you can create the var_map like
create_ssa_var_map does to include only the things you are interested
in. (and it ought to include *all* versions of a variable or the live
range stuff wont be right when its coalesced back to the root variable).
The only thing I had to break out was the bits that physically rewrote
the trees.
Your entry point is the function "remove_ssa_form (var_map)"
I'll work through any problems you run into, but thats the basic gist of
what needs to be done.
I haven't run tests or anything on this to make sure I didnt break
anything, but they are running now. I would expect no problems with
existing code, and I would think that if you create a var_map the new
entry point ought to workl just fine. There isnt much new there, so it
should work fine.
Andrew
Index: tree-ssa-live.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-live.h,v
retrieving revision 1.1.2.10
diff -c -p -r1.1.2.10 tree-ssa-live.h
*** tree-ssa-live.h 14 Nov 2003 16:50:02 -0000 1.1.2.10
--- tree-ssa-live.h 19 Nov 2003 19:34:59 -0000
*************** extern void dump_var_map (FILE *, var_ma
*** 62,67 ****
--- 62,68 ----
extern int var_union (var_map, tree, tree);
extern void change_partition_var (var_map, tree, int);
extern void compact_var_map (var_map, int);
+ extern void remove_ssa_form (var_map);
static inline int num_var_partitions (var_map);
static inline tree var_to_partition_to_var (var_map, tree);
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.153
diff -c -p -r1.1.4.153 tree-ssa.c
*** tree-ssa.c 16 Nov 2003 11:00:40 -0000 1.1.4.153
--- tree-ssa.c 19 Nov 2003 19:35:00 -0000
*************** dump_replaceable_exprs (FILE *f, tree *e
*** 2313,2396 ****
}
! /* Take function FNDECL out of SSA form.
!
! PHASE indicates which dump file from the DUMP_FILES array to use when
! dumping debugging information. */
!
! void
! rewrite_out_of_ssa (tree fndecl, enum tree_dump_index phase)
{
basic_block bb;
block_stmt_iterator si;
edge e;
! var_map map;
! tree phi, next;
! elim_graph g;
! tree_live_info_p liveinfo;
! tree *values = NULL;
! int var_flags = 0;
!
! timevar_push (TV_TREE_SSA_TO_NORMAL);
!
! dump_file = dump_begin (phase, &dump_flags);
!
! if (dump_file && (dump_flags & TDF_DETAILS))
! dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
!
! if (flag_tree_ter)
! var_flags = SSA_VAR_MAP_REF_COUNT;
! map = create_ssa_var_map (var_flags);
! eliminate_extraneous_phis (map);
!
! /* Shrink the map to include only referenced variables. */
! if (flag_tree_combine_temps)
! compact_var_map (map, VARMAP_NORMAL);
! else
! compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
!
! if (dump_file && (dump_flags & TDF_DETAILS))
! dump_var_map (dump_file, map);
!
! liveinfo = coalesce_ssa_name (map);
!
! if (dump_file && (dump_flags & TDF_DETAILS))
! {
! fprintf (dump_file, "After Coalescing:\n");
! dump_var_map (dump_file, map);
! }
! if (!flag_tree_combine_temps)
! compact_var_map (map, VARMAP_NORMAL);
!
! /* This is the final var list, so assign real variables to the different
! partitions. */
! assign_vars (map);
!
! if (dump_file && (dump_flags & TDF_DETAILS))
! {
! fprintf (dump_file, "After Root variable replacement:\n");
! dump_var_map (dump_file, map);
! }
!
! if (flag_tree_ter)
! {
! values = find_replaceable_exprs (map);
! if (values && dump_file && (dump_flags & TDF_DETAILS))
! dump_replaceable_exprs (dump_file, values);
! }
!
! if (flag_tree_combine_temps && liveinfo)
! {
! coalesce_vars (map, liveinfo);
! if (dump_file && (dump_flags & TDF_DETAILS))
! {
! fprintf (dump_file, "After variable memory coalescing:\n");
! dump_var_map (dump_file, map);
! }
! }
!
! if (liveinfo)
! delete_tree_live_info (liveinfo);
/* Replace PHI nodes with any required copies. */
g = new_elim_graph (map->num_partitions);
--- 2313,2326 ----
}
! static void
! rewrite_trees (var_map map, tree *values)
{
+ elim_graph g;
basic_block bb;
block_stmt_iterator si;
edge e;
! tree phi;
/* Replace PHI nodes with any required copies. */
g = new_elim_graph (map->num_partitions);
*************** rewrite_out_of_ssa (tree fndecl, enum tr
*** 2460,2480 ****
{
for (e = bb->pred; e; e = e->pred_next)
eliminate_phi (e, phi_arg_from_edge (phi, e), g);
- for ( ; phi; phi = next)
- {
- next = TREE_CHAIN (phi);
- remove_phi_node (phi, NULL_TREE, bb);
- }
}
}
delete_elim_graph (g);
! if (values)
! free (values);
/* If any copies were inserted on edges, actually insert them now. */
bsi_commit_edge_inserts (0, NULL);
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
--- 2390,2524 ----
{
for (e = bb->pred; e; e = e->pred_next)
eliminate_phi (e, phi_arg_from_edge (phi, e), g);
}
}
delete_elim_graph (g);
+ }
+
+ /* Remove the variables specified in a var map from SSA form. */
+ void
+ remove_ssa_form (var_map map)
+ {
+ tree_live_info_p liveinfo;
+ basic_block bb;
+ tree phi, next;
+ FILE *save;
+
+ save = dump_file;
+ dump_file = NULL;
+
+ compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
+ liveinfo = coalesce_ssa_name (map);
+ compact_var_map (map, VARMAP_NORMAL);
+ assign_vars (map);
+ if (liveinfo)
+ delete_tree_live_info (liveinfo);
+ rewrite_trees (map, NULL);
! /* Remove phi nodes which have been translated back to real variables. */
! FOR_EACH_BB (bb)
! {
! for (phi = phi_nodes (bb); phi; phi = next)
! {
! next = TREE_CHAIN (phi);
! if (var_to_partition (map, PHI_RESULT (phi)) != NO_PARTITION)
! remove_phi_node (phi, NULL_TREE, bb);
! }
! }
/* If any copies were inserted on edges, actually insert them now. */
bsi_commit_edge_inserts (0, NULL);
+
+ dump_file = save;
+ }
+
+ /* Take function FNDECL out of SSA form.
+
+ PHASE indicates which dump file from the DUMP_FILES array to use when
+ dumping debugging information. */
+
+ void
+ rewrite_out_of_ssa (tree fndecl, enum tree_dump_index phase)
+ {
+ basic_block bb;
+ var_map map;
+ tree phi, next;
+ tree_live_info_p liveinfo;
+ tree *values = NULL;
+ int var_flags = 0;
+
+ timevar_push (TV_TREE_SSA_TO_NORMAL);
+
+ dump_file = dump_begin (phase, &dump_flags);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
+
+ if (flag_tree_ter)
+ var_flags = SSA_VAR_MAP_REF_COUNT;
+ map = create_ssa_var_map (var_flags);
+ eliminate_extraneous_phis (map);
+
+ /* Shrink the map to include only referenced variables. */
+ if (flag_tree_combine_temps)
+ compact_var_map (map, VARMAP_NORMAL);
+ else
+ compact_var_map (map, VARMAP_NO_SINGLE_DEFS);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ dump_var_map (dump_file, map);
+
+ liveinfo = coalesce_ssa_name (map);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "After Coalescing:\n");
+ dump_var_map (dump_file, map);
+ }
+ if (!flag_tree_combine_temps)
+ compact_var_map (map, VARMAP_NORMAL);
+
+ /* This is the final var list, so assign real variables to the different
+ partitions. */
+ assign_vars (map);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "After Root variable replacement:\n");
+ dump_var_map (dump_file, map);
+ }
+
+ if (flag_tree_ter)
+ {
+ values = find_replaceable_exprs (map);
+ if (values && dump_file && (dump_flags & TDF_DETAILS))
+ dump_replaceable_exprs (dump_file, values);
+ }
+
+ if (flag_tree_combine_temps && liveinfo)
+ {
+ coalesce_vars (map, liveinfo);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "After variable memory coalescing:\n");
+ dump_var_map (dump_file, map);
+ }
+ }
+
+ if (liveinfo)
+ delete_tree_live_info (liveinfo);
+
+ rewrite_trees (map, values);
+
+ FOR_EACH_BB (bb)
+ {
+ for (phi = phi_nodes (bb); phi; phi = next)
+ {
+ next = TREE_CHAIN (phi);
+ remove_phi_node (phi, NULL_TREE, bb);
+ }
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);