This patch teaches lower_oacc_reductions how to handle reduction variables that were transferred to the accelerator via GOMP_MAP_FIRSTPRIVATE_POINTER, e.g. fortran dummy variables. One side effect of this change is that the ref_to_res variable gets remapped to the (void *) field decl that gets transferred into the accelerator with the argument struct. This happens, in part, because firstprivate_pointer variables are remapped after the OpenACC reduction variables have been processed. Consequently, I had to adjust the type of the ref_to_res variable during the oaccdevlow pass.
While working on this patch I noticed that I misnamed convert_{to,from}_firstprivate_pointer functions. Those functions cast 'scalar' values into something that can be handled as a GOMP_MAP_FIRSTPRIVATE_INT. Therefore, I renamed those functions as covert_{to,from}_firstprivate_int. This patch has been applied to gomp-4_0-branch. Cesar
2017-02-08 Cesar Philippidis <ce...@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. diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 4e6ed60..a9822e268 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -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) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 450d76e..bb2d1fa 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -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; diff --git a/libgomp/testsuite/libgomp.oacc-fortran/reduction-9.f90 b/libgomp/testsuite/libgomp.oacc-fortran/reduction-9.f90 new file mode 100644 index 0000000..fd64d88 --- /dev/null +++ b/libgomp/testsuite/libgomp.oacc-fortran/reduction-9.f90 @@ -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