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]

[tuples] Fix various C++ failures


This patch fixes other bugs that were causing problems in
C++:

- It re-enables clone_body and inlining of functions in High
  GIMPLE form.  It also removes support for inlining bodies in GENERIC
  form.  It was not necessary, as clone_body is called with functions
  in High GIMPLE form.

- TREE_BLOCKs were being removed because mark_all_vars_used_1 was
  handling TREE_BLOCK of expressions.  This is no longer possible,
  as there can be no expressions inside a gimple statement, so the
  gimple_block() of every statement weren't being marked as needed.
  Causing spurious failures.

- It removes gimple_shallow_copy (not used) and adds support for deep
  copying high gimple statements that have sub-statements
  (GIMPLE_BIND, GIMPLE_TRY, etc).

This fixes about 1,070 failures in C++ and 4 failures in C.  We still
don't totally build libstdc++, but this fixes enough failures that I
didn't want to hold it back.

Tested on x86.


Diego.

	* ipa-inline.c (cgraph_clone_inlined_nodes): Change uses
	of DECL_SAVED_TREE with gimple_body.
	(cgraph_decide_inlining_incrementally): Likewise.
	* gimple-iterator.c (gsi_insert_seq_before_without_update):
	Do nothing if SEQ is NULL.
	(gsi_insert_seq_after_without_update): Likewise.
	* tree-ssa-live.c (mark_all_vars_used_1): Do not handle
	EXPR trees.
	(remove_unused_locals): Mark the gimple_block of every
	statement as used.
	* tree-inline.c (remap_gimple_stmt): Forward declare.
	(remap_decls): Tidy comments.
	(remap_gimple_seq): New.
	(copy_gimple_bind): New.
	(remap_gimple_stmt): Call it.
	Handle High GIMPLE statements.
	(copy_bb): Regimplify operands on COPY_GSI instead of
	GSI.
	(copy_cfg_body): Tidy.
	(copy_generic_body): Remove unused function.
	(clone_body): Tuplify.
	* c-common.c (c_warn_unused_result): Remove assertion for
	FUNCTION_TYPE.
	* gimple.c (gimple_seq_copy): Rename from
	gimple_seq_deep_copy.  Update all users.
	(walk_gimple_stmt): Assert that STMT has no substatements
	in the default case.
	(gimple_copy_1): Merge into gimple_copy.
	(gimple_copy): Always do deep copying.
	Handle statements with substatements.
	(gimple_shallow_copy): Remove unused function.
	(gimple_deep_copy): Remove.  Update all users.
	* gimple.h: Tidy comments and structure fields
	everywhere.
	(gimple_has_substatements): New.
	(walk_stmt_fn): Change last argument to struct walk_stmt_info *.
	Update all users.

cp/ChangeLog.tuples

	* optimize.c (maybe_clone_body): Re-enable call to
	clone_body.
	* cp-gimplify.c (cp_gimplify_omp_for): Mark disabled
	code with call to gimple_unreachable.
	(cp_genericize): Fix handling of clone bodies.

Index: value-prof.c
===================================================================
--- value-prof.c	(revision 134164)
+++ value-prof.c	(working copy)
@@ -1075,7 +1075,7 @@ gimple_ic (gimple stmt, gimple call, str
   bb1end = stmt3;

   label1 = gimple_build_label (label_decl1);
-  stmt1 = gimple_deep_copy (stmt);
+  stmt1 = gimple_copy (stmt);
   gimple_call_set_fn (stmt,
 		      build_addr (direct_call->decl, current_function_decl));
   gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
@@ -1271,7 +1271,7 @@ gimple_stringop_fixed_value (gimple stmt
   bb1end = stmt3;

   label1 = gimple_build_label (label_decl1);
-  stmt1 = gimple_deep_copy (stmt);
+  stmt1 = gimple_copy (stmt);
   gimple_call_set_arg (stmt1, 2, value);
   gsi_insert_before (&gsi, label1, GSI_SAME_STMT);
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
Index: omp-low.c
===================================================================
--- omp-low.c	(revision 134164)
+++ omp-low.c	(working copy)
@@ -1444,10 +1444,10 @@ scan_omp_1_op (tree *tp, int *walk_subtr
    the current statement in GSI.  */

 static tree
-scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, void *data)
+scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
+		 struct walk_stmt_info *wi)
 {
   gimple stmt = gsi_stmt (*gsi);
-  struct walk_stmt_info *wi = data;
   omp_context *ctx = wi->info;

   if (gimple_has_location (stmt))
Index: cp/optimize.c
===================================================================
--- cp/optimize.c	(revision 134164)
+++ cp/optimize.c	(working copy)
@@ -185,12 +185,7 @@ maybe_clone_body (tree fn)
 	  *pointer_map_insert (decl_map, parm) = clone_parm;
 	}
       /* Clone the body.  */
-	 /* FIXME tuples.  */
-#if 0
       clone_body (clone, fn, decl_map);
-#else
-      gimple_unreachable ();
-#endif

       /* Clean up.  */
       pointer_map_destroy (decl_map);
Index: cp/cp-gimplify.c
===================================================================
--- cp/cp-gimplify.c	(revision 134164)
+++ cp/cp-gimplify.c	(working copy)
@@ -341,9 +341,12 @@ cp_gimplify_omp_for (tree *expr_p)
      statement expressions within the INIT, COND, or INCR expressions.  */
   cont_block = begin_bc_block (bc_continue);

-  /* FIXME tuples
+  /* FIXME tuples.  */
+#if 0
   gimplify_stmt (expr_p);
-  */
+#else
+  gimple_unreachable ();
+#endif

   OMP_FOR_BODY (for_stmt)
     = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
@@ -766,17 +769,9 @@ cp_genericize (tree fndecl)
       relayout_decl (t);
     }

-  /* If we're a clone, the body is already GIMPLE.  Find the original
-     body, and set the gimple body for this function accordingly.  */
+  /* If we're a clone, the body is already GIMPLE.  */
   if (DECL_CLONED_FUNCTION_P (fndecl))
-    {
-      tree orig = DECL_CLONED_FUNCTION (fndecl);
-      gimple_seq seq = gimple_body (orig);
-
-      gimple_set_body (fndecl, seq);
-      DECL_SAVED_TREE (fndecl) = NULL_TREE;
-      return;
-    }
+    return;

   /* We do want to see every occurrence of the parms, so we can't just use
      walk_tree's hash functionality.  */
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 134164)
+++ ipa-inline.c	(working copy)
@@ -210,7 +210,7 @@ cgraph_clone_inlined_nodes (struct cgrap
 	  && flag_unit_at_a_time)
 	{
 	  gcc_assert (!e->callee->global.inlined_to);
-	  if (DECL_SAVED_TREE (e->callee->decl))
+	  if (gimple_body (e->callee->decl))
 	    overall_insns -= e->callee->global.insns, nfunctions_inlined++;
 	  duplicate = false;
 	}
@@ -1329,7 +1329,7 @@ cgraph_decide_inlining_incrementally (st
 	    }
 	  continue;
 	}
-      if (!DECL_SAVED_TREE (e->callee->decl) && !e->callee->inline_decl)
+      if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
 	{
 	  if (dump_file)
 	    {
@@ -1406,7 +1406,7 @@ cgraph_decide_inlining_incrementally (st
 	      }
 	    continue;
 	  }
-	if (!DECL_SAVED_TREE (e->callee->decl) && !e->callee->inline_decl)
+	if (!gimple_body (e->callee->decl) && !e->callee->inline_decl)
 	  {
 	    if (dump_file)
 	      {
Index: gimple-iterator.c
===================================================================
--- gimple-iterator.c	(revision 134164)
+++ gimple-iterator.c	(working copy)
@@ -146,6 +146,9 @@ gsi_insert_seq_before_without_update (gi
 {
   gimple_seq_node first, last;

+  if (seq == NULL)
+    return;
+
   /* Don't allow inserting a sequence into itself.  */
   gcc_assert (seq != i->seq);

@@ -254,6 +257,9 @@ gsi_insert_seq_after_without_update (gim
 {
   gimple_seq_node first, last;

+  if (seq == NULL)
+    return;
+
   /* Don't allow inserting a sequence into itself.  */
   gcc_assert (seq != i->seq);

Index: tree-eh.c
===================================================================
--- tree-eh.c	(revision 134164)
+++ tree-eh.c	(working copy)
@@ -528,7 +528,7 @@ replace_goto_queue_1 (gimple stmt, struc
       seq = find_goto_replacement (tf, temp);
       if (seq)
 	{
-	  gsi_insert_seq_before (gsi, gimple_seq_deep_copy (seq), GSI_SAME_STMT);
+	  gsi_insert_seq_before (gsi, gimple_seq_copy (seq), GSI_SAME_STMT);
 	  gsi_remove (gsi, false);
 	  return;
 	}
@@ -839,7 +839,7 @@ lower_try_finally_dup_block (gimple_seq
   gimple region = NULL;
   gimple_seq new_seq;

-  new_seq = gimple_seq_deep_copy (seq);
+  new_seq = gimple_seq_copy (seq);

   if (outer_state->tf)
     region = outer_state->tf->try_finally_expr;
Index: tree-ssa-live.c
===================================================================
--- tree-ssa-live.c	(revision 134164)
+++ tree-ssa-live.c	(working copy)
@@ -402,19 +402,12 @@ static inline void mark_all_vars_used (t
 /* Helper function for mark_all_vars_used, called via walk_tree.  */

 static tree
-mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
-		      void *data)
+mark_all_vars_used_1 (tree *tp, int *walk_subtrees, void *data)
 {
   tree t = *tp;
-  enum tree_code_class c = TREE_CODE_CLASS (TREE_CODE (t));
-  tree b;

   if (TREE_CODE (t) == SSA_NAME)
     t = SSA_NAME_VAR (t);
-  if ((IS_EXPR_CODE_CLASS (c)
-       || IS_GIMPLE_STMT_CODE_CLASS (c))
-      && (b = TREE_BLOCK (t)) != NULL)
-    TREE_USED (b) = true;

   /* Ignore TREE_ORIGINAL for TARGET_MEM_REFS, as well as other
      fields that do not contain vars.  */
@@ -582,6 +575,7 @@ remove_unused_locals (void)
   bitmap global_unused_vars = NULL;

   mark_scope_block_unused (DECL_INITIAL (current_function_decl));
+
   /* Assume all locals are unused.  */
   FOR_EACH_REFERENCED_VAR (t, rvi)
     var_ann (t)->used = false;
@@ -594,8 +588,16 @@ remove_unused_locals (void)

       /* Walk the statements.  */
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-	for (i = 0; i < gimple_num_ops (gsi_stmt (gsi)); i++)
-	  mark_all_vars_used (gimple_op_ptr (gsi_stmt (gsi), i), NULL);
+	{
+	  gimple stmt = gsi_stmt (gsi);
+	  tree b = gimple_block (stmt);
+
+	  if (b)
+	    TREE_USED (b) = true;
+
+	  for (i = 0; i < gimple_num_ops (stmt); i++)
+	    mark_all_vars_used (gimple_op_ptr (gsi_stmt (gsi), i), NULL);
+	}

       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
         {
Index: tree-ssa-dce.c
===================================================================
--- tree-ssa-dce.c	(revision 134164)
+++ tree-ssa-dce.c	(working copy)
@@ -710,7 +710,7 @@ eliminate_unnecessary_stmts (void)
 			}
 		
 		      push_stmt_changes (gsi_stmt_ptr (&gsi));
-		      g = gimple_deep_copy (stmt);
+		      g = gimple_copy (stmt);
 		      gimple_call_set_lhs (g, NULL_TREE);
 		      gsi_replace (&gsi, g, false);
 		      maybe_clean_or_replace_eh_stmt (stmt, g);
Index: tree-nested.c
===================================================================
--- tree-nested.c	(revision 134164)
+++ tree-nested.c	(working copy)
@@ -1094,9 +1094,8 @@ convert_nonlocal_omp_clauses (tree *pcla

 static tree
 convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool
*handled_ops_p,
-				 void *data)
+				 struct walk_stmt_info *wi)
 {
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info;
   tree save_local_var_chain;
   bitmap save_suppress;
@@ -1454,9 +1453,8 @@ convert_local_omp_clauses (tree *pclause

 static tree
 convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
-			      void *data)
+			      struct walk_stmt_info *wi)
 {
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info;
   tree save_local_var_chain;
   bitmap save_suppress;
@@ -1545,9 +1543,8 @@ convert_local_reference_stmt (gimple_stm

 static tree
 convert_nl_goto_reference (gimple_stmt_iterator *gsi, bool *handled_ops_p,
-			   void *data)
+			   struct walk_stmt_info *wi)
 {
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info, *i;
   tree label, new_label, target_context, x, field;
   void **slot;
@@ -1617,9 +1614,8 @@ convert_nl_goto_reference (gimple_stmt_i

 static tree
 convert_nl_goto_receiver (gimple_stmt_iterator *gsi, bool *handled_ops_p,
-			  void *data)
+			  struct walk_stmt_info *wi)
 {
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info;
   tree label, new_label;
   gimple_stmt_iterator tmp_gsi;
@@ -1737,9 +1733,8 @@ convert_tramp_reference_op (tree *tp, in

 static tree
 convert_tramp_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
-			      void *data)
+			      struct walk_stmt_info *wi)
 {
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   gimple stmt = gsi_stmt (*gsi);

   switch (gimple_code (stmt))
@@ -1772,9 +1767,9 @@ convert_tramp_reference_stmt (gimple_stm
    is set up properly for the call.  */

 static tree
-convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
void *data)
+convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
+                     struct walk_stmt_info *wi)
 {
-  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
   struct nesting_info *info = wi->info;
   tree decl, target_context;
   char save_static_chain_added;
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 134164)
+++ tree-inline.c	(working copy)
@@ -127,7 +127,6 @@ eni_weights eni_time_weights;
 /* Prototypes.  */

 static tree declare_return_variable (copy_body_data *, tree, tree, tree *);
-static tree copy_generic_body (copy_body_data *);
 static bool inlinable_function_p (tree);
 static void remap_block (tree *, copy_body_data *);
 static tree remap_decls (tree, copy_body_data *);
@@ -142,6 +141,7 @@ static tree copy_decl_to_var (tree, copy
 static tree copy_result_decl_to_var (tree, copy_body_data *);
 static tree copy_decl_no_change (tree, copy_body_data *);
 static tree copy_decl_maybe_to_var (tree, copy_body_data *);
+static gimple remap_gimple_stmt (gimple, copy_body_data *);

 /* Insert a tree->tree mapping for ID.  Despite the name suggests
    that the trees should be variables, it is used for more than that.  */
@@ -448,9 +448,9 @@ remap_decls (tree decls, copy_body_data
     {
       tree new_var;

-      /* We can not chain the local static declarations into the
unexpanded_var_list
-         as we can't duplicate them or break one decl rule.  Go ahead and link
-         them into unexpanded_var_list.  */
+      /* We cannot chain the local static declarations into the
+	 unexpanded_var_list as we can't duplicate them or break one
+	 decl rule.  Go ahead and link them into unexpanded_var_list.  */
       if (!auto_var_in_fn_p (old_var, id->src_fn)
 	  && !DECL_EXTERNAL (old_var))
 	{
@@ -462,7 +462,7 @@ remap_decls (tree decls, copy_body_data
       /* Remap the variable.  */
       new_var = remap_decl (old_var, id);

-      /* If we didn't remap this variable, so we can't mess with its
+      /* If we didn't remap this variable, we can't mess with its
 	 TREE_CHAIN.  If we remapped this variable to the return slot, it's
 	 already declared somewhere else, so don't declare it here.  */
       if (!new_var || new_var == id->retvar)
@@ -559,6 +559,56 @@ copy_bind_expr (tree *tp, int *walk_subt
 }


+/* Create a new gimple_seq by remapping all the statements in BODY
+   using the inlining information in ID.  */
+
+static gimple_seq
+remap_gimple_seq (gimple_seq body, copy_body_data *id)
+{
+  gimple_stmt_iterator si;
+  gimple_seq new_body = NULL;
+
+  for (si = gsi_start (body); !gsi_end_p (si); gsi_next (&si))
+    {
+      gimple new_stmt = remap_gimple_stmt (gsi_stmt (si), id);
+      gimple_seq_add_stmt (&new_body, new_stmt);
+    }
+
+  return new_body;
+}
+
+
+/* Copy a GIMPLE_BIND statement STMT, remapping all the symbols in its
+   block using the mapping information in ID.  */
+
+static gimple
+copy_gimple_bind (gimple stmt, copy_body_data *id)
+{
+  gimple new_bind;
+  tree new_block, new_vars;
+  gimple_seq body, new_body;
+
+  /* Copy the statement.  Note that we purposely don't use copy_stmt
+     here because we need to remap statements as we copy.  */
+  body = gimple_bind_body (stmt);
+  new_body = remap_gimple_seq (body, id);
+
+  new_block = gimple_bind_block (stmt);
+  if (new_block)
+    remap_block (&new_block, id);
+
+  /* This will remap a lot of the same decls again, but this should be
+     harmless.  */
+  new_vars = gimple_bind_vars (stmt);
+  if (new_vars)
+    new_vars = remap_decls (new_vars, id);
+
+  new_bind = gimple_build_bind (new_vars, new_body, new_block);
+
+  return new_bind;
+}
+
+
 /* Remap the GIMPLE operand pointed to by *TP.  DATA is really a
    'struct walk_stmt_info *'.  DATA->INFO is a 'copy_body_data *'.
    WALK_SUBTREES is used to indicate walk_gimple_op whether to keep
@@ -985,7 +1035,7 @@ copy_tree_body_r (tree *tp, int *walk_su
 static gimple
 remap_gimple_stmt (gimple stmt, copy_body_data *id)
 {
-  gimple copy;
+  gimple copy = NULL;
   struct walk_stmt_info wi;
   tree new_block;

@@ -1005,47 +1055,89 @@ remap_gimple_stmt (gimple stmt, copy_bod

       /* If we're returning something, just turn that into an
 	 assignment into the equivalent of the original RESULT_DECL.
-	 If RETVAL  is just the result decl, the result decl has
+	 If RETVAL is just the result decl, the result decl has
 	 already been set (e.g. a recent "foo (&result_decl, ...)");
 	 just toss the entire GIMPLE_RETURN.  */
       if (retval && TREE_CODE (retval) != RESULT_DECL)
-	{
-	  gimple s = gimple_build_assign (id->retvar, retval);
-	  return remap_gimple_stmt (s, id);
-	}
+	copy = gimple_build_assign (id->retvar, retval);
       else
 	return gimple_build_nop ();
     }
-  else if (gimple_code (stmt) == GIMPLE_BIND)
-    /* FIXME tuples: Should be removed?
-       Was copy_bind_expr (tp, walk_subtrees, id);  */
-    gcc_unreachable ();
-
-  /* Here we handle statements that are not completely rewritten.
-     First we detect some inlining-induced bogosities for
-     discarding.  */
-  if (gimple_assign_copy_p (stmt)
-      && gimple_assign_lhs (stmt) == gimple_assign_rhs1 (stmt)
-      && auto_var_in_fn_p (gimple_assign_lhs (stmt), id->src_fn))
+  else if (gimple_has_substatements (stmt))
     {
-      /* Some assignments VAR = VAR; don't generate any rtl code
-	 and thus don't count as variable modification.  Avoid
-	 keeping bogosities like 0 = 0.  */
-      tree decl = gimple_assign_lhs (stmt), value;
-      tree *n;
+      gimple_seq s1, s2;

-      n = (tree *) pointer_map_contains (id->decl_map, decl);
-      if (n)
+      /* When cloning bodies from the C++ front end, we will be handed bodies
+	 in High GIMPLE form.  Handle here all the High GIMPLE statements that
+	 have embedded statements.  */
+      switch (gimple_code (stmt))
 	{
-	  value = *n;
-	  STRIP_TYPE_NOPS (value);
-	  if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
-	    return gimple_build_nop ();
+	case GIMPLE_BIND:
+	  copy = copy_gimple_bind (stmt, id);
+	  break;
+
+	case GIMPLE_CATCH:
+	  s1 = remap_gimple_seq (gimple_catch_handler (stmt), id);
+	  copy = gimple_build_catch (gimple_catch_types (stmt), s1);
+	  break;
+
+	case GIMPLE_EH_FILTER:
+	  s1 = remap_gimple_seq (gimple_eh_filter_failure (stmt), id);
+	  copy = gimple_build_eh_filter (gimple_eh_filter_types (stmt), s1);
+	  break;
+
+	case GIMPLE_TRY:
+	  s1 = remap_gimple_seq (gimple_try_eval (stmt), id);
+	  s2 = remap_gimple_seq (gimple_try_cleanup (stmt), id);
+	  copy = gimple_build_try (s1, s2, gimple_try_kind (stmt));
+	  break;
+
+	case GIMPLE_WITH_CLEANUP_EXPR:
+	  s1 = remap_gimple_seq (gimple_wce_cleanup (stmt), id);
+	  copy = gimple_build_wce (s1);
+	  break;
+
+	  /* FIXME tuples.  */
+	case GIMPLE_OMP_FOR:
+	case GIMPLE_OMP_MASTER:
+	case GIMPLE_OMP_ORDERED:
+	case GIMPLE_OMP_SECTION:
+	case GIMPLE_OMP_PARALLEL:
+	case GIMPLE_OMP_SECTIONS:
+	case GIMPLE_OMP_SINGLE:
+	default:
+	  gcc_unreachable ();
 	}
     }
+  else
+    {
+      if (gimple_assign_copy_p (stmt)
+	  && gimple_assign_lhs (stmt) == gimple_assign_rhs1 (stmt)
+	  && auto_var_in_fn_p (gimple_assign_lhs (stmt), id->src_fn))
+	{
+	  /* Here we handle statements that are not completely rewritten.
+	     First we detect some inlining-induced bogosities for
+	     discarding.  */

-  /* Create a new deep copy of the statement.  */
-  copy = gimple_deep_copy (stmt);
+	  /* Some assignments VAR = VAR; don't generate any rtl code
+	     and thus don't count as variable modification.  Avoid
+	     keeping bogosities like 0 = 0.  */
+	  tree decl = gimple_assign_lhs (stmt), value;
+	  tree *n;
+
+	  n = (tree *) pointer_map_contains (id->decl_map, decl);
+	  if (n)
+	    {
+	      value = *n;
+	      STRIP_TYPE_NOPS (value);
+	      if (TREE_CONSTANT (value) || TREE_READONLY_DECL_P (value))
+		return gimple_build_nop ();
+	    }
+	}
+
+      /* Create a new deep copy of the statement.  */
+      copy = gimple_copy (stmt);
+    }

   /* If STMT has a block defined, map it to the newly constructed
      block.  When inlining we want statements without a block to
@@ -1115,12 +1207,13 @@ copy_bb (copy_body_data *id, basic_block
 	  || id->regimplify)
 	{
 	  tree new_rhs;
-	  new_rhs = force_gimple_operand_gsi (&gsi, gimple_assign_rhs1 (stmt),
+	  new_rhs = force_gimple_operand_gsi (&copy_gsi,
+	                                      gimple_assign_rhs1 (stmt),
 	                                      true, NULL, true, GSI_SAME_STMT);
 	  gimple_assign_set_rhs1 (stmt, new_rhs);
 	}
       else if (id->regimplify)
-	gimple_regimplify_operands (stmt, &gsi);
+	gimple_regimplify_operands (stmt, &copy_gsi);

       gsi_insert_after (&copy_gsi, stmt, GSI_NEW_STMT);

@@ -1623,7 +1716,6 @@ copy_cfg_body (copy_body_data * id, gcov

   cfun_to_copy = id->src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);

-
   ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = entry_block_map;
   EXIT_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy)->aux = exit_block_map;
   entry_block_map->aux = ENTRY_BLOCK_PTR_FOR_FUNCTION (cfun_to_copy);
@@ -1646,17 +1738,21 @@ copy_cfg_body (copy_body_data * id, gcov
     }

   last = last_basic_block;
+
   /* Now that we've duplicated the blocks, duplicate their edges.  */
   FOR_ALL_BB_FN (bb, cfun_to_copy)
     copy_edges_for_bb (bb, count_scale, exit_block_map);
+
   if (gimple_in_ssa_p (cfun))
     FOR_ALL_BB_FN (bb, cfun_to_copy)
       copy_phis_for_bb (bb, id);
+
   FOR_ALL_BB_FN (bb, cfun_to_copy)
     {
       ((basic_block)bb->aux)->aux = NULL;
       bb->aux = NULL;
     }
+
   /* Zero out AUX fields of newly created block during EH edge
      insertion. */
   for (; last < last_basic_block; last++)
@@ -1667,22 +1763,6 @@ copy_cfg_body (copy_body_data * id, gcov
   return new_fndecl;
 }

-/* Make a copy of the GENERIC body of FN so that it can be inserted
-   inline in another function.  */
-
-static tree
-copy_generic_body (copy_body_data *id)
-{
-  tree body;
-  tree fndecl = id->src_fn;
-
-  gcc_assert (!gimple_body (fndecl));
-  body = DECL_SAVED_TREE (fndecl);
-  walk_tree (&body, copy_tree_body_r, id, NULL);
-
-  return body;
-}
-
 /* Make a copy of the GIMPLE body of function ID->SRC_FN.  Profile and
    coverage count are in FREQUENCY and COUNT.  ENTRY_BLOCK_MAP and
    EXIT_BLOCK_MAP are the entry and exit blocks to the region.  */
@@ -2204,10 +2284,9 @@ inline_forbidden_p_op (tree *nodep, int

 static tree
 inline_forbidden_p_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
-			 void *wip)
+			 struct walk_stmt_info *wip)
 {
-  struct walk_stmt_info wi = *(struct walk_stmt_info *) wip;
-  tree fn = (tree) wi.info;
+  tree fn = (tree) wip->info;
   tree t;
   gimple stmt = gsi_stmt (*gsi);

@@ -2895,7 +2974,9 @@ count_insns_seq (gimple_seq seq, eni_wei
   return n;
 }

+
 /* Install new lexical TREE_BLOCK underneath 'current_block'.  */
+
 static void
 add_lexical_block (tree current_block, tree new_block)
 {
@@ -3401,14 +3482,18 @@ optimize_inline_calls (tree fn)
 }


-/* FN is a function that has a complete body, and CLONE is a function
-   whose body is to be set to a copy of FN, mapping argument
-   declarations according to the ARG_MAP splay_tree.  */
+/* FN is a function in High GIMPLE form that has a complete body and no
+   CFG.  CLONE is a function whose body is to be set to a copy of FN,
+   mapping argument declarations according to the ARG_MAP splay_tree.  */

 void
 clone_body (tree clone, tree fn, void *arg_map)
 {
   copy_body_data id;
+  gimple_seq new_body;
+
+  /* FN must already be in GIMPLE form.  */
+  gcc_assert (gimple_body (fn));

   /* Clone the body, as if we were making an inline call.  But, remap
      the parameters in the callee to the parameters of caller.  */
@@ -3427,11 +3512,9 @@ clone_body (tree clone, tree fn, void *a
   /* We're not inside any EH region.  */
   id.eh_region = -1;

-  gcc_unreachable ();
-
   /* Actually copy the body.  */
-  /* FIXME tuples.  DECL_SAVED_TREE needs to be changed to gimple_body.  */
-  append_to_statement_list_force (copy_generic_body (&id),
&DECL_SAVED_TREE (clone));
+  new_body = remap_gimple_seq (gimple_body (fn), &id);
+  gimple_set_body (clone, new_body);
 }

 /* Passed to walk_tree.  Copies the node pointed to, if appropriate.  */
Index: c-common.c
===================================================================
--- c-common.c	(revision 134164)
+++ c-common.c	(working copy)
@@ -6749,7 +6749,6 @@ c_warn_unused_result (gimple_seq seq)
 	      /* Look past pointer-to-function to the function type itself.  */
 	      ftype = TREE_TYPE (ftype);
 	    }
-	  gcc_assert (TREE_CODE (ftype) == FUNCTION_TYPE);

 	  if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
 	    {
Index: gimple.c
===================================================================
--- gimple.c	(revision 134164)
+++ gimple.c	(working copy)
@@ -1150,7 +1150,7 @@ empty_body_p (gimple_seq body)
 /* Perform a deep copy of sequence SRC and return the result.  */

 gimple_seq
-gimple_seq_deep_copy (gimple_seq src)
+gimple_seq_copy (gimple_seq src)
 {
   gimple_stmt_iterator gsi;
   gimple_seq new = gimple_seq_alloc ();
@@ -1158,7 +1158,7 @@ gimple_seq_deep_copy (gimple_seq src)

   for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
     {
-      stmt = gimple_deep_copy (gsi_stmt (gsi));
+      stmt = gimple_copy (gsi_stmt (gsi));
       gimple_seq_add_stmt (&new, stmt);
     }

@@ -1586,7 +1586,6 @@ walk_gimple_stmt (gimple_stmt_iterator *
 	return wi->callback_result;

       /* FALL THROUGH.  */
-
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_OMP_MASTER:
     case GIMPLE_OMP_ORDERED:
@@ -1608,6 +1607,7 @@ walk_gimple_stmt (gimple_stmt_iterator *
       break;

     default:
+      gcc_assert (!gimple_has_substatements (stmt));
       break;
     }

@@ -1904,33 +1904,119 @@ gimple_set_lhs (gimple stmt, tree lhs)
 }


-/* Helper for gimple_deep_copy and gimple_shallow_copy.  If
-   IS_DEEP_COPY is true, return a deep copy of STMT (all the operands
-   are copied with unshare_expr).  Otherwise, return a shallow copy of
-   STMT (all the operands in the new copy point to the operands in the
-   original). The DEF, USE, VDEF and VUSE operand arrays in the new
-   copy are set to NULL.  */
+/* Return a deep copy of statement STMT.  All the operands from STMT
+   are reallocated and copied using unshare_expr.  The DEF, USE, VDEF
+   and VUSE operand arrays are set to empty in the new copy.  */

-static inline gimple
-gimple_copy_1 (gimple stmt, bool is_deep_copy)
+gimple
+gimple_copy (gimple stmt)
 {
   enum gimple_code code = gimple_code (stmt);
   size_t num_ops = gimple_num_ops (stmt);
   gimple copy = gimple_alloc (code);
   unsigned i;

+  /* Shallow copy all the fields from STMT.  */
   memcpy (copy, stmt, gimple_size (code));
+
+  /* If STMT has sub-statements, deep-copy them as well.  */
+  if (gimple_has_substatements (stmt))
+    {
+      gimple_seq new_seq;
+      tree t;
+
+      switch (gimple_code (stmt))
+	{
+	case GIMPLE_BIND:
+	  new_seq = gimple_seq_copy (gimple_bind_body (stmt));
+	  gimple_bind_set_body (copy, new_seq);
+	  gimple_bind_set_vars (copy, unshare_expr (gimple_bind_vars (stmt)));
+	  gimple_bind_set_block (copy, unshare_expr (gimple_bind_block (stmt)));
+	  break;
+
+	case GIMPLE_CATCH:
+	  new_seq = gimple_seq_copy (gimple_catch_handler (stmt));
+	  gimple_catch_set_handler (copy, new_seq);
+	  t = unshare_expr (gimple_catch_types (stmt));
+	  gimple_catch_set_types (copy, t);
+	  break;
+
+	case GIMPLE_EH_FILTER:
+	  new_seq = gimple_seq_copy (gimple_eh_filter_failure (stmt));
+	  gimple_eh_filter_set_failure (copy, new_seq);
+	  t = unshare_expr (gimple_eh_filter_types (stmt));
+	  gimple_eh_filter_set_types (copy, t);
+	  break;
+
+	case GIMPLE_TRY:
+	  new_seq = gimple_seq_copy (gimple_try_eval (stmt));
+	  gimple_try_set_eval (copy, new_seq);
+	  new_seq = gimple_seq_copy (gimple_try_cleanup (stmt));
+	  gimple_try_set_cleanup (copy, new_seq);
+	  break;
+
+	case GIMPLE_OMP_FOR:
+	  new_seq = gimple_seq_copy (gimple_omp_for_pre_body (stmt));
+	  gimple_omp_for_set_pre_body (copy, new_seq);
+	  t = unshare_expr (gimple_omp_for_clauses (stmt));
+	  gimple_omp_for_set_clauses (copy, t);
+	  t = unshare_expr (gimple_omp_for_initial (stmt));
+	  gimple_omp_for_set_initial (copy, t);
+	  t = unshare_expr (gimple_omp_for_final (stmt));
+	  gimple_omp_for_set_final (copy, t);
+	  t = unshare_expr (gimple_omp_for_incr (stmt));
+	  gimple_omp_for_set_incr (copy, t);
+	  goto copy_omp_body;
+
+	case GIMPLE_OMP_PARALLEL:
+	  t = unshare_expr (gimple_omp_parallel_clauses (stmt));
+	  gimple_omp_parallel_set_clauses (copy, t);
+	  t = unshare_expr (gimple_omp_parallel_child_fn (stmt));
+	  gimple_omp_parallel_set_child_fn (copy, t);
+	  t = unshare_expr (gimple_omp_parallel_data_arg (stmt));
+	  gimple_omp_parallel_set_data_arg (copy, t);
+	  goto copy_omp_body;
+
+	case GIMPLE_OMP_CRITICAL:
+	  t = unshare_expr (gimple_omp_critical_name (stmt));
+	  gimple_omp_critical_set_name (copy, t);
+	  goto copy_omp_body;
+
+	case GIMPLE_OMP_SECTIONS:
+	  t = unshare_expr (gimple_omp_sections_clauses (stmt));
+	  gimple_omp_sections_set_clauses (copy, t);
+	  t = unshare_expr (gimple_omp_sections_control (stmt));
+	  gimple_omp_sections_set_control (copy, t);
+	  /* FALLTHRU  */
+
+	case GIMPLE_OMP_SINGLE:
+	case GIMPLE_OMP_SECTION:
+	case GIMPLE_OMP_MASTER:
+	case GIMPLE_OMP_ORDERED:
+	copy_omp_body:
+	  new_seq = gimple_seq_copy (gimple_omp_body (stmt));
+	  gimple_omp_set_body (copy, new_seq);
+	  break;
+
+	case GIMPLE_WITH_CLEANUP_EXPR:
+	  new_seq = gimple_seq_copy (gimple_wce_cleanup (stmt));
+	  gimple_wce_set_cleanup (copy, new_seq);
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+    }
+
+  /* Make copy of operands.  */
   if (num_ops > 0)
     {
       gimple_alloc_ops (copy, num_ops);
-      if (is_deep_copy)
-	for (i = 0; i < num_ops; i++)
-	  gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
-      else
-	for (i = 0; i < num_ops; i++)
-	  gimple_set_op (copy, i, gimple_op (stmt, i));
+      for (i = 0; i < num_ops; i++)
+	gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
     }

+  /* Clear out SSA operand vectors on COPY.  */
   if (gimple_has_ops (stmt))
     {
       gimple_set_def_ops (copy, NULL);
@@ -1950,33 +2036,6 @@ gimple_copy_1 (gimple stmt, bool is_deep
 }


-/* Return a shallow copy of statement STMT.  The operands in the new
-   statement will point to the original operands in STMT.  The DEF,
-   USE, VDEF and VUSE operand arrays are set to empty in the new copy.
-
-   NOTE: The copy returned by this function is not suitable for
-   insertion into the IL, as it shares the operands with the original
-   statement.  It is used by transformations like inlining which will
-   remap operands from one function to another.  */
-
-gimple
-gimple_shallow_copy (gimple stmt)
-{
-  return gimple_copy_1 (stmt, false);
-}
-
-
-/* Return a deep copy of statement STMT.  All the operands from STMT
-   are reallocated and copied using unshare_expr.  The DEF, USE, VDEF
-   and VUSE operand arrays are set to empty in the new copy.  */
-
-gimple
-gimple_deep_copy (gimple stmt)
-{
-  return gimple_copy_1 (stmt, true);
-}
-
-
 /* Return a copy of statement STMT.  The copy should not retain any use
    information for the variables that appear within it.  */
 /* FIXME tuples.  The charter of this function is unclear.  It was
Index: gimple.h
===================================================================
--- gimple.h	(revision 134164)
+++ gimple.h	(working copy)
@@ -340,6 +340,7 @@ struct gimple_statement_eh_filter GTY(()

   /* Filter types.  */
   tree types;
+
   /* Failure actions.  */
   gimple_seq failure;
 };
@@ -423,6 +424,7 @@ struct gimple_statement_asm GTY(())
 struct gimple_statement_omp_critical GTY(())
 {
   struct gimple_statement_omp omp;
+
   /* Critical section name.  */
   tree name;
 };
@@ -434,14 +436,19 @@ struct gimple_statement_omp_for GTY(())
 {
   struct gimple_statement_omp omp;
   tree clauses;
+
   /* Index variable.  */
   tree index;
+
   /* Initial value.  */
   tree initial;
+
   /* Final value.  */
   tree final;
+
   /* Increment.  */
   tree incr;
+
   /* Pre-body evaluated before the loop body begins.  */
   gimple_seq pre_body;
 };
@@ -452,8 +459,13 @@ struct gimple_statement_omp_for GTY(())
 struct gimple_statement_omp_parallel GTY(())
 {
   struct gimple_statement_omp omp;
+
+  /* Clauses.  */
   tree clauses;
+
+  /* Child function holding the body of the parallel region.  */
   tree child_fn;
+
   /* Shared data argument.  */
   tree data_arg;
 };
@@ -604,7 +616,7 @@ gimple_seq gimple_body (tree);
 gimple_seq gimple_seq_alloc (void);
 void gimple_seq_free (gimple_seq);
 void gimple_seq_add_seq (gimple_seq *, gimple_seq);
-gimple_seq gimple_seq_deep_copy (gimple_seq);
+gimple_seq gimple_seq_copy (gimple_seq);
 int gimple_call_flags (gimple);
 bool gimple_assign_copy_p (gimple);
 bool gimple_assign_single_p (gimple);
@@ -615,8 +627,7 @@ void gimple_assign_set_rhs_from_tree (gi
 void gimple_assign_set_rhs_with_ops (gimple, enum tree_code, tree, tree);
 tree gimple_get_lhs (gimple);
 void gimple_set_lhs (gimple, tree);
-gimple gimple_deep_copy (gimple);
-gimple gimple_shallow_copy (gimple);
+gimple gimple_copy (gimple);
 gimple gimple_copy_no_def_use (gimple);
 bool is_gimple_operand (const_tree);
 void gimple_set_modified (gimple, bool);
@@ -671,6 +682,34 @@ gimple_subcode (const_gimple g)
 }


+/* Return true if statement G has sub-statements.  This is only true for
+   High GIMPLE statements.  */
+
+static inline bool
+gimple_has_substatements (gimple g)
+{
+  switch (gimple_code (g))
+    {
+    case GIMPLE_BIND:
+    case GIMPLE_CATCH:
+    case GIMPLE_EH_FILTER:
+    case GIMPLE_TRY:
+    case GIMPLE_OMP_FOR:
+    case GIMPLE_OMP_MASTER:
+    case GIMPLE_OMP_ORDERED:
+    case GIMPLE_OMP_SECTION:
+    case GIMPLE_OMP_PARALLEL:
+    case GIMPLE_OMP_SECTIONS:
+    case GIMPLE_OMP_SINGLE:
+    case GIMPLE_WITH_CLEANUP_EXPR:
+      return true;
+
+    default:
+      return false;
+    }
+}
+	
+
 /* Return the basic block holding statement G.  */

 static inline struct basic_block_def *
@@ -3352,15 +3391,6 @@ void gsi_commit_one_edge_insert (edge, b
 void gsi_commit_edge_inserts (void);


-/* Callback for walk_gimple_stmt.  Called for every statement found
-   during traversal.  The first argument points to the statement to
-   walk.  The second argument is a flag that the callback sets to
-   'false' if it needs walk_gimple_stmt to also traverse the operands
-   and sub-statements (for statements with associated bodies like
-   GIMPLE_BIND).  The third argument is an anonymous pointer to data
-   to be used by the callback.  */
-typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *, void *);
-
 /* Convenience routines to walk all statements of a gimple function.
    Note that this is useful exclusively before the code is converted
    into SSA form.  Once the program is in SSA form, the standard
@@ -3410,6 +3440,16 @@ struct walk_stmt_info
   tree callback_result;
 };

+/* Callback for walk_gimple_stmt.  Called for every statement found
+   during traversal.  The first argument points to the statement to
+   walk.  The second argument is a flag that the callback sets to
+   'true' if it the callback handled all the operands and
+   sub-statements of the statement (the default value of this flag is
+   'false').  The third argument is an anonymous pointer to data
+   to be used by the callback.  */
+typedef tree (*walk_stmt_fn) (gimple_stmt_iterator *, bool *,
+			      struct walk_stmt_info *);
+
 gimple walk_gimple_seq (gimple_seq, walk_stmt_fn, walk_tree_fn,
 		        struct walk_stmt_info *);
 tree walk_gimple_stmt (gimple_stmt_iterator *, walk_stmt_fn, walk_tree_fn,
Index: tree-cfg.c
===================================================================
--- tree-cfg.c	(revision 134164)
+++ tree-cfg.c	(working copy)
@@ -4711,7 +4711,7 @@ gimple_duplicate_bb (basic_block bb)

       /* Create a new copy of STMT and duplicate STMT's virtual
 	 operands.  */
-      copy = gimple_deep_copy (stmt);
+      copy = gimple_copy (stmt);
       gsi_insert_after (&gsi_tgt, copy, GSI_NEW_STMT);
       copy_virtual_operands (copy, stmt);
       region = lookup_stmt_eh_region (stmt);


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