public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Kwok Cheung Yeung <kcy@codesourcery.com>
To: Jakub Jelinek <jakub@redhat.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: [PATCH] openmp: Add warning when functions containing metadirectives with 'construct={target}' called directly
Date: Fri, 28 Jan 2022 16:33:29 +0000	[thread overview]
Message-ID: <2c37dd8b-4a59-6b18-b49e-4c914f45f4f7@codesourcery.com> (raw)
In-Reply-To: <20210726212329.GE2380545@tucnak>

[-- Attachment #1: Type: text/plain, Size: 3035 bytes --]

Hello

Regarding this issue which we discussed previously - I have created a 
patch that adds a warning when this situation is detected.

When a metadirective in a explicitly marked target function is 
gimplified, it is checked to see if it contains a 'construct={target}' 
selector - if it does, then the containing function is marked with 'omp 
metadirective construct target'.

In the omp-low pass, when function calls are processed, the target 
function is checked to see if it contains the marker. If it does and the 
call is not made in a target context, a warning is emitted.

This will obviously not catch every possible occurence (e.g. if the 
function containing the metadirective is called from another target 
function which is then called locally, or if the call is made via a 
function pointer), but it might still be useful? Okay for mainline (once 
the metadirective patches are done)?

Thanks

Kwok

On 26/07/2021 10:23 pm, Jakub Jelinek wrote:
> On Mon, Jul 26, 2021 at 10:19:35PM +0100, Kwok Cheung Yeung wrote:
>>> Yes, that is a target variant, but I'm pretty sure we've decided that
>>> the target construct added for declare target is actually not a dynamic
>>> property.  So basically mostly return to the 5.0 wording with clarifications
>>> for Fortran.  See
>>> https://github.com/OpenMP/spec/issues/2612#issuecomment-849742988
>>> for details.
>>> Making the target in construct dynamic would pretty much force all the
>>> scoring to be dynamic as well.
>>
>> In that comment, Deepak says:
>>
>> So, we decided to keep the target trait static, requiring that the declare
>> target directive must be explicit and that the function version must be
>> different from the version of the function that may be called outside of a
>> target region (with the additional clarification that whether it differs or
>> not will be implementation defined).
>>
>> "the function version must be different from the version of the function
>> that may be called outside of a target region": This is what we do not have
>> in GCC at the moment - the function versions called within and outside
>> target regions are the same on the host.
>>
>> "whether it differs or not will be implementation defined": So whether a
>> function with 'declare target' and a metadirective involving a 'target'
>> construct behaves the same or not when called from both inside and outside
>> of a target region is implementation defined?
>>
>> I will leave the treatment of target constructs in the selector as it is
>> then, with both calls going to the same function with the metadirective
>> resolving to the 'target' variant. I will try to address your other concerns
>> later.
> 
> I think you're right, it should differ in the host vs. target version iff
> it is in explicit declare target block, my memory is weak, but let's implement
> the 5.0 wording for now (and ignore the 5.1 wording later on) and only when
> we'll be doing 5.2 change this (and change for both metadirective and
> declare variant at that point).
> Ok?
> 
> 	Jakub
> 

[-- Attachment #2: 0001-openmp-Add-warning-when-functions-containing-metadir.patch --]
[-- Type: text/plain, Size: 8613 bytes --]

From 741b037a8cd6b85d43a6273ab305ce07705dfa23 Mon Sep 17 00:00:00 2001
From: Kwok Cheung Yeung <kcy@codesourcery.com>
Date: Fri, 28 Jan 2022 13:56:33 +0000
Subject: [PATCH] openmp: Add warning when functions containing metadirectives
 with 'construct={target}' called directly

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.cc (gimplify_omp_metadirective): Mark offloadable functions
	containing metadirectives with 'construct={target}' in the selector.
	* omp-general.cc (omp_has_target_constructor_p): New.
	* omp-general.h (omp_has_target_constructor_p): New prototype.
	* omp-low.cc (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.cc                               | 21 +++++++++++++++++++
 gcc/omp-general.cc                            | 21 +++++++++++++++++++
 gcc/omp-general.h                             |  1 +
 gcc/omp-low.cc                                | 18 ++++++++++++++++
 .../c-c++-common/gomp/metadirective-4.c       |  2 +-
 .../gfortran.dg/gomp/metadirective-4.f90      |  2 +-
 .../libgomp.c-c++-common/metadirective-2.c    |  2 +-
 .../libgomp.fortran/metadirective-2.f90       |  2 +-
 8 files changed, 65 insertions(+), 4 deletions(-)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 78bae567ae4..c8a01a4ca52 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -14775,6 +14775,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);
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 4edeb58cc73..842e9fd868f 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -2922,6 +2922,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.  */
 
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index fdde4a3dfb0..ccdea015e15 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -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);
diff --git a/gcc/omp-low.cc b/gcc/omp-low.cc
index 59804300c28..07613362ef0 100644
--- a/gcc/omp-low.cc
+++ b/gcc/omp-low.cc
@@ -14300,6 +14300,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))
diff --git a/gcc/testsuite/c-c++-common/gomp/metadirective-4.c b/gcc/testsuite/c-c++-common/gomp/metadirective-4.c
index c4b109295db..25efbe046bf 100644
--- a/gcc/testsuite/c-c++-common/gomp/metadirective-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/metadirective-4.c
@@ -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;
  }
diff --git a/gcc/testsuite/gfortran.dg/gomp/metadirective-4.f90 b/gcc/testsuite/gfortran.dg/gomp/metadirective-4.f90
index b82c9ea96d9..65eb05cd2fb 100644
--- a/gcc/testsuite/gfortran.dg/gomp/metadirective-4.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/metadirective-4.f90
@@ -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
diff --git a/libgomp/testsuite/libgomp.c-c++-common/metadirective-2.c b/libgomp/testsuite/libgomp.c-c++-common/metadirective-2.c
index cd5c6c5e21a..55a6098e525 100644
--- a/libgomp/testsuite/libgomp.c-c++-common/metadirective-2.c
+++ b/libgomp/testsuite/libgomp.c-c++-common/metadirective-2.c
@@ -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)
diff --git a/libgomp/testsuite/libgomp.fortran/metadirective-2.f90 b/libgomp/testsuite/libgomp.fortran/metadirective-2.f90
index 32017a00077..d83474cf2db 100644
--- a/libgomp/testsuite/libgomp.fortran/metadirective-2.f90
+++ b/libgomp/testsuite/libgomp.fortran/metadirective-2.f90
@@ -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
-- 
2.25.1


  parent reply	other threads:[~2022-01-28 16:33 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-09 11:16 [WIP, OpenMP] OpenMP metadirectives support Kwok Cheung Yeung
2021-07-26 11:38 ` Kwok Cheung Yeung
2021-07-26 14:29 ` Jakub Jelinek
2021-07-26 19:28   ` Kwok Cheung Yeung
2021-07-26 19:56     ` Jakub Jelinek
2021-07-26 21:19       ` Kwok Cheung Yeung
2021-07-26 21:23         ` Jakub Jelinek
2021-07-26 21:27           ` Kwok Cheung Yeung
2022-01-28 16:33           ` Kwok Cheung Yeung [this message]
2021-12-10 17:27   ` Kwok Cheung Yeung
2021-12-10 17:29 ` [PATCH 0/7] openmp: " Kwok Cheung Yeung
2021-12-10 17:31   ` [PATCH 1/7] openmp: Add C support for parsing metadirectives Kwok Cheung Yeung
2022-02-18 21:09     ` [PATCH] openmp: Improve handling of nested OpenMP metadirectives in C and C++ (was: Re: [PATCH 1/7] openmp: Add C support for parsing metadirectives) Kwok Cheung Yeung
2022-02-18 21:26       ` [og11][committed] openmp: Improve handling of nested OpenMP metadirectives in C and C++ Kwok Cheung Yeung
2022-05-27 17:44     ` [PATCH 1/7] openmp: Add C support for parsing metadirectives Jakub Jelinek
2021-12-10 17:33   ` [PATCH 2/7] openmp: Add middle-end support for metadirectives Kwok Cheung Yeung
2022-05-30 10:54     ` Jakub Jelinek
2021-12-10 17:35   ` [PATCH 3/7] openmp: Add support for resolving metadirectives during parsing and Gimplification Kwok Cheung Yeung
2022-05-30 11:13     ` Jakub Jelinek
2021-12-10 17:36   ` [PATCH 4/7] openmp: Add support for streaming metadirectives and resolving them after LTO Kwok Cheung Yeung
2022-05-30 11:33     ` Jakub Jelinek
2021-12-10 17:37   ` [PATCH 5/7] openmp: Add C++ support for parsing metadirectives Kwok Cheung Yeung
2022-05-30 11:52     ` Jakub Jelinek
2021-12-10 17:39   ` [PATCH 6/7] openmp, fortran: Add Fortran " Kwok Cheung Yeung
2022-02-14 15:09     ` Kwok Cheung Yeung
2022-02-14 15:17     ` Kwok Cheung Yeung
2021-12-10 17:40   ` [PATCH 7/7] openmp: Add testcases for metadirectives Kwok Cheung Yeung
2022-05-27 13:42     ` Jakub Jelinek
2022-01-24 21:28   ` [PATCH] openmp: Metadirective patch fixes Kwok Cheung Yeung

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2c37dd8b-4a59-6b18-b49e-4c914f45f4f7@codesourcery.com \
    --to=kcy@codesourcery.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).