]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Add warning when functions containing metadirectives with 'construct={target...
authorKwok Cheung Yeung <kcy@codesourcery.com>
Fri, 28 Jan 2022 13:56:33 +0000 (13:56 +0000)
committerKwok Cheung Yeung <kcy@codesourcery.com>
Fri, 28 Jan 2022 15:44:23 +0000 (15:44 +0000)
void f(void)
{
  #pragma omp metadirective \
    when (construct={target}: A) \
    default (B)
    ...
}
...
{
  #pragma omp target
    f(); // Target call

  f(); // Local call
}

With the OpenMP 5.0/5.1 specifications, we would expect A to be selected in
the metadirective when the target call is made, but B when f is called
directly outside of a target context.  However, since GCC does not have
separate copies of f for local and target calls, and the construct selector
is static, it must be resolved one way or the other at compile-time (currently
in the favour of selecting A), which may be unexpected behaviour.

This patch attempts to detect the above situation, and will emit a warning
if found.

2022-01-28  Kwok Cheung Yeung  <kcy@codesourcery.com>

gcc/
* gimplify.c (gimplify_omp_metadirective): Mark offloadable functions
containing metadirectives with 'construct={target}' in the selector.
* omp-general.c (omp_has_target_constructor_p): New.
* omp-general.h (omp_has_target_constructor_p): New prototype.
* omp-low.c (lower_omp_1): Emit warning if marked functions called
outside of a target context.

gcc/testsuite/
* c-c++-common/gomp/metadirective-4.c (main): Add expected warning.
* gfortran.dg/gomp/metadirective-4.f90 (test): Likewise.

libgomp/
* testsuite/libgomp.c-c++-common/metadirective-2.c (main): Add
expected warning.
* testsuite/libgomp.fortran/metadirective-2.f90 (test): Likewise.

gcc/gimplify.c
gcc/omp-general.c
gcc/omp-general.h
gcc/omp-low.c
gcc/testsuite/c-c++-common/gomp/metadirective-4.c
gcc/testsuite/gfortran.dg/gomp/metadirective-4.f90
libgomp/testsuite/libgomp.c-c++-common/metadirective-2.c
libgomp/testsuite/libgomp.fortran/metadirective-2.f90

index d33da65778d3fc4123b4a35d9f6083b51f1e51d8..6e0c900e26c9526addbf79f94707e4f12cc286bd 100644 (file)
@@ -15251,6 +15251,27 @@ gimplify_omp_metadirective (tree *expr_p, gimple_seq *pre_p, gimple_seq *,
 {
   auto_vec<tree> selectors;
 
+  /* Mark offloadable functions containing metadirectives that specify
+     a 'construct' selector with a 'target' constructor.  */
+  if (offloading_function_p (current_function_decl))
+    {
+      for (tree clause = OMP_METADIRECTIVE_CLAUSES (*expr_p);
+          clause != NULL_TREE; clause = TREE_CHAIN (clause))
+       {
+         tree selector = TREE_PURPOSE (clause);
+
+         if (omp_has_target_constructor_p (selector))
+           {
+             tree id = get_identifier ("omp metadirective construct target");
+
+             DECL_ATTRIBUTES (current_function_decl)
+               = tree_cons (id, NULL_TREE,
+                            DECL_ATTRIBUTES (current_function_decl));
+             break;
+           }
+       }
+    }
+
   /* Try to resolve the metadirective.  */
   vec<struct omp_metadirective_variant> candidates
     = omp_resolve_metadirective (*expr_p);
index bf54b969133aa2ea82cf067a555b6f21a1f285e8..33c2a9b514a7bf668576708250edd3799d105bc2 100644 (file)
@@ -2931,6 +2931,27 @@ omp_resolve_metadirective (gimple *gs)
   return omp_get_dynamic_candidates (variants);
 }
 
+bool
+omp_has_target_constructor_p (tree selector)
+{
+  if (selector == NULL_TREE)
+    return false;
+
+  tree selector_set = TREE_PURPOSE (selector);
+  if (strcmp (IDENTIFIER_POINTER (selector_set), "construct") != 0)
+    return false;
+
+  enum tree_code constructs[5];
+  int nconstructs
+    = omp_constructor_traits_to_codes (TREE_VALUE (selector), constructs);
+
+  for (int i = 0; i < nconstructs; i++)
+    if (constructs[i] == OMP_TARGET)
+      return true;
+
+  return false;
+}
+
 /* Encode an oacc launch argument.  This matches the GOMP_LAUNCH_PACK
    macro on gomp-constants.h.  We do not check for overflow.  */
 
index f6c70ccd348c527575fc2b32d3020f75b0e95e3a..cac03951192b4d2b72a6f10cbf62c202187265d1 100644 (file)
@@ -126,6 +126,7 @@ extern tree omp_get_context_selector (tree, const char *, const char *);
 extern tree omp_resolve_declare_variant (tree);
 extern vec<struct omp_metadirective_variant> omp_resolve_metadirective (tree);
 extern vec<struct omp_metadirective_variant> omp_resolve_metadirective (gimple *);
+extern bool omp_has_target_constructor_p (tree);
 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);
index 9445a6b18ddbb0be650f4c72928d5f62f54060cf..05e32f225f375e0e349b81ecddcf614122ad17b5 100644 (file)
@@ -14893,6 +14893,24 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       tree fndecl;
       call_stmt = as_a <gcall *> (stmt);
       fndecl = gimple_call_fndecl (call_stmt);
+      if (fndecl
+         && lookup_attribute ("omp metadirective construct target",
+                              DECL_ATTRIBUTES (fndecl)))
+       {
+         bool in_target_ctx = false;
+
+         for (omp_context *up = ctx; up; up = up->outer)
+           if (gimple_code (up->stmt) == GIMPLE_OMP_TARGET)
+             {
+               in_target_ctx = true;
+               break;
+             }
+         if (!ctx || !in_target_ctx)
+           warning_at (gimple_location (stmt), 0,
+                       "direct calls to an offloadable function containing "
+                       "metadirectives with a %<construct={target}%> "
+                       "selector may produce unexpected results");
+       }
       if (fndecl
          && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
        switch (DECL_FUNCTION_CODE (fndecl))
index c4b109295db25e57b82de977a4bbe707e78477dc..25efbe046bf23367edba6cac17b19f0a8fdc678d 100644 (file)
@@ -25,7 +25,7 @@ void f(double a[], double x) {
 
   /* TODO: This does not execute a version of f with the default clause
      active as might be expected.  */
-  f (a, 2.71828);
+  f (a, 2.71828); /* { dg-warning "direct calls to an offloadable function containing metadirectives with a 'construct={target}' selector may produce unexpected results" } */
 
   return 0;
  }
index b82c9ea96d96589a2dad7b90d0bb34fced7b13b7..65eb05cd2fbaf6d623d3a8fc5d619475426b07fc 100644 (file)
@@ -13,7 +13,7 @@ program test
 
   ! TODO: This does not execute a version of f with the default clause
   ! active as might be expected.
-  call f (a, 2.71828)
+  call f (a, 2.71828) ! { dg-warning "direct calls to an offloadable function containing metadirectives with a 'construct={target}' selector may produce unexpected results" }
 contains
   subroutine f (a, x)
     integer :: i
index cd5c6c5e21a16522ac819cbd98ec406155a8aae4..55a6098e525a0ca4d8bd282d75712ea964da963f 100644 (file)
@@ -31,7 +31,7 @@ void f(double a[], double x) {
 
   /* TODO: This does not execute a version of f with the default clause
      active as might be expected.  */
-  f (a, M_E);
+  f (a, M_E); /* { dg-warning "direct calls to an offloadable function containing metadirectives with a 'construct={target}' selector may produce unexpected results" } */
 
   for (i = 0; i < N; i++)
     if (fabs (a[i] - (M_E * i)) > EPSILON)
index 32017a000779fafc2009b0bdcf11bf126d3daf4f..d83474cf2db991d25f1c70849dbbac3fe84205fd 100644 (file)
@@ -19,7 +19,7 @@ program test
 
   ! TODO: This does not execute a version of f with the default clause
   ! active as might be expected.
-  call f (a, E_CONST)
+  call f (a, E_CONST) ! { dg-warning "direct calls to an offloadable function containing metadirectives with a 'construct={target}' selector may produce unexpected results" }
 
   do i = 1, N
     if (abs (a(i) - (E_CONST * i)) .gt. EPSILON) stop 2