diff options
author | Thomas Schwinge <thomas@codesourcery.com> | 2019-05-17 21:13:26 +0200 |
---|---|---|
committer | Thomas Schwinge <tschwinge@gcc.gnu.org> | 2019-05-17 21:13:26 +0200 |
commit | b48f44bf77a39fefc238a16cf1225c6464c82406 (patch) | |
tree | f549ea742dbc826500b30235525ef9fb96769ad4 /gcc/omp-general.c | |
parent | 5bf04509f437ff175c001a1c84a13b3a845174eb (diff) | |
download | gcc-b48f44bf77a39fefc238a16cf1225c6464c82406.zip gcc-b48f44bf77a39fefc238a16cf1225c6464c82406.tar.gz gcc-b48f44bf77a39fefc238a16cf1225c6464c82406.tar.bz2 |
[PR89433] Repeated use of the C/C++ OpenACC 'routine' directive
gcc/
PR middle-end/89433
* omp-general.c (oacc_verify_routine_clauses): Change formal
parameters. Add checking if already marked with an OpenACC
'routine' directive. Adjust all users.
gcc/c/
PR c/89433
* c-parser.c (c_finish_oacc_routine): Rework checking if already
marked with an OpenACC 'routine' directive.
gcc/cp/
PR c++/89433
* parser.c (cp_finalize_oacc_routine): Rework checking if already
marked with an OpenACC 'routine' directive.
gcc/testsuite/
PR testsuite/89433
* c-c++-common/goacc/routine-5.c: Update.
* c-c++-common/goacc/routine-level-of-parallelism-1.c: Likewise.
* c-c++-common/goacc/routine-level-of-parallelism-2.c: New file.
From-SVN: r271345
Diffstat (limited to 'gcc/omp-general.c')
-rw-r--r-- | gcc/omp-general.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/gcc/omp-general.c b/gcc/omp-general.c index f1d859b..82f0a04 100644 --- a/gcc/omp-general.c +++ b/gcc/omp-general.c @@ -610,11 +610,14 @@ oacc_set_fn_attrib (tree fn, tree clauses, vec<tree> *args) /* Verify OpenACC routine clauses. + Returns 0 if FNDECL should be marked with an OpenACC 'routine' directive, 1 + if it has already been marked in compatible way, and -1 if incompatible. Upon returning, the chain of clauses will contain exactly one clause specifying the level of parallelism. */ -void -oacc_verify_routine_clauses (tree *clauses, location_t loc) +int +oacc_verify_routine_clauses (tree fndecl, tree *clauses, location_t loc, + const char *routine_str) { tree c_level = NULL_TREE; tree c_p = NULL_TREE; @@ -659,6 +662,80 @@ oacc_verify_routine_clauses (tree *clauses, location_t loc) OMP_CLAUSE_CHAIN (c_level) = *clauses; *clauses = c_level; } + /* In *clauses, we now have exactly one clause specifying the level of + parallelism. */ + + tree attr + = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (fndecl)); + if (attr != NULL_TREE) + { + /* If a "#pragma acc routine" has already been applied, just verify + this one for compatibility. */ + /* Collect previous directive's clauses. */ + tree c_level_p = NULL_TREE; + for (tree c = TREE_VALUE (attr); c; c = OMP_CLAUSE_CHAIN (c)) + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_GANG: + case OMP_CLAUSE_WORKER: + case OMP_CLAUSE_VECTOR: + case OMP_CLAUSE_SEQ: + gcc_checking_assert (c_level_p == NULL_TREE); + c_level_p = c; + break; + default: + gcc_unreachable (); + } + gcc_checking_assert (c_level_p != NULL_TREE); + /* ..., and compare to current directive's, which we've already collected + above. */ + tree c_diag; + tree c_diag_p; + /* Matching level of parallelism? */ + if (OMP_CLAUSE_CODE (c_level) != OMP_CLAUSE_CODE (c_level_p)) + { + c_diag = c_level; + c_diag_p = c_level_p; + goto incompatible; + } + /* Compatible. */ + return 1; + + incompatible: + if (c_diag != NULL_TREE) + error_at (OMP_CLAUSE_LOCATION (c_diag), + "incompatible %qs clause when applying" + " %<%s%> to %qD, which has already been" + " marked with an OpenACC 'routine' directive", + omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)], + routine_str, fndecl); + else if (c_diag_p != NULL_TREE) + error_at (loc, + "missing %qs clause when applying" + " %<%s%> to %qD, which has already been" + " marked with an OpenACC 'routine' directive", + omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)], + routine_str, fndecl); + else + gcc_unreachable (); + if (c_diag_p != NULL_TREE) + inform (OMP_CLAUSE_LOCATION (c_diag_p), + "... with %qs clause here", + omp_clause_code_name[OMP_CLAUSE_CODE (c_diag_p)]); + else + { + /* In the front ends, we don't preserve location information for the + OpenACC routine directive itself. However, that of c_level_p + should be close. */ + location_t loc_routine = OMP_CLAUSE_LOCATION (c_level_p); + inform (loc_routine, "... without %qs clause near to here", + omp_clause_code_name[OMP_CLAUSE_CODE (c_diag)]); + } + /* Incompatible. */ + return -1; + } + + return 0; } /* Process the OpenACC 'routine' directive clauses to generate an attribute |