public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Tobias Burnus <tobias@codesourcery.com>
To: Kwok Cheung Yeung <kcy@codesourcery.com>,
	gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Jakub Jelinek <jakub@redhat.com>
Subject: Re: [PATCH] openmp: Add support for the 'indirect' clause in C/C++
Date: Tue, 17 Oct 2023 15:12:46 +0200	[thread overview]
Message-ID: <ab895de2-534d-455d-a568-1eb6d667ced4@codesourcery.com> (raw)
In-Reply-To: <d8cddbaa-9a23-41dc-860b-f162f26e94ce@codesourcery.com>

Hi Kwok, hi Jakub, hi all,

some first comments based on both playing around and reading the
patch - and some generic comments to any patch reader.

In general, the patch looks good. I just observe:

* There is an issue with [[omp::decl(...)]]'

* <clause>(<boolean expression>) - there is a C/C++ inconsistency in
   what is expected; it possibly affects more such conditions

* Missed optimization for the host?

* Bunch of minor comments


On 08.10.23 15:13, Kwok Cheung Yeung wrote:

> This patch adds support for the 'indirect' clause in the 'declare
> target' directive in C/C++ (Fortran to follow) and adds the necessary
> infrastructure to support indirect calls in target regions. This allows
> one to pass in pointers to functions that have been declared as indirect
> from the host to the target, then invoked via the passed-in pointer on
> the target device.
> [...]
> The C++ support is currently limited to normal indirect calls - virtual
> calls on objects do not currently work. I believe the main issue is that
> the vtables are not currently copied across to the target. I have added
> some handling for OBJ_TYPE_REF to prevent the compiler from ICEing when
> it encounters a virtual call, but without the vtable this cannot work
> properly.

Side remark: Fortran polymorphic variables are similar. For them also
a vtable needs to be copied.

(For vtables, see also comment to 'libgomp.texi' far below.)

* * *

C++11 (and C23) attribute do not seem to be properly handled:

[[omp::decl (declare target,indirect(1))]]
int foo(void) { return 5; }
[[omp::decl (declare target indirect)]]
int bar(void) { return 8; }
[[omp::directive (begin declare target,indirect)]];
int baz(void) { return 11; }
[[omp::directive (end declare target)]];

While I get for the last one ("baz"):

__attribute__((omp declare target, omp declare target block, omp declare target indirect))

the first two (foo and bar) do not have any attribute; if I remove the "indirect",
I do get "__attribute__((omp declare target))". Hence, the omp::decl support seems to
partially work.

NOTE: C23 omp:: attribute support is still WIP and not yet in mainline.
Recent draft: https://gcc.gnu.org/pipermail/gcc-patches/2023-October/633007.html



The following works - but there is not a testcase for either syntax:

int bar(void) { return 8; }
[[omp::directive(declare target to(bar) , indirect(1))]];
int baz(void) { return 11; }
[[omp::directive ( declare target indirect enter(baz))]];

int bar(void) { return 8; }
#pragma omp declare target to(bar) , indirect(1)
int baz(void) { return 11; }
#pragma omp declare target indirect enter(baz)

(There is one for #pragma + 'to' in gomp/declare-target-indirect-2.c, however.)

Side remark: OpenMP 5.2 renamed 'to' to 'enter' (with deprecated alias 'to);
hence, I also use 'enter' above. The current testcases for indiredt use 'enter'.
(Not that it should make a difference as the to/enter do work.)


The following seems to work fine, but I think we do not have
a testcase for it ('bar' has no indirect, foo and baz have it):

#pragma omp begin declare target indirect(1)
int foo(void) { return 5; }
#pragma omp begin declare target indirect(0)
int bar(void) { return 8; }
int baz(void) { return 11; }
#pragma omp declare target indirect enter(baz)
#pragma omp end declare target
#pragma omp end declare target

* * *

Possibly affecting other logical flags as well, but I do notice that
gcc but not g++ accepts the following:

#pragma omp begin declare target indirect("abs")
#pragma omp begin declare target indirect(5.5)

g++ shows: error: expected constant integer expression

OpenMP requires 'constant boolean' expr (OpenMP 5.1) or
'expression of logical type','constant' (OpenMP 5.2), where for the latter it has:

"The OpenMP *logical type* supports logical variables and expressions in any base language.
"[C / C++] Any OpenMP logical expression is a scalar expression. This document uses true as
a generic term for a non-zero integer value and false as a generic term for an integer value
of zero."

I am not quite sure what to expect here; in terms of C++, conv.bool surely permits
those for those pvalues "Boolean conversions".  For C, I don't find the wording in the
standard but 'if("abc")' and 'if (5.5)' is accepted.

* * *

I notice that the {__builtin_,}GOMP_target_map_indirect_ptr call is inserted
quite late, i.e. in omp-offload.cc.  A dump and also looking at the *.s files
shows that the
   __builtin_GOMP_target_map_indirect_ptr / call    GOMP_target_map_indirect_ptr
do not only show up for the device but also for the host-fallback code.

I think the latter is not required as a host pointer can be directly executed
on the host - and device -> host pointer like in
   omp target device(ancestor:1)
do not need to be supported.

Namely the current glossary (here git version but OpenMP 5.2 is very similar);
note the "other than the host device":

"indirect device invocation - An indirect call to the device version of a
procedure on a device other than the host device, through a function pointer
(C/C++), a pointer to a member function (C++) or a procedure pointer (Fortran)
that refers to the host version of the procedure.


Can't we use  #ifdef ACCEL_COMPILER  to optimize the host fallback?

That way, we can also avoid generating the splay-tree on the host
cf. LIBGOMP_OFFLOADED_ONLY.

* * *

#pragma omp begin declare target indirect(1) device_type(host)

is accepted but it violates:

OpenMP 5.1: "Restrictions to the declare target directive are as follows:"
"If an indirect clause is present and invoked-by-fptr evaluates to true then
the only permitted device_type clause is device_type(any)" [215:1-2]

In OpenMP 5.2 that's in "7.8.3 indirect Clause" itself.

* * *

OpenMP permits pointers to member functions. Can you
also a test for those? I bet it simply works but we
should still test those.

(For vtables, see also comment below.)

class Foo {
public:
   int f(int x);
};

typedef int (Foo::*FooFptr)(int x);
...
int my_call(Foo &foo)
{
   FooFptr fn_ptr = &Foo::f;
...
   return std::invoke(fn_ptr, foo, 42);
}

* * *

Side remarks for patch readers:

Besides the existing offload functions/variables tables, a new
indirect-functions table is created; functions there do aren't
added to the function table (in the compiler-generated code).

While the code obviously affects the performance, it does not hamper
optimizations such as (modified libgomp.c-c++-common/declare-target-indirect-1.c):

#pragma omp target map (from: x)
   {
     int (*foo_ptr) (void) = &foo;
     int (*bar_ptr) (void) = &bar;
     int (*baz_ptr) (void) = &baz;
     x = (*foo_ptr) () + (*bar_ptr) () + (*baz_ptr) ();
   }
which still gives with -O1:
   _8 = *.omp_data_i_7(D).x;
   *_8 = 24;

There was some discussion at OpenMP spec level to avoid the overhead
via new assumptions which tell that 'indirect' can or cannot be
encountered. That was a more resent side discussion of the generic
questions in my Issue #3540.

I think in general there aren't that many function pointers around
and if the extra function call happens late enough (which seems to be
the case, see above), it shouldn't be a real problem in most code,
also because the indirect-reverse-lookup table is short and hopefully
there won't be too many repeated lookups with either function pointers
or C++ classes/Fortran polymorphic calls.

* * *

> --- a/gcc/omp-offload.cc +++ b/gcc/omp-offload.cc } + if
> (omp_redirect_indirect_calls + && gimple_call_fndecl (stmt) ==
> NULL_TREE) + { + gcall *orig_call = dyn_cast <gcall *> (stmt); + tree
> call_fn = gimple_call_fn (stmt); + tree map_ptr_fn + =
> builtin_decl_explicit (BUILT_IN_GOMP_TARGET_MAP_INDIRECT_PTR);

This line is too long. Maybe use a 'enum built_in_function' temporary?

> --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -304,7 +304,7
> @@ The OpenMP 4.5 specification is fully supported. @item Iterators in
> @code{target update} motion clauses and @code{map} clauses @tab N @tab
> @item Indirect calls to the device version of a procedure or function
> in - @code{target} regions @tab N @tab + @code{target} regions @tab P
> @tab Only C and C++

I think we need a new entry to handle the virtual part. However, it looks
as if that's a new OpenMP 5.2 feature. Can you add an entry under
"Other new OpenMP 5.2 features2?

At least I cannot find any existing entry and I only see in OpenMP 5.2:

"Invoking a virtual member function of an object on a device other than
the device on which the object was constructed results in unspecified
behavior, unless the object is accessible and was constructed on the
host device." [OpenMP 5.2, 287:10-12] in "Restrictions to the target construct".

> --- a/libgomp/target.c +++ b/libgomp/target.c @@ -2256,11 +2256,14 @@
> gomp_load_image_to_device (struct gomp_device_descr *devicep, unsigned
> version, void **host_funcs_end = ((void ***) host_table)[1]; void
> **host_var_table = ((void ***) host_table)[2]; void **host_vars_end =
> ((void ***) host_table)[3]; + void **host_ind_func_table = ((void ***)
> host_table)[4]; + void **host_ind_funcs_end = ((void ***) host_table)[5];

This code assumes that all calls have now 6 arguments. But that's not true for old
code. It seems as if you have to bump the version number and only access those values
when the version number is sufficiently large.

Thanks,

Tobias



-----------------
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955

  reply	other threads:[~2023-10-17 13:12 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-08 13:13 Kwok Cheung Yeung
2023-10-17 13:12 ` Tobias Burnus [this message]
2023-10-17 13:34   ` Jakub Jelinek
2023-10-17 14:41     ` Tobias Burnus
2023-11-03 19:53   ` Kwok Cheung Yeung
2023-11-06  8:48     ` Tobias Burnus
2023-11-07 21:37       ` Joseph Myers
2023-11-07 21:51         ` Jakub Jelinek
2023-11-07 21:59           ` Kwok Cheung Yeung
2023-11-09 12:24     ` Thomas Schwinge
2023-11-09 16:00       ` Tobias Burnus
2023-11-13 10:59         ` Thomas Schwinge
2023-11-13 11:47           ` Tobias Burnus
2024-04-11 10:10             ` Thomas Schwinge
2024-01-03 14:47       ` [committed] " Kwok Cheung Yeung
2024-01-03 15:54       ` Kwok Cheung Yeung
2024-01-22 20:33     ` [PATCH] openmp: Change to using a hashtab to lookup offload target addresses for indirect function calls Kwok Cheung Yeung
2024-01-24  7:06       ` rep.dot.nop
2024-01-29 17:48         ` [PATCH v2] " Kwok Cheung Yeung
2024-03-08 13:40           ` Thomas Schwinge
2024-03-14 11:38           ` Tobias Burnus
2024-01-22 20:41     ` [PATCH] openmp, fortran: Add Fortran support for indirect clause on the declare target directive Kwok Cheung Yeung
2024-01-23 19:14       ` Tobias Burnus
2024-02-05 21:37         ` [PATCH v2] " Kwok Cheung Yeung
2024-02-06  9:03           ` Tobias Burnus
2024-02-06  9:50             ` Kwok Cheung Yeung
2024-02-12  8:51               ` Tobias Burnus
2024-02-15 21:37                 ` [COMMITTED] libgomp: Update documentation for indirect calls in target regions 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=ab895de2-534d-455d-a568-1eb6d667ced4@codesourcery.com \
    --to=tobias@codesourcery.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=kcy@codesourcery.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).