Re: [PATCH] openmp: Do not emit OMPT loop-end call with inscan
Paul-Antoine Arras <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Hi Tobias,
Thanks for the review.
On 08/08/2026 19:45, Tobias Burnus wrote:
> Paul-Antoine Arras wrote:
>> When the inscan modifier is present on a for construct, a call to GOMP_loop_end
>> (or one of its variants) is already emitted. The extra call to one of the
>> *_worksharing_end functions, enabled by -fopenmp-ompt, is therefore redundant.
>
> Looking at the code and the dump, I was confused - and I know now why :-)
>
>
> With -fopenmp-ompt, the code was (before this patch):
>
> D.3286 = __builtin_GOMP_loop_static_worksharing_start (100);
> ...
> __builtin_GOMP_loop_end_nowait ();
> __builtin_GOMP_loop_static_worksharing_end ();
>
> The 'GOMP_loop_static_worksharing_start' dispatches the ompt_work_loop_static
> callback with ompt_scope_begin
>
> And both 'GOMP_loop_end_nowait' and 'GOMP_loop_static_worksharing_end'
> dispatch: 'ompt_work_loop_static' with ompt_scope_end.
>
> [Side remark: the nowait function knows the schedule type, i.e. it
> might also dispatch other callbacks; but for static both are identical.]
>
> Thus, the patch now removes the call to the latter.
> This now LGTM.
>
>
> However, without -fopenmp-ompt, the code looks as follows:
>
> D.3282 = __builtin_GOMP_loop_static_worksharing (100);
> __builtin_GOMP_loop_end_nowait ();
>
> Both invoke the ompt_work_loop_static callback - the latter, see
> above, with ompt_scope_end.
>
> However, the former with ompt_scope_beginend. - That's inconsistent!
> If there is an 'end', there needs to be a 'begin' not a 'beginend'!
>
> Hence: If there is latere a call to GOMP_loop_end_nowait, the first
> call must be to GOMP_loop_static_worksharing_start.
>
> * * *
>
>> gcc/ChangeLog:
>>
>> * omp-expand.cc (expand_omp_for_static_nochunk): Do not emit
>> *_static_worksharing_end call with inscan modifier.
>
> Spurious '*' at the front of the second line.
>
> * * *
>
>> --- a/gcc/omp-expand.cc
>> +++ b/gcc/omp-expand.cc
>> @@ -5610,7 +5610,10 @@ expand_omp_for_static_nochunk (struct omp_region *region,
>> }
>>
>> gsi = gsi_last_nondebug_bb (exit_bb);
>> - if (flag_openmp_ompt)
>> + if (flag_openmp_ompt
>> + && !(fd->have_reductemp
>> + || ((fd->have_pointer_condtemp || fd->have_scantemp)
>> + && !fd->have_nonctrl_scantemp)))
>> {
>> /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb.
>> */
>> @@ -6367,7 +6370,7 @@ expand_omp_for_static_chunk (struct omp_region *region,
>> }
>>
>> gsi = gsi_last_nondebug_bb (exit_bb);
>> - if (flag_openmp_ompt)
>> + if (flag_openmp_ompt && !(fd->have_reductemp || fd->have_pointer_condtemp))
>> {
>> /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb.
>> */
>
> In both functions:
>
> * If there will be a GOMP_loop_end_nowait call, the *static*_start call has
> to be called. [Also without -fopenmp-ompt], otherwise only with -fopenmp-ompt.
>
> Any maybe also add a comment that - as the call to GOMP_loop_end_nowait implies
> the end of the scope, '_start' has to be used and '_end' can be skipped.
>
> Maybe, it looks cleaner with some common boolean to handle the check both for the
> adding of _start and (with a !boolean) for (not) adding the _end call?
>
> * * *
>
> In libgomp/loop.c, can you add a comment to the non-"_start" function
> that the "_start" one is called if there is a "_end_nowait" call - and note
> at the "_start" function that no _end" is expected if there is an _end_nowait"
> call? – Or something like that?
Please find attached an updated patch.
Cheers,
--
PA
v2-0001-openmp-Adjust-calls-to-OMPT-variants-depending-on.patch
(text/x-patch, 7.6 KB)
From 42238c860458c7355cddab45b730ceee78c51d73 Mon Sep 17 00:00:00 2001 From: Paul-Antoine Arras <[email protected]> Date: Fri, 7 Aug 2026 15:33:37 +0200 Subject: [PATCH v2] openmp: Adjust calls to OMPT variants depending on loop-end call When the inscan modifier is present on a for construct, a call to GOMP_loop_end (or one of its variants) is already emitted. The extra call to one of the *_worksharing_end functions, enabled by -fopenmp-ompt, is therefore redundant. Furthermore, even without -fopenmp-ompt, the inscan modifier implies a call to GOMP_loop_end which requires the start variant of GOMP_loop_static_worksharing. gcc/ChangeLog: * omp-expand.cc (expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Adjust calls to OMPT variants with GOMP_loop_end. gcc/testsuite/ChangeLog: * c-c++-common/gomp/scan-8.c: New test. * c-c++-common/gomp/scan-9.c: New test. libgomp/ChangeLog: * loop.c (GOMP_loop_static_worksharing_start, GOMP_loop_static_worksharing_end): Update comments. --- gcc/omp-expand.cc | 34 +++++++++++++++++------- gcc/testsuite/c-c++-common/gomp/scan-8.c | 22 +++++++++++++++ gcc/testsuite/c-c++-common/gomp/scan-9.c | 21 +++++++++++++++ libgomp/loop.c | 6 +++-- 4 files changed, 71 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/scan-8.c create mode 100644 gcc/testsuite/c-c++-common/gomp/scan-9.c diff --git a/gcc/omp-expand.cc b/gcc/omp-expand.cc index 0d801e0d68a..65f65da4b07 100644 --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -5225,6 +5225,12 @@ expand_omp_for_static_nochunk (struct omp_region *region, t = fold_convert (itype, t); n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); + /* When GOMP_loop_end (or one of its variants) is emitted (e.g. with the + inscan modifier), which already implies the end of the scope, _start + variants of GOMP builtin calls have to be used and _end can be skipped. */ + bool has_gomp_loop_end = fd->have_reductemp + || ((fd->have_pointer_condtemp || fd->have_scantemp) + && !fd->have_nonctrl_scantemp); { /* Fetch the thread/team id and the number of threads/teams in a single call to GOMP_loop_static_worksharing or @@ -5239,13 +5245,15 @@ expand_omp_for_static_nochunk (struct omp_region *region, { case GF_OMP_FOR_KIND_FOR: decl = builtin_decl_explicit ( - flag_openmp_ompt ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START - : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING); + flag_openmp_ompt || has_gomp_loop_end + ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START + : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING); break; case GF_OMP_FOR_KIND_DISTRIBUTE: decl = builtin_decl_explicit ( - flag_openmp_ompt ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START - : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING); + flag_openmp_ompt || has_gomp_loop_end + ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START + : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING); break; default: gcc_unreachable (); @@ -5610,7 +5618,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, } gsi = gsi_last_nondebug_bb (exit_bb); - if (flag_openmp_ompt) + if (flag_openmp_ompt && !has_gomp_loop_end) { /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb. */ @@ -6056,6 +6064,10 @@ expand_omp_for_static_chunk (struct omp_region *region, n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT); + /* When GOMP_loop_end (or one of its variants) is emitted (e.g. with the + inscan modifier), which already implies the end of the scope, _start + variants of GOMP builtin calls have to be used and _end can be skipped. */ + bool has_gomp_loop_end = fd->have_reductemp || fd->have_pointer_condtemp; { /* Fetch the thread/team id and the number of threads/teams in a single call to GOMP_loop_static_worksharing or @@ -6070,13 +6082,15 @@ expand_omp_for_static_chunk (struct omp_region *region, { case GF_OMP_FOR_KIND_FOR: decl = builtin_decl_explicit ( - flag_openmp_ompt ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START - : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING); + flag_openmp_ompt || has_gomp_loop_end + ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START + : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING); break; case GF_OMP_FOR_KIND_DISTRIBUTE: decl = builtin_decl_explicit ( - flag_openmp_ompt ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START - : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING); + flag_openmp_ompt || has_gomp_loop_end + ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START + : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING); break; default: gcc_unreachable (); @@ -6367,7 +6381,7 @@ expand_omp_for_static_chunk (struct omp_region *region, } gsi = gsi_last_nondebug_bb (exit_bb); - if (flag_openmp_ompt) + if (flag_openmp_ompt && !has_gomp_loop_end) { /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb. */ diff --git a/gcc/testsuite/c-c++-common/gomp/scan-8.c b/gcc/testsuite/c-c++-common/gomp/scan-8.c new file mode 100644 index 00000000000..cff8c03b349 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-8.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fopenmp-ompt -fdump-tree-ompexp" } */ + +/* Check that an extra, OMPT variant of GOMP_loop_end is not emitted when the + inscan modifier is present on the for construct. */ + +#define N 100 + +void f(void) { + int a[N], b[N]; + int x = 0; + +#pragma omp parallel for simd reduction(inscan, +: x) + for (int k = 0; k < N; k++) { + x += a[k]; +#pragma omp scan inclusive(x) + b[k] = x; + } +} + +/* { dg-final { scan-tree-dump "__builtin_GOMP_loop_end_nowait \\(" "ompexp" } } */ +/* { dg-final { scan-tree-dump-not "__builtin_GOMP_loop_end_nowait \\(\\);\[\t\n \]*__builtin_GOMP_loop_static_worksharing_end \\(\\);" "ompexp" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/scan-9.c b/gcc/testsuite/c-c++-common/gomp/scan-9.c new file mode 100644 index 00000000000..f0335536339 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-9.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-ompexp" } */ + +/* Check that the start variant of GOMP_loop_static_worksharing is emitted + when the inscan modifier is present on the for construct. */ + +#define N 100 + +void f(void) { + int a[N], b[N]; + int x = 0; + +#pragma omp parallel for simd reduction(inscan, +: x) + for (int k = 0; k < N; k++) { + x += a[k]; +#pragma omp scan inclusive(x) + b[k] = x; + } +} + +/* { dg-final { scan-tree-dump "__builtin_GOMP_loop_static_worksharing_start \\(" "ompexp" } } */ diff --git a/libgomp/loop.c b/libgomp/loop.c index 0692663215f..7474279fcd6 100644 --- a/libgomp/loop.c +++ b/libgomp/loop.c @@ -1201,7 +1201,8 @@ GOMP_loop_static_worksharing (unsigned long long niter return nthreads + tid * 1I; } -/* OMPT variant enabled by -fopenmp-ompt. */ +/* OMPT variant enabled by -fopenmp-ompt and when GOMP_loop_end is called + (e.g. with the inscan modifier). */ _Complex int GOMP_loop_static_worksharing_start (unsigned long long niter @@ -1224,7 +1225,8 @@ GOMP_loop_static_worksharing_dispatch (unsigned long long start __attribute__ ((unused))) {} -/* Stub for OMPT callback enabled by -fopenmp-ompt. */ +/* Stub for OMPT callback enabled by -fopenmp-ompt, except when GOMP_loop_end is + already called (e.g. with the inscan modifier). */ void GOMP_loop_static_worksharing_end (void) -- 2.53.0