forked from OSchip/llvm-project
[flang][OpenMP] Upstream lowering of `ParallelOp` clauses
Note: This patch reflects the work that can be upstreamed from PR's(merged): 1. https://github.com/flang-compiler/f18-llvm-project/pull/456 2. https://github.com/flang-compiler/f18-llvm-project/pull/485 Also replaced TODO with new TODO. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D89769
This commit is contained in:
parent
a6ad077f5d
commit
1d328446bf
|
@ -11,15 +11,54 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "flang/Lower/OpenMP.h"
|
#include "flang/Lower/OpenMP.h"
|
||||||
|
#include "flang/Common/idioms.h"
|
||||||
#include "flang/Lower/Bridge.h"
|
#include "flang/Lower/Bridge.h"
|
||||||
#include "flang/Lower/FIRBuilder.h"
|
#include "flang/Lower/FIRBuilder.h"
|
||||||
#include "flang/Lower/PFTBuilder.h"
|
#include "flang/Lower/PFTBuilder.h"
|
||||||
|
#include "flang/Lower/Support/BoxValue.h"
|
||||||
|
#include "flang/Lower/Todo.h"
|
||||||
#include "flang/Parser/parse-tree.h"
|
#include "flang/Parser/parse-tree.h"
|
||||||
#include "flang/Semantics/tools.h"
|
#include "flang/Semantics/tools.h"
|
||||||
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
|
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
|
||||||
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
||||||
|
|
||||||
#define TODO() llvm_unreachable("not yet implemented")
|
static const Fortran::parser::Name *
|
||||||
|
getDesignatorNameIfDataRef(const Fortran::parser::Designator &designator) {
|
||||||
|
const auto *dataRef = std::get_if<Fortran::parser::DataRef>(&designator.u);
|
||||||
|
return dataRef ? std::get_if<Fortran::parser::Name>(&dataRef->u) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void genObjectList(const Fortran::parser::OmpObjectList &objectList,
|
||||||
|
Fortran::lower::AbstractConverter &converter,
|
||||||
|
SmallVectorImpl<Value> &operands) {
|
||||||
|
for (const auto &ompObject : objectList.v) {
|
||||||
|
std::visit(
|
||||||
|
Fortran::common::visitors{
|
||||||
|
[&](const Fortran::parser::Designator &designator) {
|
||||||
|
if (const auto *name = getDesignatorNameIfDataRef(designator)) {
|
||||||
|
const auto variable = converter.getSymbolAddress(*name->symbol);
|
||||||
|
operands.push_back(variable);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[&](const Fortran::parser::Name &name) {
|
||||||
|
const auto variable = converter.getSymbolAddress(*name.symbol);
|
||||||
|
operands.push_back(variable);
|
||||||
|
}},
|
||||||
|
ompObject.u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Op>
|
||||||
|
static void createBodyOfOp(Op &op, Fortran::lower::FirOpBuilder &firOpBuilder,
|
||||||
|
mlir::Location &loc) {
|
||||||
|
firOpBuilder.createBlock(&op.getRegion());
|
||||||
|
auto &block = op.getRegion().back();
|
||||||
|
firOpBuilder.setInsertionPointToStart(&block);
|
||||||
|
// Ensure the block is well-formed.
|
||||||
|
firOpBuilder.create<mlir::omp::TerminatorOp>(loc);
|
||||||
|
// Reset the insertion point to the start of the first block.
|
||||||
|
firOpBuilder.setInsertionPointToStart(&block);
|
||||||
|
}
|
||||||
|
|
||||||
static void genOMP(Fortran::lower::AbstractConverter &converter,
|
static void genOMP(Fortran::lower::AbstractConverter &converter,
|
||||||
Fortran::lower::pft::Evaluation &eval,
|
Fortran::lower::pft::Evaluation &eval,
|
||||||
|
@ -44,13 +83,13 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
|
||||||
converter.getCurrentLocation());
|
converter.getCurrentLocation());
|
||||||
break;
|
break;
|
||||||
case llvm::omp::Directive::OMPD_target_enter_data:
|
case llvm::omp::Directive::OMPD_target_enter_data:
|
||||||
TODO();
|
TODO("");
|
||||||
case llvm::omp::Directive::OMPD_target_exit_data:
|
case llvm::omp::Directive::OMPD_target_exit_data:
|
||||||
TODO();
|
TODO("");
|
||||||
case llvm::omp::Directive::OMPD_target_update:
|
case llvm::omp::Directive::OMPD_target_update:
|
||||||
TODO();
|
TODO("");
|
||||||
case llvm::omp::Directive::OMPD_ordered:
|
case llvm::omp::Directive::OMPD_ordered:
|
||||||
TODO();
|
TODO("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +107,10 @@ genOMP(Fortran::lower::AbstractConverter &converter,
|
||||||
TODO();
|
TODO();
|
||||||
},
|
},
|
||||||
[&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) {
|
[&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) {
|
||||||
TODO();
|
TODO("");
|
||||||
},
|
},
|
||||||
[&](const Fortran::parser::OpenMPCancellationPointConstruct
|
[&](const Fortran::parser::OpenMPCancellationPointConstruct
|
||||||
&cancellationPointConstruct) { TODO(); },
|
&cancellationPointConstruct) { TODO(""); },
|
||||||
},
|
},
|
||||||
standaloneConstruct.u);
|
standaloneConstruct.u);
|
||||||
}
|
}
|
||||||
|
@ -80,45 +119,115 @@ static void
|
||||||
genOMP(Fortran::lower::AbstractConverter &converter,
|
genOMP(Fortran::lower::AbstractConverter &converter,
|
||||||
Fortran::lower::pft::Evaluation &eval,
|
Fortran::lower::pft::Evaluation &eval,
|
||||||
const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
|
const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
|
||||||
const auto &blockDirective =
|
const auto &beginBlockDirective =
|
||||||
std::get<Fortran::parser::OmpBeginBlockDirective>(blockConstruct.t);
|
std::get<Fortran::parser::OmpBeginBlockDirective>(blockConstruct.t);
|
||||||
const auto ¶llelDirective =
|
const auto &blockDirective =
|
||||||
std::get<Fortran::parser::OmpBlockDirective>(blockDirective.t);
|
std::get<Fortran::parser::OmpBlockDirective>(beginBlockDirective.t);
|
||||||
if (parallelDirective.v == llvm::omp::OMPD_parallel) {
|
|
||||||
auto &firOpBuilder = converter.getFirOpBuilder();
|
|
||||||
auto currentLocation = converter.getCurrentLocation();
|
|
||||||
|
|
||||||
// Clauses.
|
auto &firOpBuilder = converter.getFirOpBuilder();
|
||||||
// FIXME: Add support for other clauses.
|
auto currentLocation = converter.getCurrentLocation();
|
||||||
mlir::Value numThreads;
|
llvm::ArrayRef<mlir::Type> argTy;
|
||||||
|
if (blockDirective.v == llvm::omp::OMPD_parallel) {
|
||||||
|
|
||||||
|
mlir::Value ifClauseOperand, numThreadsClauseOperand;
|
||||||
|
SmallVector<Value, 4> privateClauseOperands, firstprivateClauseOperands,
|
||||||
|
sharedClauseOperands, copyinClauseOperands;
|
||||||
|
Attribute defaultClauseOperand, procBindClauseOperand;
|
||||||
|
|
||||||
const auto ¶llelOpClauseList =
|
const auto ¶llelOpClauseList =
|
||||||
std::get<Fortran::parser::OmpClauseList>(blockDirective.t);
|
std::get<Fortran::parser::OmpClauseList>(beginBlockDirective.t);
|
||||||
for (const auto &clause : parallelOpClauseList.v) {
|
for (const auto &clause : parallelOpClauseList.v) {
|
||||||
if (const auto &numThreadsClause =
|
if (const auto &ifClause =
|
||||||
std::get_if<Fortran::parser::OmpClause::NumThreads>(&clause.u)) {
|
std::get_if<Fortran::parser::OmpIfClause>(&clause.u)) {
|
||||||
|
auto &expr = std::get<Fortran::parser::ScalarLogicalExpr>(ifClause->t);
|
||||||
|
ifClauseOperand = fir::getBase(
|
||||||
|
converter.genExprValue(*Fortran::semantics::GetExpr(expr)));
|
||||||
|
} else if (const auto &numThreadsClause =
|
||||||
|
std::get_if<Fortran::parser::OmpClause::NumThreads>(
|
||||||
|
&clause.u)) {
|
||||||
// OMPIRBuilder expects `NUM_THREAD` clause as a `Value`.
|
// OMPIRBuilder expects `NUM_THREAD` clause as a `Value`.
|
||||||
numThreads = converter.genExprValue(
|
numThreadsClauseOperand = fir::getBase(converter.genExprValue(
|
||||||
*Fortran::semantics::GetExpr(numThreadsClause->v));
|
*Fortran::semantics::GetExpr(numThreadsClause->v)));
|
||||||
|
} else if (const auto &privateClause =
|
||||||
|
std::get_if<Fortran::parser::OmpClause::Private>(
|
||||||
|
&clause.u)) {
|
||||||
|
const Fortran::parser::OmpObjectList &ompObjectList = privateClause->v;
|
||||||
|
genObjectList(ompObjectList, converter, privateClauseOperands);
|
||||||
|
} else if (const auto &firstprivateClause =
|
||||||
|
std::get_if<Fortran::parser::OmpClause::Firstprivate>(
|
||||||
|
&clause.u)) {
|
||||||
|
const Fortran::parser::OmpObjectList &ompObjectList =
|
||||||
|
firstprivateClause->v;
|
||||||
|
genObjectList(ompObjectList, converter, firstprivateClauseOperands);
|
||||||
|
} else if (const auto &sharedClause =
|
||||||
|
std::get_if<Fortran::parser::OmpClause::Shared>(
|
||||||
|
&clause.u)) {
|
||||||
|
const Fortran::parser::OmpObjectList &ompObjectList = sharedClause->v;
|
||||||
|
genObjectList(ompObjectList, converter, sharedClauseOperands);
|
||||||
|
} else if (const auto ©inClause =
|
||||||
|
std::get_if<Fortran::parser::OmpClause::Copyin>(
|
||||||
|
&clause.u)) {
|
||||||
|
const Fortran::parser::OmpObjectList &ompObjectList = copyinClause->v;
|
||||||
|
genObjectList(ompObjectList, converter, copyinClauseOperands);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
llvm::ArrayRef<mlir::Type> argTy;
|
|
||||||
Attribute defaultValue, procBindValue;
|
|
||||||
// Create and insert the operation.
|
// Create and insert the operation.
|
||||||
// Create the Op with empty ranges for clauses that are yet to be lowered.
|
|
||||||
auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>(
|
auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>(
|
||||||
currentLocation, argTy, Value(), numThreads,
|
currentLocation, argTy, ifClauseOperand, numThreadsClauseOperand,
|
||||||
defaultValue.dyn_cast_or_null<StringAttr>(), ValueRange(), ValueRange(),
|
defaultClauseOperand.dyn_cast_or_null<StringAttr>(),
|
||||||
ValueRange(), ValueRange(), ValueRange(), ValueRange(),
|
privateClauseOperands, firstprivateClauseOperands, sharedClauseOperands,
|
||||||
procBindValue.dyn_cast_or_null<StringAttr>());
|
copyinClauseOperands, ValueRange(), ValueRange(),
|
||||||
firOpBuilder.createBlock(¶llelOp.getRegion());
|
procBindClauseOperand.dyn_cast_or_null<StringAttr>());
|
||||||
auto &block = parallelOp.getRegion().back();
|
// Handle attribute based clauses.
|
||||||
firOpBuilder.setInsertionPointToStart(&block);
|
for (const auto &clause : parallelOpClauseList.v) {
|
||||||
// Ensure the block is well-formed.
|
if (const auto &defaultClause =
|
||||||
firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation);
|
std::get_if<Fortran::parser::OmpDefaultClause>(&clause.u)) {
|
||||||
|
switch (defaultClause->v) {
|
||||||
// Place the insertion point to the start of the first block.
|
case Fortran::parser::OmpDefaultClause::Type::Private:
|
||||||
firOpBuilder.setInsertionPointToStart(&block);
|
parallelOp.default_valAttr(firOpBuilder.getStringAttr(
|
||||||
|
omp::stringifyClauseDefault(omp::ClauseDefault::defprivate)));
|
||||||
|
break;
|
||||||
|
case Fortran::parser::OmpDefaultClause::Type::Firstprivate:
|
||||||
|
parallelOp.default_valAttr(
|
||||||
|
firOpBuilder.getStringAttr(omp::stringifyClauseDefault(
|
||||||
|
omp::ClauseDefault::deffirstprivate)));
|
||||||
|
break;
|
||||||
|
case Fortran::parser::OmpDefaultClause::Type::Shared:
|
||||||
|
parallelOp.default_valAttr(firOpBuilder.getStringAttr(
|
||||||
|
omp::stringifyClauseDefault(omp::ClauseDefault::defshared)));
|
||||||
|
break;
|
||||||
|
case Fortran::parser::OmpDefaultClause::Type::None:
|
||||||
|
parallelOp.default_valAttr(firOpBuilder.getStringAttr(
|
||||||
|
omp::stringifyClauseDefault(omp::ClauseDefault::defnone)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (const auto &procBindClause =
|
||||||
|
std::get_if<Fortran::parser::OmpProcBindClause>(&clause.u)) {
|
||||||
|
switch (procBindClause->v) {
|
||||||
|
case Fortran::parser::OmpProcBindClause::Type::Master:
|
||||||
|
parallelOp.proc_bind_valAttr(
|
||||||
|
firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind(
|
||||||
|
omp::ClauseProcBindKind::master)));
|
||||||
|
break;
|
||||||
|
case Fortran::parser::OmpProcBindClause::Type::Close:
|
||||||
|
parallelOp.proc_bind_valAttr(
|
||||||
|
firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind(
|
||||||
|
omp::ClauseProcBindKind::close)));
|
||||||
|
break;
|
||||||
|
case Fortran::parser::OmpProcBindClause::Type::Spread:
|
||||||
|
parallelOp.proc_bind_valAttr(
|
||||||
|
firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind(
|
||||||
|
omp::ClauseProcBindKind::spread)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createBodyOfOp<omp::ParallelOp>(parallelOp, firOpBuilder, currentLocation);
|
||||||
|
} else if (blockDirective.v == llvm::omp::OMPD_master) {
|
||||||
|
auto masterOp =
|
||||||
|
firOpBuilder.create<mlir::omp::MasterOp>(currentLocation, argTy);
|
||||||
|
createBodyOfOp<omp::MasterOp>(masterOp, firOpBuilder, currentLocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,18 +243,18 @@ void Fortran::lower::genOpenMPConstruct(
|
||||||
genOMP(converter, eval, standaloneConstruct);
|
genOMP(converter, eval, standaloneConstruct);
|
||||||
},
|
},
|
||||||
[&](const Fortran::parser::OpenMPSectionsConstruct
|
[&](const Fortran::parser::OpenMPSectionsConstruct
|
||||||
§ionsConstruct) { TODO(); },
|
§ionsConstruct) { TODO(""); },
|
||||||
[&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
|
[&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
|
||||||
TODO();
|
TODO("");
|
||||||
},
|
},
|
||||||
[&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
|
[&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
|
||||||
genOMP(converter, eval, blockConstruct);
|
genOMP(converter, eval, blockConstruct);
|
||||||
},
|
},
|
||||||
[&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
|
[&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
|
||||||
TODO();
|
TODO("");
|
||||||
},
|
},
|
||||||
[&](const Fortran::parser::OpenMPCriticalConstruct
|
[&](const Fortran::parser::OpenMPCriticalConstruct
|
||||||
&criticalConstruct) { TODO(); },
|
&criticalConstruct) { TODO(""); },
|
||||||
},
|
},
|
||||||
ompConstruct.u);
|
ompConstruct.u);
|
||||||
}
|
}
|
||||||
|
@ -153,5 +262,5 @@ void Fortran::lower::genOpenMPConstruct(
|
||||||
void Fortran::lower::genOpenMPEndLoop(
|
void Fortran::lower::genOpenMPEndLoop(
|
||||||
Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &,
|
Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &,
|
||||||
const Fortran::parser::OmpEndLoopDirective &) {
|
const Fortran::parser::OmpEndLoopDirective &) {
|
||||||
TODO();
|
TODO("");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue