2017-02-08 Cesar Philippidis <cesar@codesourcery.com>
gcc/
* config/nvptx/nvptx.c (nvptx_adjust_reduction_type): New function.
(nvptx_goacc_reduction_setup): Use it to adjust the type of ref_to_res.
(nvptx_goacc_reduction_fini): Likewise.
(nvptx_goacc_reduction_teardown): Likewise.
* omp-low.c (lower_oacc_reductions): Handle reduction decls mapped
with GOMP_MAP_FIRSTPRIVATE_POINTER.
* convert_to_firstprivate_pointer: Rename to ...
* convert_to_firstprivate_int: ... this.
* convert_from_firstprivate_pointer: Rename to ...
* convert_from_firstprivate_int: ... this.
(lower_omp_target): Update calls to convert_{to,from}_firstprivate_int.
(default_goacc_reduction): Retype ref_to_res as necessary.
libgomp/
* testsuite/libgomp.oacc-fortran/reduction-9.f90: New test.
@@ -4794,6 +4794,23 @@ nvptx_vector_reduction (location_t loc, gimple_stmt_iterator *gsi,
return new_var;
}
+/* Dummy reduction vars that have GOMP_MAP_FIRSTPRIVATE_POINTER data
+ mappings gets retyped to (void *). Adjust the type of VAR to TYPE
+ as appropriate. */
+
+static tree
+nvptx_adjust_reduction_type (tree var, tree type, gimple_seq *seq)
+{
+ if (TREE_TYPE (TREE_TYPE (var)) == type)
+ return var;
+
+ tree ptype = build_pointer_type (type);
+ tree t = make_ssa_name (ptype);
+ tree expr = fold_build1 (NOP_EXPR, ptype, var);
+ gimple_seq_add_stmt (seq, gimple_build_assign (t, expr));
+ return t;
+}
+
/* NVPTX implementation of GOACC_REDUCTION_SETUP. */
static void
@@ -4813,7 +4830,11 @@ nvptx_goacc_reduction_setup (gcall *call)
tree ref_to_res = gimple_call_arg (call, 1);
if (!integer_zerop (ref_to_res))
- var = build_simple_mem_ref (ref_to_res);
+ {
+ ref_to_res = nvptx_adjust_reduction_type (ref_to_res, TREE_TYPE (var),
+ &seq);
+ var = build_simple_mem_ref (ref_to_res);
+ }
}
if (level == GOMP_DIM_WORKER)
@@ -4954,7 +4975,11 @@ nvptx_goacc_reduction_fini (gcall *call)
else if (integer_zerop (ref_to_res))
r = var;
else
- accum = ref_to_res;
+ {
+ ref_to_res = nvptx_adjust_reduction_type (ref_to_res, TREE_TYPE (var),
+ &seq);
+ accum = ref_to_res;
+ }
if (accum)
{
@@ -5003,7 +5028,11 @@ nvptx_goacc_reduction_teardown (gcall *call)
tree ref_to_res = gimple_call_arg (call, 1);
if (!integer_zerop (ref_to_res))
- gimplify_assign (build_simple_mem_ref (ref_to_res), var, &seq);
+ {
+ ref_to_res = nvptx_adjust_reduction_type (ref_to_res, TREE_TYPE (var),
+ &seq);
+ gimplify_assign (build_simple_mem_ref (ref_to_res), var, &seq);
+ }
}
if (lhs)
@@ -5818,6 +5818,7 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
tree ref_to_res = NULL_TREE;
tree incoming, outgoing, v1, v2, v3;
bool is_private = false;
+ bool is_fpp = false;
enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
if (rcode == MINUS_EXPR)
@@ -5876,19 +5877,37 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
is_private = true;
goto do_lookup;
}
+ else if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (cls)
+ == GOMP_MAP_FIRSTPRIVATE_POINTER)
+ && orig == OMP_CLAUSE_DECL (cls))
+ {
+ is_fpp = true;
+ goto do_lookup;
+ }
}
do_lookup:
/* This is the outermost construct with this reduction,
see if there's a mapping for it. */
if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
- && maybe_lookup_field (orig, outer) && !is_private)
+ && (maybe_lookup_field (orig, outer) || is_fpp) && !is_private)
{
- ref_to_res = build_receiver_ref (orig, false, outer);
- if (is_reference (orig))
- ref_to_res = build_simple_mem_ref (ref_to_res);
-
tree type = TREE_TYPE (var);
+
+ if (is_fpp)
+ {
+ tree x = create_tmp_var (type);
+ gimplify_assign (x, lookup_decl (orig, outer), fork_seq);
+ ref_to_res = x;
+ }
+ else
+ {
+ ref_to_res = build_receiver_ref (orig, false, outer);
+ if (is_reference (orig))
+ ref_to_res = build_simple_mem_ref (ref_to_res);
+ }
+
if (POINTER_TYPE_P (type))
type = TREE_TYPE (type);
@@ -16460,7 +16479,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
mappings. */
static tree
-convert_to_firstprivate_pointer (tree var, gimple_seq *gs)
+convert_to_firstprivate_int (tree var, gimple_seq *gs)
{
tree type = TREE_TYPE (var), new_type = NULL_TREE;
tree tmp = NULL_TREE;
@@ -16504,10 +16523,10 @@ convert_to_firstprivate_pointer (tree var, gimple_seq *gs)
return var;
}
-/* Like convert_to_firstprivate_pointer, but restore the original type. */
+/* Like convert_to_firstprivate_int, but restore the original type. */
static tree
-convert_from_firstprivate_pointer (tree var, bool is_ref, gimple_seq *gs)
+convert_from_firstprivate_int (tree var, bool is_ref, gimple_seq *gs)
{
tree type = TREE_TYPE (var);
tree new_type = NULL_TREE;
@@ -16747,8 +16766,8 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
gcc_assert (is_gimple_omp_oacc (ctx->stmt));
if (oacc_firstprivate_int)
- x = convert_from_firstprivate_pointer (x, is_reference (var),
- &fplist);
+ x = convert_from_firstprivate_int (x, is_reference (var),
+ &fplist);
else if (is_reference (new_var)
&& TREE_CODE (var_type) != POINTER_TYPE)
{
@@ -17020,7 +17039,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (is_gimple_reg (var)
&& OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
TREE_NO_WARNING (var) = 1;
- var = convert_to_firstprivate_pointer (var, &ilist);
+ var = convert_to_firstprivate_int (var, &ilist);
}
else if (!is_reference (var))
{
@@ -20939,6 +20958,17 @@ default_goacc_reduction (gcall *call)
if (!integer_zerop (ref_to_res))
{
+ /* Dummy reduction vars that have GOMP_MAP_FIRSTPRIVATE_POINTER data
+ mappings gets retyped to (void *). Adjust the type of ref_to_res
+ as appropriate. */
+ if (TREE_TYPE (TREE_TYPE (ref_to_res)) != TREE_TYPE (var))
+ {
+ tree ptype = build_pointer_type (TREE_TYPE (var));
+ tree t = make_ssa_name (ptype);
+ tree expr = fold_build1 (NOP_EXPR, ptype, ref_to_res);
+ gimple_seq_add_stmt (&seq, gimple_build_assign (t, expr));
+ ref_to_res = t;
+ }
tree dst = build_simple_mem_ref (ref_to_res);
tree src = var;
new file mode 100644
@@ -0,0 +1,54 @@
+! Test gang reductions on dummy variables.
+
+! { dg-do run }
+
+program main
+ implicit none
+
+ integer g, w, v, c
+
+ g = 0
+ w = 0
+ v = 0
+ c = 0
+
+ call reduction (g, w, v, c)
+
+ if (g /= 10) call abort
+ if (w /= 10) call abort
+ if (v /= 10) call abort
+ if (c /= 100) call abort
+end program main
+
+subroutine reduction (g, w, v, c)
+ implicit none
+
+ integer g, w, v, c, i
+
+ !$acc parallel
+ !$acc loop reduction(+:g) gang
+ do i = 1, 10
+ g = g + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel
+ !$acc loop reduction(+:w) worker
+ do i = 1, 10
+ w = w + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel
+ !$acc loop reduction(+:v) vector
+ do i = 1, 10
+ v = v + 1
+ end do
+ !$acc end parallel
+
+ !$acc parallel loop reduction(+:c) gang worker vector
+ do i = 1, 100
+ c = c + 1
+ end do
+ !$acc end parallel loop
+end subroutine reduction