BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_ATOMIC_END, "GOMP_atomic_end",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REDUCTION_START, "GOMP_reduction_start",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_GOMP_BUILTIN (BUILT_IN_GOMP_REDUCTION_END, "GOMP_reduction_end",
+ BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER, "GOMP_barrier_ext", BT_FN_VOID_INT,
ATTR_NOTHROW_LEAF_LIST)
DEF_GOMP_BUILTIN (BUILT_IN_GOMP_BARRIER_CANCEL, "GOMP_barrier_cancel_ext",
}
}
- stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
- 0);
+ stmt
+ = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START),
+ 0);
gimple_seq_add_stmt (stmt_seqp, stmt);
gimple_seq_add_seq (stmt_seqp, sub_seq);
*clist = NULL;
}
- stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
+ stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END),
0);
gimple_seq_add_stmt (stmt_seqp, stmt);
}
&clist, ctx);
if (clist)
{
- tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
gcall *g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&olist, g);
gimple_seq_add_seq (&olist, clist);
- fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&olist, g);
}
&bind_body, &clist, ctx);
if (clist)
{
- tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
gcall *g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&bind_body, g);
gimple_seq_add_seq (&bind_body, clist);
- fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&bind_body, g);
}
if (clist)
{
- tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_START);
gcall *g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&body, g);
gimple_seq_add_seq (&body, clist);
- fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_REDUCTION_END);
g = gimple_build_call (fndecl, 0);
gimple_seq_add_stmt (&body, g);
}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-ompexp" } */
+
+/* Check that an GIMPLE_OMP_ATOMIC statement expands to GOMP_atomic_start/end
+ when atomic operations cannot be used and a mutex is required. */
+
+void bar (__int128 a, __int128 b) {
+ #pragma omp atomic capture
+ b = a++;
+}
+
+/* { dg-final { scan-tree-dump "GOMP_atomic_start" "ompexp" } } */
+/* { dg-final { scan-tree-dump "GOMP_atomic_end" "ompexp" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-omplower" } */
+
+/* Check that, for reductions, critical sections are bracketed with
+ GOMP_reduction_start/end rather than GOMP_atomic_start/end. Two scalar
+ reductions force the critical-section path (a single scalar reduction would
+ use an atomic update instead). */
+
+void foo (int);
+
+void r_for (int n) {
+ int a = 0, b = 0, i;
+ #pragma omp parallel
+ #pragma omp for reduction(+: a, b)
+ for (i = 0; i < n; i++) { a += i; b += i; }
+}
+
+void r_sections (void) {
+ int a = 0, b = 0;
+ #pragma omp parallel
+ #pragma omp sections reduction(+: a, b)
+ { foo (a + b); }
+}
+
+void r_scope (void) {
+ int a = 0, b = 0;
+ #pragma omp parallel
+ #pragma omp scope reduction(+: a, b)
+ foo (a + b);
+}
+
+void r_teams (void) {
+ int a = 0, b = 0;
+ #pragma omp teams reduction(+: a, b)
+ foo (a + b);
+}
+
+void r_parallel (void) {
+ int a = 0, b = 0;
+ #pragma omp parallel reduction(+: a, b)
+ foo (a + b);
+}
+
+/* { dg-final { scan-tree-dump-times "GOMP_reduction_start \\(" 5 "omplower" } } */
+/* { dg-final { scan-tree-dump-times "GOMP_reduction_end \\(" 5 "omplower" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_atomic_start" "omplower" } } */
+/* { dg-final { scan-tree-dump-not "GOMP_atomic_end" "omplower" } } */
#undef DEF_SYNC_BUILTIN
case BUILT_IN_GOMP_ATOMIC_START:
case BUILT_IN_GOMP_ATOMIC_END:
+ case BUILT_IN_GOMP_REDUCTION_START:
+ case BUILT_IN_GOMP_REDUCTION_END:
case BUILT_IN_GOMP_BARRIER:
case BUILT_IN_GOMP_BARRIER_CANCEL:
case BUILT_IN_GOMP_TASKWAIT:
gomp_mutex_unlock (&atomic_lock);
}
+void
+GOMP_reduction_start (void)
+{
+ gomp_mutex_lock (&atomic_lock);
+}
+
+void
+GOMP_reduction_end (void)
+{
+ gomp_mutex_unlock (&atomic_lock);
+}
+
#if !GOMP_MUTEX_INIT_0
static void __attribute__((constructor))
initialize_atomic (void)
GOMP_distribute_static_worksharing;
GOMP_barrier_ext;
GOMP_barrier_cancel_ext;
+ GOMP_reduction_start;
+ GOMP_reduction_end;
} GOMP_6.0.1;
OACC_2.0 {
extern void GOMP_critical_end (void);
extern void GOMP_critical_name_start (void **);
extern void GOMP_critical_name_end (void **);
+extern void GOMP_reduction_start (void);
+extern void GOMP_reduction_end (void);
/* loop.c */