Skip to content

Commit a6cae4b

Browse files
kparzyszgithub-actions[bot]
authored andcommitted
Automerge: [flang][OpenMP] Handle conflicts between REQUIRES and ATOMIC restrict… (#163805)
…ions When the atomic default memory order specified on a REQUIRES directive is disallowed on a given ATOMIC operation, and it's not ACQ_REL, the order reverts to RELAXED. ACQ_REL decays to either ACQUIRE or RELEASE, depending on the operation. This fixes MLIR verification failure in Fortran/gfortran/regression/gomp/requires-9.f90
2 parents 5a84c87 + 527f7f5 commit a6cae4b

File tree

7 files changed

+149
-16
lines changed

7 files changed

+149
-16
lines changed

flang/lib/Lower/OpenMP/Atomic.cpp

Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "flang/Optimizer/Builder/FIRBuilder.h"
2121
#include "flang/Optimizer/Builder/Todo.h"
2222
#include "flang/Parser/parse-tree.h"
23+
#include "flang/Semantics/openmp-utils.h"
2324
#include "flang/Semantics/semantics.h"
2425
#include "flang/Semantics/type.h"
2526
#include "flang/Support/Fortran.h"
@@ -183,12 +184,8 @@ getMemoryOrderFromRequires(const semantics::Scope &scope) {
183184
// scope.
184185
// For safety, traverse all enclosing scopes and check if their symbol
185186
// contains REQUIRES.
186-
for (const auto *sc{&scope}; sc->kind() != semantics::Scope::Kind::Global;
187-
sc = &sc->parent()) {
188-
const semantics::Symbol *sym = sc->symbol();
189-
if (!sym)
190-
continue;
191-
187+
const semantics::Scope &unitScope = semantics::omp::GetProgramUnit(scope);
188+
if (auto *symbol = unitScope.symbol()) {
192189
const common::OmpMemoryOrderType *admo = common::visit(
193190
[](auto &&s) {
194191
using WithOmpDeclarative = semantics::WithOmpDeclarative;
@@ -198,7 +195,8 @@ getMemoryOrderFromRequires(const semantics::Scope &scope) {
198195
}
199196
return static_cast<const common::OmpMemoryOrderType *>(nullptr);
200197
},
201-
sym->details());
198+
symbol->details());
199+
202200
if (admo)
203201
return getMemoryOrderKind(*admo);
204202
}
@@ -214,19 +212,83 @@ getDefaultAtomicMemOrder(semantics::SemanticsContext &semaCtx) {
214212
return std::nullopt;
215213
}
216214

217-
static std::optional<mlir::omp::ClauseMemoryOrderKind>
215+
static std::pair<std::optional<mlir::omp::ClauseMemoryOrderKind>, bool>
218216
getAtomicMemoryOrder(semantics::SemanticsContext &semaCtx,
219217
const omp::List<omp::Clause> &clauses,
220218
const semantics::Scope &scope) {
221219
for (const omp::Clause &clause : clauses) {
222220
if (auto maybeKind = getMemoryOrderKind(clause.id))
223-
return *maybeKind;
221+
return std::make_pair(*maybeKind, /*canOverride=*/false);
224222
}
225223

226224
if (auto maybeKind = getMemoryOrderFromRequires(scope))
227-
return *maybeKind;
225+
return std::make_pair(*maybeKind, /*canOverride=*/true);
228226

229-
return getDefaultAtomicMemOrder(semaCtx);
227+
return std::make_pair(getDefaultAtomicMemOrder(semaCtx),
228+
/*canOverride=*/false);
229+
}
230+
231+
static std::optional<mlir::omp::ClauseMemoryOrderKind>
232+
makeValidForAction(std::optional<mlir::omp::ClauseMemoryOrderKind> memOrder,
233+
int action0, int action1, unsigned version) {
234+
// When the atomic default memory order specified on a REQUIRES directive is
235+
// disallowed on a given ATOMIC operation, and it's not ACQ_REL, the order
236+
// reverts to RELAXED. ACQ_REL decays to either ACQUIRE or RELEASE, depending
237+
// on the operation.
238+
239+
if (!memOrder) {
240+
return memOrder;
241+
}
242+
243+
using Analysis = parser::OpenMPAtomicConstruct::Analysis;
244+
// Figure out the main action (i.e. disregard a potential capture operation)
245+
int action = action0;
246+
if (action1 != Analysis::None)
247+
action = action0 == Analysis::Read ? action1 : action0;
248+
249+
// Avaliable orderings: acquire, acq_rel, relaxed, release, seq_cst
250+
251+
if (action == Analysis::Read) {
252+
// "acq_rel" decays to "acquire"
253+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Acq_rel)
254+
return mlir::omp::ClauseMemoryOrderKind::Acquire;
255+
} else if (action == Analysis::Write) {
256+
// "acq_rel" decays to "release"
257+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Acq_rel)
258+
return mlir::omp::ClauseMemoryOrderKind::Release;
259+
}
260+
261+
if (version > 50) {
262+
if (action == Analysis::Read) {
263+
// "release" prohibited
264+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Release)
265+
return mlir::omp::ClauseMemoryOrderKind::Relaxed;
266+
}
267+
if (action == Analysis::Write) {
268+
// "acquire" prohibited
269+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Acquire)
270+
return mlir::omp::ClauseMemoryOrderKind::Relaxed;
271+
}
272+
} else {
273+
if (action == Analysis::Read) {
274+
// "release" prohibited
275+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Release)
276+
return mlir::omp::ClauseMemoryOrderKind::Relaxed;
277+
} else {
278+
if (action & Analysis::Write) { // include "update"
279+
// "acquire" prohibited
280+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Acquire)
281+
return mlir::omp::ClauseMemoryOrderKind::Relaxed;
282+
if (action == Analysis::Update) {
283+
// "acq_rel" prohibited
284+
if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Acq_rel)
285+
return mlir::omp::ClauseMemoryOrderKind::Relaxed;
286+
}
287+
}
288+
}
289+
}
290+
291+
return memOrder;
230292
}
231293

232294
static mlir::omp::ClauseMemoryOrderKindAttr
@@ -449,16 +511,19 @@ void Fortran::lower::omp::lowerAtomic(
449511
mlir::Value atomAddr =
450512
fir::getBase(converter.genExprAddr(atom, stmtCtx, &loc));
451513
mlir::IntegerAttr hint = getAtomicHint(converter, clauses);
452-
std::optional<mlir::omp::ClauseMemoryOrderKind> memOrder =
453-
getAtomicMemoryOrder(semaCtx, clauses,
454-
semaCtx.FindScope(construct.source));
514+
auto [memOrder, canOverride] = getAtomicMemoryOrder(
515+
semaCtx, clauses, semaCtx.FindScope(construct.source));
516+
517+
unsigned version = semaCtx.langOptions().OpenMPVersion;
518+
int action0 = analysis.op0.what & analysis.Action;
519+
int action1 = analysis.op1.what & analysis.Action;
520+
if (canOverride)
521+
memOrder = makeValidForAction(memOrder, action0, action1, version);
455522

456523
if (auto *cond = get(analysis.cond)) {
457524
(void)cond;
458525
TODO(loc, "OpenMP ATOMIC COMPARE");
459526
} else {
460-
int action0 = analysis.op0.what & analysis.Action;
461-
int action1 = analysis.op1.what & analysis.Action;
462527
mlir::Operation *captureOp = nullptr;
463528
fir::FirOpBuilder::InsertPoint preAt = builder.saveInsertionPoint();
464529
fir::FirOpBuilder::InsertPoint atomicAt, postAt;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
2+
!RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
3+
4+
!CHECK: omp.atomic.read %{{[0-9]+}}#0 = %{{[0-9]+}}#0 memory_order(acquire)
5+
6+
subroutine f00(x, v)
7+
integer :: x, v
8+
!$omp requires atomic_default_mem_order(acq_rel)
9+
!$omp atomic read
10+
v = x
11+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
2+
!RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
3+
4+
!CHECK: omp.atomic.write %{{[0-9]+}}#0 = %{{[0-9]+}} memory_order(relaxed)
5+
6+
subroutine f02(x, v)
7+
integer :: x, v
8+
!$omp requires atomic_default_mem_order(acquire)
9+
!$omp atomic write
10+
x = v
11+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
2+
!RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
3+
4+
!CHECK: omp.atomic.update memory_order(relaxed)
5+
6+
subroutine f05(x, v)
7+
integer :: x, v
8+
!$omp requires atomic_default_mem_order(acq_rel)
9+
!$omp atomic update
10+
x = x + 1
11+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
!RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
2+
!RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
3+
4+
!CHECK: omp.atomic.capture memory_order(relaxed)
5+
6+
subroutine f06(x, v)
7+
integer :: x, v
8+
!$omp requires atomic_default_mem_order(acquire)
9+
!$omp atomic update capture
10+
v = x
11+
x = x + 1
12+
!$omp end atomic
13+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: bbc %openmp_flags -fopenmp-version=60 -emit-hlfir %s -o - | FileCheck %s
2+
!RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=60 %s -o - | FileCheck %s
3+
4+
!CHECK: omp.atomic.read %{{[0-9]+}}#0 = %{{[0-9]+}}#0 memory_order(relaxed)
5+
6+
subroutine f01(x, v)
7+
integer :: x, v
8+
!$omp requires atomic_default_mem_order(release)
9+
!$omp atomic read
10+
v = x
11+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: bbc %openmp_flags -fopenmp-version=60 -emit-hlfir %s -o - | FileCheck %s
2+
!RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=60 %s -o - | FileCheck %s
3+
4+
!CHECK: omp.atomic.write %{{[0-9]+}}#0 = %{{[0-9]+}} memory_order(relaxed)
5+
6+
subroutine f02(x, v)
7+
integer :: x, v
8+
!$omp requires atomic_default_mem_order(acquire)
9+
!$omp atomic write
10+
x = v
11+
end

0 commit comments

Comments
 (0)