aboutsummaryrefslogtreecommitdiff
path: root/gcc/omp-general.c
diff options
context:
space:
mode:
authorThomas Schwinge <thomas@codesourcery.com>2019-05-17 21:13:26 +0200
committerThomas Schwinge <tschwinge@gcc.gnu.org>2019-05-17 21:13:26 +0200
commitb48f44bf77a39fefc238a16cf1225c6464c82406 (patch)
treef549ea742dbc826500b30235525ef9fb96769ad4 /gcc/omp-general.c
parent5bf04509f437ff175c001a1c84a13b3a845174eb (diff)
downloadgcc-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.c81
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