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] New fix for PR 24703


This patch re-enables generation of combined parallel loop directives when 
the loop has OMP_PRE_BODY set.  The problem was that the gimplification of 
the loop header was happening inside the wrong context.

Since the loop will become part of a child function, and the prefix code 
needs to be emitted inside the parent, what I did is have the gimplifier 
detect combined parallel+workshare constructs.  If one is detected, it 
sets two new fields in the current gimplifier context: 

- combined_pre_p, pointing to the current prefix pad, so that prefix code 
can be emitted in the same prefix pad as the parallel directive.

- combined_ctxp, pointing to the current gimplifier context, so that any 
new temporaries are declared inside the context of the parallel directive.

Inside gimplify_omp_for, we now use OMP_FOR_PRE_BODY for the prefix pad or 
the parent's prefix pad when gimplifying the header of the loop.

Bootstrapped and tested x86, x86-64, ia64 and ppc64.
2005-11-13  Diego Novillo  <dnovillo@redhat.com>

	* omp-low.c (determine_parallel_type): Make extern.
	Do not return IS_PARALLEL if OMP_FOR_PRE_BODY is set.
	(enum omp_parallel_type): Move ...
	* tree-gimple.h (enum omp_parallel): ... here.
	(determine_parallel_type): Declare.
	* gimplify.c (struct gimplify_ctx): Add fields combined_pre_p
	and combined_ctxp.
	(gimplify_expr_in_ctx): New.
	(gimplify_omp_for): Call it if gimplify_ctxp->combined_pre_p
	is set.
	(gimplify_omp_parallel): Set gimplify_ctxp->combined_pre_p
	and gimplify_ctxp->combined_ctxp if this is a combined
	parallel+workshare directive.

Index: omp-low.c
===================================================================
--- omp-low.c	(revision 106755)
+++ omp-low.c	(working copy)
@@ -59,21 +59,6 @@ Software Foundation, 51 Franklin Street,
    optimal, but lexically nested parallels effectively only happens in
    test suites.  */
 
-/* Type of parallel constructs.  Used to decide what runtime function
-   to use for launching children threads.  */
-
-enum omp_parallel_type {
-    IS_NOT_PARALLEL = 0,
-
-    /* Regular omp parallel  */
-    IS_PARALLEL,
-
-    /* Combined parallel + workshare (parallel loop and parallel
-       sections).  */
-    IS_COMBINED_PARALLEL
-};
-
-
 /* Context structure.  Used to store information about each parallel
    directive in the code.  */
 
@@ -784,7 +769,7 @@ create_omp_child_function (omp_context *
    or a single OMP_SECTIONS then this is a combined directive.
    Otherwise, it is a regular parallel directive.  */
 
-static enum omp_parallel_type
+enum omp_parallel_type
 determine_parallel_type (tree stmt)
 {
   enum omp_parallel_type par_type;
@@ -812,11 +797,6 @@ determine_parallel_type (tree stmt)
 	par_type = IS_PARALLEL;
       else if (find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
 	par_type = IS_PARALLEL;
-      /* ??? The pre-body contains things needed to compute the bounds of
-	 the loop.  For now, simply disable combining.  We need to come up
-	 with a better way of solving the gimplification problem.  */
-      else if (OMP_FOR_PRE_BODY (t))
-	par_type = IS_PARALLEL;
       else
 	par_type = IS_COMBINED_PARALLEL;
     }
Index: tree-gimple.h
===================================================================
--- tree-gimple.h	(revision 106755)
+++ tree-gimple.h	(working copy)
@@ -107,6 +107,21 @@ enum gimplify_status {
   GS_ALL_DONE	= 1	/* The expression is fully gimplified.  */
 };
 
+/* Type of parallel constructs.  Used to decide what runtime function
+   to use for launching children threads and the gimplification
+   strategy.  */
+
+enum omp_parallel_type {
+    IS_NOT_PARALLEL = 0,
+
+    /* Regular omp parallel  */
+    IS_PARALLEL,
+
+    /* Combined parallel + workshare (parallel loop and parallel
+       sections).  */
+    IS_COMBINED_PARALLEL
+};
+
 extern enum gimplify_status gimplify_expr (tree *, tree *, tree *,
 					   bool (*) (tree), fallback_t);
 extern void gimplify_type_sizes (tree, tree *);
@@ -135,6 +150,7 @@ extern void omp_firstprivatize_variable 
 extern tree find_omp_clause (tree, enum tree_code);
 extern void diagnose_omp_structured_block_errors (tree);
 extern tree omp_reduction_init (tree, tree);
+enum omp_parallel_type determine_parallel_type (tree stmt);
 
 /* In tree-nested.c.  */
 extern void lower_nested_functions (tree);
Index: gimplify.c
===================================================================
--- gimplify.c	(revision 106755)
+++ gimplify.c	(working copy)
@@ -92,6 +92,16 @@ struct gimplify_ctx
   int conditions;
   bool save_stack;
   bool into_ssa;
+
+  /* When gimplifying combined omp parallel directives (omp parallel
+     loop and omp parallel sections), any prefix code needed to setup
+     the associated worksharing construct needs to be emitted in the
+     pre-queue of its parent parallel, otherwise the lowering process
+     will move that code to the child function.  Similarly, we need to
+     move up to the gimplification context of the parent parallel
+     directive so temporaries are declared in the right context.  */
+  tree *combined_pre_p;
+  struct gimplify_ctx *combined_ctxp;
 };
 
 static struct gimplify_ctx *gimplify_ctxp;
@@ -4117,6 +4127,25 @@ gimplify_to_stmt_list (tree *stmt_p)
     }
 }
 
+/* Gimplify *EXPR_P as if it had been used inside the gimplification
+   context CTX_P.  The other arguments are as in gimplify_expr.  */
+
+static enum gimplify_status
+gimplify_expr_in_ctx (tree *expr_p, tree *pre_p, tree *post_p, 
+		      bool (* gimple_test_f) (tree), fallback_t fallback,
+		      struct gimplify_ctx *ctx_p)
+{
+  enum gimplify_status ret;
+  struct gimplify_ctx *prev_ctxp;
+  
+  prev_ctxp = gimplify_ctxp;
+  gimplify_ctxp = ctx_p;
+  ret = gimplify_expr (expr_p, pre_p, post_p, gimple_test_f, fallback);
+  gimplify_ctxp = prev_ctxp;
+
+  return ret;
+}
+
 /* Add FIRSTPRIVATE entries for DECL in the OpenMP the surrounding parallels
    to CTX.  If entries already exist, force them to be some flavor of private.
    If there is no enclosing parallel, do nothing.  */
@@ -4656,9 +4685,19 @@ gimplify_omp_parallel (tree *expr_p, tre
   gimplify_scan_omp_clauses (&OMP_PARALLEL_CLAUSES (expr), pre_p, true);
 
   push_gimplify_context ();
+
+  if (determine_parallel_type (expr) == IS_COMBINED_PARALLEL)
+    {
+      gimplify_ctxp->combined_pre_p = pre_p;
+      gimplify_ctxp->combined_ctxp = gimplify_ctxp->prev_context;
+    }
+
   gimplify_stmt (&OMP_PARALLEL_BODY (expr));
   pop_gimplify_context (OMP_PARALLEL_BODY (expr));
 
+  gimplify_ctxp->combined_pre_p = NULL;
+  gimplify_ctxp->combined_ctxp = NULL;
+
   gimplify_adjust_omp_clauses (&OMP_PARALLEL_CLAUSES (expr));
 
   return GS_ALL_DONE;
@@ -4689,14 +4728,31 @@ gimplify_omp_for (tree *expr_p, tree *pr
   else
     omp_add_variable (gimplify_omp_ctxp, decl, GOVD_PRIVATE | GOVD_SEEN);
 
-  ret |= gimplify_expr (&TREE_OPERAND (t, 1), &OMP_FOR_PRE_BODY (for_stmt),
-			NULL, is_gimple_val, fb_rvalue);
+  /* Gimplify inside our parent's context if this is part of a combined
+     parallel+workshare directive.  */
+  if (gimplify_ctxp->combined_pre_p)
+    ret |= gimplify_expr_in_ctx (&TREE_OPERAND (t, 1),
+				 gimplify_ctxp->combined_pre_p, NULL,
+				 is_gimple_val, fb_rvalue,
+				 gimplify_ctxp->combined_ctxp);
+  else
+    ret |= gimplify_expr (&TREE_OPERAND (t, 1), &OMP_FOR_PRE_BODY (for_stmt),
+			  NULL, is_gimple_val, fb_rvalue);
 
   t = OMP_FOR_COND (for_stmt);
   gcc_assert (COMPARISON_CLASS_P (t));
   gcc_assert (TREE_OPERAND (t, 0) == decl);
-  ret |= gimplify_expr (&TREE_OPERAND (t, 1), &OMP_FOR_PRE_BODY (for_stmt),
-			NULL, is_gimple_val, fb_rvalue);
+
+  /* Gimplify inside our parent's context if this is part of a combined
+     parallel+workshare directive.  */
+  if (gimplify_ctxp->combined_pre_p)
+    ret |= gimplify_expr_in_ctx (&TREE_OPERAND (t, 1),
+				 gimplify_ctxp->combined_pre_p, NULL,
+				 is_gimple_val, fb_rvalue,
+				 gimplify_ctxp->combined_ctxp);
+  else
+    ret |= gimplify_expr (&TREE_OPERAND (t, 1), &OMP_FOR_PRE_BODY (for_stmt),
+			  NULL, is_gimple_val, fb_rvalue);
 
   t = OMP_FOR_INCR (for_stmt);
   switch (TREE_CODE (t))
@@ -4733,9 +4789,18 @@ gimplify_omp_for (tree *expr_p, tree *pr
 	default:
 	  gcc_unreachable ();
 	}
-      ret |= gimplify_expr (&TREE_OPERAND (t, 1),
-			    &OMP_FOR_PRE_BODY (for_stmt),
-			    NULL, is_gimple_val, fb_rvalue);
+
+      /* Gimplify inside our parent's context if this is part of a
+	 combined parallel+workshare directive.  */
+      if (gimplify_ctxp->combined_pre_p)
+	ret |= gimplify_expr_in_ctx (&TREE_OPERAND (t, 1),
+				     gimplify_ctxp->combined_pre_p, NULL,
+				     is_gimple_val, fb_rvalue,
+				     gimplify_ctxp->combined_ctxp);
+      else
+	ret |= gimplify_expr (&TREE_OPERAND (t, 1),
+	                      &OMP_FOR_PRE_BODY (for_stmt), NULL,
+			      is_gimple_val, fb_rvalue);
       break;
 
     default:

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