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. */