[flang-commits] [flang] [flang][openacc] Enable lowering support for OpenACC atomic operations (PR #65776)
Slava Zakharin via flang-commits
flang-commits at lists.llvm.org
Fri Sep 8 09:47:06 PDT 2023
================
@@ -0,0 +1,606 @@
+//===-- Lower/DirectivesCommon.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+///
+/// A location to place directive utilities shared across multiple lowering
+/// files, e.g. utilities shared in OpenMP and OpenACC. The header file can
+/// be used for both declarations and templated/inline implementations.
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_LOWER_DIRECTIVES_COMMON_H
+#define FORTRAN_LOWER_DIRECTIVES_COMMON_H
+
+#include "flang/Common/idioms.h"
+#include "flang/Lower/Bridge.h"
+#include "flang/Lower/ConvertExpr.h"
+#include "flang/Lower/ConvertVariable.h"
+#include "flang/Lower/OpenACC.h"
+#include "flang/Lower/OpenMP.h"
+#include "flang/Lower/PFTBuilder.h"
+#include "flang/Lower/StatementContext.h"
+#include "flang/Optimizer/Builder/BoxValue.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "flang/Parser/parse-tree.h"
+#include "flang/Semantics/openmp-directive-sets.h"
+#include "flang/Semantics/tools.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
+#include "mlir/Dialect/SCF/IR/SCF.h"
+#include "llvm/Frontend/OpenMP/OMPConstants.h"
+#include <type_traits>
+
+namespace Fortran {
+namespace lower {
+
+/// Checks if the assignment statement has a single variable on the RHS.
+static inline bool checkForSingleVariableOnRHS(
+ const Fortran::parser::AssignmentStmt &assignmentStmt) {
+ const Fortran::parser::Expr &expr{
+ std::get<Fortran::parser::Expr>(assignmentStmt.t)};
+ const Fortran::common::Indirection<Fortran::parser::Designator> *designator =
+ std::get_if<Fortran::common::Indirection<Fortran::parser::Designator>>(
+ &expr.u);
+ const Fortran::parser::Name *name =
+ designator
+ ? Fortran::semantics::getDesignatorNameIfDataRef(designator->value())
+ : nullptr;
+ return name != nullptr;
+}
+
+/// Checks if the symbol on the LHS of the assignment statement is present in
+/// the RHS expression.
+static inline bool
+checkForSymbolMatch(const Fortran::parser::AssignmentStmt &assignmentStmt) {
+ const auto &var{std::get<Fortran::parser::Variable>(assignmentStmt.t)};
+ const auto &expr{std::get<Fortran::parser::Expr>(assignmentStmt.t)};
+ const auto *e{Fortran::semantics::GetExpr(expr)};
+ const auto *v{Fortran::semantics::GetExpr(var)};
+ auto varSyms{Fortran::evaluate::GetSymbolVector(*v)};
+ const Fortran::semantics::Symbol &varSymbol{*varSyms.front()};
+ for (const Fortran::semantics::Symbol &symbol :
+ Fortran::evaluate::GetSymbolVector(*e))
+ if (varSymbol == symbol)
+ return true;
+ return false;
+}
+
+/// Populates \p hint and \p memoryOrder with appropriate clause information
+/// if present on atomic construct.
+static inline void genOmpAtomicHintAndMemoryOrderClauses(
+ Fortran::lower::AbstractConverter &converter,
+ const Fortran::parser::OmpAtomicClauseList &clauseList,
+ mlir::IntegerAttr &hint,
+ mlir::omp::ClauseMemoryOrderKindAttr &memoryOrder) {
+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
+ for (const Fortran::parser::OmpAtomicClause &clause : clauseList.v) {
+ if (const auto *ompClause =
+ std::get_if<Fortran::parser::OmpClause>(&clause.u)) {
+ if (const auto *hintClause =
+ std::get_if<Fortran::parser::OmpClause::Hint>(&ompClause->u)) {
+ const auto *expr = Fortran::semantics::GetExpr(hintClause->v);
+ uint64_t hintExprValue = *Fortran::evaluate::ToInt64(*expr);
+ hint = firOpBuilder.getI64IntegerAttr(hintExprValue);
+ }
+ } else if (const auto *ompMemoryOrderClause =
+ std::get_if<Fortran::parser::OmpMemoryOrderClause>(
+ &clause.u)) {
+ if (std::get_if<Fortran::parser::OmpClause::Acquire>(
+ &ompMemoryOrderClause->v.u)) {
+ memoryOrder = mlir::omp::ClauseMemoryOrderKindAttr::get(
+ firOpBuilder.getContext(),
+ mlir::omp::ClauseMemoryOrderKind::Acquire);
+ } else if (std::get_if<Fortran::parser::OmpClause::Relaxed>(
+ &ompMemoryOrderClause->v.u)) {
+ memoryOrder = mlir::omp::ClauseMemoryOrderKindAttr::get(
+ firOpBuilder.getContext(),
+ mlir::omp::ClauseMemoryOrderKind::Relaxed);
+ } else if (std::get_if<Fortran::parser::OmpClause::SeqCst>(
+ &ompMemoryOrderClause->v.u)) {
+ memoryOrder = mlir::omp::ClauseMemoryOrderKindAttr::get(
+ firOpBuilder.getContext(),
+ mlir::omp::ClauseMemoryOrderKind::Seq_cst);
+ } else if (std::get_if<Fortran::parser::OmpClause::Release>(
+ &ompMemoryOrderClause->v.u)) {
+ memoryOrder = mlir::omp::ClauseMemoryOrderKindAttr::get(
+ firOpBuilder.getContext(),
+ mlir::omp::ClauseMemoryOrderKind::Release);
+ }
+ }
+ }
+}
+
+/// Used to generate atomic.read operation which is created in existing
+/// location set by builder.
+template <typename AtomicListT>
+static inline void genOmpAccAtomicCaptureStatement(
+ Fortran::lower::AbstractConverter &converter,
+ Fortran::lower::pft::Evaluation &eval, mlir::Value fromAddress,
----------------
vzakhari wrote:
nit: it looks like `eval` is unused, but we may keep it since this is coming from the original OpenMP code. It may be cleaned up later like in https://github.com/llvm/llvm-project/pull/65678
https://github.com/llvm/llvm-project/pull/65776
More information about the flang-commits
mailing list