[flang-commits] [flang] [flang][OpenMP] Handle REQUIRES ADMO in lowering (PR #144362)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Wed Jun 18 08:53:13 PDT 2025
================
@@ -2715,58 +2715,129 @@ static mlir::IntegerAttr getAtomicHint(lower::AbstractConverter &converter,
return nullptr;
}
-static mlir::omp::ClauseMemoryOrderKindAttr
-getAtomicMemoryOrder(lower::AbstractConverter &converter,
- semantics::SemanticsContext &semaCtx,
- const List<Clause> &clauses) {
- std::optional<mlir::omp::ClauseMemoryOrderKind> kind;
+static mlir::omp::ClauseMemoryOrderKind
+getMemoryOrderKind(common::OmpMemoryOrderType kind) {
+ switch (kind) {
+ case common::OmpMemoryOrderType::Acq_Rel:
+ return mlir::omp::ClauseMemoryOrderKind::Acq_rel;
+ case common::OmpMemoryOrderType::Acquire:
+ return mlir::omp::ClauseMemoryOrderKind::Acquire;
+ case common::OmpMemoryOrderType::Relaxed:
+ return mlir::omp::ClauseMemoryOrderKind::Relaxed;
+ case common::OmpMemoryOrderType::Release:
+ return mlir::omp::ClauseMemoryOrderKind::Release;
+ case common::OmpMemoryOrderType::Seq_Cst:
+ return mlir::omp::ClauseMemoryOrderKind::Seq_cst;
+ }
+ llvm_unreachable("Unexpected kind");
+}
+
+static std::optional<mlir::omp::ClauseMemoryOrderKind>
+getMemoryOrderKind(llvm::omp::Clause clauseId) {
+ switch (clauseId) {
+ case llvm::omp::Clause::OMPC_acq_rel:
+ return mlir::omp::ClauseMemoryOrderKind::Acq_rel;
+ case llvm::omp::Clause::OMPC_acquire:
+ return mlir::omp::ClauseMemoryOrderKind::Acquire;
+ case llvm::omp::Clause::OMPC_relaxed:
+ return mlir::omp::ClauseMemoryOrderKind::Relaxed;
+ case llvm::omp::Clause::OMPC_release:
+ return mlir::omp::ClauseMemoryOrderKind::Release;
+ case llvm::omp::Clause::OMPC_seq_cst:
+ return mlir::omp::ClauseMemoryOrderKind::Seq_cst;
+ default:
+ return std::nullopt;
+ }
+}
+
+static std::optional<mlir::omp::ClauseMemoryOrderKind>
+getMemoryOrderFromRequires(const semantics::Scope &scope) {
+ // The REQUIRES construct is only allowed in the main program scope
+ // and module scope, but seems like we also accept it in a subprogram
+ // scope.
+ // For safety, traverse all enclosing scopes and check if their symbol
+ // contains REQUIRES.
+ for (const auto *sc{&scope}; sc->kind() != semantics::Scope::Kind::Global;
+ sc = &sc->parent()) {
+ const semantics::Symbol *sym = sc->symbol();
+ if (!sym)
+ continue;
+
+ const common::OmpMemoryOrderType *admo = common::visit(
+ [](auto &&s) {
+ using WithOmpDeclarative = semantics::WithOmpDeclarative;
+ if constexpr (std::is_convertible_v<decltype(s),
+ const WithOmpDeclarative &>) {
+ return s.ompAtomicDefaultMemOrder();
+ }
+ return static_cast<const common::OmpMemoryOrderType *>(nullptr);
+ },
+ sym->details());
+ if (admo)
+ return getMemoryOrderKind(*admo);
+ }
+
+ return std::nullopt;
+}
+
+static std::optional<mlir::omp::ClauseMemoryOrderKind>
+getDefaultAtomicMemOrder(semantics::SemanticsContext &semaCtx) {
unsigned version = semaCtx.langOptions().OpenMPVersion;
+ if (version > 50)
+ return mlir::omp::ClauseMemoryOrderKind::Relaxed;
+ return std::nullopt;
+}
+static std::optional<mlir::omp::ClauseMemoryOrderKind>
+getAtomicMemoryOrder(semantics::SemanticsContext &semaCtx,
+ const List<Clause> &clauses,
+ const semantics::Scope &scope) {
for (const Clause &clause : clauses) {
- switch (clause.id) {
- case llvm::omp::Clause::OMPC_acq_rel:
- kind = mlir::omp::ClauseMemoryOrderKind::Acq_rel;
- break;
- case llvm::omp::Clause::OMPC_acquire:
- kind = mlir::omp::ClauseMemoryOrderKind::Acquire;
- break;
- case llvm::omp::Clause::OMPC_relaxed:
- kind = mlir::omp::ClauseMemoryOrderKind::Relaxed;
- break;
- case llvm::omp::Clause::OMPC_release:
- kind = mlir::omp::ClauseMemoryOrderKind::Release;
- break;
- case llvm::omp::Clause::OMPC_seq_cst:
- kind = mlir::omp::ClauseMemoryOrderKind::Seq_cst;
- break;
- default:
- break;
- }
+ if (auto maybeKind = getMemoryOrderKind(clause.id))
+ return *maybeKind;
}
- // Starting with 5.1, if no memory-order clause is present, the effect
- // is as if "relaxed" was present.
- if (!kind) {
- if (version <= 50)
- return nullptr;
- kind = mlir::omp::ClauseMemoryOrderKind::Relaxed;
+ if (auto maybeKind = getMemoryOrderFromRequires(scope))
+ return *maybeKind;
+
+ return getDefaultAtomicMemOrder(semaCtx);
+}
+
+static mlir::omp::ClauseMemoryOrderKindAttr
+makeMemOrderAttr(lower::AbstractConverter &converter,
+ std::optional<mlir::omp::ClauseMemoryOrderKind> maybeKind) {
+ if (maybeKind) {
+ return mlir::omp::ClauseMemoryOrderKindAttr::get(
+ converter.getFirOpBuilder().getContext(), *maybeKind);
}
- fir::FirOpBuilder &builder = converter.getFirOpBuilder();
- return mlir::omp::ClauseMemoryOrderKindAttr::get(builder.getContext(), *kind);
+ return nullptr;
}
static mlir::Operation * //
-genAtomicRead(lower::AbstractConverter &converter, mlir::Location loc,
+genAtomicRead(lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx, mlir::Location loc,
lower::StatementContext &stmtCtx, mlir::Value atomAddr,
const semantics::SomeExpr &atom,
const evaluate::Assignment &assign, mlir::IntegerAttr hint,
- mlir::omp::ClauseMemoryOrderKindAttr memOrder,
+ std::optional<mlir::omp::ClauseMemoryOrderKind> memOrder,
fir::FirOpBuilder::InsertPoint preAt,
fir::FirOpBuilder::InsertPoint atomicAt,
fir::FirOpBuilder::InsertPoint postAt) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
builder.restoreInsertionPoint(preAt);
+ // If the atomic clause is read then the memory-order clause must
+ // not be release.
+ if (memOrder) {
+ if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Release) {
+ // Reset it back to the default.
+ memOrder = getDefaultAtomicMemOrder(semaCtx);
+ } else if (*memOrder == mlir::omp::ClauseMemoryOrderKind::Acq_rel) {
----------------
kparzysz wrote:
There is a gap in the 5.2+ spec. The ATOMIC_DEFAULT_MEM_ORDER was allowed to have "acquire" and "release" as values, yet at the same time it didn't specify the behavior on a construct that doesn't allow these values.
The recommendation from @dreachem was to allow such cases, and simply not apply the ADMO to such constructs. This is effectively applying the default memory order (i.e. "relaxed") to them.
https://github.com/llvm/llvm-project/pull/144362
More information about the flang-commits
mailing list