Common Var(flag_omit_frame_pointer) Optimization
When possible do not generate stack frames.
+fopenmp-ompt
+Common Var(flag_openmp_ompt) EnabledBy(fopenmp-ompt-detailed)
+Emit additional calls into libgomp, enabling OMPT callbacks before and after some OpenMP worksharing constructs.
+
+fopenmp-ompt-detailed
+Common Var(flag_openmp_ompt_detailed)
+Like -fopenmp-ompt, and emit additional calls into libgomp, enabling OMPT dispatch callbacks.
+
fopenmp-target-simd-clone
Common Alias(fopenmp-target-simd-clone=,any,none)
fomit-frame-pointer
UrlSuffix(gcc/Optimize-Options.html#index-fno-omit-frame-pointer)
+fopenmp-ompt
+UrlSuffix(gcc/OpenMP-and-OpenACC-Options.html#index-fno-openmp-ompt)
+
+fopenmp-ompt-detailed
+UrlSuffix(gcc/OpenMP-and-OpenACC-Options.html#index-fno-openmp-ompt-detailed)
+
fopenmp-target-simd-clone
UrlSuffix(gcc/OpenMP-and-OpenACC-Options.html#index-fno-openmp-target-simd-clone)
@xref{OpenMP and OpenACC Options,,Options Controlling OpenMP and OpenACC}.
@gccoptlist{-foffload=@var{arg} -foffload-options=@var{arg}
-fopenacc -fopenacc-dim=@var{geom}
--fopenmp -fopenmp-simd -fopenmp-target-simd-clone@r{[}=@var{device-type}@r{]}}
+-fopenmp -fopenmp-simd -fopenmp-ompt -fopenmp-ompt-detailed
+-fopenmp-target-simd-clone@r{[}=@var{device-type}@r{]}}
@item Diagnostic Message Formatting Options
@xref{Diagnostic Message Formatting Options,,Options to Control Diagnostic Messages Formatting}.
@option{-fopenmp} is additionally specified, the @code{loop} region binds
to the current task region, independent of the specified @code{bind} clause.
+@opindex fopenmp-ompt
+@opindex fno-openmp-ompt
+@cindex OpenMP OMPT
+@item -fopenmp-ompt
+Emit additional calls into libgomp, enabling OMPT callbacks around some OpenMP
+worksharing constructs (namely statically scheduled @code{for} and
+@code{distribute}, @code{single}, @code{masked} and @code{master}), so that an
+OMPT tool can observe their start and end. Requires @option{-fopenmp}.
+
+@opindex fopenmp-ompt-detailed
+@opindex fno-openmp-ompt-detailed
+@cindex OpenMP OMPT
+@item -fopenmp-ompt-detailed
+Like @option{-fopenmp-ompt}, and additionally emit calls into libgomp, enabling
+OMPT dispatch callbacks that get called at the beginning of each workshare chunk
+for statically scheduled @code{for} and @code{distribute}. Requires
+@option{-fopenmp}.
+
@opindex fopenmp-target-simd-clone
@opindex fno-openmp-target-simd-clone
@cindex OpenMP target SIMD clone
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_START, "GOMP_single_start",
BT_FN_BOOL, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_START_WITH_END,
+ "GOMP_single_start_with_end", BT_FN_BOOL,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_END, "GOMP_single_end", BT_FN_VOID,
+ ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_START, "GOMP_single_copy_start",
BT_FN_PTR, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_SINGLE_COPY_END, "GOMP_single_copy_end",
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_HAS_MASKED_THREAD_NUM,
"GOMP_has_masked_thread_num", BT_FN_BOOL_INT,
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_MASKED_END, "GOMP_masked_end", BT_FN_VOID,
+ ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING,
"GOMP_loop_static_worksharing", BT_FN_COMPLEX_INT,
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START,
+ "GOMP_loop_static_worksharing_start", BT_FN_COMPLEX_INT,
+ ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_END,
+ "GOMP_loop_static_worksharing_end", BT_FN_VOID,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_DISPATCH,
+ "GOMP_loop_static_worksharing_dispatch", BT_FN_VOID,
+ ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING,
"GOMP_distribute_static_worksharing", BT_FN_COMPLEX_INT,
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START,
+ "GOMP_distribute_static_worksharing_start", BT_FN_COMPLEX_INT,
+ ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_END,
+ "GOMP_distribute_static_worksharing_end", BT_FN_VOID,
+ ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_DISPATCH,
+ "GOMP_distribute_static_worksharing_dispatch", BT_FN_VOID,
+ ATTR_NOTHROW_LEAF_LIST)
switch (gimple_omp_for_kind (fd->for_stmt))
{
case GF_OMP_FOR_KIND_FOR:
- decl = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING);
+ decl = builtin_decl_explicit (
+ flag_openmp_ompt ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START
+ : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING);
break;
case GF_OMP_FOR_KIND_DISTRIBUTE:
- decl = builtin_decl_explicit (BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING);
+ decl = builtin_decl_explicit (
+ flag_openmp_ompt ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START
+ : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING);
break;
default:
gcc_unreachable ();
cont_bb, body_bb);
}
- /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
+ if (flag_openmp_ompt_detailed)
+ {
+ /* Insert call to GOMP_*_static_worksharing_dispatch at the end of
+ seq_start_bb. */
+ gsi = gsi_last_nondebug_bb (seq_start_bb);
+ tree decl;
+ switch (gimple_omp_for_kind (fd->for_stmt))
+ {
+ case GF_OMP_FOR_KIND_FOR:
+ decl = builtin_decl_explicit (
+ BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_DISPATCH);
+ break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ decl = builtin_decl_explicit (
+ BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_DISPATCH);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gcall *g = gimple_build_call (decl, 0);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+
gsi = gsi_last_nondebug_bb (exit_bb);
+ if (flag_openmp_ompt)
+ {
+ /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb.
+ */
+ tree decl;
+ switch (gimple_omp_for_kind (fd->for_stmt))
+ {
+ case GF_OMP_FOR_KIND_FOR:
+ decl
+ = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_END);
+ break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ decl = builtin_decl_explicit (
+ BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_END);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gcall *g = gimple_build_call (decl, 0);
+ gsi_insert_after (&gsi, g, GSI_SAME_STMT);
+ }
+
+ /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
{
t = gimple_omp_return_lhs (gsi_stmt (gsi));
exit3_bb = split_block (exit2_bb, g)->dest;
gsi = gsi_after_labels (exit3_bb);
}
+
gsi_remove (&gsi, true);
/* Connect all the blocks. */
switch (gimple_omp_for_kind (fd->for_stmt))
{
case GF_OMP_FOR_KIND_FOR:
- decl = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING);
+ decl = builtin_decl_explicit (
+ flag_openmp_ompt ? BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_START
+ : BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING);
break;
case GF_OMP_FOR_KIND_DISTRIBUTE:
- decl = builtin_decl_explicit (BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING);
+ decl = builtin_decl_explicit (
+ flag_openmp_ompt ? BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_START
+ : BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING);
break;
default:
gcc_unreachable ();
gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
}
- /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
gsi = gsi_last_nondebug_bb (exit_bb);
+ if (flag_openmp_ompt)
+ {
+ /* Insert call to GOMP_*_static_worksharing_end at the end of exit_bb.
+ */
+ tree decl;
+ switch (gimple_omp_for_kind (fd->for_stmt))
+ {
+ case GF_OMP_FOR_KIND_FOR:
+ decl
+ = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_END);
+ break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ decl = builtin_decl_explicit (
+ BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_END);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gcall *g = gimple_build_call (decl, 0);
+ gsi_insert_after (&gsi, g, GSI_SAME_STMT);
+ }
+
+ /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
{
t = gimple_omp_return_lhs (gsi_stmt (gsi));
}
gsi_remove (&gsi, true);
+ if (flag_openmp_ompt_detailed)
+ {
+ /* Insert call to GOMP_*_static_worksharing_dispatch at the end of
+ seq_start_bb. */
+ gsi = gsi_last_nondebug_bb (seq_start_bb);
+ tree decl;
+ switch (gimple_omp_for_kind (fd->for_stmt))
+ {
+ case GF_OMP_FOR_KIND_FOR:
+ decl = builtin_decl_explicit (
+ BUILT_IN_GOMP_LOOP_STATIC_WORKSHARING_DISPATCH);
+ break;
+ case GF_OMP_FOR_KIND_DISTRIBUTE:
+ decl = builtin_decl_explicit (
+ BUILT_IN_GOMP_DISTRIBUTE_STATIC_WORKSHARING_DISPATCH);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ gcall *g = gimple_build_call (decl, 0);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+
/* Connect the new blocks. */
find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
gimple *call, *cond;
tree lhs, decl;
- decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
+ decl = builtin_decl_explicit (flag_openmp_ompt
+ ? BUILT_IN_GOMP_SINGLE_START_WITH_END
+ : BUILT_IN_GOMP_SINGLE_START);
lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
call = gimple_build_call (decl, 0);
gimple_call_set_lhs (call, lhs);
gimple *g = gimple_build_omp_return (nowait);
gimple_seq_add_stmt (&bind_body_tail, g);
maybe_add_implicit_barrier_cancel (ctx, g, &bind_body_tail);
+
+ if (flag_openmp_ompt && !ctx->record_type)
+ {
+ /* Insert call to GOMP_single_end. */
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_END);
+ gimple *stmt = gimple_build_call (decl, 0);
+ gimple_seq_add_stmt (&bind_body_tail, stmt);
+ }
+
if (ctx->record_type)
{
gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
gimple_bind_add_seq (bind, gimple_omp_body (stmt));
gimple_omp_set_body (stmt, NULL);
+ if (flag_openmp_ompt)
+ {
+ /* Insert call to GOMP_masked_end at the end of the body. */
+ tree decl = builtin_decl_explicit (BUILT_IN_GOMP_MASKED_END);
+ gcall *g = gimple_build_call (decl, 0);
+ gimple_bind_add_stmt (bind, g);
+ }
+
gimple_bind_add_stmt (bind, gimple_build_label (lab));
gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
" %<-fstrict-flex-arrays%> is not present");
}
+ if ((opts->x_flag_openmp_ompt || opts->x_flag_openmp_ompt_detailed)
+ && !opts->x_flag_openmp)
+ error_at (
+ loc,
+ "%<-fopenmp-ompt%> and %<-fopenmp-ompt-detailed%> require %<-fopenmp%>");
+
diagnose_options (opts, opts_set, loc);
}
+++ /dev/null
-/* { dg-do compile } */
-/* { dg-additional-options "-fdump-tree-ompexp" } */
-
-/* Check that the static loop and distribute expanders fetch the thread/team
- id and count through a single GOMP_loop_static_worksharing /
- GOMP_distribute_static_worksharing call rather than separate
- omp_get_thread_num/omp_get_num_threads or omp_get_team_num/omp_get_num_teams
- calls. */
-
-void bar (int);
-
-/* Static schedule without a chunk size goes through
- expand_omp_for_static_nochunk. */
-
-void
-f1 (int n)
-{
- int i;
- #pragma omp for schedule(static)
- for (i = 0; i < n; ++i)
- bar (i);
-}
-
-/* Static schedule with a chunk size goes through
- expand_omp_for_static_chunk. */
-
-void
-f2 (int n)
-{
- int i;
- #pragma omp for schedule(static, 4)
- for (i = 0; i < n; ++i)
- bar (i);
-}
-
-/* Distribute without a chunk size goes through
- expand_omp_for_static_nochunk. */
-
-void
-f3 (int n)
-{
- int i;
-#pragma omp teams
-#pragma omp distribute
- for (i = 0; i < n; ++i)
- bar (i);
-}
-
-/* Distribute with a chunk size goes through
- expand_omp_for_static_chunk. */
-
-void
-f4 (int n)
-{
- int i;
-#pragma omp teams
-#pragma omp distribute dist_schedule(static, 4)
- for (i = 0; i < n; ++i)
- bar (i);
-}
-
-/* { dg-final { scan-tree-dump "GOMP_loop_static_worksharing" "ompexp" } } */
-/* { dg-final { scan-tree-dump "GOMP_distribute_static_worksharing" "ompexp" } } */
-/* { dg-final { scan-tree-dump-not "omp_get_num_threads" "ompexp" } } */
-/* { dg-final { scan-tree-dump-not "omp_get_thread_num" "ompexp" } } */
-/* { dg-final { scan-tree-dump-not "omp_get_num_teams" "ompexp" } } */
-/* { dg-final { scan-tree-dump-not "omp_get_team_num" "ompexp" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-ompexp" } */
+
+/* Check that the static loop and distribute expanders fetch the thread/team
+ id and count through a single GOMP_loop_static_worksharing /
+ GOMP_distribute_static_worksharing call rather than separate
+ omp_get_thread_num/omp_get_num_threads or omp_get_team_num/omp_get_num_teams
+ calls. */
+
+#include "for-static.h"
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_static_worksharing \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_distribute_static_worksharing \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "omp_get_num_threads" "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "omp_get_thread_num" "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "omp_get_num_teams" "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "omp_get_team_num" "ompexp" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp-ompt -fdump-tree-ompexp" } */
+
+/* Check that, with -fopenmp-ompt, the _start and _end variants are called. */
+
+#include "for-static.h"
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_static_worksharing_start \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_static_worksharing_end \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_distribute_static_worksharing_start \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_distribute_static_worksharing_end \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_loop_static_worksharing \\(" "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_loop_static_worksharing_dispatch" "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_distribute_static_worksharing \\(" "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_distribute_static_worksharing_dispatch" "ompexp" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp-ompt-detailed -fdump-tree-ompexp" } */
+
+/* Check that, with -fopenmp-ompt-detailed, _dispatch builtins are called along
+ with the _start and _end variants. */
+
+#include "for-static.h"
+
+/* { dg-final { scan-tree-dump-times "GOMP_loop_static_worksharing_start \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_static_worksharing_dispatch \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_loop_static_worksharing_end \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_distribute_static_worksharing_start \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_distribute_static_worksharing_dispatch \\(" 2 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_distribute_static_worksharing_end \\(" 2 "ompexp" } } */
--- /dev/null
+void bar (int);
+
+/* Static schedule without a chunk size goes through
+ expand_omp_for_static_nochunk. */
+
+void
+f1 (int n)
+{
+ int i;
+ #pragma omp for schedule(static)
+ for (i = 0; i < n; ++i)
+ bar (i);
+}
+
+/* Static schedule with a chunk size goes through
+ expand_omp_for_static_chunk. */
+
+void
+f2 (int n)
+{
+ int i;
+ #pragma omp for schedule(static, 4)
+ for (i = 0; i < n; ++i)
+ bar (i);
+}
+
+/* Distribute without a chunk size goes through
+ expand_omp_for_static_nochunk. */
+
+void
+f3 (int n)
+{
+ int i;
+#pragma omp teams
+#pragma omp distribute
+ for (i = 0; i < n; ++i)
+ bar (i);
+}
+
+/* Distribute with a chunk size goes through
+ expand_omp_for_static_chunk. */
+
+void
+f4 (int n)
+{
+ int i;
+#pragma omp teams
+#pragma omp distribute dist_schedule(static, 4)
+ for (i = 0; i < n; ++i)
+ bar (i);
+}
}
/* { dg-final { scan-tree-dump "GOMP_has_masked_thread_num" "omplower" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_masked_end" "omplower" } } */
/* { dg-final { scan-tree-dump-not "omp_get_thread_num" "omplower" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp-ompt -fdump-tree-omplower" } */
+
+void bar (void);
+
+void
+foo (void)
+{
+ #pragma omp masked
+ bar ();
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_has_masked_thread_num" 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_masked_end" 1 "omplower" } } */
+/* { dg-final { scan-tree-dump-not "omp_get_thread_num" "omplower" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-ompt" } */
+
+/* { dg-error ".-fopenmp-ompt. and .-fopenmp-ompt-detailed. require .-fopenmp." "" { target *-*-* } 0 } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fopenmp-ompt-detailed" } */
+
+/* { dg-error ".-fopenmp-ompt. and .-fopenmp-ompt-detailed. require .-fopenmp." "" { target *-*-* } 0 } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp-ompt -fdump-tree-ompexp" } */
+
+void
+foo (void)
+{
+ #pragma omp single
+ ;
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_single_start_with_end" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_single_end" 1 "ompexp" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_single_start \\(" "ompexp" } } */
return nteams + tid * 1I;
}
+/* OMPT variant enabled by -fopenmp-ompt. */
+
+_Complex int
+GOMP_distribute_static_worksharing_start (void)
+{
+ int __lds *gomp_team_num = (int __lds *) GOMP_TEAM_NUM;
+ unsigned tid = *gomp_team_num;
+ unsigned nteams = gomp_num_teams_var + 1;
+ return nteams + tid * 1I;
+}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt-detailed. */
+
+void
+GOMP_distribute_static_worksharing_dispatch (void)
+{}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt. */
+
+void
+GOMP_distribute_static_worksharing_end (void)
+{}
+
int
omp_get_num_teams (void)
{
return nteams + tid * 1I;
}
+/* OMPT variant enabled by -fopenmp-ompt. */
+
+_Complex int
+GOMP_distribute_static_worksharing_start (void)
+{
+ unsigned tid = __gomp_team_num;
+ unsigned nteams = gomp_num_teams_var + 1;
+ return nteams + tid * 1I;
+}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt-detailed. */
+
+void
+GOMP_distribute_static_worksharing_dispatch (void)
+{}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt. */
+
+void
+GOMP_distribute_static_worksharing_end (void)
+{}
int
omp_get_num_teams (void)
{
GOMP_6.0.2 {
global:
GOMP_has_masked_thread_num;
+ GOMP_masked_end;
GOMP_loop_static_worksharing;
+ GOMP_loop_static_worksharing_start;
+ GOMP_loop_static_worksharing_dispatch;
+ GOMP_loop_static_worksharing_end;
GOMP_distribute_static_worksharing;
+ GOMP_distribute_static_worksharing_start;
+ GOMP_distribute_static_worksharing_dispatch;
+ GOMP_distribute_static_worksharing_end;
GOMP_barrier_ext;
GOMP_barrier_cancel_ext;
GOMP_reduction_start;
GOMP_reduction_end;
+ GOMP_single_start_with_end;
+ GOMP_single_end;
} GOMP_6.0.1;
OACC_2.0 {
extern void GOMP_loop_end_nowait (void);
extern bool GOMP_loop_end_cancel (void);
+extern __complex__ int GOMP_loop_static_worksharing (void);
+extern __complex__ int GOMP_loop_static_worksharing_start (void);
+extern void GOMP_loop_static_worksharing_dispatch (void);
+extern void GOMP_loop_static_worksharing_end (void);
+
/* loop_ull.c */
extern bool GOMP_loop_ull_static_start (bool, unsigned long long,
extern bool GOMP_cancel (int, bool);
extern bool GOMP_cancellation_point (int);
extern bool GOMP_has_masked_thread_num (int);
-extern __complex__ int GOMP_loop_static_worksharing (void);
+extern void GOMP_masked_end (void);
/* task.c */
/* single.c */
extern bool GOMP_single_start (void);
+extern bool GOMP_single_start_with_end (void);
+extern void GOMP_single_end (void);
extern void *GOMP_single_copy_start (void);
extern void GOMP_single_copy_end (void *);
extern void GOMP_teams_reg (void (*) (void *), void *, unsigned, unsigned,
unsigned);
extern __complex__ int GOMP_distribute_static_worksharing (void);
+extern __complex__ int GOMP_distribute_static_worksharing_start (void);
+extern void GOMP_distribute_static_worksharing_dispatch (void);
+extern void GOMP_distribute_static_worksharing_end (void);
/* allocator.c */
return gomp_loop_ordered_guided_next (istart, iend);
}
#endif
+
+/* For a worksharing-loop construct with static schedule, return the thread ID
+ and number of threads packed into a single complex value. */
+
+_Complex int
+GOMP_loop_static_worksharing (void)
+{
+ struct gomp_team *team = gomp_thread ()->ts.team;
+ unsigned tid = gomp_thread ()->ts.team_id;
+ unsigned nthreads = team ? team->nthreads : 1;
+ return nthreads + tid * 1I;
+}
+
+/* OMPT variant enabled by -fopenmp-ompt. */
+
+_Complex int
+GOMP_loop_static_worksharing_start (void)
+{
+ struct gomp_team *team = gomp_thread ()->ts.team;
+ unsigned tid = gomp_thread ()->ts.team_id;
+ unsigned nthreads = team ? team->nthreads : 1;
+ return nthreads + tid * 1I;
+}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt-detailed. */
+
+void
+GOMP_loop_static_worksharing_dispatch (void)
+{}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt. */
+
+void
+GOMP_loop_static_worksharing_end (void)
+{}
return true;
}
-/* For a worksharing-loop construct with static schedule, return the thread ID
- and number of threads packed into a single complex value. */
-
-_Complex int
-GOMP_loop_static_worksharing (void)
-{
- struct gomp_team *team = gomp_thread ()->ts.team;
- unsigned tid = gomp_thread ()->ts.team_id;
- unsigned nthreads = team ? team->nthreads : 1;
- return nthreads + tid * 1I;
-}
-
/* Return true if the current thread number equals TID.
Used to implement the masked construct's filter clause. */
{
return tid == gomp_thread ()->ts.team_id;
}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt. */
+
+void
+GOMP_masked_end (void)
+{}
\f
/* The public OpenMP API for thread and team related inquiries. */
#endif
}
+/* OMPT variant enabled by -fopenmp-ompt. */
+
+bool
+GOMP_single_start_with_end (void)
+{
+#ifdef HAVE_SYNC_BUILTINS
+ struct gomp_thread *thr = gomp_thread ();
+ struct gomp_team *team = thr->ts.team;
+ unsigned long single_count;
+
+ if (__builtin_expect (team == NULL, 0))
+ return true;
+
+ single_count = thr->ts.single_count++;
+ return __sync_bool_compare_and_swap (&team->single_count, single_count,
+ single_count + 1L);
+#else
+ bool ret = gomp_work_share_start (0);
+ if (ret)
+ gomp_work_share_init_done ();
+ gomp_work_share_end_nowait ();
+ return ret;
+#endif
+}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt. */
+
+void
+GOMP_single_end (void)
+{}
+
/* This routine is called when first encountering a SINGLE construct that
does have a COPYPRIVATE clause. Returns NULL if this is the thread
that should execute the clause; otherwise the return value is pointer
void *ret;
first = gomp_work_share_start (0);
-
+
if (first)
{
gomp_work_share_init_done ();
return nteams + tid * 1I;
}
+/* OMPT variant enabled by -fopenmp-ompt. */
+
+_Complex int
+GOMP_distribute_static_worksharing_start (void)
+{
+ struct gomp_thread *thr = gomp_thread ();
+ unsigned tid = thr->team_num;
+ unsigned nteams = thr->num_teams + 1;
+ return nteams + tid * 1I;
+}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt-detailed. */
+
+void
+GOMP_distribute_static_worksharing_dispatch (void)
+{}
+
+/* Stub for OMPT callback enabled by -fopenmp-ompt. */
+
+void
+GOMP_distribute_static_worksharing_end (void)
+{}
+
int
omp_get_num_teams (void)
{
--- /dev/null
+/* { dg-do link { target offload_target_any } } */
+/* { dg-additional-options "-O0 -foffload=-fdump-tree-optimized" } */
+
+/* Check that the static distribute expanders fetch the team id and count
+ through a single GOMP_distribute_static_worksharing call rather than separate
+ omp_get_team_num and omp_get_num_teams calls, and that this function exists
+ on the target side. */
+
+#include "for-static.h"
+
+/* { dg-final { scan-offload-tree-dump-times "GOMP_distribute_static_worksharing \\(" 2 "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-not "omp_get_num_teams" "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-not "omp_get_team_num" "optimized" } } */
--- /dev/null
+/* { dg-do link { target offload_target_any } } */
+/* { dg-additional-options "-O0 -foffload=-fdump-tree-optimized -fopenmp-ompt" } */
+
+/* Check that, with -fopenmp-ompt, the _start and _end variants are called. */
+
+#include "for-static.h"
+
+/* { dg-final { scan-offload-tree-dump-times "GOMP_distribute_static_worksharing_start \\(" 2 "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-times "GOMP_distribute_static_worksharing_end \\(" 2 "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-not "GOMP_distribute_static_worksharing \\(" "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-not "GOMP_distribute_static_worksharing_dispatch" "optimized" } } */
--- /dev/null
+/* { dg-do link { target offload_target_any } } */
+/* { dg-additional-options "-O0 -foffload=-fdump-tree-optimized -fopenmp-ompt-detailed" } */
+
+/* Check that, with -fopenmp-ompt-detailed, _dispatch builtins are called along
+ with the _start and _end variants. */
+
+#include "for-static.h"
+
+/* { dg-final { scan-offload-tree-dump-times "GOMP_distribute_static_worksharing_start \\(" 2 "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-times "GOMP_distribute_static_worksharing_dispatch \\(" 2 "optimized" } } */
+/* { dg-final { scan-offload-tree-dump-times "GOMP_distribute_static_worksharing_end \\(" 2 "optimized" } } */
--- /dev/null
+void bar (int a)
+{}
+
+/* Distribute without a chunk size goes through
+ expand_omp_for_static_nochunk. */
+
+void
+f3 (int n)
+{
+ int i;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute
+ for (i = 0; i < n; ++i)
+ bar (i);
+}
+
+/* Distribute with a chunk size goes through
+ expand_omp_for_static_chunk. */
+
+void
+f4 (int n)
+{
+ int i;
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute dist_schedule(static, 4)
+ for (i = 0; i < n; ++i)
+ bar (i);
+}
+
+int main (void)
+{
+ f3(0);
+ f4(1);
+ return 0;
+}