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]

[gomp] Fix -O0 builds and private vars mapping


When unit at a time is disabled, we cannot call cgraph_finalize_function
directly because it will try to expand the new function while we
are expanding another one.

The new function has to be added to the call graph *and* marked
as needed.  However, the call to cgraph_mark_needed_node will
refuse to add nodes that are not marked as finalized.

The patch also moves the variable mapping logic into
tree-inline.c.  In the near future, I will need to abstract a
bunch of functionality out of the inliner.  We are starting to
use it for quite a few things (procedure cloning, OpenMP function
outlining and inlining per-se).  But I don't want to do this on
the branch, so I'll wait for mainline to be in stage 1 again to
rearrange things.





	* cgraph.c (cgraph_add_new_function): When unit at a time is
	disabled, just add the new function to the graph and mark it
	as needed.
	* gimple-low.c (struct remap_locals_d, add_decls_to_set,
	build_remap_info, remap_locals_r, remap_locals_in_gomp_body):
	Move ...
	* tree-inline.c: ... here.
	(move_decl_to): New local function.
	(remap_locals_r): Call it.
	* tree-inline.h (remap_locals_in_gomp_body): Declare.

Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.77.4.3
diff -d -u -p -r1.77.4.3 cgraph.c
--- cgraph.c	28 Jul 2005 19:28:42 -0000	1.77.4.3
+++ cgraph.c	3 Aug 2005 23:32:12 -0000
@@ -1044,7 +1044,23 @@ cgraph_add_new_function (tree fndecl)
   cfun->function_end_locus = input_location;
   current_function_decl = fndecl;
   gimplify_function_tree (fndecl);
-  cgraph_finalize_function (fndecl, false);
+  if (flag_unit_at_a_time)
+    {
+      /* Add the function to the callgraph to be processed after we
+	 parse all the functions in the compilation unit.  */
+      cgraph_finalize_function (fndecl, false);
+    }
+  else
+    {
+      /* When not compiling the whole unit at a time, the compiler
+	 will output functions right after parsing them.  Since we are
+	 adding a brand new function body that the parser will not
+	 see, we need to make sure it's added at the end of the queue
+	 of callgraph nodes to be expanded.  */
+      struct cgraph_node *n = cgraph_node (fndecl);
+      n->local.finalized = 1;
+      cgraph_mark_needed_node (n);
+    }
 
   /* Restore CFUN and CURRENT_FUNCTION_DECL.  */
   cfun = saved_cfun;
Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 2.24.4.3
diff -d -u -p -r2.24.4.3 gimple-low.c
--- gimple-low.c	1 Aug 2005 21:39:03 -0000	2.24.4.3
+++ gimple-low.c	3 Aug 2005 23:32:12 -0000
@@ -154,139 +154,6 @@ lower_stmt_body (tree expr, struct lower
 }
 
 
-/* Data structure used for remap_locals_r.  */
-
-struct remap_locals_d
-{
-  /* FUNCTION_DECL of the new artificial function containing the
-     pragma's body.  */
-  tree gomp_fn;
-  
-  /* Sets of DECLs representing the different data sharing clauses.  */
-  bitmap private;
-  bitmap firstprivate;
-  bitmap lastprivate;
-  bitmap shared;
-
-  /* Sets of DECLs representing the different data copying clauses.  */
-  bitmap copyin;
-  bitmap copyprivate;
-};
-  
-
-/* Add all the variables in LIST to the bitmap *SET_P.  Create a new
-   bitmap, if necessary.  */
-
-static void
-add_decls_to_set (bitmap *set_p, tree list)
-{
-  tree t;
-
-  if (*set_p == NULL)
-    *set_p = BITMAP_ALLOC (NULL);
-
-  for (t = list; t; t = TREE_CHAIN (t))
-    {
-      tree var = TREE_VALUE (t);
-      bitmap_set_bit (*set_p, DECL_UID (var));
-    }
-}
-
-
-/* Fill in all the data sharing and copying bitmaps in REMAP_INFO_P
-   using the clauses in LIST.  */
-
-static void
-build_remap_info (struct remap_locals_d *remap_info_p, tree list)
-{
-  tree c;
-
-  for (c = list; c; c = TREE_CHAIN (c))
-    {
-      tree clause = TREE_VALUE (c);
-      bitmap *set_p = NULL;
-
-      if (TREE_CODE (clause) == GOMP_CLAUSE_PRIVATE)
-	set_p = &remap_info_p->private;
-      else if (TREE_CODE (clause) == GOMP_CLAUSE_SHARED)
-	set_p = &remap_info_p->shared;
-      else if (TREE_CODE (clause) == GOMP_CLAUSE_FIRSTPRIVATE)
-	set_p = &remap_info_p->firstprivate;
-      else if (TREE_CODE (clause) == GOMP_CLAUSE_LASTPRIVATE)
-	set_p = &remap_info_p->lastprivate;
-      else if (TREE_CODE (clause) == GOMP_CLAUSE_COPYIN)
-	set_p = &remap_info_p->copyin;
-      else if (TREE_CODE (clause) == GOMP_CLAUSE_COPYPRIVATE)
-	set_p = &remap_info_p->copyprivate;
-
-      if (set_p)
-	add_decls_to_set (set_p, TREE_OPERAND (clause, 0));
-    }
-
-  /* FIXME.  Add checking code to disallow variables in multiple sets.
-     Variables may only appear in exactly one set, except for
-     firstprivate and lastprivate.  */
-}
-
-
-/* Callback for walk_tree to change the context of all the local
-   variables found in *TP accordingly to what is described by the
-   data clauses of DATA.GOMP_EXPR.  */
-
-static tree
-remap_locals_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
-{
-  struct remap_locals_d *remap_info = (struct remap_locals_d *)data;
-  tree t, gomp_fn;
-
-  gomp_fn = remap_info->gomp_fn;
-
-  t = *tp;
-  if (TREE_CODE (t) == PARM_DECL)
-    {
-      gcc_unreachable ();
-    }
-  else if (TREE_CODE (t) == VAR_DECL
-           && !is_global_var (t)
-	   && decl_function_context (t) != gomp_fn)
-    {
-      struct function *f = DECL_STRUCT_FUNCTION (gomp_fn);
-      DECL_CONTEXT (t) = gomp_fn;
-      f->unexpanded_var_list = tree_cons (NULL_TREE, t, f->unexpanded_var_list);
-    }
-
-  return NULL;
-}
-
-
-/* Rewrite references to local variables inside the body of GOMP_EXPR
-   using the data sharing information from the directive clauses.
-   GOMP_FN is the compiler generated function that contains the body
-   of GOMP_EXPR.  */
-
-static void
-remap_locals_in_gomp_body (tree gomp_expr, tree gomp_fn)
-{
-  tree_stmt_iterator i;
-  struct remap_locals_d remap_info;
-  tree body = GOMP_PARALLEL_BODY (gomp_expr);
-
-  memset (&remap_info, 0, sizeof (remap_info));
-  remap_info.gomp_fn = gomp_fn;
-
-  /* Build the sets of data sharing clauses.  */
-  build_remap_info (&remap_info, GOMP_PARALLEL_CLAUSES (gomp_expr));
-
-  /* Rewrite all the private local variables so that their context is
-     GOMP_FN.  */
-  for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
-    walk_tree (tsi_stmt_ptr (i), remap_locals_r, &remap_info, NULL);
-
-  /* Add initialization/finalization code in GOMP_FN to model copyin,
-     firstprivate and lastprivate.  */
-}
-
-
 /* Build a new nested function to hold the body of GOMP_EXPR (an
    OpenMP pragma).  The new function is added to the call graph and
    the FUNCTION_DECL representing it, returned.  */
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.192.4.3
diff -d -u -p -r1.192.4.3 tree-inline.c
--- tree-inline.c	28 Jul 2005 19:30:23 -0000	1.192.4.3
+++ tree-inline.c	3 Aug 2005 23:32:12 -0000
@@ -2620,3 +2620,203 @@ inlining_p (inline_data *id)
 {
   return (!id->saving_p && !id->cloning_p);
 }
+
+
+/* Data structure used for remap_locals_r.  */
+
+struct remap_locals_d
+{
+  /* Structure used by the inliner to create mapping between decls
+     when moving them into the artificial function representing the
+     body of an OpenMP directive.  */
+  inline_data id;
+
+  /* Sets of DECLs representing the different data sharing clauses.  */
+  bitmap private;
+  bitmap firstprivate;
+  bitmap lastprivate;
+  bitmap shared;
+
+  /* Sets of DECLs representing the different data copying clauses.  */
+  bitmap copyin;
+  bitmap copyprivate;
+};
+  
+
+/* Add all the variables in LIST to the bitmap *SET_P.  Create a new
+   bitmap, if necessary.  */
+
+static void
+add_decls_to_set (bitmap *set_p, tree list)
+{
+  tree t;
+
+  if (*set_p == NULL)
+    *set_p = BITMAP_ALLOC (NULL);
+
+  for (t = list; t; t = TREE_CHAIN (t))
+    {
+      tree var = TREE_VALUE (t);
+      bitmap_set_bit (*set_p, DECL_UID (var));
+    }
+}
+
+
+/* Fill in all the data sharing and copying bitmaps in REMAP_INFO_P
+   using the clauses in LIST.  */
+
+static void
+build_remap_info (struct remap_locals_d *remap_info_p, tree list)
+{
+  tree c;
+
+  for (c = list; c; c = TREE_CHAIN (c))
+    {
+      tree clause = TREE_VALUE (c);
+      bitmap *set_p = NULL;
+
+      if (TREE_CODE (clause) == GOMP_CLAUSE_PRIVATE)
+	set_p = &remap_info_p->private;
+      else if (TREE_CODE (clause) == GOMP_CLAUSE_SHARED)
+	set_p = &remap_info_p->shared;
+      else if (TREE_CODE (clause) == GOMP_CLAUSE_FIRSTPRIVATE)
+	set_p = &remap_info_p->firstprivate;
+      else if (TREE_CODE (clause) == GOMP_CLAUSE_LASTPRIVATE)
+	set_p = &remap_info_p->lastprivate;
+      else if (TREE_CODE (clause) == GOMP_CLAUSE_COPYIN)
+	set_p = &remap_info_p->copyin;
+      else if (TREE_CODE (clause) == GOMP_CLAUSE_COPYPRIVATE)
+	set_p = &remap_info_p->copyprivate;
+
+      if (set_p)
+	add_decls_to_set (set_p, TREE_OPERAND (clause, 0));
+    }
+
+  /* FIXME.  Add checking code to disallow variables in multiple sets.
+     Variables may only appear in exactly one set, except for
+     firstprivate and lastprivate.  */
+}
+
+
+/* Move local variable VAR from ID->CALLEE into ID->CALLER.  If VAR had
+   not been mapped before, add it to the unexpanded variable list in
+   ID->CALLER.  Return a new VAR_DECL declared inside ID->CALLER to
+   replace VAR.  */
+
+static tree
+move_decl_to (tree var, inline_data *id)
+{
+  tree new_decl;
+  bool first_time_p;
+
+  first_time_p = (splay_tree_lookup (id->decl_map, (splay_tree_key) var) != 0);
+  new_decl = remap_decl (var, id);
+
+  /* If this is the first time that we map VAR, add it to the
+     unexpanded variable list for ID->CALLER.  */
+  if (first_time_p)
+    {
+      struct function *f = DECL_STRUCT_FUNCTION (id->caller);
+      DECL_CONTEXT (new_decl) = id->caller;
+      DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1;
+      f->unexpanded_var_list = tree_cons (NULL_TREE, new_decl,
+					  f->unexpanded_var_list);
+    }
+
+  return new_decl;
+}
+
+
+/* Callback for walk_tree to change the context of all the local
+   variables found in *TP accordingly to what is described by the
+   sets in DATA.  */
+
+static tree
+remap_locals_r (tree *tp, int *ws ATTRIBUTE_UNUSED, void *data)
+{
+  struct remap_locals_d *remap_info = (struct remap_locals_d *)data;
+  tree t, gomp_fn;
+
+  gomp_fn = remap_info->id.caller;
+
+  t = *tp;
+  if (TREE_CODE (t) == PARM_DECL)
+    {
+      gcc_unreachable ();
+    }
+  else if (TREE_CODE (t) == VAR_DECL && !is_global_var (t))
+    {
+      tree new_decl = NULL_TREE;
+
+      /* Remap local variables into GOMP_FN if they appear in one of
+	 the private sets.  */
+      if (remap_info->private
+	  && bitmap_bit_p (remap_info->private, DECL_UID (t)))
+	{
+	  /* Private variables need only be declared inside GOMP_FN.  */
+	  new_decl = move_decl_to (t, &remap_info->id);
+	}
+      else if (remap_info->firstprivate
+	       && bitmap_bit_p (remap_info->firstprivate, DECL_UID (t)))
+	gcc_unreachable ();
+      else if (remap_info->lastprivate
+	       && bitmap_bit_p (remap_info->lastprivate, DECL_UID (t)))
+	gcc_unreachable ();
+      else if (remap_info->shared
+	       && bitmap_bit_p (remap_info->shared, DECL_UID (t)))
+	gcc_unreachable ();
+      else if (remap_info->copyin
+	       && bitmap_bit_p (remap_info->copyin, DECL_UID (t)))
+	gcc_unreachable ();
+      else if (remap_info->copyprivate
+	       && bitmap_bit_p (remap_info->copyprivate, DECL_UID (t)))
+	gcc_unreachable ();
+
+      if (new_decl)
+	*tp = new_decl;
+    }
+
+  return NULL;
+}
+
+
+/* Rewrite references to local variables inside the body of GOMP_EXPR
+   using the data sharing information from the directive clauses.
+   GOMP_FN is the compiler generated function that contains the body
+   of GOMP_EXPR.  */
+
+void
+remap_locals_in_gomp_body (tree gomp_expr, tree gomp_fn)
+{
+  tree_stmt_iterator i;
+  struct remap_locals_d remap_info;
+  tree body = GOMP_PARALLEL_BODY (gomp_expr);
+
+  /* Setup an INLINE_DATA structure to use the generic DECL mapping
+     functions used by the inliner.
+     
+     Notice that since we are outlining the body of GOMP_EXPR into
+     GOMP_FN, we are doing the opposite operation to inlining.  So, we
+     need to switch the roles of CALLEE and CALLER in the inline_data
+     structure to get the desired effect in functions like remap_decl.
+
+     FIXME, the fields CALLER and CALLEE need to be renamed and the
+     generic utility functions in the inliner need to be made more
+     independent.  These functions are now used for procedure cloning,
+     outlining of OpenMP directives and inlining.  */
+  memset (&remap_info, 0, sizeof (remap_info));
+  remap_info.id.callee = current_function_decl;
+  remap_info.id.caller = gomp_fn;
+  remap_info.id.decl_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
+
+  /* Build the sets of data sharing clauses.  */
+  build_remap_info (&remap_info, GOMP_PARALLEL_CLAUSES (gomp_expr));
+
+  /* Rewrite all the private local variables so that their context is
+     GOMP_FN.  */
+  for (i = tsi_start (body); !tsi_end_p (i); tsi_next (&i))
+    walk_tree (tsi_stmt_ptr (i), remap_locals_r, &remap_info, NULL);
+
+  /* Add initialization/finalization code in GOMP_FN to model copyin,
+     firstprivate and lastprivate.  */
+}
Index: tree-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.h,v
retrieving revision 1.17.4.1
diff -d -u -p -r1.17.4.1 tree-inline.h
--- tree-inline.h	6 Jul 2005 17:39:40 -0000	1.17.4.1
+++ tree-inline.h	3 Aug 2005 23:32:12 -0000
@@ -33,6 +33,7 @@ int estimate_move_cost (tree type);
 void push_cfun (struct function *new_cfun);
 void pop_cfun (void);
 int estimate_num_insns (tree expr);
+void remap_locals_in_gomp_body (tree, tree);
 
 /* 0 if we should not perform inlining.
    1 if we should expand functions calls inline at the tree level.


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