I've committed this patch, which replaces IFN_GOACC_FORK and IFN_GOACC_JOIN with a single IFN_UNIQUE function. This makes the fork & join handling slightly more tricky, but reduces the invasion into the rest of the compiler -- the unique predicate function only need check a single value and is worth making inline.

nathan
2015-09-14  Nathan Sidwell  <nat...@codesourcery.com>

	* gimple.h (gimple_call_internal_unique_p): Make inline.
	* internal-fn.def (UNIQUE): New.
	(GOACC_FORK, GOACC_JOIN): Delete.
	(IFN_UNIQUE_UNSPEC, IFN_UNIQUE_OACC_FORK,
	IFN_UNIQUE_OACC_JOIN): Define.
	* internal-fn.c (gimple_call_internal_unique_p): Delete.
	(expand_UNIQUE): New.  Absorb ...
	(expand_GOACC_FORK, expand_GOACC_JOIN): ... these.  Delete.
	* omp-low.c (lower_oacc_loop_helper): Emit IFN_UNIQUE call.
	(lower_pacc_loop_enter_exit): Adjust.
	(execute_oacc_transform): Check IFN_UNIQUE for fork & join.
	* config/nvptx/nvptx.c (nvptx_xform_fork_join): Adjust arg
	position.

Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h	(revision 227759)
+++ gcc/gimple.h	(working copy)
@@ -2691,8 +2691,11 @@ gimple_call_internal_fn (const_gimple gs
 
 /* Return true, if this internal gimple call is unique.  */
 
-extern bool
-gimple_call_internal_unique_p (const_gimple);
+inline bool
+gimple_call_internal_unique_p (const_gimple gs)
+{
+  return gimple_call_internal_fn (gs) == IFN_UNIQUE;
+}
 
 /* If CTRL_ALTERING_P is true, mark GIMPLE_CALL S to be a stmt
    that could alter control flow.  */
Index: gcc/internal-fn.def
===================================================================
--- gcc/internal-fn.def	(revision 227759)
+++ gcc/internal-fn.def	(working copy)
@@ -65,15 +65,12 @@ DEF_INTERNAL_FN (TSAN_FUNC_EXIT, ECF_NOV
 DEF_INTERNAL_FN (VA_ARG, ECF_NOTHROW | ECF_LEAF, NULL)
 DEF_INTERNAL_FN (GOACC_DATA_END_WITH_ARG, ECF_NOTHROW, ".r")
 
-/* FORK and JOIN mark the points at which partitioned execution is
-   entered or exited.  We arrange for these two function to be
-   unduplicable and uncombinable in order to preserve the SESE CFG
-   property of partitioned loops.  These are non-const functions to prevent
-   optimizations migrating memory accesses across a partition change
-   boundary.  They take a single INTEGER_CST
-   argument and return nothing.  */
-DEF_INTERNAL_FN (GOACC_FORK, ECF_NOTHROW | ECF_LEAF, ".")
-DEF_INTERNAL_FN (GOACC_JOIN, ECF_NOTHROW | ECF_LEAF, ".")
+/* An unduplicable, uncombinable function.  Generally used to preserve
+   a CFG property in the face of jump threading, tail merging or
+   other such optimizations. The optional first argument distinguishes
+   between uses.  Other arguments are as needed for use.  The return
+   type depends on use too. */
+DEF_INTERNAL_FN (UNIQUE, ECF_NOTHROW | ECF_LEAF, NULL)
 
 /* DIM_SIZE and DIM_POS return the size of a particular compute
    dimension and the executing thread's position within that
@@ -109,3 +106,11 @@ DEF_INTERNAL_FN (GOACC_REDUCTION_INIT, E
 DEF_INTERNAL_FN (GOACC_REDUCTION_FINI, ECF_NOTHROW, NULL)
 DEF_INTERNAL_FN (GOACC_REDUCTION_TEARDOWN, ECF_NOTHROW, NULL)
 
+/* IFN_UNIQUE uses an INTEGER_CST first argument to discriminate use.  */
+#define IFN_UNIQUE_UNSPEC 0
+
+/* FORK and JOIN mark the points at which partitioned execution is
+   entered or exited.  They take an INTEGER_CST argument, indicating
+   the axis of forking or joining and return nothing.  */
+#define IFN_UNIQUE_OACC_FORK 1
+#define IFN_UNIQUE_OACC_JOIN 2
Index: gcc/omp-low.c
===================================================================
--- gcc/omp-low.c	(revision 227759)
+++ gcc/omp-low.c	(working copy)
@@ -4862,7 +4862,7 @@ oacc_fake_gang_reduction (omp_context *c
 static unsigned
 lower_oacc_loop_helper (tree clauses, gimple_seq *ilist, gimple_seq *olist,
 			 omp_context *ctx, enum internal_fn f1,
-			 enum internal_fn f2, enum internal_fn fork_join,
+			 enum internal_fn f2, unsigned fork_join,
 			 unsigned loop_dim, unsigned loop_mask,
 			 bool emit_f1)
 {
@@ -4872,7 +4872,8 @@ lower_oacc_loop_helper (tree clauses, gi
 
   lower_oacc_reductions (f1, loop_dim, clauses, ilist, ctx, emit_f1);
   gwv = build_int_cst (unsigned_type_node, loop_dim);
-  call = gimple_build_call_internal (fork_join, 1, gwv);
+  call = gimple_build_call_internal
+    (IFN_UNIQUE, 2, build_int_cst (unsigned_type_node, fork_join), gwv);
   gimple_seq_add_stmt (ilist, call);
   lower_oacc_reductions (f2, loop_dim, clauses, ilist, ctx, true);
   loop_mask = loop_mask & ~GOMP_DIM_MASK (loop_dim);
@@ -11199,7 +11200,7 @@ lower_oacc_loop_enter_exit (bool enter_l
 	    lower_oacc_loop_helper (clauses, ilist, &oacc_gang_reduction_init,
 				    ctx, IFN_GOACC_REDUCTION_SETUP,
 				    IFN_GOACC_REDUCTION_INIT,
-				    IFN_GOACC_FORK, i, loop_dim_mask,
+				    IFN_UNIQUE_OACC_FORK, i, loop_dim_mask,
 				    enter_loop);
     }
   else
@@ -11210,7 +11211,7 @@ lower_oacc_loop_enter_exit (bool enter_l
 	    lower_oacc_loop_helper (clauses, ilist, &oacc_gang_reduction_fini,
 				    ctx, IFN_GOACC_REDUCTION_FINI,
 				    IFN_GOACC_REDUCTION_TEARDOWN,
-				    IFN_GOACC_JOIN, i, loop_dim_mask,
+				    IFN_UNIQUE_OACC_JOIN, i, loop_dim_mask,
 				    enter_loop);
     }
 }
@@ -14907,18 +14908,26 @@ execute_oacc_transform ()
 		      needs_rescan = true;
 		    continue;
 
-		  case IFN_GOACC_FORK:
-		  case IFN_GOACC_JOIN:
-		    if (targetm.goacc.fork_join
-			(stmt, dims, ifn_code == IFN_GOACC_FORK))
-		      {
-		      remove:
-			replace_uses_by (gimple_vdef (stmt),
-					 gimple_vuse (stmt));
-			gsi_remove (&gsi, true);
-			/* Removal will have advanced the iterator.  */
-			continue;
-		      }
+		  case IFN_UNIQUE:
+		    {
+		      unsigned code;
+
+		      code = TREE_INT_CST_LOW (gimple_call_arg (stmt, 0));
+
+		      if ((code == IFN_UNIQUE_OACC_FORK
+			   || code == IFN_UNIQUE_OACC_JOIN)
+			  && (targetm.goacc.fork_join
+			      (stmt, dims, code == IFN_UNIQUE_OACC_FORK)))
+			{
+			remove:
+			  replace_uses_by (gimple_vdef (stmt),
+					   gimple_vuse (stmt));
+			  gsi_remove (&gsi, true);
+			  /* Removal will have advanced the iterator.  */
+			  continue;
+			}
+		    }
+		  
 		    break;
 		  }
 	      }
Index: gcc/internal-fn.c
===================================================================
--- gcc/internal-fn.c	(revision 227759)
+++ gcc/internal-fn.c	(working copy)
@@ -78,20 +78,6 @@ init_internal_fns ()
   internal_fn_fnspec_array[IFN_LAST] = 0;
 }
 
-/* Return true if this internal fn call is a unique marker -- it
-   should not be duplicated or merged.  */
-
-bool
-gimple_call_internal_unique_p (const_gimple gs)
-{
-  switch (gimple_call_internal_fn (gs))
-    {
-    default: return false;
-    case IFN_GOACC_FORK: return true;
-    case IFN_GOACC_JOIN: return true;
-    }
-}
-
 /* ARRAY_TYPE is an array of vector modes.  Return the associated insn
    for load-lanes-style optab OPTAB.  The insn must exist.  */
 
@@ -1956,37 +1942,52 @@ expand_VA_ARG (gcall *stmt ATTRIBUTE_UNU
   gcc_unreachable ();
 }
 
-/* GOACC_DATA_END_WITH_ARG is supposed to be expanded at pass_late_lower_omp.
-   So this dummy function should never be called.  */
-
 static void
-expand_GOACC_DATA_END_WITH_ARG (gcall *stmt ATTRIBUTE_UNUSED)
+expand_UNIQUE (gcall *stmt)
 {
-  gcc_unreachable ();
-}
+  rtx pattern = NULL_RTX;
 
-static void
-expand_GOACC_FORK (gcall *ARG_UNUSED (stmt))
-{
+  switch (TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)))
+    {
+    default:
+      gcc_unreachable ();
+
+    case IFN_UNIQUE_UNSPEC:
+#ifdef HAVE_unique
+      pattern = gen_unique ();
+#endif
+      break;
+
+    case IFN_UNIQUE_OACC_FORK:
 #ifdef HAVE_oacc_fork
-  rtx dim = expand_normal (gimple_call_arg (stmt, 0));
-  
-  emit_insn (gen_oacc_fork (dim));
+      pattern = expand_normal (gimple_call_arg (stmt, 1));
+      pattern = gen_oacc_fork (pattern);
 #else
-  gcc_unreachable ();
+      gcc_unreachable ();
 #endif
+      break;
+
+    case IFN_UNIQUE_OACC_JOIN:
+#ifdef HAVE_oacc_join
+      pattern = expand_normal (gimple_call_arg (stmt, 1));
+      pattern = gen_oacc_join (pattern);
+#else
+      gcc_unreachable ();
+#endif
+      break;
+    }
+
+  if (pattern)
+    emit_insn (pattern);
 }
 
+/* GOACC_DATA_END_WITH_ARG is supposed to be expanded at pass_late_lower_omp.
+   So this dummy function should never be called.  */
+
 static void
-expand_GOACC_JOIN (gcall *ARG_UNUSED (stmt))
+expand_GOACC_DATA_END_WITH_ARG (gcall *stmt ATTRIBUTE_UNUSED)
 {
-#ifdef HAVE_oacc_join
-  rtx dim = expand_normal (gimple_call_arg (stmt, 0));
-  
-  emit_insn (gen_oacc_join (dim));
-#else
   gcc_unreachable ();
-#endif
 }
 
 static void
Index: gcc/config/nvptx/nvptx.c
===================================================================
--- gcc/config/nvptx/nvptx.c	(revision 227759)
+++ gcc/config/nvptx/nvptx.c	(working copy)
@@ -4404,7 +4404,7 @@ static bool
 nvptx_xform_fork_join (gimple stmt, const int dims[],
 		       bool ARG_UNUSED (is_fork))
 {
-  tree arg = gimple_call_arg (stmt, 0);
+  tree arg = gimple_call_arg (stmt, 1);
   unsigned axis = TREE_INT_CST_LOW (arg);
 
   /* We only care about worker and vector partitioning.  */

Reply via email to