This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[pretty-ipa, PATCH 3/3] Move param notes to ipa-prop for wider audience


New version, previously posted here:
http://gcc.gnu.org/ml/gcc-patches/2009-04/msg00231.html

Updated so that it works after A-I merge.


2009-04-06  Martin Jambor  <mjambor@suse.cz>

	* ipa-sra.c (struct new_parm_note): Removed.
	(dump_struct_1): Moved to ipa-prop.c.
	(dump_struct): Moved to ipa-prop.c.
	(dump_param_notes): Removed.
	(get_param_index): New function.
	(turn_representatives_into_notes): Use new notes.
	(modify_parameters): Removed.
	(get_replaced_param_substitute): Use new notes.
	(replace_removed_params_ssa_names): Use new notes.
	(sra_ipa_modify_expr): Use new notes.
	(build_access_expr_1): Renamed to build_ref_for_offset_1.
	(build_access_expr): Renamed to build_ref_for_offset.
	(convert_call): Removed.
	(check_callers): Removed.
	(convert_callers): Use new notes and ipa_modify_call_arguments.
	(modify_function): Use new notes.
	(ipa_early_sra): Use new notes.
	* ipa-prop.h (struct ipa_parm_note): New type.
	(ipa_modify_formal_parameters): Declare.
	(ipa_modify_call_arguments): Declare.
	(ipa_combine_notes): Declare.
	(ipa_dump_param_notes): Declare.
	(build_ref_for_offset): Declare.
	* ipa-prop.c (dump_aggregate_1): Moved here from ipa-sra.c.
	(dump_aggregate): Moved here from ipa-sra.c.
	(count_formal_parameters): New function.
	(ipa_get_vector_of_formal_parms): New function.
	(get_vector_of_formal_parm_types): New function.
	(ipa_modify_formal_parameters): New function.
	(ipa_modify_call_arguments): New function.
	(ipa_dump_param_notes): New function.

Index: isra/gcc/ipa-prop.c
===================================================================
--- isra.orig/gcc/ipa-prop.c
+++ isra/gcc/ipa-prop.c
@@ -1317,3 +1317,552 @@ ipa_print_all_params (FILE * f)
   for (node = cgraph_nodes; node; node = node->next)
     ipa_print_node_params (f, node);
 }
+
+/* Helper function for dump_aggregate, dumps a substructure type TYPE, indented
+   by INDENT.  */
+
+static void
+dump_aggregate_1 (tree type, int indent)
+{
+  tree fld;
+  static char buffer[100];
+
+  print_node_brief (dump_file, "type:", type, 1);
+
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      fprintf (dump_file, " size in bytes: %i\n",
+	       (int) int_size_in_bytes (type));
+      for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+	{
+	  int i;
+	  if (TREE_CODE (fld) != FIELD_DECL)
+	    continue;
+
+	  for (i = 0; i < indent; i++)
+	    putc(' ', dump_file);
+
+	  snprintf (buffer, 100, "offset: %u",
+		    (unsigned) int_bit_position (fld));
+	  print_node_brief (dump_file, buffer, fld, indent);
+	  dump_aggregate_1 (TREE_TYPE (fld), indent + 2);
+	}
+
+      break;
+    case ARRAY_TYPE:
+      print_node_brief (dump_file, "element: ", TREE_TYPE (type), 1);
+
+      /* fall through */
+    default:
+      fprintf (dump_file, "\n");
+      break;
+    }
+  return;
+}
+
+/* Dump the type of tree T to dump_file in a way that makes it easy to find out
+   which offsets correspond to what fields/elements.  Indent by INDENT.  */
+
+static void
+dump_aggregate (tree t, int indent)
+{
+  tree type = TREE_TYPE (t);
+
+  print_generic_expr (dump_file, t, 0);
+  print_node_brief (dump_file, " - ", t, indent);
+
+  if (POINTER_TYPE_P (type))
+    {
+      fprintf (dump_file, " -> ");
+      dump_aggregate_1 (TREE_TYPE (type), indent + 2);
+    }
+  else
+    dump_aggregate_1 (type, indent);
+}
+
+/* Return how many formal parameters FNDECL has.  */
+
+static inline int
+count_formal_parameters (tree fndecl)
+{
+  tree parm;
+  int count = 0;
+
+  for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+    count++;
+
+  return count;
+}
+
+/* Return a heap allocated vector containing formal parameters of FNDECL.  */
+
+VEC(tree, heap) *
+ipa_get_vector_of_formal_parms (tree fndecl)
+{
+  VEC(tree, heap) *args;
+  int count;
+  tree parm;
+
+  count = count_formal_parameters (fndecl);
+  args = VEC_alloc (tree, heap, count);
+  for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+    VEC_quick_push (tree, args, parm);
+
+  return args;
+}
+
+/* Return a heap allocated vector containing types of formal parameters of
+   function type FNTYPE.  */
+
+static inline VEC(tree, heap) *
+get_vector_of_formal_parm_types (tree fntype)
+{
+  VEC(tree, heap) *types;
+  int count = 0;
+  tree t;
+
+  for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
+    count++;
+
+  types = VEC_alloc (tree, heap, count);
+  for (t = TYPE_ARG_TYPES (fntype); t; t = TREE_CHAIN (t))
+    VEC_quick_push (tree, types, TREE_VALUE (t));
+
+  return types;
+}
+
+/* Modify the function declaration FNDECL and its type according to the plan in
+   NOTES.  It also sets base fields of notes to reflect the actual parameters
+   being modified which are determined by the base_index field.  */
+
+void
+ipa_modify_formal_parameters (tree fndecl, VEC (ipa_parm_note_t, heap) *notes,
+			      const char *synth_parm_prefix)
+{
+  VEC(tree, heap) *oparms, *otypes;
+  tree orig_type, new_type = NULL;
+  tree old_arg_types, t, new_arg_types = NULL;
+  tree parm, *link = &DECL_ARGUMENTS (fndecl);
+  int i, len = VEC_length (ipa_parm_note_t, notes);
+  tree new_reversed = NULL;
+  bool care_for_types, last_parm_void;
+
+  if (!synth_parm_prefix)
+    synth_parm_prefix = "SYNTH";
+
+  oparms = ipa_get_vector_of_formal_parms (fndecl);
+  orig_type = TREE_TYPE (fndecl);
+  old_arg_types = TYPE_ARG_TYPES (orig_type);
+
+  /* The following test is an ugly hack, some functions simply don't have any
+     arguments in their type.  This is probably a bug but well... */
+  care_for_types = (old_arg_types != NULL_TREE);
+  if (care_for_types)
+    {
+      last_parm_void = (TREE_VALUE (tree_last (old_arg_types))
+			== void_type_node);
+      otypes = get_vector_of_formal_parm_types (orig_type);
+      if (last_parm_void)
+	gcc_assert (VEC_length (tree, oparms) + 1 == VEC_length (tree, otypes));
+      else
+	gcc_assert (VEC_length (tree, oparms) == VEC_length (tree, otypes));
+    }
+  else
+    {
+      last_parm_void = false;
+      otypes = NULL;
+    }
+
+  for (i = 0; i < len; i++)
+    {
+      struct ipa_parm_note *note;
+      gcc_assert (link);
+
+      note = VEC_index (ipa_parm_note_t, notes, i);
+      parm = VEC_index (tree, oparms, note->base_index);
+      note->base = parm;
+
+      if (note->copy_param)
+	{
+	  if (care_for_types)
+	    new_arg_types = tree_cons (NULL_TREE, VEC_index (tree, otypes,
+							     note->base_index),
+				       new_arg_types);
+	  *link = parm;
+	  link = &TREE_CHAIN (parm);
+	}
+      else if (!note->remove_param)
+	{
+	  tree new_parm;
+	  tree ptype;
+
+	  if (note->by_ref)
+	    ptype = build_pointer_type (note->type);
+	  else
+	    ptype = note->type;
+
+	  if (care_for_types)
+	    new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
+
+	  new_parm = build_decl (PARM_DECL, NULL_TREE, ptype);
+	  DECL_NAME (new_parm) = create_tmp_var_name (synth_parm_prefix);
+
+	  DECL_ARTIFICIAL (new_parm) = 1;
+	  DECL_ARG_TYPE (new_parm) = ptype;
+	  DECL_CONTEXT (new_parm) = fndecl;
+	  TREE_USED (new_parm) = 1;
+	  DECL_IGNORED_P (new_parm) = 1;
+	  layout_decl (new_parm, 0);
+
+	  add_referenced_var (new_parm);
+	  mark_sym_for_renaming (new_parm);
+	  note->base = parm;
+	  note->reduction = new_parm;
+
+	  *link = new_parm;
+
+	  link = &TREE_CHAIN (new_parm);
+	}
+    }
+
+  *link = NULL_TREE;
+
+  if (care_for_types)
+    {
+      new_reversed = nreverse (new_arg_types);
+      if (last_parm_void)
+	{
+	  if (new_reversed)
+	    TREE_CHAIN (new_arg_types) = void_list_node;
+	  else
+	    new_reversed = void_list_node;
+	}
+    }
+
+  /* Use copy_node to preserve as much as possible from original type
+     (debug info, attribute lists etc.)
+     Exception is METHOD_TYPEs must have THIS argument.
+     When we are asked to remove it, we need to build new FUNCTION_TYPE
+     instead.  */
+  if (TREE_CODE (orig_type) != METHOD_TYPE
+       || (VEC_index (ipa_parm_note_t, notes, 0)->copy_param
+	  && VEC_index (ipa_parm_note_t, notes, 0)->base_index == 0))
+    {
+      new_type = copy_node (orig_type);
+      TYPE_ARG_TYPES (new_type) = new_reversed;
+    }
+  else
+    {
+      new_type
+        = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
+							 new_reversed));
+      TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
+      DECL_VINDEX (fndecl) = NULL_TREE;
+    }
+
+  /* This is a new type, not a copy of an old type.  Need to reassociate
+     variants.  We can handle everything except the main variant lazily.  */
+  t = TYPE_MAIN_VARIANT (orig_type);
+  if (orig_type != t)
+    {
+      TYPE_MAIN_VARIANT (new_type) = t;
+      TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
+      TYPE_NEXT_VARIANT (t) = new_type;
+    }
+  else
+    {
+      TYPE_MAIN_VARIANT (new_type) = new_type;
+      TYPE_NEXT_VARIANT (new_type) = NULL;
+    }
+
+  TREE_TYPE (fndecl) = new_type;
+  if (otypes)
+    VEC_free (tree, heap, otypes);
+  VEC_free (tree, heap, oparms);
+
+  return;
+}
+
+/* Modify actual arguments of a function call CS as indicated in NOTES.  If
+   this is a directly recursive call, CS must be NULL.  Otherwise it must
+   contain the corresponding call graph edge.  */
+
+void
+ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt,
+			   VEC (ipa_parm_note_t, heap) *notes)
+{
+  VEC(tree, heap) *vargs;
+  gimple new_stmt;
+  gimple_stmt_iterator gsi;
+  tree callee_decl;
+  int i, len;
+
+  len = VEC_length (ipa_parm_note_t, notes);
+  vargs = VEC_alloc (tree, heap, len);
+
+  gsi = gsi_for_stmt (stmt);
+  for (i = 0; i < len; i++)
+    {
+      struct ipa_parm_note *note = VEC_index (ipa_parm_note_t, notes, i);
+
+      if (note->copy_param)
+	{
+	  tree arg = gimple_call_arg (stmt, note->base_index);
+
+	  VEC_quick_push (tree, vargs, arg);
+	}
+      else if (!note->remove_param)
+	{
+	  tree expr, orig_expr;
+	  bool allow_ptr, repl_found;
+
+	  orig_expr = expr = gimple_call_arg (stmt, note->base_index);
+	  if (TREE_CODE (expr) == ADDR_EXPR)
+	    {
+	      allow_ptr = false;
+	      expr = TREE_OPERAND (expr, 0);
+	    }
+	  else
+	    allow_ptr = true;
+
+	  /* FIXME Either make dump_struct public and move it to a more
+	     appropriate place or remove the following dump.  */
+
+	  if (dump_file && (dump_flags & TDF_DETAILS))
+	    {
+	      fprintf (dump_file, "Searching for reduced component:\n");
+	      if (note->by_ref)
+		print_node_brief (dump_file, "ref to type: ", note->type, 0);
+	      else
+		print_node_brief (dump_file, "type: ", note->type, 0);
+	      print_node_brief (dump_file, "\nbase: ", expr, 0);
+	      fprintf (dump_file, "\noffset: %i\nin\n", (int) note->offset);
+	      dump_aggregate (expr, 2);
+	    }
+
+	  repl_found = build_ref_for_offset (&expr, TREE_TYPE (expr),
+					     note->offset, note->type,
+					     allow_ptr);
+	  if (repl_found)
+	    {
+	      if (note->by_ref)
+		expr = build_fold_addr_expr (expr);
+	    }
+	  else
+	    {
+	      tree type = build_pointer_type (note->type);
+	      expr = orig_expr;
+	      if (!POINTER_TYPE_P (TREE_TYPE (expr)))
+		expr = build_fold_addr_expr (expr);
+	      expr = fold_build2 (POINTER_PLUS_EXPR, type, expr,
+				  build_int_cst (size_type_node,
+						 note->offset / BITS_PER_UNIT));
+	      if (!note->by_ref)
+		expr = fold_build1 (INDIRECT_REF, note->type, expr);
+	    }
+	  expr = force_gimple_operand_gsi (&gsi, expr, true, NULL, true,
+					   GSI_SAME_STMT);
+
+	  VEC_quick_push (tree, vargs, expr);
+	}
+    }
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "replacing stmt:");
+      print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, 0);
+    }
+
+  callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl;
+  new_stmt = gimple_build_call_vec (callee_decl, vargs);
+  VEC_free (tree, heap, vargs);
+  if (gimple_call_lhs (stmt))
+    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
+
+  gimple_set_block (new_stmt, gimple_block (stmt));
+  if (gimple_has_location (stmt))
+    gimple_set_location (new_stmt, gimple_location (stmt));
+
+  /* Carry all the flags to the new GIMPLE_CALL.  */
+  gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
+  gimple_call_set_tail (new_stmt, gimple_call_tail_p (stmt));
+  gimple_call_set_cannot_inline (new_stmt,
+				 gimple_call_cannot_inline_p (stmt));
+  gimple_call_set_return_slot_opt (new_stmt,
+				   gimple_call_return_slot_opt_p (stmt));
+  gimple_call_set_from_thunk (new_stmt, gimple_call_from_thunk_p (stmt));
+  gimple_call_set_va_arg_pack (new_stmt, gimple_call_va_arg_pack_p (stmt));
+
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "with stmt:");
+      print_gimple_stmt (dump_file, new_stmt, 0, 0);
+      fprintf (dump_file, "\n");
+    }
+  gsi_replace (&gsi, new_stmt, true);
+  if (cs)
+    cgraph_set_call_stmt (cs, new_stmt);
+
+  update_ssa (TODO_update_ssa);
+  free_dominance_info (CDI_DOMINATORS);
+
+  return;
+}
+
+/* Return true iff BASE_INDEX is in  NOTES twice or more times.  */
+
+static bool
+index_in_notes_multiple_times_p (int base_index,
+				 VEC (ipa_parm_note_t, heap) *notes)
+{
+  int i, len = VEC_length (ipa_parm_note_t, notes);
+  bool one = false;
+
+  for (i = 0; i < len; i++)
+    {
+      struct ipa_parm_note *note = VEC_index (ipa_parm_note_t, notes, i);
+
+      if (note->base_index == base_index)
+	{
+	  if (one)
+	    return true;
+	  else
+	    one = true;
+	}
+    }
+  return false;
+}
+
+
+/* Return notes that should have the same effect on function parameters and
+   call arguments as if they were first changed according to notes in INNER and
+   then by notes in OUTER.  */
+
+VEC (ipa_parm_note_t, heap) *
+ipa_combine_notes (VEC (ipa_parm_note_t, heap) *inner,
+		   VEC (ipa_parm_note_t, heap) *outer)
+{
+  int i, outlen = VEC_length (ipa_parm_note_t, outer);
+  int inlen = VEC_length (ipa_parm_note_t, inner);
+  int removals = 0;
+  VEC (ipa_parm_note_t, heap) *notes, *tmp;
+
+  tmp = VEC_alloc (ipa_parm_note_t, heap, inlen);
+  for (i = 0; i < inlen; i++)
+    {
+      struct ipa_parm_note *n = VEC_index (ipa_parm_note_t, inner, i);
+
+      if (n->remove_param)
+	removals++;
+      else
+	VEC_quick_push (ipa_parm_note_t, tmp, n);
+    }
+
+  notes = VEC_alloc (ipa_parm_note_t, heap, outlen + removals);
+  for (i = 0; i < outlen; i++)
+    {
+      struct ipa_parm_note *r;
+      struct ipa_parm_note *out = VEC_index (ipa_parm_note_t, outer, i);
+      struct ipa_parm_note *in = VEC_index (ipa_parm_note_t, tmp,
+					    out->base_index);
+
+      gcc_assert (!in->remove_param);
+      if (out->remove_param)
+	{
+	  if (!index_in_notes_multiple_times_p (in->base_index, tmp))
+	    {
+	      r = VEC_quick_push (ipa_parm_note_t, notes, NULL);
+	      memset (r, 0, sizeof (*r));
+	      r->remove_param = true;
+	    }
+	  continue;
+	}
+
+      r = VEC_quick_push (ipa_parm_note_t, notes, NULL);
+      memset (r, 0, sizeof (*r));
+      r->base_index = in->base_index;
+      r->type = out->type;
+
+      /* FIXME:  Create nonlocal value too.  */
+
+      if (in->copy_param && out->copy_param)
+	r->copy_param = true;
+      else if (in->copy_param)
+	r->offset = out->offset;
+      else if (out->copy_param)
+	r->offset = in->offset;
+      else
+	r->offset = in->offset + out->offset;
+    }
+
+  tmp = VEC_alloc (ipa_parm_note_t, heap, inlen);
+  for (i = 0; i < inlen; i++)
+    {
+      struct ipa_parm_note *n = VEC_index (ipa_parm_note_t, inner, i);
+
+      if (n->remove_param)
+	VEC_quick_push (ipa_parm_note_t, tmp, n);
+    }
+
+  VEC_free (ipa_parm_note_t, heap, tmp);
+  return notes;
+}
+
+
+/* Dump the notes in the vector NOTES to dump_file in a human friendly way,
+   assuming they are menat to be applied to FNDECL.  */
+
+void
+ipa_dump_param_notes (FILE *file, VEC (ipa_parm_note_t, heap) *notes,
+		      tree fndecl)
+{
+  int i, len = VEC_length (ipa_parm_note_t, notes);
+  bool first = true;
+  VEC(tree, heap) *parms = ipa_get_vector_of_formal_parms (fndecl);
+
+  fprintf (file, "IPA param notes: ");
+  for (i = 0; i < len; i++)
+    {
+      struct ipa_parm_note *note = VEC_index (ipa_parm_note_t, notes, i);
+
+      if (!first)
+	fprintf (file, "                 ");
+      else
+	first = false;
+
+      fprintf (file, "%i. base_index: %i - ", i, note->base_index);
+      print_generic_expr (file, VEC_index (tree, parms, note->base_index), 0);
+      if (note->base)
+	{
+	  fprintf (file, ", base: ");
+	  print_generic_expr (file, note->base, 0);
+	}
+      if (note->reduction)
+	{
+	  fprintf (file, ", reduction: ");
+	  print_generic_expr (file, note->reduction, 0);
+	}
+      if (note->new_ssa_base)
+	{
+	  fprintf (file, ", new_ssa_base: ");
+	  print_generic_expr (file, note->new_ssa_base, 0);
+	}
+
+      if (note->copy_param)
+	fprintf (file, ", copy_param");
+      else if (note->remove_param)
+	fprintf (file, ", remove_param");
+      else
+	fprintf (file, ", offset %li", (long) note->offset);
+      if (note->by_ref)
+	fprintf (file, ", by_ref");
+      print_node_brief (file, ", type: ", note->type, 0);
+      fprintf (file, "\n");
+    }
+  VEC_free (tree, heap, parms);
+  return;
+}
+
Index: isra/gcc/ipa-prop.h
===================================================================
--- isra.orig/gcc/ipa-prop.h
+++ isra/gcc/ipa-prop.h
@@ -389,4 +389,69 @@ void ipa_print_all_params (FILE *);
 void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node);
 void ipa_print_all_jump_functions (FILE * f);
 
+
+/* Structure do describe transformations of formal parameters and actual
+   arguments.  Each instance describes one new parameter and they are meant to
+   be stored in a vector.  Additionally, most users will probably want to store
+   notes about parameters that are being removed altogether so that SSA names
+   belonging to them can be replaced by SSA names of an artificial
+   variable.  */
+struct ipa_parm_note
+{
+  tree base;			/* The original PARM_DECL itself, helpful for
+				   processing of the body of the function
+				   itself.  Intended for traversing function
+				   bodies.  ipa_modify_formal_parameters,
+				   ipa_modify_call_arguments and
+				   ipa_combine_notes ignore this and use
+				   base_index.  ipa_modify_formal_parameters
+				   actually sets this.  */
+  tree type;			/* Type of the new parameter.  However, if
+				   by_ref is true, the real type will be a
+				   pointer to this type.  */
+  tree reduction;		/* The new declaration.  !!! */
+  tree new_ssa_base;		/* New declaration of a substitute variable
+				   that we may use to replace all
+				   non-default-def ssa names when a parm decl
+				   is going away.  */
+  tree nonlocal_value;		/* If non-NULL and the original parameter is to
+				   be removed (copy_param below is NULL), this
+				   is going to be its nonlocalized vars
+				   value.  */
+  HOST_WIDE_INT offset;		/* Offset into the original parameter (for the
+				   cases when the new parameter is a component
+				   of an original one).  */
+  int base_index;		/* Zero based index of the original parameter
+				   this one is based on.  (ATM there is no way
+				   to insert a new parameter out of the blue
+				   because there is no need but if it arises
+				   the code can be easily exteded to do
+				   so.)  */
+  unsigned copy_param : 1; 	/* This new parameter is an unmodified
+				   parameter at index base_index. */
+  unsigned remove_param : 1;	/* This note describes a parameter that is
+				   about to be removed completely.  Most users
+				   will probably need to book keep those so
+				   that they don't leave behinfd any non
+				   default def ssa names belonging to them.  */
+  unsigned by_ref : 1;		/* The parameter is to be passed by
+				   reference.  */
+};
+
+typedef struct ipa_parm_note ipa_parm_note_t;
+DEF_VEC_O (ipa_parm_note_t);
+DEF_VEC_ALLOC_O (ipa_parm_note_t, heap);
+
+VEC(tree, heap) *ipa_get_vector_of_formal_parms (tree fndecl);
+void ipa_modify_formal_parameters (tree fndecl, VEC (ipa_parm_note_t, heap) *,
+				   const char *);
+void ipa_modify_call_arguments (struct cgraph_edge *, gimple,
+				VEC (ipa_parm_note_t, heap) *);
+VEC (ipa_parm_note_t, heap) *ipa_combine_notes (VEC (ipa_parm_note_t, heap) *,
+						VEC (ipa_parm_note_t, heap) *);
+void ipa_dump_param_notes (FILE *, VEC (ipa_parm_note_t, heap) *, tree);
+
+/* From ipa-sra.c:  */
+bool build_ref_for_offset (tree *, tree, HOST_WIDE_INT, tree, bool);
+
 #endif /* IPA_PROP_H */
Index: isra/gcc/ipa-sra.c
===================================================================
--- isra.orig/gcc/ipa-sra.c
+++ isra/gcc/ipa-sra.c
@@ -61,7 +61,7 @@ along with GCC; see the file COPYING3.
       associated parameters are always dereferenced when the function is run.
       Then decisions are made as to what parameters are to be split into what
       components and this decision is represented in form of vector of struct
-      new_parm_note.  Each structure describes one parameter of the function
+      ipa_parm_note.  Each structure describes one parameter of the function
       after the function is modified (and how it relates to original
       parameters) but may also represent a decision to remove a parameter
       altogether.  Finally, we check that all callers can be modified to pass
@@ -247,28 +247,6 @@ typedef struct access *access_p;
 DEF_VEC_P (access_p);
 DEF_VEC_ALLOC_P (access_p, heap);
 
-/* Structure for the final plan what to do in IPA modes.  */
-struct new_parm_note
-{
-  tree base;
-  tree type;
-  tree reduction;
-  tree new_ssa_base;
-  HOST_WIDE_INT offset;
-
-  int stmt_no;
-
-  unsigned copy_param : 1; 	/* Untouched copied parameter. */
-  unsigned remove_param : 1;	/* Remove an unused parameter. */
-  unsigned last_reduction : 1;	/* Last reduction component of an original
-				   parameter.  */
-  unsigned by_ref : 1;		/* Create a parameter passed by reference? */
-};
-
-typedef struct new_parm_note new_parm_note_t;
-DEF_VEC_O (new_parm_note_t);
-DEF_VEC_ALLOC_O (new_parm_note_t, heap);
-
 /* Alloc pool for allocating access structures.  */
 static alloc_pool access_pool;
 /* Base (tree) -> Vector (VEC(access_p,heap) *) map.  */
@@ -339,71 +317,6 @@ dump_access (struct access *access, bool
 	     access->stmt_no);
 }
 
-/* Helper function for dump_struct, dumps a substructure type TYPE, indented by
-   INDENT.  */
-
-static void
-dump_struct_1 (tree type, int indent)
-{
-  tree fld;
-  static char buffer[100];
-
-  print_node_brief (dump_file, "type:", type, 1);
-
-  switch (TREE_CODE (type))
-    {
-    case RECORD_TYPE:
-    case UNION_TYPE:
-    case QUAL_UNION_TYPE:
-      fprintf (dump_file, " size in bytes: %i\n",
-	       (int) int_size_in_bytes (type));
-      for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
-	{
-	  int i;
-	  if (TREE_CODE (fld) != FIELD_DECL)
-	    continue;
-
-	  for (i = 0; i < indent; i++)
-	    putc(' ', dump_file);
-
-	  snprintf (buffer, 100, "offset: %u",
-		    (unsigned) int_bit_position (fld));
-	  print_node_brief (dump_file, buffer, fld, indent);
-	  dump_struct_1 (TREE_TYPE (fld), indent + 2);
-	}
-
-      break;
-    case ARRAY_TYPE:
-      print_node_brief (dump_file, "element: ", TREE_TYPE (type), 1);
-
-      /* fall through */
-    default:
-      fprintf (dump_file, "\n");
-      break;
-    }
-  return;
-}
-
-/* Dump the type of tree T to dump_file in a way that makes it easy to find out
-   which offsets correspond to what fields/elements.  Indent by INDENT.  */
-
-static void
-dump_struct (tree t, int indent)
-{
-  tree type = TREE_TYPE (t);
-
-  print_generic_expr (dump_file, t, 0);
-  print_node_brief (dump_file, " - ", t, indent);
-
-  if (POINTER_TYPE_P (type))
-    {
-      fprintf (dump_file, " -> ");
-      dump_struct_1 (TREE_TYPE (type), indent + 2);
-    }
-  else
-    dump_struct_1 (type, indent);
-}
-
 /* Return a vector of pointers to accesses for the variable given in BASE or
    NULL if there is none.  */
 
@@ -782,57 +695,6 @@ analyze_caller_dereference_legality (voi
   return;
 }
 
-/* Dump the notes in the vector NOTES to dump_file in a human friendly way.  */
-
-static void
-dump_param_notes (VEC (new_parm_note_t, heap) *notes)
-{
-  int i, len = VEC_length (new_parm_note_t, notes);
-  struct new_parm_note *d;
-  bool comma = false;
-  tree parm = DECL_ARGUMENTS (current_function_decl);
-
-  if (!dump_file)
-    return;
-
-  fprintf (dump_file, "Param note offsets: * ");
-
-  print_generic_expr (dump_file, parm, 0);
-  fprintf (dump_file, ": ");
-  for (i = 0; i < len; i++)
-    {
-      d = VEC_index (new_parm_note_t, notes, i);
-
-      if (comma)
-	fprintf (dump_file, ", ");
-      else
-	comma = true;
-      fprintf (dump_file, "%i", (int) d->offset);
-      if (d->copy_param)
-	fprintf (dump_file, " copy_param");
-      if (d->remove_param)
-	fprintf (dump_file, " remove_param");
-      if (d->last_reduction)
-	fprintf (dump_file, " last_reduction");
-      if (d->by_ref)
-	fprintf (dump_file, " by_ref");
-      if (d->copy_param || d->last_reduction || d->remove_param)
-        {
-	  fprintf (dump_file, "\n");
-	  parm = TREE_CHAIN (parm);
-	  if (parm)
-	    {
-	      fprintf (dump_file, "                    * ");
-	      print_generic_expr (dump_file, parm, 0);
-	      fprintf (dump_file, ": ");
-	    }
-	  comma = false;
-        }
-    }
-  fprintf (dump_file, "\n");
-  return;
-}
-
 /* Allocate necessary structures.  */
 
 static void
@@ -1795,20 +1657,36 @@ splice_all_param_accesses (VEC (access_p
   return result;
 }
 
+/* Return the index of BASE in PARMS.  Abort if it i not found.  */
+
+static inline int
+get_param_index (tree base, VEC(tree, heap) *parms)
+{
+  int i, len;
+
+  len = VEC_length (tree, parms);
+  for (i = 0; i < len; i++)
+    if (VEC_index (tree, parms, i) == base)
+      return i;
+  gcc_unreachable ();
+}
+
 /* Convert the decisions made at the representative level into compact notes.
    REPRESENTATIVES are pointers to first representatives of each param
    accesses, NOTE_COUNT is the expected final number of notes.  */
 
-static VEC (new_parm_note_t, heap) *
+static VEC (ipa_parm_note_t, heap) *
 turn_representatives_into_notes (VEC (access_p, heap) *representatives,
 				 int note_count)
 {
-  VEC (new_parm_note_t, heap) *notes;
+  VEC (tree, heap) *parms;
+  VEC (ipa_parm_note_t, heap) *notes;
   tree parm;
   int i;
 
   gcc_assert (note_count > 0);
-  notes = VEC_alloc (new_parm_note_t, heap, note_count);
+  parms = ipa_get_vector_of_formal_parms (current_function_decl);
+  notes = VEC_alloc (ipa_parm_note_t, heap, note_count);
   parm = DECL_ARGUMENTS (current_function_decl);
   for (i = 0; i < func_param_count; i++, parm = TREE_CHAIN (parm))
     {
@@ -1816,10 +1694,11 @@ turn_representatives_into_notes (VEC (ac
 
       if (!repr || no_accesses_p (repr))
 	{
-	  struct new_parm_note *note;
+	  struct ipa_parm_note *note;
 
-	  note = VEC_quick_push (new_parm_note_t, notes, NULL);
+	  note = VEC_quick_push (ipa_parm_note_t, notes, NULL);
 	  memset (note, 0, sizeof (*note));
+	  note->base_index = get_param_index (parm, parms);
 	  note->base = parm;
 	  if (!repr)
 	    note->copy_param = 1;
@@ -1828,38 +1707,40 @@ turn_representatives_into_notes (VEC (ac
 	}
       else
 	{
-	  struct new_parm_note *note;
+	  struct ipa_parm_note *note;
+	  int index = get_param_index (parm, parms);
 
 	  for (; repr; repr = repr->next_grp)
 	    {
-	      note = VEC_quick_push (new_parm_note_t, notes, NULL);
+	      note = VEC_quick_push (ipa_parm_note_t, notes, NULL);
 	      memset (note, 0, sizeof (*note));
 	      gcc_assert (repr->base == parm);
+	      note->base_index = index;
 	      note->base = repr->base;
 	      note->type = repr->type;
 	      note->offset = repr->offset;
 	      note->by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base))
 			      && (repr->grp_maybe_modified
 				  || !repr->always_safe));
-	      note->stmt_no = repr->stmt_no;
+
 	    }
-	  note->last_reduction = 1;
 	}
     }
+  VEC_free (tree, heap, parms);
   return notes;
 }
 
 /* Analyze the collected accesses and produce a plan what to do with the
    parameters in the form of notes, NULL meaning nothing.  */
 
-static VEC (new_parm_note_t, heap) *
+static VEC (ipa_parm_note_t, heap) *
 analyze_all_param_acesses (void)
 {
   enum ipa_splicing_result repr_state;
   bool proceed = false;
   int i, note_count = 0;
   VEC (access_p, heap) *representatives;
-  VEC (new_parm_note_t, heap) *notes;
+  VEC (ipa_parm_note_t, heap) *notes;
 
   repr_state = splice_all_param_accesses (&representatives);
   if (repr_state == NO_GOOD_ACCESS)
@@ -1996,161 +1877,12 @@ make_fancy_name (tree expr)
   return XOBFINISH (&name_obstack, char *);
 }
 
-/* Modify the function declaration FNDECL and its type according to the plan in
-   NOTES.  */
-
-static void
-modify_parameters (tree fndecl, VEC (new_parm_note_t, heap) *notes)
-{
-  tree orig_type, new_type = NULL;
-  tree old_arg_types, t, new_arg_types = NULL;
-  tree *parm = &DECL_ARGUMENTS (fndecl);
-  tree new_reversed = NULL;
-  int i, len = VEC_length (new_parm_note_t, notes);
-  struct new_parm_note *note;
-  bool care_for_types, last_parm_void, decomposed = false;
-
-  orig_type = TREE_TYPE (fndecl);
-  old_arg_types = TYPE_ARG_TYPES (orig_type);
-
-  /* The following test is an ugly hack, some functions simply don't have any
-     arguments in their type.  This is basically a bug but well... */
-  care_for_types = (old_arg_types != NULL_TREE);
-  if (care_for_types)
-    last_parm_void = (TREE_VALUE (tree_last (old_arg_types)) == void_type_node);
-  else
-    last_parm_void = false;
-
-  for (i = 0; i < len; i++)
-    {
-      gcc_assert (parm);
-      gcc_assert (*parm);
-
-      note = VEC_index (new_parm_note_t, notes, i);
-      if (note->copy_param)
-	{
-	  gcc_assert (!decomposed);
-	  if (care_for_types)
-	    {
-	      new_arg_types = tree_cons (NULL_TREE, TREE_VALUE (old_arg_types),
-					 new_arg_types);
-	      old_arg_types = TREE_CHAIN (old_arg_types);
-	    }
-
-	  parm = &TREE_CHAIN (*parm);
-	}
-      else if (note->remove_param)
-	{
-	  gcc_assert (!decomposed);
-	  *parm = TREE_CHAIN (*parm);
-	}
-      else
-	{
-	  tree new_parm;
-	  tree ptype;
-
-	  if (note->by_ref)
-	      ptype = build_pointer_type (note->type);
-	  else
-	      ptype = note->type;
-
-	  if (care_for_types)
-	    new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
-
-	  new_parm = build_decl (PARM_DECL, NULL_TREE, ptype);
-	  DECL_NAME (new_parm) = create_tmp_var_name ("isra");
-
-	  DECL_ARTIFICIAL (new_parm) = 1;
-	  DECL_ARG_TYPE (new_parm) = ptype;
-	  DECL_CONTEXT (new_parm) = current_function_decl;
-	  TREE_USED (new_parm) = 1;
-	  DECL_IGNORED_P (new_parm) = 1;
-	  layout_decl (new_parm, 0);
-
-	  add_referenced_var (new_parm);
-	  mark_sym_for_renaming (new_parm);
-	  note->base = *parm;
-	  note->reduction = new_parm;
-
-	  TREE_CHAIN (new_parm) = *parm;
-	  *parm = new_parm;
-
-	  parm = &TREE_CHAIN (new_parm);
-
-	  if (note->last_reduction)
-	    {
-	      if (care_for_types)
-		old_arg_types = TREE_CHAIN (old_arg_types);
-	      decomposed = false;
-
-	      *parm = TREE_CHAIN (*parm);
-	    }
-	  else
-	    decomposed = true;
-	}
-    }
-
-  /* FIXME: the rest is _almost_ entirely cut'n'pasted from
-     build_function_type_skip_args, we should somehow unify this later on.
-     This will probably happen when notes will become a part of the cloning
-     infrastructure.  */
-  if (care_for_types)
-    {
-      new_reversed = nreverse (new_arg_types);
-      if (last_parm_void)
-	{
-	  if (new_reversed)
-	    TREE_CHAIN (new_arg_types) = void_list_node;
-	  else
-	    new_reversed = void_list_node;
-	}
-    }
-
-  /* Use copy_node to preserve as much as possible from original type
-     (debug info, attribute lists etc.)
-     Exception is METHOD_TYPEs must have THIS argument.
-     When we are asked to remove it, we need to build new FUNCTION_TYPE
-     instead.  */
-  if (TREE_CODE (orig_type) != METHOD_TYPE
-      || VEC_index (new_parm_note_t, notes, 0)->copy_param)
-    {
-      new_type = copy_node (orig_type);
-      TYPE_ARG_TYPES (new_type) = new_reversed;
-    }
-  else
-    {
-      new_type
-        = build_distinct_type_copy (build_function_type (TREE_TYPE (orig_type),
-							 new_reversed));
-      TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
-      DECL_VINDEX (fndecl) = NULL_TREE;
-    }
-
-  /* This is a new type, not a copy of an old type.  Need to reassociate
-     variants.  We can handle everything except the main variant lazily.  */
-  t = TYPE_MAIN_VARIANT (orig_type);
-  if (orig_type != t)
-    {
-      TYPE_MAIN_VARIANT (new_type) = t;
-      TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
-      TYPE_NEXT_VARIANT (t) = new_type;
-    }
-  else
-    {
-      TYPE_MAIN_VARIANT (new_type) = new_type;
-      TYPE_NEXT_VARIANT (new_type) = NULL;
-    }
-
-  TREE_TYPE (fndecl) = new_type;
-  return;
-}
-
 /* If a parameter replacement identified by NOTE does not yet exist in the form
    of declaration, create it and record it, otherwise return the previously
    created one.  */
 
 static tree
-get_replaced_param_substitute (struct new_parm_note *note)
+get_replaced_param_substitute (struct ipa_parm_note *note)
 {
   tree repl;
   if (!note->new_ssa_base)
@@ -2178,7 +1910,7 @@ get_replaced_param_substitute (struct ne
 static bool
 replace_removed_params_ssa_names (gimple stmt, void *data)
 {
-  VEC (new_parm_note_t, heap) *notes = (VEC (new_parm_note_t, heap) *) data;
+  VEC (ipa_parm_note_t, heap) *notes = (VEC (ipa_parm_note_t, heap) *) data;
   tree lhs, decl;
   int i, len;
 
@@ -2197,11 +1929,11 @@ replace_removed_params_ssa_names (gimple
   if (TREE_CODE (decl) != PARM_DECL)
     return false;
 
-  len = VEC_length (new_parm_note_t, notes);
+  len = VEC_length (ipa_parm_note_t, notes);
   for (i = 0; i < len; i++)
     {
       tree repl, name;
-      struct new_parm_note *note = VEC_index (new_parm_note_t, notes, i);
+      struct ipa_parm_note *note = VEC_index (ipa_parm_note_t, notes, i);
 
       if (note->copy_param || note->base != decl)
 	continue;
@@ -2240,9 +1972,9 @@ static bool
 sra_ipa_modify_expr (tree *expr, gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
 		     bool write ATTRIBUTE_UNUSED, void *data)
 {
-  VEC (new_parm_note_t, heap) *notes = (VEC (new_parm_note_t, heap) *) data;
-  int i, len = VEC_length (new_parm_note_t, notes);
-  struct new_parm_note *note, *cand = NULL;
+  VEC (ipa_parm_note_t, heap) *notes = (VEC (ipa_parm_note_t, heap) *) data;
+  int i, len = VEC_length (ipa_parm_note_t, notes);
+  struct ipa_parm_note *note, *cand = NULL;
   HOST_WIDE_INT offset, size, max_size;
   tree base, src;
 
@@ -2285,7 +2017,7 @@ sra_ipa_modify_expr (tree *expr, gimple_
   gcc_assert (DECL_P (base));
   for (i = 0; i < len; i++)
     {
-      note = VEC_index (new_parm_note_t, notes, i);
+      note = VEC_index (ipa_parm_note_t, notes, i);
 
       if (note->base == base &&
 	  (note->offset == offset || note->remove_param))
@@ -2353,7 +2085,8 @@ sra_ipa_modify_assign (gimple *stmt_ptr,
 /* helper function for build_access_expr.  */
 
 static bool
-build_access_expr_1 (tree *res, tree type, HOST_WIDE_INT offset, tree exp_type)
+build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
+			tree exp_type)
 {
   while (1)
     {
@@ -2393,8 +2126,8 @@ build_access_expr_1 (tree *res, tree typ
 		}
 	      else
 		expr_ptr = NULL;
-	      if (build_access_expr_1 (expr_ptr, TREE_TYPE (fld), offset - pos,
-				       exp_type))
+	      if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld),
+					  offset - pos, exp_type))
 		{
 		  if (res)
 		    *res = expr;
@@ -2435,11 +2168,16 @@ build_access_expr_1 (tree *res, tree typ
 /* Construct an expression that would reference a part of aggregate *EXPR of
    type TYPE at the given OFFSET of the type EXP_TYPE.  If EXPR is NULL, the
    function only determines whether it can build such a reference without
-   actually doing it. */
+   actually doing it.
 
-static bool
-build_access_expr (tree *expr, tree type, HOST_WIDE_INT offset, tree exp_type,
-		   bool allow_ptr)
+   FIXME: Eventually this should be replaced with
+   maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a
+   minor rewrite of fold_stmt.
+ */
+
+bool
+build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset,
+		      tree exp_type, bool allow_ptr)
 {
   if (allow_ptr && POINTER_TYPE_P (type))
     {
@@ -2448,195 +2186,13 @@ build_access_expr (tree *expr, tree type
 	*expr = fold_build1 (INDIRECT_REF, type, *expr);
     }
 
-  return build_access_expr_1 (expr, type, offset, exp_type);
-}
-
-/* Convert the call site given by CS and STMT to pass the parameters as
-   specified in NOTES.  If DO_CONVERT is true, really do convert the call,
-   otherwise just check that is is possible and return true iff so.  */
-
-static bool
-convert_call (struct cgraph_edge *cs, gimple stmt,
-	      VEC (new_parm_note_t, heap) *notes, bool do_convert)
-{
-  VEC(tree, heap) *vargs;
-  gimple new_stmt;
-  gimple_stmt_iterator gsi;
-  int i, len, orig_idx;
-
-  if (!do_convert && dump_file)
-    {
-      if (cs)
-	fprintf (dump_file, "Checking call %s -> %s\n",
-		 cgraph_node_name (cs->caller),
-		 cgraph_node_name (cs->callee));
-      else
-        fprintf (dump_file, "Checking recursive call");
-    }
-
-  len = VEC_length (new_parm_note_t, notes);
-  if (do_convert)
-    vargs = VEC_alloc (tree, heap, len);
-  else
-    vargs = NULL;
-
-  gsi = gsi_for_stmt (stmt);
-  orig_idx = 0;
-  for (i = 0; i < len; i++)
-    {
-      struct new_parm_note *note = VEC_index (new_parm_note_t, notes, i);
-
-      if (note->copy_param)
-	{
-	  tree arg = gimple_call_arg (stmt, orig_idx);
-	  if (do_convert)
-	    VEC_quick_push (tree, vargs, arg);
-	  orig_idx++;
-	}
-      else if (note->remove_param)
-	orig_idx++;
-      else
-	{
-	  tree expr, *expr_ptr;
-	  bool allow_ptr, repl_found;
-
-	  expr = gimple_call_arg (stmt, orig_idx);
-	  if (TREE_CODE (expr) == ADDR_EXPR)
-	    {
-	      allow_ptr = false;
-	      expr = TREE_OPERAND (expr, 0);
-	    }
-	  else
-	    allow_ptr = true;
-
-	  if (!do_convert && dump_file)
-	    {
-	      fprintf (dump_file, "Searching for reduced component:\n");
-	      if (note->by_ref)
-		print_node_brief (dump_file, "ref to type: ", note->type, 0);
-	      else
-		print_node_brief (dump_file, "type: ", note->type, 0);
-	      print_node_brief (dump_file, "\nbase: ", expr, 0);
-	      fprintf (dump_file, "\noffset: %i\nin\n", (int) note->offset);
-	      dump_struct (expr, 2);
-	    }
-
-	  if (do_convert)
-	    expr_ptr = &expr;
-	  else
-	    expr_ptr = NULL;
-
-	  repl_found = build_access_expr (expr_ptr, TREE_TYPE (expr),
-					  note->offset, note->type, allow_ptr);
-	  gcc_assert (!do_convert || repl_found);
-
-	  if (!repl_found)
-	    return false;
-
-	  if (note->last_reduction)
-	    orig_idx++;
-
-	  if (!do_convert)
-	    continue;
-
-	  if (note->by_ref)
-	    expr = build_fold_addr_expr (expr);
-	  expr = force_gimple_operand_gsi (&gsi, expr, true, NULL, true,
-					   GSI_SAME_STMT);
-
-	  VEC_quick_push (tree, vargs, expr);
-	}
-    }
-
-  if (!do_convert)
-    return true;
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "replacing stmt:");
-      print_gimple_stmt (dump_file, gsi_stmt (gsi), 0, 0);
-    }
-
-  new_stmt = gimple_build_call_vec (!cs ? current_function_decl : cs->callee->decl, vargs);
-  VEC_free (tree, heap, vargs);
-  if (gimple_call_lhs (stmt))
-    gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
-
-  gimple_set_block (new_stmt, gimple_block (stmt));
-  if (gimple_has_location (stmt))
-    gimple_set_location (new_stmt, gimple_location (stmt));
-
-  /* Carry all the flags to the new GIMPLE_CALL.  */
-  gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
-  gimple_call_set_tail (new_stmt, gimple_call_tail_p (stmt));
-  gimple_call_set_cannot_inline (new_stmt,
-				 gimple_call_cannot_inline_p (stmt));
-  gimple_call_set_return_slot_opt (new_stmt,
-				   gimple_call_return_slot_opt_p (stmt));
-  gimple_call_set_from_thunk (new_stmt, gimple_call_from_thunk_p (stmt));
-  gimple_call_set_va_arg_pack (new_stmt, gimple_call_va_arg_pack_p (stmt));
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "by stmt:");
-      print_gimple_stmt (dump_file, new_stmt, 0, 0);
-      fprintf (dump_file, "\n");
-    }
-  gsi_replace (&gsi, new_stmt, true);
-  if (cs)
-    cgraph_set_call_stmt (cs, new_stmt);
-
-  update_ssa (TODO_update_ssa);
-  free_dominance_info (CDI_DOMINATORS);
-
-  return true;
-}
-
-/* Check that all callers of NODE can be converted to pass parameters as given
-   in NOTES and return true iff so. */
-
-static bool
-check_callers (struct cgraph_node *node, VEC (new_parm_note_t, heap) *notes)
-{
-  tree old_cur_fndecl = current_function_decl;
-  struct cgraph_edge *cs;
-  bool res = true;
-  basic_block this_block;
-
-  for (cs = node->callers; cs && res; cs = cs->next_caller)
-    {
-      current_function_decl = cs->caller->decl;
-      push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
-
-      if (!convert_call (cs, cs->call_stmt, notes, false))
-	res = false;
-
-      pop_cfun ();
-    }
-  current_function_decl = old_cur_fndecl;
-  if (!res)
-    return false;
-  FOR_EACH_BB (this_block)
-    {
-      gimple_stmt_iterator gsi;
-
-      for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
-        {
-	  gimple stmt = gsi_stmt (gsi);
-	  if (gimple_code (stmt) == GIMPLE_CALL
-	      && gimple_call_fndecl (stmt) == node->decl)
-	    if (!convert_call (NULL, stmt, notes, false))
-	      return false;
-	}
-    }
-
-  return true;
+  return build_ref_for_offset_1 (expr, type, offset, exp_type);
 }
 
 /* Convert all callers of NODE to pass parameters as given in NOTES.  */
 
 static void
-convert_callers (struct cgraph_node *node, VEC (new_parm_note_t, heap) *notes)
+convert_callers (struct cgraph_node *node, VEC (ipa_parm_note_t, heap) *notes)
 {
   tree old_cur_fndecl = current_function_decl;
   struct cgraph_edge *cs;
@@ -2647,7 +2203,12 @@ convert_callers (struct cgraph_node *nod
       current_function_decl = cs->caller->decl;
       push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl));
 
-      convert_call (cs, cs->call_stmt, notes, true);
+      if (dump_file)
+	fprintf (dump_file, "Checking call %s -> %s\n",
+		 cgraph_node_name (cs->caller),
+		 cgraph_node_name (cs->callee));
+
+      ipa_modify_call_arguments (cs, cs->call_stmt, notes);
       compute_inline_parameters (cs->caller);
 
       pop_cfun ();
@@ -2662,7 +2223,11 @@ convert_callers (struct cgraph_node *nod
 	  gimple stmt = gsi_stmt (gsi);
 	  if (gimple_code (stmt) == GIMPLE_CALL
 	      && gimple_call_fndecl (stmt) == node->decl)
-	    convert_call (NULL, stmt, notes, true);
+	    {
+	      if (dump_file)
+		fprintf (dump_file, "Checking recursive call");
+	      ipa_modify_call_arguments (NULL, stmt, notes);
+	    }
 	}
     }
 
@@ -2781,9 +2346,9 @@ create_debug_constructor (tree type, tre
    as given in NOTES.  */
 
 static void
-modify_function (struct cgraph_node *node, VEC (new_parm_note_t, heap) *notes)
+modify_function (struct cgraph_node *node, VEC (ipa_parm_note_t, heap) *notes)
 {
-  modify_parameters (current_function_decl, notes);
+  ipa_modify_formal_parameters (current_function_decl, notes, "ISRA");
   scan_function (sra_ipa_modify_expr, sra_ipa_modify_assign,
 		 replace_removed_params_ssa_names, false, notes);
   convert_callers (node, notes);
@@ -2798,7 +2363,7 @@ static unsigned int
 ipa_early_sra (void)
 {
   struct cgraph_node *node = cgraph_node (current_function_decl);
-  VEC (new_parm_note_t, heap) *notes;
+  VEC (ipa_parm_note_t, heap) *notes;
   int ret = 0;
 
   if (!cgraph_node_can_be_local_p (node))
@@ -2847,13 +2412,11 @@ ipa_early_sra (void)
   notes = analyze_all_param_acesses ();
   if (!notes)
     goto out;
-  dump_param_notes (notes);
-
-  if (!check_callers (node, notes))
-    goto out;
+  if (dump_file)
+    ipa_dump_param_notes (dump_file, notes, current_function_decl);
 
   modify_function (node, notes);
-  VEC_free (new_parm_note_t, heap, notes);
+  VEC_free (ipa_parm_note_t, heap, notes);
   ret = TODO_update_ssa;
 
  out:
@@ -3327,9 +2890,9 @@ generate_subtree_copies (struct access *
 	  bool repl_found;
 	  gimple stmt;
 
-	  repl_found = build_access_expr (&expr, TREE_TYPE (agg),
-					  access->offset - top_offset,
-					  access->type, false);
+	  repl_found = build_ref_for_offset (&expr, TREE_TYPE (agg),
+					     access->offset - top_offset,
+					     access->type, false);
 	  gcc_assert (repl_found);
 
 	  if (write)
@@ -3616,9 +3179,10 @@ load_assign_lhs_subreplacements (struct
 		  *refreshed = true;
 		}
 
-	      repl_found = build_access_expr (&expr, TREE_TYPE (top_racc->base),
-					      lacc->offset - left_offset,
-					      lacc->type, false);
+	      repl_found = build_ref_for_offset (&expr,
+						 TREE_TYPE (top_racc->base),
+						 lacc->offset - left_offset,
+						 lacc->type, false);
 	      gcc_assert (repl_found);
 
 	      stmt = gimple_build_assign (get_access_replacement (lacc), expr);
@@ -3758,8 +3322,8 @@ fix_modified_assign_compatibility (gimpl
       && (!lacc || !lacc->first_child))
     {
       tree expr = unshare_expr (lhs);
-      bool found = build_access_expr (&expr, ltype, racc->offset, rtype,
-				      false);
+      bool found = build_ref_for_offset (&expr, ltype, racc->offset, rtype,
+					 false);
       if (found)
 	{
 	  gimple_assign_set_lhs (*stmt, expr);
@@ -3771,8 +3335,8 @@ fix_modified_assign_compatibility (gimpl
       && (!racc || !racc->first_child))
     {
       tree expr = unshare_expr (*rhs);
-      bool found = build_access_expr (&expr, rtype, lacc->offset, ltype,
-				      false);
+      bool found = build_ref_for_offset (&expr, rtype, lacc->offset, ltype,
+					 false);
       if (found)
 	{
 	  gimple_assign_set_rhs1 (*stmt, expr);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]