146 lines
5.4 KiB
C++
146 lines
5.4 KiB
C++
//===-- Utils..cpp ----------------------------------------------*- 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/
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Utils.h"
|
|
|
|
#include "Clauses.h"
|
|
#include <flang/Lower/AbstractConverter.h>
|
|
#include <flang/Lower/ConvertType.h>
|
|
#include <flang/Lower/PFTBuilder.h>
|
|
#include <flang/Optimizer/Builder/FIRBuilder.h>
|
|
#include <flang/Parser/parse-tree.h>
|
|
#include <flang/Parser/tools.h>
|
|
#include <flang/Semantics/tools.h>
|
|
#include <llvm/Support/CommandLine.h>
|
|
|
|
llvm::cl::opt<bool> treatIndexAsSection(
|
|
"openmp-treat-index-as-section",
|
|
llvm::cl::desc("In the OpenMP data clauses treat `a(N)` as `a(N:N)`."),
|
|
llvm::cl::init(true));
|
|
|
|
llvm::cl::opt<bool> enableDelayedPrivatization(
|
|
"openmp-enable-delayed-privatization",
|
|
llvm::cl::desc(
|
|
"Emit `[first]private` variables as clauses on the MLIR ops."),
|
|
llvm::cl::init(false));
|
|
|
|
namespace Fortran {
|
|
namespace lower {
|
|
namespace omp {
|
|
|
|
int64_t getCollapseValue(const List<Clause> &clauses) {
|
|
auto iter = llvm::find_if(clauses, [](const Clause &clause) {
|
|
return clause.id == llvm::omp::Clause::OMPC_collapse;
|
|
});
|
|
if (iter != clauses.end()) {
|
|
const auto &collapse = std::get<clause::Collapse>(iter->u);
|
|
return evaluate::ToInt64(collapse.v).value();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
uint32_t getOpenMPVersion(mlir::ModuleOp mod) {
|
|
if (mlir::Attribute verAttr = mod->getAttr("omp.version"))
|
|
return llvm::cast<mlir::omp::VersionAttr>(verAttr).getVersion();
|
|
llvm_unreachable("Expecting OpenMP version attribute in module");
|
|
}
|
|
|
|
void genObjectList(const ObjectList &objects,
|
|
Fortran::lower::AbstractConverter &converter,
|
|
llvm::SmallVectorImpl<mlir::Value> &operands) {
|
|
for (const Object &object : objects) {
|
|
const Fortran::semantics::Symbol *sym = object.id();
|
|
assert(sym && "Expected Symbol");
|
|
if (mlir::Value variable = converter.getSymbolAddress(*sym)) {
|
|
operands.push_back(variable);
|
|
} else if (const auto *details =
|
|
sym->detailsIf<Fortran::semantics::HostAssocDetails>()) {
|
|
operands.push_back(converter.getSymbolAddress(details->symbol()));
|
|
converter.copySymbolBinding(details->symbol(), *sym);
|
|
}
|
|
}
|
|
}
|
|
|
|
mlir::Type getLoopVarType(Fortran::lower::AbstractConverter &converter,
|
|
std::size_t loopVarTypeSize) {
|
|
// OpenMP runtime requires 32-bit or 64-bit loop variables.
|
|
loopVarTypeSize = loopVarTypeSize * 8;
|
|
if (loopVarTypeSize < 32) {
|
|
loopVarTypeSize = 32;
|
|
} else if (loopVarTypeSize > 64) {
|
|
loopVarTypeSize = 64;
|
|
mlir::emitWarning(converter.getCurrentLocation(),
|
|
"OpenMP loop iteration variable cannot have more than 64 "
|
|
"bits size and will be narrowed into 64 bits.");
|
|
}
|
|
assert((loopVarTypeSize == 32 || loopVarTypeSize == 64) &&
|
|
"OpenMP loop iteration variable size must be transformed into 32-bit "
|
|
"or 64-bit");
|
|
return converter.getFirOpBuilder().getIntegerType(loopVarTypeSize);
|
|
}
|
|
|
|
Fortran::semantics::Symbol *
|
|
getIterationVariableSymbol(const Fortran::lower::pft::Evaluation &eval) {
|
|
return eval.visit(Fortran::common::visitors{
|
|
[&](const Fortran::parser::DoConstruct &doLoop) {
|
|
if (const auto &maybeCtrl = doLoop.GetLoopControl()) {
|
|
using LoopControl = Fortran::parser::LoopControl;
|
|
if (auto *bounds = std::get_if<LoopControl::Bounds>(&maybeCtrl->u)) {
|
|
static_assert(
|
|
std::is_same_v<decltype(bounds->name),
|
|
Fortran::parser::Scalar<Fortran::parser::Name>>);
|
|
return bounds->name.thing.symbol;
|
|
}
|
|
}
|
|
return static_cast<Fortran::semantics::Symbol *>(nullptr);
|
|
},
|
|
[](auto &&) {
|
|
return static_cast<Fortran::semantics::Symbol *>(nullptr);
|
|
},
|
|
});
|
|
}
|
|
|
|
void gatherFuncAndVarSyms(
|
|
const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause,
|
|
llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) {
|
|
for (const Object &object : objects)
|
|
symbolAndClause.emplace_back(clause, *object.id());
|
|
}
|
|
|
|
Fortran::semantics::Symbol *
|
|
getOmpObjectSymbol(const Fortran::parser::OmpObject &ompObject) {
|
|
Fortran::semantics::Symbol *sym = nullptr;
|
|
std::visit(
|
|
Fortran::common::visitors{
|
|
[&](const Fortran::parser::Designator &designator) {
|
|
if (auto *arrayEle =
|
|
Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
|
|
designator)) {
|
|
sym = GetFirstName(arrayEle->base).symbol;
|
|
} else if (auto *structComp = Fortran::parser::Unwrap<
|
|
Fortran::parser::StructureComponent>(designator)) {
|
|
sym = structComp->component.symbol;
|
|
} else if (const Fortran::parser::Name *name =
|
|
Fortran::semantics::getDesignatorNameIfDataRef(
|
|
designator)) {
|
|
sym = name->symbol;
|
|
}
|
|
},
|
|
[&](const Fortran::parser::Name &name) { sym = name.symbol; }},
|
|
ompObject.u);
|
|
return sym;
|
|
}
|
|
|
|
} // namespace omp
|
|
} // namespace lower
|
|
} // namespace Fortran
|