aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/openmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/openmp.c')
-rw-r--r--gcc/fortran/openmp.c251
1 files changed, 187 insertions, 64 deletions
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index b143ba7..608ff5a 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -802,6 +802,9 @@ enum omp_mask1
OMP_CLAUSE_USE_DEVICE_PTR,
OMP_CLAUSE_USE_DEVICE_ADDR, /* OpenMP 5.0. */
OMP_CLAUSE_DEVICE_TYPE, /* OpenMP 5.0. */
+ OMP_CLAUSE_ATOMIC, /* OpenMP 5.0. */
+ OMP_CLAUSE_CAPTURE, /* OpenMP 5.0. */
+ OMP_CLAUSE_MEMORDER, /* OpenMP 5.0. */
OMP_CLAUSE_NOWAIT,
/* This must come last. */
OMP_MASK1_LAST
@@ -1017,6 +1020,22 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
n->expr = alignment;
continue;
}
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("acq_rel") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_ACQ_REL;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("acquire") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_ACQUIRE;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_ASYNC)
&& !c->async
&& gfc_match ("async") == MATCH_YES)
@@ -1055,6 +1074,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
continue;
break;
case 'c':
+ if ((mask & OMP_CLAUSE_CAPTURE)
+ && !c->capture
+ && gfc_match ("capture") == MATCH_YES)
+ {
+ c->capture = true;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_COLLAPSE)
&& !c->collapse)
{
@@ -1681,6 +1708,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
}
break;
case 'r':
+ if ((mask & OMP_CLAUSE_ATOMIC)
+ && c->atomic_op == GFC_OMP_ATOMIC_UNSET
+ && gfc_match ("read") == MATCH_YES)
+ {
+ c->atomic_op = GFC_OMP_ATOMIC_READ;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_REDUCTION)
&& gfc_match ("reduction ( ") == MATCH_YES)
{
@@ -1801,6 +1836,22 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
else
gfc_current_locus = old_loc;
}
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("relaxed") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_RELAXED;
+ needs_space = true;
+ continue;
+ }
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("release") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_RELEASE;
+ needs_space = true;
+ continue;
+ }
break;
case 's':
if ((mask & OMP_CLAUSE_SAFELEN)
@@ -1885,6 +1936,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_MEMORDER)
+ && c->memorder == OMP_MEMORDER_UNSET
+ && gfc_match ("seq_cst") == MATCH_YES)
+ {
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_SHARED)
&& gfc_match_omp_variable_list ("shared (",
&c->lists[OMP_LIST_SHARED],
@@ -1945,6 +2004,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
c->untied = needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_ATOMIC)
+ && c->atomic_op == GFC_OMP_ATOMIC_UNSET
+ && gfc_match ("update") == MATCH_YES)
+ {
+ c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+ needs_space = true;
+ continue;
+ }
if ((mask & OMP_CLAUSE_USE_DEVICE)
&& gfc_match_omp_variable_list ("use_device (",
&c->lists[OMP_LIST_USE_DEVICE],
@@ -2026,6 +2093,14 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
needs_space = true;
continue;
}
+ if ((mask & OMP_CLAUSE_ATOMIC)
+ && c->atomic_op == GFC_OMP_ATOMIC_UNSET
+ && gfc_match ("write") == MATCH_YES)
+ {
+ c->atomic_op = GFC_OMP_ATOMIC_WRITE;
+ needs_space = true;
+ continue;
+ }
break;
}
break;
@@ -2658,6 +2733,9 @@ cleanup:
(omp_mask (OMP_CLAUSE_THREADS) | OMP_CLAUSE_SIMD)
#define OMP_DECLARE_TARGET_CLAUSES \
(omp_mask (OMP_CLAUSE_TO) | OMP_CLAUSE_LINK | OMP_CLAUSE_DEVICE_TYPE)
+#define OMP_ATOMIC_CLAUSES \
+ (omp_mask (OMP_CLAUSE_ATOMIC) | OMP_CLAUSE_CAPTURE | OMP_CLAUSE_HINT \
+ | OMP_CLAUSE_MEMORDER)
static match
@@ -2768,7 +2846,7 @@ gfc_match_omp_flush (void)
gfc_omp_namelist *list = NULL;
gfc_omp_clauses *c = NULL;
gfc_gobble_whitespace ();
- enum gfc_omp_memorder mo = OMP_MEMORDER_LAST;
+ enum gfc_omp_memorder mo = OMP_MEMORDER_UNSET;
if (gfc_match_omp_eos () == MATCH_NO && gfc_peek_ascii_char () != '(')
{
if (gfc_match ("acq_rel") == MATCH_YES)
@@ -2786,7 +2864,7 @@ gfc_match_omp_flush (void)
c->memorder = mo;
}
gfc_match_omp_variable_list (" (", &list, true);
- if (list && mo != OMP_MEMORDER_LAST)
+ if (list && mo != OMP_MEMORDER_UNSET)
{
gfc_error ("List specified together with memory order clause in FLUSH "
"directive at %C");
@@ -4014,49 +4092,28 @@ gfc_match_omp_ordered_depend (void)
}
-static match
-gfc_match_omp_oacc_atomic (bool omp_p)
+/* omp atomic [clause-list]
+ - atomic-clause: read | write | update
+ - capture
+ - memory-order-clause: seq_cst | acq_rel | release | acquire | relaxed
+ - hint(hint-expr)
+*/
+
+match
+gfc_match_omp_atomic (void)
{
- gfc_omp_atomic_op op = GFC_OMP_ATOMIC_UPDATE;
- int seq_cst = 0;
- if (gfc_match ("% seq_cst") == MATCH_YES)
- seq_cst = 1;
- locus old_loc = gfc_current_locus;
- if (seq_cst && gfc_match_char (',') == MATCH_YES)
- seq_cst = 2;
- if (seq_cst == 2
- || gfc_match_space () == MATCH_YES)
- {
- gfc_gobble_whitespace ();
- if (gfc_match ("update") == MATCH_YES)
- op = GFC_OMP_ATOMIC_UPDATE;
- else if (gfc_match ("read") == MATCH_YES)
- op = GFC_OMP_ATOMIC_READ;
- else if (gfc_match ("write") == MATCH_YES)
- op = GFC_OMP_ATOMIC_WRITE;
- else if (gfc_match ("capture") == MATCH_YES)
- op = GFC_OMP_ATOMIC_CAPTURE;
- else
- {
- if (seq_cst == 2)
- gfc_current_locus = old_loc;
- goto finish;
- }
- if (!seq_cst
- && (gfc_match (", seq_cst") == MATCH_YES
- || gfc_match ("% seq_cst") == MATCH_YES))
- seq_cst = 1;
- }
- finish:
- if (gfc_match_omp_eos () != MATCH_YES)
- {
- gfc_error ("Unexpected junk after $OMP ATOMIC statement at %C");
- return MATCH_ERROR;
- }
- new_st.op = (omp_p ? EXEC_OMP_ATOMIC : EXEC_OACC_ATOMIC);
- if (seq_cst)
- op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
- else if (omp_p)
+ gfc_omp_clauses *c;
+ locus loc = gfc_current_locus;
+
+ if (gfc_match_omp_clauses (&c, OMP_ATOMIC_CLAUSES, true, true) != MATCH_YES)
+ return MATCH_ERROR;
+ if (c->atomic_op == GFC_OMP_ATOMIC_UNSET)
+ c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+
+ if (c->capture && c->atomic_op != GFC_OMP_ATOMIC_UPDATE)
+ gfc_error ("OMP ATOMIC at %L with CAPTURE clause must be UPDATE", &loc);
+
+ if (c->memorder == OMP_MEMORDER_UNSET)
{
gfc_namespace *prog_unit = gfc_current_ns;
while (prog_unit->parent)
@@ -4065,32 +4122,95 @@ gfc_match_omp_oacc_atomic (bool omp_p)
{
case 0:
case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED:
+ c->memorder = OMP_MEMORDER_RELAXED;
break;
case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST:
- op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_SEQ_CST);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
break;
case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL:
- op = (gfc_omp_atomic_op) (op | GFC_OMP_ATOMIC_ACQ_REL);
+ if (c->atomic_op == GFC_OMP_ATOMIC_READ)
+ c->memorder = OMP_MEMORDER_ACQUIRE;
+ else if (c->atomic_op == GFC_OMP_ATOMIC_READ)
+ c->memorder = OMP_MEMORDER_RELEASE;
+ else
+ c->memorder = OMP_MEMORDER_ACQ_REL;
break;
default:
gcc_unreachable ();
}
}
- new_st.ext.omp_atomic = op;
+ else
+ switch (c->atomic_op)
+ {
+ case GFC_OMP_ATOMIC_READ:
+ if (c->memorder == OMP_MEMORDER_ACQ_REL
+ || c->memorder == OMP_MEMORDER_RELEASE)
+ {
+ gfc_error ("!$OMP ATOMIC READ at %L incompatible with "
+ "ACQ_REL or RELEASE clauses", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ break;
+ case GFC_OMP_ATOMIC_WRITE:
+ if (c->memorder == OMP_MEMORDER_ACQ_REL
+ || c->memorder == OMP_MEMORDER_ACQUIRE)
+ {
+ gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with "
+ "ACQ_REL or ACQUIRE clauses", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ break;
+ case GFC_OMP_ATOMIC_UPDATE:
+ if (c->memorder == OMP_MEMORDER_ACQ_REL
+ || c->memorder == OMP_MEMORDER_ACQUIRE)
+ {
+ gfc_error ("!$OMP ATOMIC UPDATE at %L incompatible with "
+ "ACQ_REL or ACQUIRE clauses", &loc);
+ c->memorder = OMP_MEMORDER_SEQ_CST;
+ }
+ break;
+ default:
+ break;
+ }
+ gfc_error_check ();
+ new_st.ext.omp_clauses = c;
+ new_st.op = EXEC_OMP_ATOMIC;
return MATCH_YES;
}
+
+/* acc atomic [ read | write | update | capture]
+ acc atomic update capture. */
+
match
gfc_match_oacc_atomic (void)
{
- return gfc_match_omp_oacc_atomic (false);
+ gfc_omp_clauses *c = gfc_get_omp_clauses ();
+ c->atomic_op = GFC_OMP_ATOMIC_UPDATE;
+ c->memorder = OMP_MEMORDER_RELAXED;
+ gfc_gobble_whitespace ();
+ if (gfc_match ("update capture") == MATCH_YES)
+ c->capture = true;
+ else if (gfc_match ("update") == MATCH_YES)
+ ;
+ else if (gfc_match ("read") == MATCH_YES)
+ c->atomic_op = GFC_OMP_ATOMIC_READ;
+ else if (gfc_match ("write") == MATCH_YES)
+ c->atomic_op = GFC_OMP_ATOMIC_WRITE;
+ else if (gfc_match ("capture") == MATCH_YES)
+ c->capture = true;
+ gfc_gobble_whitespace ();
+ if (gfc_match_omp_eos () != MATCH_YES)
+ {
+ gfc_error ("Unexpected junk after !$ACC ATOMIC statement at %C");
+ gfc_free_omp_clauses (c);
+ return MATCH_ERROR;
+ }
+ new_st.ext.omp_clauses = c;
+ new_st.op = EXEC_OACC_ATOMIC;
+ return MATCH_YES;
}
-match
-gfc_match_omp_atomic (void)
-{
- return gfc_match_omp_oacc_atomic (true);
-}
match
gfc_match_omp_barrier (void)
@@ -5514,11 +5634,12 @@ is_conversion (gfc_expr *expr, bool widening)
static void
resolve_omp_atomic (gfc_code *code)
{
- gfc_code *atomic_code = code;
+ gfc_code *atomic_code = code->block;
gfc_symbol *var;
gfc_expr *expr2, *expr2_tmp;
gfc_omp_atomic_op aop
- = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK);
+ = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
+ & GFC_OMP_ATOMIC_MASK);
code = code->block->next;
/* resolve_blocks asserts this is initially EXEC_ASSIGN.
@@ -5531,7 +5652,7 @@ resolve_omp_atomic (gfc_code *code)
gfc_error ("unexpected !$OMP ATOMIC expression at %L", &code->loc);
return;
}
- if (aop != GFC_OMP_ATOMIC_CAPTURE)
+ if (!atomic_code->ext.omp_clauses->capture)
{
if (code->next != NULL)
goto unexpected;
@@ -5591,7 +5712,11 @@ resolve_omp_atomic (gfc_code *code)
"must be scalar and cannot reference var at %L",
&expr2->where);
return;
- case GFC_OMP_ATOMIC_CAPTURE:
+ default:
+ break;
+ }
+ if (atomic_code->ext.omp_clauses->capture)
+ {
expr2_tmp = expr2;
if (expr2 == code->expr2)
{
@@ -5640,9 +5765,6 @@ resolve_omp_atomic (gfc_code *code)
if (expr2 == NULL)
expr2 = code->expr2;
}
- break;
- default:
- break;
}
if (gfc_expr_attr (code->expr1).allocatable)
@@ -5652,12 +5774,12 @@ resolve_omp_atomic (gfc_code *code)
return;
}
- if (aop == GFC_OMP_ATOMIC_CAPTURE
+ if (atomic_code->ext.omp_clauses->capture
&& code->next == NULL
&& code->expr2->rank == 0
&& !expr_references_sym (code->expr2, var, NULL))
- atomic_code->ext.omp_atomic
- = (gfc_omp_atomic_op) (atomic_code->ext.omp_atomic
+ atomic_code->ext.omp_clauses->atomic_op
+ = (gfc_omp_atomic_op) (atomic_code->ext.omp_clauses->atomic_op
| GFC_OMP_ATOMIC_SWAP);
else if (expr2->expr_type == EXPR_OP)
{
@@ -5867,7 +5989,7 @@ resolve_omp_atomic (gfc_code *code)
gfc_error ("!$OMP ATOMIC assignment must have an operator or "
"intrinsic on right hand side at %L", &expr2->where);
- if (aop == GFC_OMP_ATOMIC_CAPTURE && code->next)
+ if (atomic_code->ext.omp_clauses->capture && code->next)
{
code = code->next;
if (code->expr1->expr_type != EXPR_VARIABLE
@@ -6866,6 +6988,7 @@ gfc_resolve_omp_directive (gfc_code *code, gfc_namespace *ns ATTRIBUTE_UNUSED)
"FROM clause", &code->loc);
break;
case EXEC_OMP_ATOMIC:
+ resolve_omp_clauses (code, code->block->ext.omp_clauses, NULL);
resolve_omp_atomic (code);
break;
case EXEC_OMP_CRITICAL: