public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [RFC] New SSA variable mapping infrastructure
@ 2007-10-03 18:26 Richard Guenther
  2007-10-04  6:27 ` Michael Matz
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Richard Guenther @ 2007-10-03 18:26 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 3268 bytes --]

This is an introduction to the SSA varmap infrastructure.  The
infrastructure was added to address the shortcoming that we only
can remember one user variable (name) per SSA name.  This makes
producing accurate debug information difficult.

Variable mappings build on the requirement to associate user
variables (that is, VAR_DECLs or PARAM_DECLs represented by their UID)
with values that are computed in a program.  In SSA representation
conveniently values can be mapped to SSA names which yields both a
handle for an (unchanging) value and a location for its definition.

SSA names have one associated variable, their SSA_NAME_VAR.  The
ability is added to on demand adding further variables to an SSA name
via a bitmap that is stored in a hashtable mapping SSA name version
to a bitmap of variable UIDs that at some point in the program give
a name to the SSA names value.

Throughout optimization the variable mapping of a SSA name changes
in the following occasions:
 - The SSA name is deleted.  In this case the variable mapping is
   deleted as well.
 - The SSA name is copied to another SSA name.  This relates both
   SSA names and their variable mapping becomes the union of both
   variable mappings.

New SSA names get their variable mappings initialized by either
based off an existing user variable, being initialized by copying
from another SSA name or by being defined as a result of a PHI
operation.  In the latter case its variable mapping is the
intersection of all variable mappings of the PHI arguments.

Unless we start creating/writing debug information for DECLs early,
we need to get hold of the DECLs referenced in the variable mappings.
This is done by a separate hashtable indexed by the DECL uids to not
artificially keep the referenced var list big.

At the time of going out-of SSA we need to attach the variable mapping
to the SSA name defining statement.  This is not yet implemented and
TER may require to attach the information to expression nodes instead.

During RTL optimization a reference or placeholder DECL from the
sets of associated variables will make var-tracking work as before.
Only at the time we write out debug information we will need to go
back to the variable sets and create copies of the variable location
lists for each of the variable in the associated set.  (fingers crossing,
this is all pure speculation)

Note that as opposed to the DEBUG_STMT/INSN approach this is _not_
a way we can conveniently cause values to be preserved that would
otherwise be deleted.

Note that the implementation detail that bitmaps are used is subject
to change dependent on statistical analysis how many variables are
in the mappings for typical programs.  For C I expect this number
to be pretty low making bitmaps a high overhead solution.  For C++
the story may be different.

Note that in the current implementation only the places where we
clearly lose information (DCE of a copy and substituting an inlined
PARAM_DECL for its argument) are "fixed".  The idea is to run a
(yet unimplemented) propagation pass just before out-of SSA instead
of keeping the sets propagated always.

I'll continue working on this, but any comments are welcome.  Please
also consider the different approach from Alexandre.

Thanks,
Richard.

[-- Attachment #2: debug-varmap --]
[-- Type: application/octet-stream, Size: 26237 bytes --]

2007-10-03  Richard Guenther  <rguenther@suse.de>

	* bitmap.h (struct int_bitmap_map): Declare.
	(int_bitmap_map_eq): Likewise.
	(int_bitmap_map_hash): Likewise.
	* bitmap.c (int_bitmap_map_eq): New function.
	(int_bitmap_map_hash): Likewise.
	* function.h (struct function): Add varmap_hash, varmap_vars
	and varmap_obstack members.
	* tree-ssanames.c (release_ssa_name): Call ssa_varmap_release.
	(release_defs): Process a copy for updating variable mappings.
	(ssa_varmap_lookup): New function.
	(ssa_varmap_set): Likewise.
	(ssa_varmap_replace): Likewise.
	(ssa_varmap_release): Likewise.
	(ssa_varmap_add_ref): Likewise.
	(ssa_varmap_get_ref): Likewise.
	(ssa_varmap_process_copy_1): Likewise.
	(ssa_varmap_process_copy): Likewise.
	(ssa_varmap_add_var): Likewise.
	(ssa_varmap_process_phi): Likewise.
	(ssa_varmap_process_all): Likewise.
	(print_ssa_varmap): Likewise.
	* function.c (allocate_struct_function): Initialize varmap members.
	* tree-dfa.c (referenced_var_lookup): Do not ICE on non-existing
	vars.
	* tree-dump.c (struct dump_option_value_in): Add vars modifier.
	* tree-inline.c (setup_one_parameter): Add the decl of the param
	to the argument SSA_NAME varmap.
	* tree-pass.h (TDF_VARS): Define.
	* tree-pretty-print.c (print_varmap): New helper function.
	(dump_generic_node): Call it on defs and return expressions.
	* tree.h (ssa_varmap_lookup): Declare.
	(ssa_varmap_add_ref): Likewise.
	(ssa_varmap_get_ref): Likewise.
	(ssa_varmap_process_copy_1): Likewise.
	(ssa_varmap_process_copy): Likewise.
	(ssa_varmap_add_var): Likewise.
	(ssa_varmap_process_phi): Likewise.
	(ssa_varmap_process_all): Likewise.
	(print_ssa_varmap): Likewise.
	* passes.c (execute_function_todo): Print variable mapping
	info if requested.

Index: trunk/gcc/bitmap.c
===================================================================
*** trunk.orig/gcc/bitmap.c	2007-10-03 13:15:56.000000000 +0200
--- trunk/gcc/bitmap.c	2007-10-03 13:47:01.000000000 +0200
*************** bitmap_hash (const_bitmap head)
*** 1969,1972 ****
--- 1969,1988 ----
    return (hashval_t)hash;
  }
  
+ /* Equality function for uid to bitmap map.  */
+ 
+ int int_bitmap_map_eq (const void *va, const void *vb)
+ {
+   const struct int_bitmap_map *a = (const struct int_bitmap_map *) va;
+   const struct int_bitmap_map *b = (const struct int_bitmap_map *) vb;
+   return (a->uid == b->uid);
+ }
+ 
+ /* Hash value for uid to bitmap map.  */
+ 
+ unsigned int int_bitmap_map_hash (const void *item)
+ {
+   return ((const struct int_bitmap_map *)item)->uid;
+ }
+ 
  #include "gt-bitmap.h"
Index: trunk/gcc/bitmap.h
===================================================================
*** trunk.orig/gcc/bitmap.h	2007-10-03 13:12:04.000000000 +0200
--- trunk/gcc/bitmap.h	2007-10-03 13:46:31.000000000 +0200
*************** bmp_iter_and_compl (bitmap_iterator *bi,
*** 580,583 ****
--- 580,591 ----
         bmp_iter_and_compl (&(ITER), &(BITNUM));				\
         bmp_iter_next (&(ITER), &(BITNUM)))
  
+ struct int_bitmap_map {
+   int uid;
+   bitmap map;
+ };
+ 
+ int int_bitmap_map_eq (const void *va, const void *vb);
+ unsigned int int_bitmap_map_hash (const void *item);
+ 
  #endif /* GCC_BITMAP_H */
Index: trunk/gcc/function.h
===================================================================
*** trunk.orig/gcc/function.h	2007-10-03 12:05:54.000000000 +0200
--- trunk/gcc/function.h	2007-10-03 19:05:02.000000000 +0200
*************** along with GCC; see the file COPYING3.  
*** 23,28 ****
--- 23,29 ----
  
  #include "tree.h"
  #include "hashtab.h"
+ #include "bitmap.h"
  
  /* Stack of pending (incomplete) sequences saved by `start_sequence'.
     Each element describes one pending sequence.
*************** struct function GTY(())
*** 322,327 ****
--- 323,336 ----
    /* The variables unexpanded so far.  */
    tree unexpanded_var_list;
  
+   /* The mapping of SSA_NAMEs to user variables.  The varmap hashtable is
+      indexed by the SSA_NAME version and contains bitmaps that contain
+      variable declaration UIDs allocated from the varmap obstack.
+      The vars hashtable keeps a reference to all used DECLs.  */
+   htab_t GTY((skip)) varmap_hash;
+   htab_t GTY((param_is (struct int_tree_map))) varmap_vars;
+   bitmap_obstack varmap_obstack;
+ 
    /* Assembly labels for the hot and cold text sections, to
       be used by debugger functions for determining the size of text
       sections.  */
Index: trunk/gcc/tree-ssanames.c
===================================================================
*** trunk.orig/gcc/tree-ssanames.c	2007-10-03 12:05:34.000000000 +0200
--- trunk/gcc/tree-ssanames.c	2007-10-03 19:20:45.000000000 +0200
*************** along with GCC; see the file COPYING3.  
*** 26,31 ****
--- 26,32 ----
  #include "ggc.h"
  #include "tree-flow.h"
  #include "tree-pass.h"
+ #include "diagnostic.h"
  
  /* Rewriting a function into SSA form can create a huge number of SSA_NAMEs,
     many of which may be thrown away shortly after their creation if jumps
*************** unsigned int ssa_name_nodes_reused;
*** 67,72 ****
--- 68,75 ----
  unsigned int ssa_name_nodes_created;
  #endif
  
+ static void ssa_varmap_release (tree var);
+ 
  /* Initialize management of SSA_NAMEs.  */
  
  void
*************** release_ssa_name (tree var)
*** 177,182 ****
--- 180,188 ----
    if (!var)
      return;
  
+   /* Remove variable mapping for this name.  */
+   ssa_varmap_release (var);
+ 
    /* Never release the default definition for a symbol.  It's a
       special SSA name that should always exist once it's created.  */
    if (SSA_NAME_IS_DEFAULT_DEF (var))
*************** release_defs (tree stmt)
*** 290,295 ****
--- 296,307 ----
       to garbage.  */
    gcc_assert (gimple_in_ssa_p (cfun));
  
+   /* If this was a copy stmt, save what the lhs knows about variables.  */
+   if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+       && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
+       && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME)
+     ssa_varmap_process_copy (stmt);
+ 
    FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
      if (TREE_CODE (def) == SSA_NAME)
        release_ssa_name (def);
*************** replace_ssa_name_symbol (tree ssa_name, 
*** 305,310 ****
--- 317,682 ----
    TREE_TYPE (ssa_name) = TREE_TYPE (sym);
  }
  
+ bitmap
+ ssa_varmap_lookup (tree name)
+ {
+   struct int_bitmap_map x;
+   struct int_bitmap_map **loc;
+ 
+   x.uid = SSA_NAME_VERSION (name);
+   loc = (struct int_bitmap_map **)
+ 	htab_find_slot_with_hash (cfun->varmap_hash, &x,
+  				  SSA_NAME_VERSION (name), NO_INSERT);
+   if (!loc)
+     return NULL;
+   return (*loc)->map;
+ }
+ 
+ static void
+ ssa_varmap_set (tree name, bitmap map)
+ {
+   struct int_bitmap_map x;
+   struct int_bitmap_map **loc;
+ 
+   x.uid = SSA_NAME_VERSION (name);
+   loc = (struct int_bitmap_map **)
+ 	htab_find_slot_with_hash (cfun->varmap_hash, &x,
+  				  SSA_NAME_VERSION (name), INSERT);
+   if (!*loc)
+     {
+       /* ???  We need to free this memory somewhere.  */
+       *loc = XNEW (struct int_bitmap_map);
+       (*loc)->uid = SSA_NAME_VERSION (name);
+     }
+   /* ???  If we had a reference counter on bitmaps we could eventually
+      free the old (*loc)->map.  */
+   (*loc)->map = map;
+ }
+ 
+ static void
+ ssa_varmap_replace (tree name, bitmap map)
+ {
+   struct int_bitmap_map x;
+   struct int_bitmap_map **loc;
+ 
+   x.uid = SSA_NAME_VERSION (name);
+   loc = (struct int_bitmap_map **)
+ 	htab_find_slot_with_hash (cfun->varmap_hash, &x,
+  				  SSA_NAME_VERSION (name), INSERT);
+   if (!*loc)
+     {
+       /* ???  We need to free this memory somewhere.  */
+       *loc = XNEW (struct int_bitmap_map);
+       (*loc)->uid = SSA_NAME_VERSION (name);
+       (*loc)->map = BITMAP_ALLOC (&cfun->varmap_obstack);
+     }
+   bitmap_copy ((*loc)->map, map);
+ }
+ 
+ /* Releases the variable mapping information for SSA_NAME var.  */
+ 
+ static void
+ ssa_varmap_release (tree var)
+ {
+   struct int_bitmap_map x;
+   struct int_bitmap_map **loc;
+ 
+   x.uid = SSA_NAME_VERSION (var);
+   loc = (struct int_bitmap_map **)
+ 	htab_find_slot_with_hash (cfun->varmap_hash, &x,
+  				  SSA_NAME_VERSION (var), NO_INSERT);
+   if (loc)
+     htab_remove_elt_with_hash (cfun->varmap_hash, &x, SSA_NAME_VERSION (var));
+ }
+ 
+ /* Reference the variable VAR used in variable mappings.
+    ???  Do this only if creating debug information.  */
+ 
+ void
+ ssa_varmap_add_ref (tree var)
+ {
+   struct int_tree_map in;
+   struct int_tree_map **loc;
+ 
+   in.uid = DECL_UID (var);
+   in.to = var;
+   loc = (struct int_tree_map **)
+ 	htab_find_slot_with_hash (cfun->varmap_vars, &in,
+ 				  DECL_UID (var), INSERT);
+   if (*loc)
+     return;
+ 
+   *loc = GGC_NEW (struct int_tree_map);
+   (*loc)->uid = DECL_UID (var);
+   (*loc)->to = var;
+ }
+ 
+ /* Get hands on the DECL stored by UID.  */
+ 
+ tree
+ ssa_varmap_get_ref (int uid)
+ {
+   struct int_tree_map in;
+   struct int_tree_map **loc;
+ 
+   in.uid = uid;
+   loc = (struct int_tree_map **)
+ 	htab_find_slot_with_hash (cfun->varmap_vars, &in,
+ 				  uid, NO_INSERT);
+   if (!loc)
+     return referenced_var (uid);
+ 
+   return (*loc)->to;
+ }
+ 
+ /* Update the two SSA_NAMEs variable map appearing in the copy
+    relation LHS = RHS.  */
+ 
+ void
+ ssa_varmap_process_copy_1 (tree lhs, tree rhs)
+ {
+   bitmap lhs_vars, rhs_vars;
+ 
+   if (dump_file && dump_flags & TDF_VARS)
+     {
+       fprintf (dump_file, "Processing copy relation ");
+       print_generic_expr (dump_file, lhs, 0);
+       fprintf (dump_file, " = ");
+       print_generic_expr (dump_file, rhs, 0);
+       fprintf (dump_file, "\n");
+     }
+ 
+   /* We cannot blindly exchange an artificial vars ssa_name variable
+      with another as this may create overlapping life-ranges.  So we
+      also cannot assume that artificial vars do not have a variable map.  */
+ 
+   /* Instead we merge variable maps if available or add the variable
+      uids of non-artificial variables to the maps.  */
+   lhs_vars = ssa_varmap_lookup (lhs);
+   rhs_vars = ssa_varmap_lookup (rhs);
+   if (lhs_vars && rhs_vars)
+     {
+       bitmap_ior_into (lhs_vars, rhs_vars);
+       ssa_varmap_set (rhs, lhs_vars);
+     }
+   else if (lhs_vars
+ 	   && !rhs_vars && !DECL_ARTIFICIAL (SSA_NAME_VAR (rhs)))
+     {
+       bitmap_set_bit (lhs_vars, DECL_UID (SSA_NAME_VAR (rhs)));
+       ssa_varmap_set (rhs, lhs_vars);
+     }
+   else if (!lhs_vars && !DECL_ARTIFICIAL (SSA_NAME_VAR (lhs))
+ 	   && rhs_vars)
+     {
+       bitmap_set_bit (rhs_vars, DECL_UID (SSA_NAME_VAR (lhs)));
+       ssa_varmap_set (lhs, rhs_vars);
+     }
+   else if (SSA_NAME_VAR (lhs) != SSA_NAME_VAR (rhs)
+ 	   && !DECL_ARTIFICIAL (SSA_NAME_VAR (rhs))
+ 	   && !DECL_ARTIFICIAL (SSA_NAME_VAR (lhs)))
+     {
+       bitmap tmp = BITMAP_ALLOC (&cfun->varmap_obstack);
+       bitmap_set_bit (tmp, DECL_UID (SSA_NAME_VAR (lhs)));
+       bitmap_set_bit (tmp, DECL_UID (SSA_NAME_VAR (rhs)));
+       ssa_varmap_set (lhs, tmp);
+       ssa_varmap_set (rhs, tmp);
+     }
+ }
+ 
+ /* Update the two SSA_NAMEs variable map appearing in the copy
+    relation STMT.  */
+ 
+ void
+ ssa_varmap_process_copy (tree stmt)
+ {
+   gcc_assert (gimple_in_ssa_p (cfun)
+ 	      && TREE_CODE (stmt) == GIMPLE_MODIFY_STMT);
+ 
+   ssa_varmap_process_copy_1 (GIMPLE_STMT_OPERAND (stmt, 0),
+ 			     GIMPLE_STMT_OPERAND (stmt, 1));
+ }
+ 
+ /* Add a single variable VAR to the mapping of SSA_NAME NAME.  */
+ 
+ void
+ ssa_varmap_add_var (tree name, tree var)
+ {
+   bitmap lhs_vars;
+ 
+   if (dump_file && dump_flags & TDF_VARS)
+     {
+       fprintf (dump_file, "Adding variable ");
+       print_generic_expr (dump_file, var, 0);
+       fprintf (dump_file, " to SSA_NAME ");
+       print_generic_expr (dump_file, name, 0);
+       fprintf (dump_file, " map\n");
+     }
+ 
+   if (DECL_ARTIFICIAL (var))
+     return;
+ 
+   lhs_vars = ssa_varmap_lookup (name);
+   if (lhs_vars)
+     bitmap_set_bit (lhs_vars, DECL_UID (var));
+   else if (SSA_NAME_VAR (name) != var)
+     {
+       bitmap tmp = BITMAP_ALLOC (&cfun->varmap_obstack);
+       if (!DECL_ARTIFICIAL (SSA_NAME_VAR (name)))
+         bitmap_set_bit (tmp, DECL_UID (SSA_NAME_VAR (name)));
+       bitmap_set_bit (tmp, DECL_UID (var));
+       ssa_varmap_set (name, tmp);
+     }
+ 
+   ssa_varmap_add_ref (var);
+ }
+ 
+ /* Update the PHI_RESULTs variable map of STMT based on the PHI arguments.  */
+ 
+ void
+ ssa_varmap_process_phi (tree stmt)
+ {
+   tree lhs;
+   bitmap arg_vars;
+   bitmap tmp;
+   ssa_op_iter i;
+   use_operand_p use;
+   bool first_p;
+ 
+   gcc_assert (gimple_in_ssa_p (cfun)
+ 	      && TREE_CODE (stmt) == PHI_NODE);
+ 
+   if (MTAG_P (SSA_NAME_VAR (PHI_RESULT (stmt))))
+     return;
+ 
+   /* A PHI nodes result represents the intersection of all decls of
+      the PHI arguments.  */
+   tmp = BITMAP_ALLOC (&cfun->varmap_obstack);
+   first_p = true;
+   FOR_EACH_PHI_ARG (use, stmt, i, SSA_OP_USE)
+     {
+       tree op = USE_FROM_PTR (use);
+ 
+       /* Look up vars for the argument.  If it is the first variable
+ 	 we visit, initialize the temporary map with its map.  */
+       arg_vars = ssa_varmap_lookup (op);
+       if (arg_vars)
+         {
+ 	  if (first_p)
+ 	    bitmap_copy (tmp, arg_vars);
+ 	  else
+ 	    bitmap_and_into (tmp, arg_vars);
+ 	}
+       else
+ 	{
+ 	  if (first_p
+ 	      && !DECL_ARTIFICIAL (SSA_NAME_VAR (op)))
+ 	    bitmap_set_bit (tmp, DECL_UID (SSA_NAME_VAR (op)));
+ 	  else if (!bitmap_bit_p (tmp, DECL_UID (SSA_NAME_VAR (op))))
+ 	    {
+ 	      bitmap_clear (tmp);
+ 	      break;
+ 	    }
+ 	}
+ 
+       if (bitmap_empty_p (tmp))
+         break;
+       first_p = false;
+     }
+ 
+   /* Clearing the PHI results bit first makes the following easier.  */
+   lhs = PHI_RESULT (stmt);
+   bitmap_clear_bit (tmp, DECL_UID (SSA_NAME_VAR (lhs)));
+ 
+   /* The result is now the argument intersection.  If that is empty
+      there is nothing to do.  */
+   if (bitmap_empty_p (tmp))
+     {
+       BITMAP_FREE (tmp);
+       return;
+     }
+ 
+   /* Otherwise re-add the UID from the PHI result var and replace the
+      map.  Note this by purpose affects all shared copies.  */
+   if (!DECL_ARTIFICIAL (SSA_NAME_VAR (lhs)))
+     bitmap_set_bit (tmp, DECL_UID (SSA_NAME_VAR (lhs)));
+   ssa_varmap_replace (lhs, tmp);
+   BITMAP_FREE (tmp);
+ }
+ 
+ /* Scan all stmts in a function, updating and propagating variable
+    maps.
+    ???  We want to do this in dominator order.  */
+ 
+ void
+ ssa_varmap_process_all (void)
+ {
+   basic_block bb;
+ 
+   FOR_EACH_BB (bb)
+     {
+       block_stmt_iterator bsi;
+       tree phi;
+ 
+       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+         ssa_varmap_process_phi (phi);
+ 
+       for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+         {
+           tree stmt = bsi_stmt (bsi);
+           if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+               && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
+               && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME)
+             ssa_varmap_process_copy (stmt);
+         }
+     }
+ }
+ 
+ /* Print variable maps to FILE.  */
+ 
+ void
+ print_ssa_varmap (FILE *file)
+ {
+   int live_ssa_names = 0, with_map = 0, max_vars = 0, total_vars = 0;
+   unsigned int i;
+ 
+   fprintf (file, "\nSSA variable maps:\n");
+   for (i = 0; i < num_ssa_names; ++i)
+     {
+       tree name = ssa_name (i);
+       int n = 0;
+       bitmap_iterator bi;
+       unsigned int i;
+       bitmap vars;
+       if (!name)
+         continue;
+       live_ssa_names++;
+       vars = ssa_varmap_lookup (name);
+       if (!vars)
+         continue;
+       with_map++;
+       fprintf (file, "  ");
+       print_generic_expr (file, name, 0);
+       fprintf (file, ": ");
+       EXECUTE_IF_SET_IN_BITMAP (vars, 0, i, bi)
+ 	{
+ 	  tree var = ssa_varmap_get_ref (i);
+ 	  n++;
+ 	  if (var)
+ 	    print_generic_expr (file, var, 0);
+ 	  else
+ 	    fprintf (file, "%u", i);
+ 	  fprintf (file, " ");
+ 	}
+       total_vars += n;
+       if (n > max_vars)
+ 	max_vars = n;
+       fprintf (file, "\n");
+     }
+   fprintf (file, "%d SSA_NAMEs, %d with variable map\n"
+ 	   "with average %.3f variables (%d max)\n\n", live_ssa_names,
+ 	   with_map, total_vars / (float)with_map, max_vars);
+ }
+ 
  /* Return SSA names that are unused to GGC memory.  This is used to keep
     footprint of compiler during interprocedural optimization.
     As a side effect the SSA_NAME_VERSION number reuse is reduced
Index: trunk/gcc/function.c
===================================================================
*** trunk.orig/gcc/function.c	2007-10-03 13:58:15.000000000 +0200
--- trunk/gcc/function.c	2007-10-03 19:21:27.000000000 +0200
*************** along with GCC; see the file COPYING3.  
*** 65,70 ****
--- 65,71 ----
  #include "df.h"
  #include "timevar.h"
  #include "vecprim.h"
+ #include "tree-flow.h"
  
  #ifndef LOCAL_ALIGNMENT
  #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
*************** allocate_struct_function (tree fndecl)
*** 3911,3916 ****
--- 3912,3924 ----
        /* Assume all registers in stdarg functions need to be saved.  */
        cfun->va_list_gpr_size = VA_LIST_MAX_GPR_SIZE;
        cfun->va_list_fpr_size = VA_LIST_MAX_FPR_SIZE;
+ 
+       /* Initialize the variable mapping.  */
+       bitmap_obstack_initialize (&cfun->varmap_obstack);
+       cfun->varmap_hash = htab_create (7, int_bitmap_map_hash,
+ 				       int_bitmap_map_eq, NULL);
+       cfun->varmap_vars = htab_create_ggc (7, int_tree_map_hash,
+ 					   int_tree_map_eq, NULL);
      }
  
    invoke_set_current_function_hook (fndecl);
Index: trunk/gcc/tree-dfa.c
===================================================================
*** trunk.orig/gcc/tree-dfa.c	2007-10-03 14:36:30.000000000 +0200
--- trunk/gcc/tree-dfa.c	2007-10-03 14:36:47.000000000 +0200
*************** referenced_var_lookup (unsigned int uid)
*** 639,645 ****
    in.uid = uid;
    h = (struct int_tree_map *)
  	htab_find_with_hash (gimple_referenced_vars (cfun), &in, uid);
!   gcc_assert (h || uid == 0);
    if (h)
      return h->to;
    return NULL_TREE;
--- 639,645 ----
    in.uid = uid;
    h = (struct int_tree_map *)
  	htab_find_with_hash (gimple_referenced_vars (cfun), &in, uid);
!   /* ???  gcc_assert (h || uid == 0); */
    if (h)
      return h->to;
    return NULL_TREE;
Index: trunk/gcc/tree-dump.c
===================================================================
*** trunk.orig/gcc/tree-dump.c	2007-10-03 13:59:43.000000000 +0200
--- trunk/gcc/tree-dump.c	2007-10-03 14:00:32.000000000 +0200
*************** static const struct dump_option_value_in
*** 825,830 ****
--- 825,831 ----
    {"uid", TDF_UID},
    {"stmtaddr", TDF_STMTADDR},
    {"memsyms", TDF_MEMSYMS},
+   {"vars", TDF_VARS},
    {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA 
  	    | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC)},
    {NULL, 0}
Index: trunk/gcc/tree-inline.c
===================================================================
*** trunk.orig/gcc/tree-inline.c	2007-10-03 15:47:28.000000000 +0200
--- trunk/gcc/tree-inline.c	2007-10-03 18:22:48.000000000 +0200
*************** setup_one_parameter (copy_body_data *id,
*** 1458,1463 ****
--- 1458,1473 ----
  	  || is_gimple_min_invariant (rhs))
        && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def))
      {
+ #if 0
+       /* This doesn't work as the SSA_NAMEs are from two different functions.
+ 	 ???  Add a cfun parameter to all ssa_varmap functions.  */
+       if (TREE_CODE (rhs) == SSA_NAME)
+ 	ssa_varmap_process_copy_1 (def, rhs);
+ #endif
+       /* This remembers the parameters name but loses its variable mapping
+ 	 from inside the inlined function.  */
+       if (TREE_CODE (rhs) == SSA_NAME)
+ 	ssa_varmap_add_var (rhs, SSA_NAME_VAR (def));
        insert_decl_map (id, def, rhs);
        return;
      }
Index: trunk/gcc/tree-into-ssa.c
===================================================================
*** trunk.orig/gcc/tree-into-ssa.c	2007-10-03 14:40:49.000000000 +0200
--- trunk/gcc/tree-into-ssa.c	2007-10-03 15:42:52.000000000 +0200
*************** rewrite_into_ssa (void)
*** 2293,2298 ****
--- 2293,2301 ----
  
    fini_ssa_renamer ();
  
+   /* Update variable maps.
+   ssa_varmap_process_all (); */
+ 
    timevar_pop (TV_TREE_SSA_OTHER);
    return 0;
  }
Index: trunk/gcc/tree-pass.h
===================================================================
*** trunk.orig/gcc/tree-pass.h	2007-10-03 13:58:37.000000000 +0200
--- trunk/gcc/tree-pass.h	2007-10-03 13:59:38.000000000 +0200
*************** enum tree_dump_index
*** 73,78 ****
--- 73,80 ----
  #define TDF_DIAGNOSTIC	(1 << 15)	/* A dump to be put in a diagnostic
  					   message.  */
  
+ #define TDF_VARS	(1 << 16)	/* Dump variable mappings.  */
+ 
  extern char *get_dump_file_name (enum tree_dump_index);
  extern int dump_enabled_p (enum tree_dump_index);
  extern int dump_initialized_p (enum tree_dump_index);
Index: trunk/gcc/tree-pretty-print.c
===================================================================
*** trunk.orig/gcc/tree-pretty-print.c	2007-10-03 14:00:44.000000000 +0200
--- trunk/gcc/tree-pretty-print.c	2007-10-03 15:42:15.000000000 +0200
*************** dump_symbols (pretty_printer *buffer, bi
*** 435,440 ****
--- 435,467 ----
  }
  
  
+ static void
+ print_varmap (pretty_printer *buffer, tree name, int spc, int flags)
+ {
+   bitmap vars;
+   bitmap_iterator bi;
+   unsigned int i;
+ 
+   if (DECL_ARTIFICIAL (SSA_NAME_VAR (name)))
+     return;
+ 
+   vars = ssa_varmap_lookup (name);
+   if (!vars)
+     return;
+ 
+   pp_string (buffer, "\t{ ");
+   EXECUTE_IF_SET_IN_BITMAP (vars, 0, i, bi)
+     {
+       tree var = referenced_var (i);
+       if (var)
+ 	dump_generic_node (buffer, var, spc, flags, false);
+       else
+ 	pp_string (buffer, "[optimized out]");
+       pp_space (buffer);
+     }
+   pp_character (buffer, '}');
+ }
+ 
  /* Dump the node NODE on the pretty_printer BUFFER, SPC spaces of indent.
     FLAGS specifies details to show in the dump (see TDF_* in tree-pass.h).
     If IS_STMT is true, the object printed is considered to be a statement
*************** dump_generic_node (pretty_printer *buffe
*** 1099,1104 ****
--- 1126,1135 ----
        pp_space (buffer);
        dump_generic_node (buffer, GENERIC_TREE_OPERAND (node, 1), spc, flags,
  	  		 false);
+       if (flags & TDF_VARS
+ 	  && TREE_CODE (node) == GIMPLE_MODIFY_STMT
+ 	  && TREE_CODE (GIMPLE_STMT_OPERAND (node, 0)) == SSA_NAME)
+ 	print_varmap (buffer, GIMPLE_STMT_OPERAND (node, 0), spc, flags);
        break;
  
      case TARGET_EXPR:
*************** dump_generic_node (pretty_printer *buffe
*** 1594,1603 ****
  	  pp_space (buffer);
  	  if (TREE_CODE (op0) == MODIFY_EXPR
  	      || TREE_CODE (op0) == GIMPLE_MODIFY_STMT)
! 	    dump_generic_node (buffer, GENERIC_TREE_OPERAND (op0, 1),
! 			       spc, flags, false);
! 	  else
! 	    dump_generic_node (buffer, op0, spc, flags, false);
  	}
        break;
  
--- 1625,1635 ----
  	  pp_space (buffer);
  	  if (TREE_CODE (op0) == MODIFY_EXPR
  	      || TREE_CODE (op0) == GIMPLE_MODIFY_STMT)
! 	    op0 = GENERIC_TREE_OPERAND (op0, 1);
! 	  dump_generic_node (buffer, op0, spc, flags, false);
! 	  if (flags & TDF_VARS
! 	      && TREE_CODE (op0) == SSA_NAME)
! 	    print_varmap (buffer, op0, spc, flags);
  	}
        break;
  
Index: trunk/gcc/tree-ssa-propagate.c
===================================================================
*** trunk.orig/gcc/tree-ssa-propagate.c	2007-10-03 14:18:50.000000000 +0200
--- trunk/gcc/tree-ssa-propagate.c	2007-10-03 15:47:18.000000000 +0200
*************** replace_phi_args_in (tree phi, prop_valu
*** 1117,1123 ****
  	    }
  	}
      }
!   
    if (replaced && dump_file && (dump_flags & TDF_DETAILS))
      {
        fprintf (dump_file, "Folded PHI node: ");
--- 1117,1128 ----
  	    }
  	}
      }
! 
! #if 0
!   if (replaced)
!     ssa_varmap_process_phi (phi);
! #endif
! 
    if (replaced && dump_file && (dump_flags & TDF_DETAILS))
      {
        fprintf (dump_file, "Folded PHI node: ");
*************** substitute_and_fold (prop_value_t *prop_
*** 1265,1270 ****
--- 1270,1282 ----
  	      fold_stmt (bsi_stmt_ptr (i));
  	      stmt = bsi_stmt (i);
  
+ #if 0
+ 	      if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+ 		  && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
+ 		  && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)) == SSA_NAME)
+ 		ssa_varmap_process_copy (stmt);
+ #endif
+ 
                /* If we cleaned up EH information from the statement,
                   remove EH edges.  */
  	      if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
Index: trunk/gcc/tree.h
===================================================================
*** trunk.orig/gcc/tree.h	2007-10-03 14:07:25.000000000 +0200
--- trunk/gcc/tree.h	2007-10-03 19:18:53.000000000 +0200
*************** extern void duplicate_ssa_name_ptr_info 
*** 3893,3898 ****
--- 3893,3909 ----
  extern void release_ssa_name (tree);
  extern void release_defs (tree);
  extern void replace_ssa_name_symbol (tree, tree);
+ extern bitmap ssa_varmap_lookup (tree);
+ extern void ssa_varmap_process_copy_1 (tree, tree);
+ extern void ssa_varmap_process_copy (tree);
+ extern void ssa_varmap_add_var (tree, tree);
+ extern void ssa_varmap_process_phi (tree);
+ extern void ssa_varmap_process_all (void);
+ tree ssa_varmap_get_ref (int);
+ void ssa_varmap_add_ref (tree);
+ #ifdef BUFSIZ
+ extern void print_ssa_varmap (FILE *);
+ #endif
  
  #ifdef GATHER_STATISTICS
  extern void ssanames_print_statistics (void);
Index: trunk/gcc/passes.c
===================================================================
*** trunk.orig/gcc/passes.c	2007-10-03 18:00:13.000000000 +0200
--- trunk/gcc/passes.c	2007-10-03 18:01:06.000000000 +0200
*************** execute_function_todo (void *data)
*** 900,905 ****
--- 900,908 ----
        unsigned update_flags = flags & TODO_update_ssa_any;
        update_ssa (update_flags);
        cfun->last_verified &= ~TODO_verify_ssa;
+ 
+       if (dump_flags & TDF_VARS)
+ 	print_ssa_varmap (dump_file);
      }
    
    if (flags & TODO_rebuild_alias)

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2007-11-24 21:43 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-03 18:26 [RFC] New SSA variable mapping infrastructure Richard Guenther
2007-10-04  6:27 ` Michael Matz
2007-11-07  8:29   ` Alexandre Oliva
2007-10-18 12:46 ` Paolo Bonzini
2007-11-07  8:14 ` Alexandre Oliva
2007-11-07 10:34   ` Richard Guenther
2007-11-07 19:29     ` Alexandre Oliva
2007-11-08  9:25       ` Richard Guenther
2007-11-08 17:25         ` Alexandre Oliva
2007-11-08 20:51           ` Richard Guenther
2007-11-09  1:11             ` Alexandre Oliva
2007-11-09 11:55               ` Richard Guenther
2007-11-12 18:40                 ` Alexandre Oliva
2007-11-13 11:13                   ` Richard Guenther
2007-11-25 11:23                     ` Alexandre Oliva
2007-11-25 13:38                       ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).