... instead of having an incomplete local implementation.
With these changes in place, we can then also revert the work-around r267213
"[nvptx] Unify C/Fortran routine handling in nvptx_goacc_validate_dims".
gcc/fortran/
PR fortran/72741
* gfortran.h (oacc_routine_lop): New enum.
(symbol_attribute): Use it.
* openmp.c (gfc_oacc_routine_dims): Replace with...
(gfc_oacc_routine_lop): ... this new function.
(gfc_match_oacc_routine): Adjust.
* trans-decl.c (add_attributes_to_decl): Likewise.
gcc/
PR fortran/72741
* omp-general.c (oacc_replace_fn_attrib): Mostly split out into...
(oacc_replace_fn_attrib_attr): ... this new function.
* omp-general.h (oacc_replace_fn_attrib_attr): New prototype.
* config/nvptx/nvptx.c (nvptx_goacc_validate_dims_1): Revert workaround.
gcc/testsuite/
PR fortran/72741
* gfortran.dg/goacc/classify-routine.f95: Adjust.
Co-Authored-By: Cesar Philippidis <cesar@codesourcery.com>
From-SVN: r269105
+2019-02-22 Thomas Schwinge <thomas@codesourcery.com>
+
+ PR fortran/72741
+ * omp-general.c (oacc_replace_fn_attrib): Mostly split out into...
+ (oacc_replace_fn_attrib_attr): ... this new function.
+ * omp-general.h (oacc_replace_fn_attrib_attr): New prototype.
+ * config/nvptx/nvptx.c (nvptx_goacc_validate_dims_1): Revert workaround.
+
2019-02-22 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/arm/arm-cpus.in (ares): Rename to...
else
gcc_unreachable ();
- if (routine_p)
- {
- /* OpenACC routines in C arrive here with the following attributes
- (omitting the 'omp declare target'):
- seq : __attribute__((oacc function (0 1, 0 1, 0 1)))
- vector: __attribute__((oacc function (0 1, 0 1, 1 0)))
- worker: __attribute__((oacc function (0 1, 1 0, 1 0)))
- gang : __attribute__((oacc function (1 0, 1 0, 1 0)))
-
- If we take f.i. the oacc function attribute of the worker routine
- (0 1, 1 0, 1 0), then:
- - the slice (0, 1, 1) is interpreted by oacc_fn_attrib_level as
- meaning: worker routine, that is:
- - can't contain gang loop (0),
- - can contain worker loop (1),
- - can contain vector loop (1).
- - the slice (1, 0, 0) is interpreted by oacc_validate_dims as the
- dimensions: gang: 1, worker: 0, vector: 0.
-
- OTOH, routines in Fortran arrive here with these attributes:
- seq : __attribute__((oacc function (0 0, 0 0, 0 0)))
- vector: __attribute__((oacc function (0 0, 0 0, 1 0)))
- worker: __attribute__((oacc function (0 0, 1 0, 1 0)))
- gang : __attribute__((oacc function (1 0, 1 0, 1 0)))
- that is, the same as for C but with the dimensions set to 0.
-
- This is due to a bug in the Fortran front-end: PR72741. Work around
- this bug by forcing the dimensions to be the same in Fortran as for C,
- to be able to handle C and Fortran routines uniformly in this
- function. */
- dims[GOMP_DIM_VECTOR] = fn_level > GOMP_DIM_VECTOR ? 1 : 0;
- dims[GOMP_DIM_WORKER] = fn_level > GOMP_DIM_WORKER ? 1 : 0;
- dims[GOMP_DIM_GANG] = fn_level > GOMP_DIM_GANG ? 1 : 0;
- }
-
if (oacc_min_dims_p)
{
gcc_assert (dims[GOMP_DIM_VECTOR] == 1);
+2019-02-22 Thomas Schwinge <thomas@codesourcery.com>
+ Cesar Philippidis <cesar@codesourcery.com>
+
+ PR fortran/72741
+ * gfortran.h (oacc_routine_lop): New enum.
+ (symbol_attribute): Use it.
+ * openmp.c (gfc_oacc_routine_dims): Replace with...
+ (gfc_oacc_routine_lop): ... this new function.
+ (gfc_match_oacc_routine): Adjust.
+ * trans-decl.c (add_attributes_to_decl): Likewise.
+
2019-02-22 Thomas Schwinge <thomas@codesourcery.com>
* openmp.c (gfc_match_oacc_declare): Revert earlier changes.
{ SAVE_NONE = 0, SAVE_EXPLICIT, SAVE_IMPLICIT
};
+/* OpenACC 'routine' directive's level of parallelism. */
+enum oacc_routine_lop
+{ OACC_ROUTINE_LOP_NONE = 0,
+ OACC_ROUTINE_LOP_GANG,
+ OACC_ROUTINE_LOP_WORKER,
+ OACC_ROUTINE_LOP_VECTOR,
+ OACC_ROUTINE_LOP_SEQ
+};
+
/* Strings for all symbol attributes. We use these for dumping the
parse tree, in error messages, and also when reading and writing
modules. In symbol.c. */
unsigned oacc_declare_device_resident:1;
unsigned oacc_declare_link:1;
- /* This is an OpenACC acclerator function at level N - 1 */
- unsigned oacc_function:3;
+ /* OpenACC 'routine' directive's level of parallelism. */
+ ENUM_BITFIELD (oacc_routine_lop) oacc_routine_lop:3;
/* Attributes set by compiler extensions (!GCC$ ATTRIBUTES). */
unsigned ext_attr:EXT_ATTR_NUM;
return MATCH_YES;
}
-/* Determine the loop level for a routine. */
+/* Determine the OpenACC 'routine' directive's level of parallelism. */
-static int
-gfc_oacc_routine_dims (gfc_omp_clauses *clauses)
+static oacc_routine_lop
+gfc_oacc_routine_lop (gfc_omp_clauses *clauses)
{
- int level = -1;
+ oacc_routine_lop ret = OACC_ROUTINE_LOP_SEQ;
if (clauses)
{
- unsigned mask = 0;
+ unsigned n_lop_clauses = 0;
if (clauses->gang)
- level = GOMP_DIM_GANG, mask |= GOMP_DIM_MASK (level);
+ {
+ ++n_lop_clauses;
+ ret = OACC_ROUTINE_LOP_GANG;
+ }
if (clauses->worker)
- level = GOMP_DIM_WORKER, mask |= GOMP_DIM_MASK (level);
+ {
+ ++n_lop_clauses;
+ ret = OACC_ROUTINE_LOP_WORKER;
+ }
if (clauses->vector)
- level = GOMP_DIM_VECTOR, mask |= GOMP_DIM_MASK (level);
+ {
+ ++n_lop_clauses;
+ ret = OACC_ROUTINE_LOP_VECTOR;
+ }
if (clauses->seq)
- level = GOMP_DIM_MAX, mask |= GOMP_DIM_MASK (level);
+ {
+ ++n_lop_clauses;
+ ret = OACC_ROUTINE_LOP_SEQ;
+ }
- if (mask != (mask & -mask))
+ if (n_lop_clauses > 1)
gfc_error ("Multiple loop axes specified for routine");
}
- if (level < 0)
- level = GOMP_DIM_MAX;
-
- return level;
+ return ret;
}
match
gfc_current_ns->proc_name->name,
&old_loc))
goto cleanup;
- gfc_current_ns->proc_name->attr.oacc_function
- = gfc_oacc_routine_dims (c) + 1;
+ gfc_current_ns->proc_name->attr.oacc_routine_lop
+ = gfc_oacc_routine_lop (c);
}
if (n)
#include "trans-stmt.h"
#include "gomp-constants.h"
#include "gimplify.h"
+#include "omp-general.h"
#define MAX_LABEL_VALUE 99999
list = tree_cons (get_identifier ("omp declare target"),
NULL_TREE, list);
- if (sym_attr.oacc_function)
+ if (sym_attr.oacc_routine_lop != OACC_ROUTINE_LOP_NONE)
{
- tree dims = NULL_TREE;
- int ix;
- int level = sym_attr.oacc_function - 1;
-
- for (ix = GOMP_DIM_MAX; ix--;)
- dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
- integer_zero_node, dims);
+ omp_clause_code code;
+ switch (sym_attr.oacc_routine_lop)
+ {
+ case OACC_ROUTINE_LOP_GANG:
+ code = OMP_CLAUSE_GANG;
+ break;
+ case OACC_ROUTINE_LOP_WORKER:
+ code = OMP_CLAUSE_WORKER;
+ break;
+ case OACC_ROUTINE_LOP_VECTOR:
+ code = OMP_CLAUSE_VECTOR;
+ break;
+ case OACC_ROUTINE_LOP_SEQ:
+ code = OMP_CLAUSE_SEQ;
+ break;
+ case OACC_ROUTINE_LOP_NONE:
+ default:
+ gcc_unreachable ();
+ }
+ tree c = build_omp_clause (UNKNOWN_LOCATION, code);
- list = tree_cons (get_identifier ("oacc function"),
- dims, list);
+ tree dims = oacc_build_routine_dims (c);
+ list = oacc_replace_fn_attrib_attr (list, dims);
}
return list;
/* Replace any existing oacc fn attribute with updated dimensions. */
-void
-oacc_replace_fn_attrib (tree fn, tree dims)
+/* Variant working on a list of attributes. */
+
+tree
+oacc_replace_fn_attrib_attr (tree attribs, tree dims)
{
tree ident = get_identifier (OACC_FN_ATTRIB);
- tree attribs = DECL_ATTRIBUTES (fn);
/* If we happen to be present as the first attrib, drop it. */
if (attribs && TREE_PURPOSE (attribs) == ident)
attribs = TREE_CHAIN (attribs);
- DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
+ return tree_cons (ident, dims, attribs);
+}
+
+/* Variant working on a function decl. */
+
+void
+oacc_replace_fn_attrib (tree fn, tree dims)
+{
+ DECL_ATTRIBUTES (fn)
+ = oacc_replace_fn_attrib_attr (DECL_ATTRIBUTES (fn), dims);
}
/* Scan CLAUSES for launch dimensions and attach them to the oacc
extern poly_uint64 omp_max_vf (void);
extern int omp_max_simt_vf (void);
extern tree oacc_launch_pack (unsigned code, tree device, unsigned op);
+extern tree oacc_replace_fn_attrib_attr (tree attribs, tree dims);
extern void oacc_replace_fn_attrib (tree fn, tree dims);
extern void oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args);
extern tree oacc_build_routine_dims (tree clauses);
2019-02-22 Thomas Schwinge <thomas@codesourcery.com>
+ PR fortran/72741
+ * gfortran.dg/goacc/classify-routine.f95: Adjust.
+
* c-c++-common/goacc/routine-5.c: Revert earlier changes.
* g++.dg/goacc/template.C: Likewise.
end subroutine ROUTINE
! Check the offloaded function's attributes.
-! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp declare target, oacc function \\(0 0, 1 0, 1 0\\)\\)\\)" 1 "ompexp" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(omp declare target, oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "ompexp" } }
! Check the offloaded function's classification and compute dimensions (will
! always be 1 x 1 x 1 for non-offloading compilation).
! { dg-final { scan-tree-dump-times "(?n)Function is OpenACC routine level 1" 1 "oaccdevlow" } }
! { dg-final { scan-tree-dump-times "(?n)Compute dimensions \\\[1, 1, 1\\\]" 1 "oaccdevlow" } }
-! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 1, 1 1\\), omp declare target, oacc function \\(0 0, 1 0, 1 0\\)\\)\\)" 1 "oaccdevlow" } }
+! { dg-final { scan-tree-dump-times "(?n)__attribute__\\(\\(oacc function \\(0 1, 1 1, 1 1\\), omp declare target, oacc function \\(0 1, 1 0, 1 0\\)\\)\\)" 1 "oaccdevlow" } }