Basic infrastructure for substitution tracking

Martin Jambor mjambor@suse.cz
Mon Sep 21 12:52:00 GMT 2009


Hi,

On Sun, Sep 20, 2009 at 08:18:44PM +0200, Richard Guenther wrote:
> On Sun, 20 Sep 2009, Jan Hubicka wrote:
> 
> > > 
> > > Ok, so this is equivalent to inserting DEBUG_STMTs for all param decls
> > > in the caller at the start of the callee copy.  But it is cheaper
> > > because when that function is inlined we don't copy those DEBUG_STMTs
> > > but instead via NONLOCALIZED_VARS we know they were the same.
> >
> > ...
> > 
>
> Ok.  Let's see what others think of your patch.
> 

I'd like to point out that DEBUG_STMTs are, as far as I know, for
gimple registers only, whereas NONLOCALIZED_VARS also work for
aggregates.  On the pretty-ipa branch version of intra-SRA, I used to
have code creating debug constructors in NONLOCALIZED_VAR_VALUES to
map the original aggregate to the new places where their components
were stored and to update the mappings already in the
NONLOCALIZED_VARs if some of the variables involved in them are
scalarized. I think that updating such stuff in DEBUG_STMTs would be
quite a burden.

I have a patch for trunk as well, you can find it below and it should
compile but it may not necessarily be of commit quality because it is
rather old and never underwent any testing (on trunk).  Obviously, it
needs to be applied on top of Honza's patch.  Again, bits of the code
are slightly more complicated than necessary because they were meant
to be shared with similar stuff for IPA-SRA (although that mapping has
never really worked but that is a different story).

HTH,

Martin


Index: mine/gcc/tree-sra.c
===================================================================
--- mine.orig/gcc/tree-sra.c
+++ mine/gcc/tree-sra.c
@@ -1143,6 +1143,114 @@ build_ref_for_offset (tree *expr, tree t
   return build_ref_for_offset_1 (expr, type, offset, exp_type);
 }
 
+/* Returns a constructor for aggregate of TYPE type which is a part of DECL at
+   offset OFFSET and accessible through EXPR.  SEARCH is a callback function
+   which locates values given their offset and size.  If EXPR is NULL, the
+   parts of the aggregate which have not been located by SEARCH have been
+   optimized out.  Returns error_mark_node if something goes wrong and this
+   cannot be achieved, for example when array index bounds cannot be
+   determined.  DATA is passed to SEARCH and not interpreted in any way.  */
+
+static tree
+create_debug_constructor (tree type, tree decl, tree expr,
+			  HOST_WIDE_INT offset,
+			  tree (*search) (tree, HOST_WIDE_INT, HOST_WIDE_INT,
+					  void *), void *data)
+{
+  tree fld, el, domain, index, max, tree_size;
+  HOST_WIDE_INT size;
+  VEC(constructor_elt,gc) *vals = VEC_alloc (constructor_elt, gc, 8);
+
+  gcc_assert (AGGREGATE_TYPE_P (type));
+
+  switch (TREE_CODE (type))
+    {
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+    case RECORD_TYPE:
+      for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+	{
+	  HOST_WIDE_INT pos;
+	  tree fld_type, ref;
+	  constructor_elt *elt;
+	  tree value;
+
+	  if (TREE_CODE (fld) != FIELD_DECL)
+	    continue;
+	  pos = int_bit_position (fld);
+	  elt = VEC_safe_push (constructor_elt, gc, vals, NULL);
+	  elt->index = fld;
+	  if (expr)
+	    ref = build3 (COMPONENT_REF, TREE_TYPE (fld), expr, fld,
+			  NULL_TREE);
+	  else
+	    ref = NULL;
+	  fld_type = TREE_TYPE (fld);
+	  tree_size = TYPE_SIZE (TREE_TYPE (fld));
+	  gcc_assert (tree_size && host_integerp (tree_size, 1));
+	  size = tree_low_cst (tree_size, 1);
+
+	  value = search (decl, offset + pos, size, data);
+	  if (!value)
+	    {
+	      if (AGGREGATE_TYPE_P (fld_type))
+		value = create_debug_constructor (fld_type, decl, ref,
+						  offset + pos, search, data);
+	      else
+		value = ref;
+	    }
+	  elt->value = value;
+	}
+
+      break;
+    case ARRAY_TYPE:
+      domain = TYPE_DOMAIN (type);
+
+      if (!domain || !TYPE_MIN_VALUE (domain) || !TYPE_MAX_VALUE (domain))
+	return error_mark_node;
+
+      el = TREE_TYPE (type);
+      tree_size = TYPE_SIZE (el);
+      gcc_assert (tree_size && host_integerp (tree_size, 1));
+      size = tree_low_cst (tree_size, 1);
+      index =  TYPE_MIN_VALUE (domain);
+      max = TYPE_MAX_VALUE (domain);
+      while (!tree_int_cst_lt (max, index))
+	{
+	  constructor_elt *elt;
+	  tree ref, value;
+
+	  if (expr)
+	    ref = build4 (ARRAY_REF, TREE_TYPE (type), expr, index,
+			  NULL_TREE, NULL_TREE);
+	  else
+	    ref = NULL;
+
+	  elt = VEC_safe_push (constructor_elt, gc, vals, NULL);
+	  elt->index = index;
+
+	  value = search (decl, offset, size, data);
+	  if (!value)
+	    {
+	      if (AGGREGATE_TYPE_P (el))
+		value = create_debug_constructor (el, decl, ref, offset,
+						  search, data);
+	      else
+		value = ref;
+	    }
+	  elt->value = value;
+	  offset += size;
+	  index = int_const_binop (PLUS_EXPR, index, integer_one_node, 0);
+	}
+
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  return build_constructor (type, vals);
+}
+
 /* The very first phase of intraprocedural SRA.  It marks in candidate_bitmap
    those with type which is suitable for scalarization.  */
 
@@ -2354,6 +2462,80 @@ initialize_parameter_reductions (void)
     gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
 }
 
+/* Callback used by build_debug_constructor to locate a replacement in access
+   tree.  */
+
+static tree
+access_tree_debug_search (tree decl, HOST_WIDE_INT offset,
+			  HOST_WIDE_INT size, void *data ATTRIBUTE_UNUSED)
+{
+  struct access *access = get_var_base_offset_size_access (decl, offset, size);
+  if (access && access->grp_to_be_replaced)
+    {
+      /* We read replacement_decl here directly because after the
+	 function has been modified it really ought to exist.  */
+      gcc_assert (access->replacement_decl);
+      return access->replacement_decl;
+    }
+  else
+    return NULL;
+}
+
+/* If any of values of NONLOCALIZED_VARS holds an aggregate that was split into
+   components by intra-SRA,  replace it with an appropriate constructor.  */
+
+static void
+intra_remap_nonlocalized_vars (tree block)
+{
+  int i, n;
+  tree t;
+
+  n = BLOCK_NUM_NONLOCALIZED_VARS (block);
+  for (i = 0; i < n; i++)
+    {
+      tree var = BLOCK_NONLOCALIZED_VAR_VALUE (block, i);
+
+      if (var && DECL_P (var)
+	  && bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
+	{
+	  BLOCK_NONLOCALIZED_VAR_VALUE (block, i)
+	    = create_debug_constructor (TREE_TYPE (var), var, var, 0,
+					access_tree_debug_search, NULL);
+	}
+    }
+
+  for (t = BLOCK_SUBBLOCKS (block); t ; t = BLOCK_CHAIN (t))
+    intra_remap_nonlocalized_vars (t);
+}
+
+/* Store information describing how aggregates were split up by intra-SRA to be
+   used later when generating debug info, if the debug info level requires it
+   it.  */
+
+static void
+intra_store_all_debug_information (void)
+{
+  tree var;
+  referenced_var_iterator rvi;
+
+  if (debug_info_level <= DINFO_LEVEL_TERSE)
+    return;
+
+  FOR_EACH_REFERENCED_VAR (var, rvi)
+    {
+      if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
+	{
+	  tree cst;
+
+	  cst = create_debug_constructor (TREE_TYPE (var), var, var, 0,
+					  access_tree_debug_search, NULL);
+	  SET_DECL_VALUE_EXPR (var, cst);
+	}
+    }
+
+  intra_remap_nonlocalized_vars (DECL_INITIAL (current_function_decl));
+}
+
 /* The "main" function of intraprocedural SRA passes.  Runs the analysis and if
    it reveals there are components of some aggregates to be scalarized, it runs
    the required transformations.  */
@@ -2388,6 +2570,8 @@ perform_intra_sra (void)
   statistics_counter_event (cfun, "Separate LHS and RHS handling",
 			    sra_stats.separate_lhs_rhs_handling);
 
+  intra_store_all_debug_information();
+
   ret = TODO_update_ssa;
 
  out:



More information about the Gcc-patches mailing list