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] rearrange data clauses vs ctors


The ctors work I'd done was pretty fragile, and it was easy to
get it to evaluate things in the wrong context, which can also
lead to ICEs.  A patch that will follow shortly would cause that
to happen almost all the time.

We now cache the results of lookups done in the correct context.


r~


        * langhooks.h (omp_clause_default_ctor): Add clause argument.
        (omp_clause_copy_ctor, omp_clause_assign_op): Likewise.
        (omp_clause_dtor): Likewise.
        * langhooks-def.h: Update to match.
        * langhooks.c (lhd_omp_assignment): Likewise.
        * hooks.c (hook_tree_tree_null): Remove.
        (hook_tree_tree_tree_null): New.
        * hooks.h: Update to match.
        * omp-low.c (expand_rec_input_clauses): Add new lang_hook arguments.
        (expand_lastprivate_clauses, expand_copyprivate_clauses): Likewise.
        * gimplify.c (GOVD_EXPLICIT, GOVD_DATA_SHARE_CLASS): New.
        (omp_add_variable): Gracefully handle errors.
        (omp_notice_variable): Likewise.
        (gimplify_scan_omp_clauses): Rename from
        gimplify_deconstruct_omp_clauses; don't remove nodes; use
        GOVD_EXPLICIT.
        (gimplify_adjust_omp_clauses_1): Rename from
        gimplify_reconstruct_omp_clauses_1; don't do anything for
        EXPLICIT or LOCAL variables; remove LASTPRIVATE special case.
        (gimplify_adjust_omp_clauses): Rename from
        gimplify_reconstruct_omp_clauses; prefer updates to creation.
cp/
        * cp-objcp-common.h (LANG_HOOKS_OMP_CLAUSE_DTOR):
        Use cxx_omp_clause_dtor.
        * cp-tree.h (CP_OMP_CLAUSE_INFO): New.
        (cxx_omp_clause_dtor): New.
        * cp-gimplify.c (cxx_omp_clause_apply_fn): New.
        (cxx_omp_clause_default_ctor): Use it.
        (cxx_omp_clause_copy_ctor, cxx_omp_clause_assign_op): Likewise.
        (cxx_omp_clause_dtor): New.
        * semantics.c (finish_omp_clauses): Rewrite cdtor checking to
        fill in CP_OMP_CLAUSE_INFO.  Don't specialcase LASTPRIVATE for
        removal.
        (cxx_omp_clause_default_ctor, cxx_omp_clause_copy_ctor,
        cxx_omp_clause_assign_op): Move to cp-gimplify.c.

Index: gcc/hooks.c
===================================================================
--- gcc/hooks.c	(revision 106267)
+++ gcc/hooks.c	(working copy)
@@ -257,7 +257,7 @@ hook_tree_tree_tree_bool_null (tree t0 A
 }
 
 tree
-hook_tree_tree_null (tree t ATTRIBUTE_UNUSED)
+hook_tree_tree_tree_null (tree t0 ATTRIBUTE_UNUSED, tree t1 ATTRIBUTE_UNUSED)
 {
   return NULL;
 }
Index: gcc/hooks.h
===================================================================
--- gcc/hooks.h	(revision 106267)
+++ gcc/hooks.h	(working copy)
@@ -54,7 +54,7 @@ extern int hook_int_rtx_0 (rtx);
 extern int hook_int_size_t_constcharptr_int_0 (size_t, const char *, int);
 extern int hook_int_void_no_regs (void);
 
-extern tree hook_tree_tree_null (tree);
+extern tree hook_tree_tree_tree_null (tree, tree);
 extern tree hook_tree_tree_tree_tree_3rd_identity (tree, tree, tree);
 extern tree hook_tree_tree_tree_bool_null (tree, tree, bool);
 
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c	(revision 106267)
+++ gcc/omp-low.c	(working copy)
@@ -1202,13 +1202,13 @@ expand_rec_input_clauses (tree clauses, 
 	      /* FALLTHRU */
 
 	    case OMP_CLAUSE_PRIVATE:
-	      x = lang_hooks.decls.omp_clause_default_ctor (new_var);
+	      x = lang_hooks.decls.omp_clause_default_ctor (c, new_var);
 	      if (x)
 		gimplify_and_add (x, ilist);
 	      /* FALLTHRU */
 
 	    do_dtor:
-	      x = lang_hooks.decls.omp_clause_dtor (new_var);
+	      x = lang_hooks.decls.omp_clause_dtor (c, new_var);
 	      if (x)
 		{
 		  dtor = x;
@@ -1219,7 +1219,7 @@ expand_rec_input_clauses (tree clauses, 
 
 	    case OMP_CLAUSE_FIRSTPRIVATE:
 	      x = build_outer_var_ref (var, ctx);
-	      x = lang_hooks.decls.omp_clause_copy_ctor (new_var, x);
+	      x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
 	      gimplify_and_add (x, ilist);
 	      goto do_dtor;
 	      break;
@@ -1227,7 +1227,7 @@ expand_rec_input_clauses (tree clauses, 
 	    case OMP_CLAUSE_COPYIN:
 	      by_ref = use_pointer_for_field (var, false);
 	      x = build_receiver_ref (var, by_ref, ctx);
-	      x = lang_hooks.decls.omp_clause_assign_op (new_var, x);
+	      x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
 	      append_to_statement_list (x, &copyin_seq);
 	      copyin_by_ref |= by_ref;
 	      break;
@@ -1312,7 +1312,7 @@ expand_lastprivate_clauses (tree clauses
       new_var = lookup_decl (var, ctx);
 
       x = build_outer_var_ref (var, ctx);
-      x = lang_hooks.decls.omp_clause_assign_op (x, new_var);
+      x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
       append_to_statement_list (x, &sub_list);
     }
 
@@ -1503,7 +1503,7 @@ expand_copyprivate_clauses (tree clauses
 	  ref = build_fold_indirect_ref (ref);
 	  var = build_fold_indirect_ref (var);
 	}
-      x = lang_hooks.decls.omp_clause_assign_op (var, ref);
+      x = lang_hooks.decls.omp_clause_assign_op (c, var, ref);
       gimplify_and_add (x, rlist);
     }
 }
Index: gcc/cp/cp-objcp-common.h
===================================================================
--- gcc/cp/cp-objcp-common.h	(revision 106267)
+++ gcc/cp/cp-objcp-common.h	(working copy)
@@ -160,6 +160,6 @@ extern tree objcp_tsubst_copy_and_build 
 #undef LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP
 #define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP cxx_omp_clause_assign_op
 #undef LANG_HOOKS_OMP_CLAUSE_DTOR
-#define LANG_HOOKS_OMP_CLAUSE_DTOR cxx_maybe_build_cleanup
+#define LANG_HOOKS_OMP_CLAUSE_DTOR cxx_omp_clause_dtor
 
 #endif /* GCC_CP_OBJCP_COMMON */
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h	(revision 106267)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -2963,6 +2963,13 @@ extern void decl_shadowed_for_var_insert
 #define OMP_FOR_GIMPLIFYING_P(NODE) \
   (TREE_LANG_FLAG_0 (OMP_FOR_CHECK (NODE)))
 
+/* A language-specific token attached to the OpenMP data clauses to 
+   hold code (or code fragments) related to ctors, dtors, and op=.
+   See semantics.c for details.  */
+#define CP_OMP_CLAUSE_INFO(NODE) \
+  TREE_BLOCK (TREE_RANGE_CHECK (NODE, OMP_CLAUSE_PRIVATE, \
+				OMP_CLAUSE_COPYPRIVATE))
+
 /* These macros provide convenient access to the various _STMT nodes
    created when parsing template declarations.  */
 #define TRY_STMTS(NODE)		TREE_OPERAND (TRY_BLOCK_CHECK (NODE), 0)
@@ -4259,9 +4266,10 @@ extern tree finish_omp_for			(location_t
 						 tree, tree, tree, tree);
 extern void finish_omp_atomic			(enum tree_code, tree, tree);
 extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree);
-extern tree cxx_omp_clause_default_ctor		(tree);
-extern tree cxx_omp_clause_copy_ctor		(tree, tree);
-extern tree cxx_omp_clause_assign_op		(tree, tree);
+extern tree cxx_omp_clause_default_ctor		(tree, tree);
+extern tree cxx_omp_clause_copy_ctor		(tree, tree, tree);
+extern tree cxx_omp_clause_assign_op		(tree, tree, tree);
+extern tree cxx_omp_clause_dtor			(tree, tree);
 
 /* in tree.c */
 extern void lang_check_failed			(const char *, int,
Index: gcc/cp/cp-gimplify.c
===================================================================
--- gcc/cp/cp-gimplify.c	(revision 106267)
+++ gcc/cp/cp-gimplify.c	(working copy)
@@ -700,3 +700,152 @@ cp_genericize (tree fndecl)
   gcc_assert (bc_label[bc_break] == NULL);
   gcc_assert (bc_label[bc_continue] == NULL);
 }
+
+/* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
+   NULL if there is in fact nothing to do.  ARG2 may be null if FN
+   actually only takes one argument.  */
+
+static tree
+cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
+{
+  if (fn == NULL)
+    return NULL;
+
+  if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
+    {
+      tree inner_type = TREE_TYPE (arg1);
+      tree start1, end1, p1;
+      tree start2 = NULL, p2 = NULL;
+      tree ret = NULL, lab, t;
+
+      start1 = arg1;
+      start2 = arg2;
+      do
+	{
+	  inner_type = TREE_TYPE (inner_type);
+	  start1 = build4 (ARRAY_REF, inner_type, start1,
+			   size_zero_node, NULL, NULL);
+	  if (arg2)
+	    start2 = build4 (ARRAY_REF, inner_type, start2,
+			     size_zero_node, NULL, NULL);
+	}
+      while (TREE_CODE (inner_type) == ARRAY_TYPE);
+      start1 = build_fold_addr_expr (start1);
+      if (arg2)
+	start2 = build_fold_addr_expr (start2);
+
+      end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
+      end1 = fold_convert (TREE_TYPE (start1), end1);
+      end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
+
+      p1 = create_tmp_var (TREE_TYPE (start1), NULL);
+      t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
+      append_to_statement_list (t, &ret);
+
+      if (arg2)
+	{
+	  p2 = create_tmp_var (TREE_TYPE (start2), NULL);
+	  t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
+	  append_to_statement_list (t, &ret);
+	}
+
+      lab = create_artificial_label ();
+      t = build1 (LABEL_EXPR, void_type_node, lab);
+      append_to_statement_list (t, &ret);
+
+      t = NULL;
+      if (arg2)
+	t = tree_cons (NULL, p2, t);
+      t = tree_cons (NULL, p1, t);
+      t = build_call (fn, t);
+      append_to_statement_list (t, &ret);
+
+      t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
+      t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
+      t = build2 (MODIFY_EXPR, void_type_node, p1, t);
+      append_to_statement_list (t, &ret);
+
+      if (arg2)
+	{
+	  t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
+	  t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
+	  t = build2 (MODIFY_EXPR, void_type_node, p2, t);
+	  append_to_statement_list (t, &ret);
+	}
+
+      t = build2 (NE_EXPR, boolean_type_node, p1, end1);
+      t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
+      append_to_statement_list (t, &ret);
+
+      return ret;
+    }
+  else
+    {
+      tree t = NULL;
+      if (arg2)
+	t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
+      t = tree_cons (NULL, build_fold_addr_expr (arg1), t);
+      return build_call (fn, t);
+    }
+}
+
+/* Return code to initialize DECL with its default constructor, or
+   NULL if there's nothing to do.  */
+
+tree
+cxx_omp_clause_default_ctor (tree clause, tree decl)
+{
+  tree info = CP_OMP_CLAUSE_INFO (clause);
+  tree ret = NULL;
+
+  if (info)
+    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
+
+  return ret;
+}
+
+/* Return code to initialize DST with a copy constructor from SRC.  */
+
+tree
+cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
+{
+  tree info = CP_OMP_CLAUSE_INFO (clause);
+  tree ret = NULL;
+
+  if (info)
+    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
+  if (ret == NULL)
+    ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
+
+  return ret;
+}
+
+/* Similarly, except use an assignment operator instead.  */
+
+tree
+cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
+{
+  tree info = CP_OMP_CLAUSE_INFO (clause);
+  tree ret = NULL;
+
+  if (info)
+    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
+  if (ret == NULL)
+    ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
+
+  return ret;
+}
+
+/* Return code to destroy DECL.  */
+
+tree
+cxx_omp_clause_dtor (tree clause, tree decl)
+{
+  tree info = CP_OMP_CLAUSE_INFO (clause);
+  tree ret = NULL;
+
+  if (info)
+    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
+
+  return ret;
+}
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 106267)
+++ gcc/cp/semantics.c	(working copy)
@@ -3372,7 +3372,7 @@ finish_omp_clauses (tree clauses)
       bool need_copy_ctor = false;
       bool need_copy_assignment = false;
       bool need_implicitly_determined = false;
-      tree type;
+      tree type, inner_type;
 
       switch (c_kind)
 	{
@@ -3514,41 +3514,74 @@ finish_omp_clauses (tree clauses)
 	}
 
       /* We're interested in the base element, not arrays.  */
-      type = TREE_TYPE (t);
-      while (TREE_CODE (type) == ARRAY_TYPE)
-	type = TREE_TYPE (type);
-
-      /* Check for special function availablity by building a call to one
-	 and discarding the results.  C.f. check_constructor_callable.  */
-      if (CLASS_TYPE_P (type))
+      inner_type = type = TREE_TYPE (t);
+      while (TREE_CODE (inner_type) == ARRAY_TYPE)
+	inner_type = TREE_TYPE (inner_type);
+
+      /* Check for special function availablity by building a call to one.
+	 Save the results, because later we won't be in the right context
+	 for making these queries.  */
+      if (CLASS_TYPE_P (inner_type)
+	  && (need_default_ctor || need_copy_ctor || need_copy_assignment))
 	{
 	  int save_errorcount = errorcount;
+	  tree info;
 
-	  /* For the copy constructor and assignment op, we need
-	     an object of the appropriate type.  Pretend with an
-	     otherwise bogus INDIRECT_REF.  */
-	  if (type != TREE_TYPE (t))
-	    {
-	      t = build_int_cst (build_pointer_type (type), 0);
-	      t = build1 (INDIRECT_REF, type, t);
-	    }
+	  /* Always allocate 3 elements for simplicity.  These are the
+	     function decls for the ctor, dtor, and assignment op.
+	     This layout is known to the three lang hooks,
+	     cxx_omp_clause_default_init, cxx_omp_clause_copy_init,
+	     and cxx_omp_clause_assign_op.  */
+	  info = make_tree_vec (3);
+	  CP_OMP_CLAUSE_INFO (c) = info;
+
+	  if (need_default_ctor
+	      || (need_copy_ctor
+		  && !TYPE_HAS_TRIVIAL_INIT_REF (inner_type)))
+	    {
+	      if (need_default_ctor)
+		t = NULL;
+	      else
+		{
+		  t = build_int_cst (build_pointer_type (inner_type), 0);
+		  t = build1 (INDIRECT_REF, inner_type, t);
+		  t = build_tree_list (NULL, t);
+		}
+	      t = build_special_member_call (NULL_TREE,
+					     complete_ctor_identifier,
+					     t, inner_type, LOOKUP_NORMAL);
+	      t = get_callee_fndecl (t);
+	      TREE_VEC_ELT (info, 0) = t;
+	    }
+
+	  if ((need_default_ctor || need_copy_ctor)
+	      && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_type))
+	    {
+	      t = build_int_cst (build_pointer_type (inner_type), 0);
+	      t = build1 (INDIRECT_REF, inner_type, t);
+	      t = build_special_member_call (t, complete_dtor_identifier,
+					     NULL, inner_type, LOOKUP_NORMAL);
+	      t = get_callee_fndecl (t);
+	      TREE_VEC_ELT (info, 1) = t;
+	    }
+
+	  if (need_copy_assignment
+	      && !TYPE_HAS_TRIVIAL_ASSIGN_REF (inner_type))
+	    {
+	      t = build_int_cst (build_pointer_type (inner_type), 0);
+	      t = build1 (INDIRECT_REF, inner_type, t);
+	      t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
+					     build_tree_list (NULL, t),
+					     inner_type, LOOKUP_NORMAL);
+
+	      /* We'll have called convert_from_reference on the call, which
+		 may well have added an indirect_ref.  It's unneeded here, 
+		 and in the way, so kill it.  */
+	      if (TREE_CODE (t) == INDIRECT_REF)
+		t = TREE_OPERAND (t, 0);
 
-	  if (need_default_ctor && TYPE_NEEDS_CONSTRUCTING (type))
-	    {
-	      build_special_member_call (NULL_TREE, complete_ctor_identifier,
-					 NULL_TREE, type, LOOKUP_NORMAL);
-	    }
-	  if (need_copy_ctor && TYPE_NEEDS_CONSTRUCTING (type))
-	    {
-	      build_special_member_call (NULL_TREE, complete_ctor_identifier,
-					 build_tree_list (NULL, t),
-					 type, LOOKUP_NORMAL);
-	    }
-	  if (need_copy_assignment)
-	    {
-	      build_special_member_call (t, ansi_assopname (NOP_EXPR),
-					 build_tree_list (NULL, t),
-					 type, LOOKUP_NORMAL);
+	      t = get_callee_fndecl (t);
+	      TREE_VEC_ELT (info, 2) = t;
 	    }
 
 	  if (errorcount != save_errorcount)
@@ -3556,26 +3589,7 @@ finish_omp_clauses (tree clauses)
 	}
 
       if (remove)
-	{
-	  *pc = OMP_CLAUSE_CHAIN (c);
-
-	  /* If we don't remove the corresponding firstprivate clause, we
-	     can wind up with spurrious errors later, since this changes
-	     the set of constructors we request.  */
-	  if (c_kind == OMP_CLAUSE_LASTPRIVATE
-	      && bitmap_bit_p (&firstprivate_head,
-			       DECL_UID (OMP_CLAUSE_DECL (c))))
-	    {
-	      tree *p;
-	      for (p = &clauses; *p ; p = &OMP_CLAUSE_CHAIN (*p))
-		if (TREE_CODE (*p) == OMP_CLAUSE_FIRSTPRIVATE
-		    && OMP_CLAUSE_DECL (*p) == OMP_CLAUSE_DECL (c))
-		  {
-		    *p = OMP_CLAUSE_CHAIN (*p);
-		    break;
-		  }
-	    }
-	}
+	*pc = OMP_CLAUSE_CHAIN (c);
       else
 	pc = &OMP_CLAUSE_CHAIN (c);
     }
@@ -3803,54 +3817,6 @@ cxx_omp_predetermined_sharing (tree decl
 
   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
 }
-
-/* Build and return code to initialize DECL with its default constructor.
-   Return NULL if there's nothing to do.  */
-
-tree
-cxx_omp_clause_default_ctor (tree decl)
-{
-  tree type = TREE_TYPE (decl);
-
-  if (TREE_CODE (type) == ARRAY_TYPE)
-    {
-      tree etype = type;
-      while (TREE_CODE (etype) == ARRAY_TYPE)
-	etype = TREE_TYPE (etype);
-
-      if (TYPE_NEEDS_CONSTRUCTING (etype))
-	return build_vec_init (decl, NULL, NULL, true, 0);
-      else
-	return NULL;
-    }
-  else if (TYPE_NEEDS_CONSTRUCTING (type))
-    return build_aggr_init (decl, NULL, 0);
-  else
-    return NULL;
-}
-
-/* Build and return code for a copy constructor from SRC to DST.  */
-
-tree
-cxx_omp_clause_copy_ctor (tree dst, tree src)
-{
-  if (TREE_CODE (TREE_TYPE (dst)) == ARRAY_TYPE)
-    return build_vec_init (dst, NULL, src, false, 1);
-  else
-    return build_modify_expr (dst, INIT_EXPR, src);
-}
-
-/* Similarly, except use an assignment operator instead.  */
-
-tree
-cxx_omp_clause_assign_op (tree dst, tree src)
-{
-  if (TREE_CODE (TREE_TYPE (dst)) == ARRAY_TYPE)
-    return build_vec_init (dst, NULL, src, false, 2);
-  else
-    return build_modify_expr (dst, NOP_EXPR, src);
-}
-
 
 void
 init_cp_semantics (void)
Index: gcc/langhooks.c
===================================================================
--- gcc/langhooks.c	(revision 106267)
+++ gcc/langhooks.c	(working copy)
@@ -563,7 +563,7 @@ lhd_omp_predetermined_sharing (tree decl
 /* Generate code to copy SRC to DST.  */
 
 tree
-lhd_omp_assignment (tree dst, tree src)
+lhd_omp_assignment (tree clause ATTRIBUTE_UNUSED, tree dst, tree src)
 {
   return build2 (MODIFY_EXPR, void_type_node, dst, src);
 }
Index: gcc/langhooks.h
===================================================================
--- gcc/langhooks.h	(revision 106267)
+++ gcc/langhooks.h	(working copy)
@@ -201,19 +201,19 @@ struct lang_hooks_for_decls
      predetermined, OMP_CLAUSE_DEFAULT_UNSPECIFIED otherwise.  */
   enum omp_clause_default_kind (*omp_predetermined_sharing) (tree);
 
-  /* Build and return code for a default constructor for DECL.  Return
-     NULL if nothing to be done.  */
-  tree (*omp_clause_default_ctor) (tree decl);
+  /* Build and return code for a default constructor for DECL in
+     response to CLAUSE.  Return NULL if nothing to be done.  */
+  tree (*omp_clause_default_ctor) (tree clause, tree decl);
 
   /* Build and return code for a copy constructor from SRC to DST.  */
-  tree (*omp_clause_copy_ctor) (tree dst, tree src);
+  tree (*omp_clause_copy_ctor) (tree clause, tree dst, tree src);
 
   /* Similarly, except use an assignment operator instead.  */
-  tree (*omp_clause_assign_op) (tree dst, tree src);
+  tree (*omp_clause_assign_op) (tree clause, tree dst, tree src);
 
   /* Build and return code destructing DECL.  Return NULL if nothing
      to be done.  */
-  tree (*omp_clause_dtor) (tree decl);
+  tree (*omp_clause_dtor) (tree clause, tree decl);
 };
 
 /* Language-specific hooks.  See langhooks-def.h for defaults.  */
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(revision 106267)
+++ gcc/gimplify.c	(working copy)
@@ -53,12 +53,15 @@ Software Foundation, 51 Franklin Street,
 enum gimplify_omp_var_data
 {
   GOVD_SEEN = 1,
-  GOVD_SHARED = 2,
-  GOVD_PRIVATE = 4,
-  GOVD_FIRSTPRIVATE = 8,
-  GOVD_LASTPRIVATE = 16,
-  GOVD_REDUCTION = 32,
-  GOVD_LOCAL = 64
+  GOVD_EXPLICIT = 2,
+  GOVD_SHARED = 4,
+  GOVD_PRIVATE = 8,
+  GOVD_FIRSTPRIVATE = 16,
+  GOVD_LASTPRIVATE = 32,
+  GOVD_REDUCTION = 64,
+  GOVD_LOCAL = 128,
+  GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
+			   | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LOCAL)
 };
 
 struct gimplify_omp_ctx
@@ -4207,6 +4210,9 @@ omp_add_variable (struct gimplify_omp_ct
   unsigned int nflags;
   tree t;
 
+  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+    return;
+
   /* Never elide decls whose type has TREE_ADDRESSABLE set.  This means
      there are constructors involved somewhere.  */
   if (TREE_ADDRESSABLE (TREE_TYPE (decl))
@@ -4216,13 +4222,13 @@ omp_add_variable (struct gimplify_omp_ct
   n = splay_tree_lookup (ctx->variables, (splay_tree_key)decl);
   if (n != NULL)
     {
-      /* Except for the SEEN bit, we shouldn't be re-adding the decl with
-	 the same data sharing class.  */
-      gcc_assert ((n->value & ~GOVD_SEEN & flags) == 0);
+      /* We shouldn't be re-adding the decl with the same data
+	 sharing class.  */
+      gcc_assert ((n->value & GOVD_DATA_SHARE_CLASS & flags) == 0);
       /* The only combination of data sharing classes we should see is
 	 FIRSTPRIVATE and LASTPRIVATE.  */
       nflags = n->value | flags;
-      gcc_assert ((nflags & ~GOVD_SEEN)
+      gcc_assert ((nflags & GOVD_DATA_SHARE_CLASS)
 		  == (GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE));
       n->value = nflags;
       return;
@@ -4282,6 +4288,9 @@ omp_notice_variable (struct gimplify_omp
   splay_tree_node n;
   unsigned flags = in_code ? GOVD_SEEN : 0;
 
+  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+    return;
+
   /* Threadprivate variables are predetermined.  */
   if (is_global_var (decl))
     {
@@ -4384,72 +4393,76 @@ omp_is_private (struct gimplify_omp_ctx 
 }
 
 /* Scan the OpenMP clauses in *LIST_P, installing mappings into a new
-   and previous omp contexts.  We remove those clauses that can be 
-   potentially optimized away due to variables not actually being used.
-   These will be put back in gimplify_reconstruct_omp_clauses.  */
+   and previous omp contexts.  */
 
 static void
-gimplify_deconstruct_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel)
+gimplify_scan_omp_clauses (tree *list_p, tree *pre_p, bool in_parallel)
 {
   struct gimplify_omp_ctx *ctx, *outer_ctx;
-  tree clause;
+  tree c;
 
   ctx = new_omp_context (in_parallel);
   outer_ctx = ctx->outer_context;
 
-  while ((clause = *list_p) != NULL)
+  while ((c = *list_p) != NULL)
     {
       enum gimplify_status gs;
       bool remove = false;
+      bool notice_outer = true;
+      unsigned int flags;
+      tree decl;
 
-      switch (TREE_CODE (clause))
+      switch (TREE_CODE (c))
 	{
 	case OMP_CLAUSE_PRIVATE:
-	  omp_add_variable (ctx, OMP_CLAUSE_DECL (clause), GOVD_PRIVATE);
-	  remove = true;
-	  break;
-
+	  flags = GOVD_PRIVATE | GOVD_EXPLICIT;
+	  notice_outer = false;
+	  goto do_add;
 	case OMP_CLAUSE_SHARED:
-	  omp_add_variable (ctx, OMP_CLAUSE_DECL (clause), GOVD_SHARED);
-	  if (outer_ctx)
-	    omp_notice_variable (outer_ctx, OMP_CLAUSE_DECL (clause), false);
-	  remove = true;
-	  break;
-
+	  flags = GOVD_SHARED | GOVD_EXPLICIT;
+	  goto do_add;
 	case OMP_CLAUSE_FIRSTPRIVATE:
-	  omp_add_variable (ctx, OMP_CLAUSE_DECL (clause), GOVD_FIRSTPRIVATE);
-	  if (outer_ctx)
-	    omp_notice_variable (outer_ctx, OMP_CLAUSE_DECL (clause), false);
-	  remove = true;
-	  break;
-
+	  flags = GOVD_FIRSTPRIVATE | GOVD_EXPLICIT;
+	  goto do_add;
 	case OMP_CLAUSE_LASTPRIVATE:
-	  omp_add_variable (ctx, OMP_CLAUSE_DECL (clause),
-			    GOVD_LASTPRIVATE | GOVD_SEEN);
-	  if (outer_ctx)
-	    omp_notice_variable (outer_ctx, OMP_CLAUSE_DECL (clause), true);
-	  remove = true;
-	  break;
-
+	  flags = GOVD_LASTPRIVATE | GOVD_SEEN | GOVD_EXPLICIT;
+	  goto do_add;
 	case OMP_CLAUSE_REDUCTION:
-	  omp_add_variable (ctx, OMP_CLAUSE_DECL (clause),
-			    GOVD_REDUCTION | GOVD_SEEN);
-	  if (outer_ctx)
-	    omp_notice_variable (outer_ctx, OMP_CLAUSE_DECL (clause), true);
+	  flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT;
+	  goto do_add;
+
+	do_add:
+	  decl = OMP_CLAUSE_DECL (c);
+	  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+	    {
+	      remove = true;
+	      break;
+	    }
+	  omp_add_variable (ctx, decl, flags);
+	  if (notice_outer)
+	    goto do_notice;
 	  break;
 
 	case OMP_CLAUSE_COPYIN:
 	case OMP_CLAUSE_COPYPRIVATE:
+	  decl = OMP_CLAUSE_DECL (c);
+	  if (decl == error_mark_node || TREE_TYPE (decl) == error_mark_node)
+	    {
+	      remove = true;
+	      break;
+	    }
+	do_notice:
 	  if (outer_ctx)
-	    omp_notice_variable (outer_ctx, OMP_CLAUSE_DECL (clause), true);
+	    omp_notice_variable (outer_ctx, decl, true);
 	  break;
 
 	case OMP_CLAUSE_IF:
 	case OMP_CLAUSE_NUM_THREADS:
 	case OMP_CLAUSE_SCHEDULE:
-	  gs = gimplify_expr (&TREE_OPERAND (clause, 0), pre_p, NULL,
+	  gs = gimplify_expr (&TREE_OPERAND (c, 0), pre_p, NULL,
 			      is_gimple_val, fb_rvalue);
-	  remove = (gs == GS_ERROR);
+	  if (gs == GS_ERROR)
+	    remove = true;
 	  break;
 
 	case OMP_CLAUSE_NOWAIT:
@@ -4457,7 +4470,7 @@ gimplify_deconstruct_omp_clauses (tree *
 	  break;
 
 	case OMP_CLAUSE_DEFAULT:
-	  ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (clause);
+	  ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
 	  break;
 
 	default:
@@ -4465,26 +4478,28 @@ gimplify_deconstruct_omp_clauses (tree *
 	}
 
       if (remove)
-	*list_p = OMP_CLAUSE_CHAIN (clause);
+	*list_p = OMP_CLAUSE_CHAIN (c);
       else
-	list_p = &OMP_CLAUSE_CHAIN (clause);
+	list_p = &OMP_CLAUSE_CHAIN (c);
     }
 
   gimplify_omp_ctxp = ctx;
 }
 
-/* For all variables that were actually used within the current context,
-   regenerate PRIVATE, SHARED, and FIRSTPRIVATE clauses.  */
+/* For all variables that were not actually used within the context,
+   remove PRIVATE, SHARED, and FIRSTPRIVATE clauses.  */
 
 static int
-gimplify_reconstruct_omp_clauses_1 (splay_tree_node n, void *data)
+gimplify_adjust_omp_clauses_1 (splay_tree_node n, void *data)
 {
   tree *list_p = (tree *) data;
   tree decl = (tree) n->key;
-  tree clause;
   unsigned flags = n->value;
   enum tree_code code;
+  tree clause;
 
+  if (flags & (GOVD_EXPLICIT | GOVD_LOCAL))
+    return 0;
   if ((flags & GOVD_SEEN) == 0)
     return 0;
   if (flags & GOVD_SHARED)
@@ -4496,20 +4511,9 @@ gimplify_reconstruct_omp_clauses_1 (spla
   else if (flags & GOVD_PRIVATE)
     code = OMP_CLAUSE_PRIVATE;
   else if (flags & GOVD_FIRSTPRIVATE)
-    {
-      if (flags & GOVD_LASTPRIVATE)
-	{
-	  clause = build1 (OMP_CLAUSE_LASTPRIVATE, void_type_node, decl);
-	  OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (clause) = 1;
-	  OMP_CLAUSE_CHAIN (clause) = *list_p;
-	  *list_p = clause;
-	}
-      code = OMP_CLAUSE_FIRSTPRIVATE;
-    }
-  else if (flags & GOVD_LASTPRIVATE)
-    code = OMP_CLAUSE_LASTPRIVATE;
+    code = OMP_CLAUSE_FIRSTPRIVATE;
   else
-    return 0;
+    gcc_unreachable ();
 
   clause = build1 (code, void_type_node, decl);
   OMP_CLAUSE_CHAIN (clause) = *list_p;
@@ -4519,14 +4523,59 @@ gimplify_reconstruct_omp_clauses_1 (spla
 }
 
 static void
-gimplify_reconstruct_omp_clauses (tree *list_p)
+gimplify_adjust_omp_clauses (tree *list_p)
 {
-  struct gimplify_omp_ctx *ctx;
+  struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+  tree c, decl;
+
+  while ((c = *list_p) != NULL)
+    {
+      splay_tree_node n;
+      bool remove = false;
+
+      switch (TREE_CODE (c))
+	{
+	case OMP_CLAUSE_PRIVATE:
+	case OMP_CLAUSE_SHARED:
+	case OMP_CLAUSE_FIRSTPRIVATE:
+	  decl = OMP_CLAUSE_DECL (c);
+	  n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+	  remove = !(n->value & GOVD_SEEN);
+	  break;
+
+	case OMP_CLAUSE_LASTPRIVATE:
+	  /* Make sure OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE is set to
+	     accurately reflect the presence of a FIRSTPRIVATE clause.  */
+	  decl = OMP_CLAUSE_DECL (c);
+	  n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+	  OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
+	    = (n->value & GOVD_FIRSTPRIVATE) != 0;
+	  break;
+	  
+	case OMP_CLAUSE_REDUCTION:
+	case OMP_CLAUSE_COPYIN:
+	case OMP_CLAUSE_COPYPRIVATE:
+	case OMP_CLAUSE_IF:
+	case OMP_CLAUSE_NUM_THREADS:
+	case OMP_CLAUSE_SCHEDULE:
+	case OMP_CLAUSE_NOWAIT:
+	case OMP_CLAUSE_ORDERED:
+	case OMP_CLAUSE_DEFAULT:
+	  break;
+
+	default:
+	  gcc_unreachable ();
+	}
+
+      if (remove)
+	*list_p = OMP_CLAUSE_CHAIN (c);
+      else
+	list_p = &OMP_CLAUSE_CHAIN (c);
+    }
 
-  splay_tree_foreach (gimplify_omp_ctxp->variables,
-		      gimplify_reconstruct_omp_clauses_1, list_p);
+  /* Add in any implicit data sharing.  */
+  splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, list_p);
   
-  ctx = gimplify_omp_ctxp;
   gimplify_omp_ctxp = ctx->outer_context;
   delete_omp_context (ctx);
 }
@@ -4541,13 +4590,13 @@ gimplify_omp_parallel (tree *expr_p, tre
 {
   tree expr = *expr_p;
 
-  gimplify_deconstruct_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, true);
+  gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, true);
 
   push_gimplify_context ();
   gimplify_stmt (&OMP_PARALLEL_BODY (expr));
   pop_gimplify_context (OMP_PARALLEL_BODY (expr));
 
-  gimplify_reconstruct_omp_clauses (&OMP_PARALLEL_CLAUSES (expr));
+  gimplify_adjust_omp_clauses (&OMP_PARALLEL_CLAUSES (expr));
 
   return GS_ALL_DONE;
 }
@@ -4562,7 +4611,7 @@ gimplify_omp_for (tree *expr_p, tree *pr
 
   for_stmt = *expr_p;
 
-  gimplify_deconstruct_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, false);
+  gimplify_scan_omp_clauses (&OMP_FOR_CLAUSES (for_stmt), pre_p, false);
 
   t = OMP_FOR_INIT (for_stmt);
   gcc_assert (TREE_CODE (t) == MODIFY_EXPR);
@@ -4631,7 +4680,7 @@ gimplify_omp_for (tree *expr_p, tree *pr
     }
 
   gimplify_to_stmt_list (&OMP_FOR_BODY (for_stmt));
-  gimplify_reconstruct_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
+  gimplify_adjust_omp_clauses (&OMP_FOR_CLAUSES (for_stmt));
 
   return ret == GS_ALL_DONE ? GS_ALL_DONE : GS_ERROR;
 }
@@ -4644,9 +4693,9 @@ gimplify_omp_workshare (tree *expr_p, tr
 {
   tree stmt = *expr_p;
 
-  gimplify_deconstruct_omp_clauses (&OMP_CLAUSES (stmt), pre_p, false);
+  gimplify_scan_omp_clauses (&OMP_CLAUSES (stmt), pre_p, false);
   gimplify_to_stmt_list (&OMP_BODY (stmt));
-  gimplify_reconstruct_omp_clauses (&OMP_CLAUSES (stmt));
+  gimplify_adjust_omp_clauses (&OMP_CLAUSES (stmt));
 
   return GS_ALL_DONE;
 }
Index: gcc/langhooks-def.h
===================================================================
--- gcc/langhooks-def.h	(revision 106267)
+++ gcc/langhooks-def.h	(working copy)
@@ -89,7 +89,7 @@ extern tree lhd_callgraph_analyze_expr (
 /* Declarations for tree gimplification hooks.  */
 extern int lhd_gimplify_expr (tree *, tree *, tree *);
 extern enum omp_clause_default_kind lhd_omp_predetermined_sharing (tree);
-extern tree lhd_omp_assignment (tree, tree);
+extern tree lhd_omp_assignment (tree, tree, tree);
 
 #define LANG_HOOKS_NAME			"GNU unknown"
 #define LANG_HOOKS_IDENTIFIER_SIZE	sizeof (struct lang_identifier)
@@ -243,10 +243,10 @@ extern tree lhd_make_node (enum tree_cod
 #define LANG_HOOKS_COMDAT_GROUP lhd_comdat_group
 #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE hook_bool_tree_false
 #define LANG_HOOKS_OMP_PREDETERMINED_SHARING lhd_omp_predetermined_sharing
-#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR hook_tree_tree_null
+#define LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR hook_tree_tree_tree_null
 #define LANG_HOOKS_OMP_CLAUSE_COPY_CTOR lhd_omp_assignment
 #define LANG_HOOKS_OMP_CLAUSE_ASSIGN_OP lhd_omp_assignment
-#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_null
+#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
 
 #define LANG_HOOKS_DECLS { \
   LANG_HOOKS_GLOBAL_BINDINGS_P, \


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