Skip to content

[flang][openacc] Allow open acc routines from other modules. #136012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 9, 2025
32 changes: 15 additions & 17 deletions flang/include/flang/Lower/OpenACC.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,9 @@ class StringRef;
} // namespace llvm

namespace mlir {
namespace func {
class FuncOp;
} // namespace func
class Location;
class Type;
class ModuleOp;
@@ -31,9 +34,13 @@ class Value;

namespace fir {
class FirOpBuilder;
}
} // namespace fir

namespace Fortran {
namespace evaluate {
struct ProcedureDesignator;
} // namespace evaluate

namespace parser {
struct AccClauseList;
struct OpenACCConstruct;
@@ -42,6 +49,7 @@ struct OpenACCRoutineConstruct;
} // namespace parser

namespace semantics {
class OpenACCRoutineInfo;
class SemanticsContext;
class Symbol;
} // namespace semantics
@@ -55,9 +63,6 @@ namespace pft {
struct Evaluation;
} // namespace pft

using AccRoutineInfoMappingList =
llvm::SmallVector<std::pair<std::string, mlir::SymbolRefAttr>>;

static constexpr llvm::StringRef declarePostAllocSuffix =
"_acc_declare_update_desc_post_alloc";
static constexpr llvm::StringRef declarePreDeallocSuffix =
@@ -71,19 +76,12 @@ mlir::Value genOpenACCConstruct(AbstractConverter &,
Fortran::semantics::SemanticsContext &,
pft::Evaluation &,
const parser::OpenACCConstruct &);
void genOpenACCDeclarativeConstruct(AbstractConverter &,
Fortran::semantics::SemanticsContext &,
StatementContext &,
const parser::OpenACCDeclarativeConstruct &,
AccRoutineInfoMappingList &);
void genOpenACCRoutineConstruct(AbstractConverter &,
Fortran::semantics::SemanticsContext &,
mlir::ModuleOp,
const parser::OpenACCRoutineConstruct &,
AccRoutineInfoMappingList &);

void finalizeOpenACCRoutineAttachment(mlir::ModuleOp,
AccRoutineInfoMappingList &);
void genOpenACCDeclarativeConstruct(
AbstractConverter &, Fortran::semantics::SemanticsContext &,
StatementContext &, const parser::OpenACCDeclarativeConstruct &);
void genOpenACCRoutineConstruct(
AbstractConverter &, mlir::ModuleOp, mlir::func::FuncOp,
const std::vector<Fortran::semantics::OpenACCRoutineInfo> &);

/// Get a acc.private.recipe op for the given type or create it if it does not
/// exist yet.
44 changes: 35 additions & 9 deletions flang/include/flang/Semantics/symbol.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
#include <list>
#include <optional>
#include <set>
#include <variant>
#include <vector>

namespace llvm {
@@ -127,6 +128,9 @@ class WithBindName {
// Device type specific OpenACC routine information
class OpenACCRoutineDeviceTypeInfo {
public:
explicit OpenACCRoutineDeviceTypeInfo(
Fortran::common::OpenACCDeviceType dType)
: deviceType_{dType} {}
bool isSeq() const { return isSeq_; }
void set_isSeq(bool value = true) { isSeq_ = value; }
bool isVector() const { return isVector_; }
@@ -137,22 +141,30 @@ class OpenACCRoutineDeviceTypeInfo {
void set_isGang(bool value = true) { isGang_ = value; }
unsigned gangDim() const { return gangDim_; }
void set_gangDim(unsigned value) { gangDim_ = value; }
const std::string *bindName() const {
return bindName_ ? &*bindName_ : nullptr;
const std::variant<std::string, SymbolRef> *bindName() const {
return bindName_.has_value() ? &*bindName_ : nullptr;
}
void set_bindName(std::string &&name) { bindName_ = std::move(name); }
void set_dType(Fortran::common::OpenACCDeviceType dType) {
deviceType_ = dType;
const std::optional<std::variant<std::string, SymbolRef>> &
bindNameOpt() const {
return bindName_;
}
void set_bindName(std::string &&name) { bindName_.emplace(std::move(name)); }
void set_bindName(SymbolRef symbol) { bindName_.emplace(symbol); }

Fortran::common::OpenACCDeviceType dType() const { return deviceType_; }

friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const OpenACCRoutineDeviceTypeInfo &);

private:
bool isSeq_{false};
bool isVector_{false};
bool isWorker_{false};
bool isGang_{false};
unsigned gangDim_{0};
std::optional<std::string> bindName_;
// bind("name") -> std::string
// bind(sym) -> SymbolRef (requires namemangling in lowering)
std::optional<std::variant<std::string, SymbolRef>> bindName_;
Fortran::common::OpenACCDeviceType deviceType_{
Fortran::common::OpenACCDeviceType::None};
};
@@ -162,15 +174,29 @@ class OpenACCRoutineDeviceTypeInfo {
// in as objects in the OpenACCRoutineDeviceTypeInfo list.
class OpenACCRoutineInfo : public OpenACCRoutineDeviceTypeInfo {
public:
OpenACCRoutineInfo()
: OpenACCRoutineDeviceTypeInfo(Fortran::common::OpenACCDeviceType::None) {
}
bool isNohost() const { return isNohost_; }
void set_isNohost(bool value = true) { isNohost_ = value; }
std::list<OpenACCRoutineDeviceTypeInfo> &deviceTypeInfos() {
const std::list<OpenACCRoutineDeviceTypeInfo> &deviceTypeInfos() const {
return deviceTypeInfos_;
}
void add_deviceTypeInfo(OpenACCRoutineDeviceTypeInfo &info) {
deviceTypeInfos_.push_back(info);

OpenACCRoutineDeviceTypeInfo &add_deviceTypeInfo(
Fortran::common::OpenACCDeviceType type) {
return add_deviceTypeInfo(OpenACCRoutineDeviceTypeInfo(type));
}

OpenACCRoutineDeviceTypeInfo &add_deviceTypeInfo(
OpenACCRoutineDeviceTypeInfo &&info) {
deviceTypeInfos_.push_back(std::move(info));
return deviceTypeInfos_.back();
}

friend llvm::raw_ostream &operator<<(
llvm::raw_ostream &, const OpenACCRoutineInfo &);

private:
std::list<OpenACCRoutineDeviceTypeInfo> deviceTypeInfos_;
bool isNohost_{false};
Loading