[flang][openacc] Lower parallel construct
This patch upstream the lowering of Parallel construct that was initially done in https://github.com/flang-compiler/f18-llvm-project/pull/460. Reviewed By: jeanPerier Differential Revision: https://reviews.llvm.org/D88917
This commit is contained in:
parent
726a6e84be
commit
e944455eaf
|
@ -49,6 +49,26 @@ static void genObjectList(const Fortran::parser::AccObjectList &objectList,
|
|||
}
|
||||
}
|
||||
|
||||
template <typename Clause>
|
||||
static void
|
||||
genObjectListWithModifier(const Clause *x,
|
||||
Fortran::lower::AbstractConverter &converter,
|
||||
Fortran::parser::AccDataModifier::Modifier mod,
|
||||
SmallVectorImpl<Value> &operandsWithModifier,
|
||||
SmallVectorImpl<Value> &operands) {
|
||||
const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
|
||||
const Fortran::parser::AccObjectList &accObjectList =
|
||||
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
|
||||
const auto &modifier =
|
||||
std::get<std::optional<Fortran::parser::AccDataModifier>>(
|
||||
listWithModifier.t);
|
||||
if (modifier && (*modifier).v == mod) {
|
||||
genObjectList(accObjectList, converter, operandsWithModifier);
|
||||
} else {
|
||||
genObjectList(accObjectList, converter, operands);
|
||||
}
|
||||
}
|
||||
|
||||
static void addOperands(SmallVectorImpl<Value> &operands,
|
||||
SmallVectorImpl<int32_t> &operandSegments,
|
||||
const SmallVectorImpl<Value> &clauseOperands) {
|
||||
|
@ -228,6 +248,193 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
genACCParallelOp(Fortran::lower::AbstractConverter &converter,
|
||||
const Fortran::parser::AccClauseList &accClauseList) {
|
||||
mlir::Value async;
|
||||
mlir::Value numGangs;
|
||||
mlir::Value numWorkers;
|
||||
mlir::Value vectorLength;
|
||||
mlir::Value ifCond;
|
||||
mlir::Value selfCond;
|
||||
SmallVector<Value, 2> waitOperands, reductionOperands, copyOperands,
|
||||
copyinOperands, copyinReadonlyOperands, copyoutOperands,
|
||||
copyoutZeroOperands, createOperands, createZeroOperands, noCreateOperands,
|
||||
presentOperands, devicePtrOperands, attachOperands, privateOperands,
|
||||
firstprivateOperands;
|
||||
|
||||
// Async, wait and self clause have optional values but can be present with
|
||||
// no value as well. When there is no value, the op has an attribute to
|
||||
// represent the clause.
|
||||
bool addAsyncAttr = false;
|
||||
bool addWaitAttr = false;
|
||||
bool addSelfAttr = false;
|
||||
|
||||
auto &firOpBuilder = converter.getFirOpBuilder();
|
||||
auto currentLocation = converter.getCurrentLocation();
|
||||
|
||||
// Lower clauses values mapped to operands.
|
||||
// Keep track of each group of operands separatly as clauses can appear
|
||||
// more than once.
|
||||
for (const auto &clause : accClauseList.v) {
|
||||
if (const auto *asyncClause =
|
||||
std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
|
||||
const auto &asyncClauseValue = asyncClause->v;
|
||||
if (asyncClauseValue) { // async has a value.
|
||||
async = fir::getBase(converter.genExprValue(
|
||||
*Fortran::semantics::GetExpr(*asyncClauseValue)));
|
||||
} else {
|
||||
addAsyncAttr = true;
|
||||
}
|
||||
} else if (const auto *waitClause =
|
||||
std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
|
||||
const auto &waitClauseValue = waitClause->v;
|
||||
if (waitClauseValue) { // wait has a value.
|
||||
const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
|
||||
const std::list<Fortran::parser::ScalarIntExpr> &waitList =
|
||||
std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t);
|
||||
for (const Fortran::parser::ScalarIntExpr &value : waitList) {
|
||||
Value v = fir::getBase(
|
||||
converter.genExprValue(*Fortran::semantics::GetExpr(value)));
|
||||
waitOperands.push_back(v);
|
||||
}
|
||||
} else {
|
||||
addWaitAttr = true;
|
||||
}
|
||||
} else if (const auto *numGangsClause =
|
||||
std::get_if<Fortran::parser::AccClause::NumGangs>(
|
||||
&clause.u)) {
|
||||
numGangs = fir::getBase(converter.genExprValue(
|
||||
*Fortran::semantics::GetExpr(numGangsClause->v)));
|
||||
} else if (const auto *numWorkersClause =
|
||||
std::get_if<Fortran::parser::AccClause::NumWorkers>(
|
||||
&clause.u)) {
|
||||
numWorkers = fir::getBase(converter.genExprValue(
|
||||
*Fortran::semantics::GetExpr(numWorkersClause->v)));
|
||||
} else if (const auto *vectorLengthClause =
|
||||
std::get_if<Fortran::parser::AccClause::VectorLength>(
|
||||
&clause.u)) {
|
||||
vectorLength = fir::getBase(converter.genExprValue(
|
||||
*Fortran::semantics::GetExpr(vectorLengthClause->v)));
|
||||
} else if (const auto *ifClause =
|
||||
std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
|
||||
Value cond = fir::getBase(
|
||||
converter.genExprValue(*Fortran::semantics::GetExpr(ifClause->v)));
|
||||
ifCond = firOpBuilder.createConvert(currentLocation,
|
||||
firOpBuilder.getI1Type(), cond);
|
||||
} else if (const auto *selfClause =
|
||||
std::get_if<Fortran::parser::AccClause::Self>(&clause.u)) {
|
||||
if (selfClause->v) {
|
||||
Value cond = fir::getBase(converter.genExprValue(
|
||||
*Fortran::semantics::GetExpr(*(selfClause->v))));
|
||||
selfCond = firOpBuilder.createConvert(currentLocation,
|
||||
firOpBuilder.getI1Type(), cond);
|
||||
} else {
|
||||
addSelfAttr = true;
|
||||
}
|
||||
} else if (const auto *copyClause =
|
||||
std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
|
||||
genObjectList(copyClause->v, converter, copyOperands);
|
||||
} else if (const auto *copyinClause =
|
||||
std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
|
||||
genObjectListWithModifier<Fortran::parser::AccClause::Copyin>(
|
||||
copyinClause, converter,
|
||||
Fortran::parser::AccDataModifier::Modifier::ReadOnly,
|
||||
copyinReadonlyOperands, copyinOperands);
|
||||
} else if (const auto *copyoutClause =
|
||||
std::get_if<Fortran::parser::AccClause::Copyout>(
|
||||
&clause.u)) {
|
||||
genObjectListWithModifier<Fortran::parser::AccClause::Copyout>(
|
||||
copyoutClause, converter,
|
||||
Fortran::parser::AccDataModifier::Modifier::Zero, copyoutZeroOperands,
|
||||
copyoutOperands);
|
||||
} else if (const auto *createClause =
|
||||
std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
|
||||
genObjectListWithModifier<Fortran::parser::AccClause::Create>(
|
||||
createClause, converter,
|
||||
Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands,
|
||||
createOperands);
|
||||
} else if (const auto *noCreateClause =
|
||||
std::get_if<Fortran::parser::AccClause::NoCreate>(
|
||||
&clause.u)) {
|
||||
genObjectList(noCreateClause->v, converter, noCreateOperands);
|
||||
} else if (const auto *presentClause =
|
||||
std::get_if<Fortran::parser::AccClause::Present>(
|
||||
&clause.u)) {
|
||||
genObjectList(presentClause->v, converter, presentOperands);
|
||||
} else if (const auto *devicePtrClause =
|
||||
std::get_if<Fortran::parser::AccClause::Deviceptr>(
|
||||
&clause.u)) {
|
||||
genObjectList(devicePtrClause->v, converter, devicePtrOperands);
|
||||
} else if (const auto *attachClause =
|
||||
std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
|
||||
genObjectList(attachClause->v, converter, attachOperands);
|
||||
} else if (const auto *privateClause =
|
||||
std::get_if<Fortran::parser::AccClause::Private>(
|
||||
&clause.u)) {
|
||||
genObjectList(privateClause->v, converter, privateOperands);
|
||||
} else if (const auto *firstprivateClause =
|
||||
std::get_if<Fortran::parser::AccClause::Firstprivate>(
|
||||
&clause.u)) {
|
||||
genObjectList(firstprivateClause->v, converter, firstprivateOperands);
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the operand segement size attribute and the operands value range.
|
||||
SmallVector<Value, 8> operands;
|
||||
SmallVector<int32_t, 8> operandSegments;
|
||||
addOperand(operands, operandSegments, async);
|
||||
addOperands(operands, operandSegments, waitOperands);
|
||||
addOperand(operands, operandSegments, numGangs);
|
||||
addOperand(operands, operandSegments, numWorkers);
|
||||
addOperand(operands, operandSegments, vectorLength);
|
||||
addOperand(operands, operandSegments, ifCond);
|
||||
addOperand(operands, operandSegments, selfCond);
|
||||
addOperands(operands, operandSegments, reductionOperands);
|
||||
addOperands(operands, operandSegments, copyOperands);
|
||||
addOperands(operands, operandSegments, copyinOperands);
|
||||
addOperands(operands, operandSegments, copyinReadonlyOperands);
|
||||
addOperands(operands, operandSegments, copyoutOperands);
|
||||
addOperands(operands, operandSegments, copyoutZeroOperands);
|
||||
addOperands(operands, operandSegments, createOperands);
|
||||
addOperands(operands, operandSegments, createZeroOperands);
|
||||
addOperands(operands, operandSegments, noCreateOperands);
|
||||
addOperands(operands, operandSegments, presentOperands);
|
||||
addOperands(operands, operandSegments, devicePtrOperands);
|
||||
addOperands(operands, operandSegments, attachOperands);
|
||||
addOperands(operands, operandSegments, privateOperands);
|
||||
addOperands(operands, operandSegments, firstprivateOperands);
|
||||
|
||||
auto parallelOp = createRegionOp<mlir::acc::ParallelOp, mlir::acc::YieldOp>(
|
||||
firOpBuilder, currentLocation, operands, operandSegments);
|
||||
|
||||
if (addAsyncAttr)
|
||||
parallelOp.setAttr(mlir::acc::ParallelOp::getAsyncAttrName(),
|
||||
firOpBuilder.getUnitAttr());
|
||||
if (addWaitAttr)
|
||||
parallelOp.setAttr(mlir::acc::ParallelOp::getWaitAttrName(),
|
||||
firOpBuilder.getUnitAttr());
|
||||
if (addSelfAttr)
|
||||
parallelOp.setAttr(mlir::acc::ParallelOp::getSelfAttrName(),
|
||||
firOpBuilder.getUnitAttr());
|
||||
}
|
||||
|
||||
static void
|
||||
genACC(Fortran::lower::AbstractConverter &converter,
|
||||
Fortran::lower::pft::Evaluation &eval,
|
||||
const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
|
||||
const auto &beginBlockDirective =
|
||||
std::get<Fortran::parser::AccBeginBlockDirective>(blockConstruct.t);
|
||||
const auto &blockDirective =
|
||||
std::get<Fortran::parser::AccBlockDirective>(beginBlockDirective.t);
|
||||
const auto &accClauseList =
|
||||
std::get<Fortran::parser::AccClauseList>(beginBlockDirective.t);
|
||||
|
||||
if (blockDirective.v == llvm::acc::ACCD_parallel) {
|
||||
genACCParallelOp(converter, accClauseList);
|
||||
}
|
||||
}
|
||||
|
||||
void Fortran::lower::genOpenACCConstruct(
|
||||
Fortran::lower::AbstractConverter &converter,
|
||||
Fortran::lower::pft::Evaluation &eval,
|
||||
|
@ -236,7 +443,7 @@ void Fortran::lower::genOpenACCConstruct(
|
|||
std::visit(
|
||||
common::visitors{
|
||||
[&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
|
||||
TODO();
|
||||
genACC(converter, eval, blockConstruct);
|
||||
},
|
||||
[&](const Fortran::parser::OpenACCCombinedConstruct
|
||||
&combinedConstruct) { TODO(); },
|
||||
|
|
Loading…
Reference in a new issue