Skip to content

Commit 0ff9625

Browse files
committed
[flang][OpenMP] Added atomic update assignment statement related semantic checks
This patch adds the following semantic checks: - None of expr, and expr_list (as applicable) may access the same storage location as x - Atomic update statement should be of the form x = x operator expr or x = expr operator x or x = intrinsic_procedure(x, expr_list) or x = intrinsic_procedure(expr_list, x) - expr_list is a comma-separated, non-empty list of scalar expressions. If intrinsic_procedure_name refers to IAND, IOR, or IEOR, exactly one expression must appear in expr_list Reviewed By: TIFitis Differential Revision: https://reviews.llvm.org/D128162
1 parent 3c34245 commit 0ff9625

File tree

9 files changed

+260
-75
lines changed

9 files changed

+260
-75
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,7 @@ bool OmpStructureChecker::IsOperatorValid(const T &node, const D &variable) {
17341734
}
17351735
return common::HasMember<T, AllowedBinaryOperators>;
17361736
}
1737-
return true;
1737+
return false;
17381738
}
17391739

17401740
void OmpStructureChecker::CheckAtomicCaptureStmt(
@@ -1780,9 +1780,12 @@ void OmpStructureChecker::CheckAtomicUpdateStmt(
17801780
const parser::AssignmentStmt &assignment) {
17811781
const auto &expr{std::get<parser::Expr>(assignment.t)};
17821782
const auto &var{std::get<parser::Variable>(assignment.t)};
1783+
bool isIntrinsicProcedure{false};
1784+
bool isValidOperator{false};
17831785
common::visit(
17841786
common::visitors{
17851787
[&](const common::Indirection<parser::FunctionReference> &x) {
1788+
isIntrinsicProcedure = true;
17861789
const auto &procedureDesignator{
17871790
std::get<parser::ProcedureDesignator>(x.value().v.t)};
17881791
const parser::Name *name{
@@ -1794,46 +1797,61 @@ void OmpStructureChecker::CheckAtomicUpdateStmt(
17941797
context_.Say(expr.source,
17951798
"Invalid intrinsic procedure name in "
17961799
"OpenMP ATOMIC (UPDATE) statement"_err_en_US);
1797-
} else if (name) {
1798-
bool foundMatch{false};
1799-
if (auto varDesignatorIndirection =
1800-
std::get_if<Fortran::common::Indirection<
1801-
Fortran::parser::Designator>>(&var.u)) {
1802-
const auto &varDesignator = varDesignatorIndirection->value();
1803-
if (const auto *dataRef = std::get_if<Fortran::parser::DataRef>(
1804-
&varDesignator.u)) {
1805-
if (const auto *name =
1806-
std::get_if<Fortran::parser::Name>(&dataRef->u)) {
1807-
const auto &varSymbol = *name->symbol;
1808-
if (const auto *e{GetExpr(context_, expr)}) {
1809-
for (const Symbol &symbol :
1810-
evaluate::CollectSymbols(*e)) {
1811-
if (symbol == varSymbol) {
1812-
foundMatch = true;
1813-
break;
1814-
}
1815-
}
1816-
}
1817-
}
1818-
}
1819-
}
1820-
if (!foundMatch) {
1821-
context_.Say(expr.source,
1822-
"Atomic update variable '%s' not found in the "
1823-
"argument list of intrinsic procedure"_err_en_US,
1824-
var.GetSource().ToString());
1825-
}
18261800
}
18271801
},
18281802
[&](const auto &x) {
18291803
if (!IsOperatorValid(x, var)) {
18301804
context_.Say(expr.source,
1831-
"Invalid operator in OpenMP ATOMIC (UPDATE) "
1805+
"Invalid or missing operator in atomic update "
18321806
"statement"_err_en_US);
1833-
}
1807+
} else
1808+
isValidOperator = true;
18341809
},
18351810
},
18361811
expr.u);
1812+
if (const auto *e{GetExpr(context_, expr)}) {
1813+
const auto *v{GetExpr(context_, var)};
1814+
if (e->Rank() != 0)
1815+
context_.Say(expr.source,
1816+
"Expected scalar expression "
1817+
"on the RHS of atomic update assignment "
1818+
"statement"_err_en_US);
1819+
if (v->Rank() != 0)
1820+
context_.Say(var.GetSource(),
1821+
"Expected scalar variable "
1822+
"on the LHS of atomic update assignment "
1823+
"statement"_err_en_US);
1824+
const Symbol &varSymbol = evaluate::GetSymbolVector(*v).front();
1825+
int numOfSymbolMatches{0};
1826+
SymbolVector exprSymbols = evaluate::GetSymbolVector(*e);
1827+
for (const Symbol &symbol : exprSymbols) {
1828+
if (varSymbol == symbol)
1829+
numOfSymbolMatches++;
1830+
}
1831+
if (isIntrinsicProcedure) {
1832+
std::string varName = var.GetSource().ToString();
1833+
if (numOfSymbolMatches != 1)
1834+
context_.Say(expr.source,
1835+
"Intrinsic procedure"
1836+
" arguments in atomic update statement"
1837+
" must have exactly one occurence of '%s'"_err_en_US,
1838+
varName);
1839+
else if (varSymbol != exprSymbols.front() &&
1840+
varSymbol != exprSymbols.back())
1841+
context_.Say(expr.source,
1842+
"Atomic update statement "
1843+
"should be of the form `%s = intrinsic_procedure(%s, expr_list)` "
1844+
"OR `%s = intrinsic_procedure(expr_list, %s)`"_err_en_US,
1845+
varName, varName, varName, varName);
1846+
} else if (isValidOperator) {
1847+
if (numOfSymbolMatches != 1)
1848+
context_.Say(expr.source,
1849+
"Exactly one occurence of '%s' "
1850+
"expected on the RHS of atomic update assignment statement"_err_en_US,
1851+
var.GetSource().ToString());
1852+
}
1853+
}
1854+
18371855
ErrIfAllocatableVariable(var);
18381856
}
18391857

flang/test/Lower/OpenMP/FIR/atomic-update.f90

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ program OmpAtomicUpdate
6969
!CHECK: ^bb0(%[[ARG:.*]]: i32):
7070
!CHECK: %[[LOADED_X:.*]] = fir.load %[[X]] : !fir.ref<i32>
7171
!CHECK: %[[LOADED_Z:.*]] = fir.load %[[Z]] : !fir.ref<i32>
72-
!CHECK: %{{.*}} = arith.cmpi sgt, %[[LOADED_X]], %[[ARG]] : i32
73-
!CHECK: %{{.*}} = arith.select %{{.*}}, %[[LOADED_X]], %[[ARG]] : i32
72+
!CHECK: %{{.*}} = arith.cmpi sgt, %[[ARG]], %[[LOADED_X]] : i32
73+
!CHECK: %{{.*}} = arith.select %{{.*}}, %[[ARG]], %[[LOADED_X]] : i32
7474
!CHECK: %{{.*}} = arith.cmpi sgt, %{{.*}}, %[[LOADED_Z]] : i32
7575
!CHECK: %[[RESULT:.*]] = arith.select %{{.*}}, %{{.*}}, %[[LOADED_Z]] : i32
7676
!CHECK: omp.yield(%[[RESULT]] : i32)
@@ -84,7 +84,7 @@ program OmpAtomicUpdate
8484
!$omp atomic relaxed update hint(omp_sync_hint_uncontended)
8585
x = x - 1
8686
!$omp atomic update relaxed
87-
y = max(x, y, z)
87+
y = max(y, x, z)
8888
!$omp atomic relaxed hint(omp_sync_hint_contended)
8989
z = z + x
9090

flang/test/Semantics/OpenMP/atomic-hint-clause.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ program sample
1919
y = y + 10
2020

2121
!$omp atomic update hint(5)
22-
y = x
22+
y = x + y
2323

2424
!ERROR: Hint clause value is not a valid OpenMP synchronization value
2525
!$omp atomic hint(7) capture

flang/test/Semantics/OpenMP/atomic01.f90

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,40 +55,49 @@
5555
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
5656
!ERROR: At most one SEQ_CST clause can appear on the UPDATE directive
5757
!$omp atomic seq_cst seq_cst update
58+
!ERROR: Invalid or missing operator in atomic update statement
5859
i = j
5960
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
6061
!ERROR: At most one SEQ_CST clause can appear on the UPDATE directive
6162
!$omp atomic update seq_cst seq_cst
63+
!ERROR: Invalid or missing operator in atomic update statement
6264
i = j
6365
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
6466
!ERROR: At most one SEQ_CST clause can appear on the UPDATE directive
6567
!$omp atomic seq_cst update seq_cst
68+
!ERROR: Invalid or missing operator in atomic update statement
6669
i = j
6770

6871
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
6972
!ERROR: At most one RELEASE clause can appear on the UPDATE directive
7073
!$omp atomic release release update
74+
!ERROR: Invalid or missing operator in atomic update statement
7175
i = j
7276
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
7377
!ERROR: At most one RELEASE clause can appear on the UPDATE directive
7478
!$omp atomic update release release
79+
!ERROR: Invalid or missing operator in atomic update statement
7580
i = j
7681
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
7782
!ERROR: At most one RELEASE clause can appear on the UPDATE directive
7883
!$omp atomic release update release
84+
!ERROR: Invalid or missing operator in atomic update statement
7985
i = j
8086

8187
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
8288
!ERROR: At most one RELAXED clause can appear on the UPDATE directive
8389
!$omp atomic relaxed relaxed update
90+
!ERROR: Invalid or missing operator in atomic update statement
8491
i = j
8592
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
8693
!ERROR: At most one RELAXED clause can appear on the UPDATE directive
8794
!$omp atomic update relaxed relaxed
95+
!ERROR: Invalid or missing operator in atomic update statement
8896
i = j
8997
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
9098
!ERROR: At most one RELAXED clause can appear on the UPDATE directive
9199
!$omp atomic relaxed update relaxed
100+
!ERROR: Invalid or missing operator in atomic update statement
92101
i = j
93102

94103
!CAPTURE
@@ -240,14 +249,17 @@
240249
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
241250
!ERROR: At most one RELAXED clause can appear on the ATOMIC directive
242251
!$omp atomic relaxed relaxed
252+
!ERROR: Invalid or missing operator in atomic update statement
243253
i = j
244254
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
245255
!ERROR: At most one SEQ_CST clause can appear on the ATOMIC directive
246256
!$omp atomic seq_cst seq_cst
257+
!ERROR: Invalid or missing operator in atomic update statement
247258
i = j
248259
!ERROR: More than one memory order clause not allowed on OpenMP Atomic construct
249260
!ERROR: At most one RELEASE clause can appear on the ATOMIC directive
250261
!$omp atomic release release
262+
!ERROR: Invalid or missing operator in atomic update statement
251263
i = j
252264

253265
! 2.17.7.3
@@ -282,21 +294,27 @@
282294
i = j
283295
!ERROR: At most one HINT clause can appear on the UPDATE directive
284296
!$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative) update
297+
!ERROR: Invalid or missing operator in atomic update statement
285298
i = j
286299
!ERROR: At most one HINT clause can appear on the UPDATE directive
287300
!$omp atomic hint(omp_sync_hint_nonspeculative) update hint(omp_sync_hint_nonspeculative)
301+
!ERROR: Invalid or missing operator in atomic update statement
288302
i = j
289303
!ERROR: At most one HINT clause can appear on the UPDATE directive
290304
!$omp atomic update hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended)
305+
!ERROR: Invalid or missing operator in atomic update statement
291306
i = j
292307
!ERROR: At most one HINT clause can appear on the ATOMIC directive
293308
!$omp atomic hint(omp_sync_hint_contended) hint(omp_sync_hint_speculative)
309+
!ERROR: Invalid or missing operator in atomic update statement
294310
i = j
295311
!ERROR: At most one HINT clause can appear on the ATOMIC directive
296312
!$omp atomic hint(omp_sync_hint_none) hint(omp_sync_hint_nonspeculative)
313+
!ERROR: Invalid or missing operator in atomic update statement
297314
i = j
298315
!ERROR: At most one HINT clause can appear on the ATOMIC directive
299316
!$omp atomic hint(omp_sync_hint_none) hint (omp_sync_hint_uncontended)
317+
!ERROR: Invalid or missing operator in atomic update statement
300318
i = j
301319

302320
!ERROR: At most one HINT clause can appear on the CAPTURE directive
@@ -354,25 +372,31 @@
354372

355373
!ERROR: Clause ACQ_REL is not allowed if clause UPDATE appears on the ATOMIC directive
356374
!$omp atomic acq_rel update
375+
!ERROR: Invalid or missing operator in atomic update statement
357376
i = j
358377
!ERROR: Clause ACQ_REL is not allowed if clause UPDATE appears on the ATOMIC directive
359378
!$omp atomic update acq_rel
379+
!ERROR: Invalid or missing operator in atomic update statement
360380
i = j
361381

362382
!ERROR: Clause ACQUIRE is not allowed if clause UPDATE appears on the ATOMIC directive
363383
!$omp atomic acquire update
384+
!ERROR: Invalid or missing operator in atomic update statement
364385
i = j
365386

366387
!ERROR: Clause ACQUIRE is not allowed if clause UPDATE appears on the ATOMIC directive
367388
!$omp atomic update acquire
389+
!ERROR: Invalid or missing operator in atomic update statement
368390
i = j
369391

370392
!ERROR: Clause ACQ_REL is not allowed on the ATOMIC directive
371393
!$omp atomic acq_rel
394+
!ERROR: Invalid or missing operator in atomic update statement
372395
i = j
373396

374397
!ERROR: Clause ACQUIRE is not allowed on the ATOMIC directive
375398
!$omp atomic acquire
399+
!ERROR: Invalid or missing operator in atomic update statement
376400
i = j
377401
end program
378402

flang/test/Semantics/OpenMP/atomic02.f90

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,34 @@ program OmpAtomic
2626
!$omp atomic
2727
a = a/(b + 1)
2828
!$omp atomic
29-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
29+
!ERROR: Invalid or missing operator in atomic update statement
3030
a = a**4
3131
!$omp atomic
32-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
32+
!ERROR: Invalid or missing operator in atomic update statement
3333
c = c//d
3434
!$omp atomic
3535
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
36-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
36+
!ERROR: Invalid or missing operator in atomic update statement
3737
l = a .LT. b
3838
!$omp atomic
3939
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
40-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
40+
!ERROR: Invalid or missing operator in atomic update statement
4141
l = a .LE. b
4242
!$omp atomic
4343
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
44-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
44+
!ERROR: Invalid or missing operator in atomic update statement
4545
l = a .EQ. b
4646
!$omp atomic
4747
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
48-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
48+
!ERROR: Invalid or missing operator in atomic update statement
4949
l = a .NE. b
5050
!$omp atomic
5151
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
52-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
52+
!ERROR: Invalid or missing operator in atomic update statement
5353
l = a .GE. b
5454
!$omp atomic
5555
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
56-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
56+
!ERROR: Invalid or missing operator in atomic update statement
5757
l = a .GT. b
5858
!$omp atomic
5959
m = m .AND. n
@@ -72,30 +72,30 @@ program OmpAtomic
7272
!$omp atomic update
7373
a = a/(b + 1)
7474
!$omp atomic update
75-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
75+
!ERROR: Invalid or missing operator in atomic update statement
7676
a = a**4
7777
!$omp atomic update
78-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
78+
!ERROR: Invalid or missing operator in atomic update statement
7979
c = c//d
8080
!$omp atomic update
8181
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
82-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
82+
!ERROR: Invalid or missing operator in atomic update statement
8383
l = a .LT. b
8484
!$omp atomic update
8585
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
86-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
86+
!ERROR: Invalid or missing operator in atomic update statement
8787
l = a .LE. b
8888
!$omp atomic update
8989
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
90-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
90+
!ERROR: Invalid or missing operator in atomic update statement
9191
l = a .EQ. b
9292
!$omp atomic update
9393
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
94-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
94+
!ERROR: Invalid or missing operator in atomic update statement
9595
l = a .GE. b
9696
!$omp atomic update
9797
!ERROR: Atomic update statement should be of form `l = l operator expr` OR `l = expr operator l`
98-
!ERROR: Invalid operator in OpenMP ATOMIC (UPDATE) statement
98+
!ERROR: Invalid or missing operator in atomic update statement
9999
l = a .GT. b
100100
!$omp atomic update
101101
m = m .AND. n

0 commit comments

Comments
 (0)