Skip to content

Commit 2e73a1f

Browse files
committed
[flang][openacc] Lower exit data directive
This patch upstream the lowering of Exit Data construct that was initially done in flang-compiler#527 Reviewed By: schweitz Differential Revision: https://reviews.llvm.org/D90467
1 parent 52b86d3 commit 2e73a1f

File tree

1 file changed

+135
-1
lines changed

1 file changed

+135
-1
lines changed

flang/lib/Lower/OpenACC.cpp

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ static Op createRegionOp(Fortran::lower::FirOpBuilder &builder,
107107
return op;
108108
}
109109

110+
template <typename Op>
111+
static Op createSimpleOp(Fortran::lower::FirOpBuilder &builder,
112+
mlir::Location loc,
113+
const SmallVectorImpl<Value> &operands,
114+
const SmallVectorImpl<int32_t> &operandSegments) {
115+
llvm::ArrayRef<mlir::Type> argTy;
116+
Op op = builder.create<Op>(loc, argTy, operands);
117+
op.setAttr(Op::getOperandSegmentSizeAttr(),
118+
builder.getI32VectorAttr(operandSegments));
119+
return op;
120+
}
121+
110122
static void genACC(Fortran::lower::AbstractConverter &converter,
111123
Fortran::lower::pft::Evaluation &eval,
112124
const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
@@ -516,6 +528,128 @@ genACC(Fortran::lower::AbstractConverter &converter,
516528
}
517529
}
518530

531+
static void
532+
genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
533+
const Fortran::parser::AccClauseList &accClauseList) {
534+
mlir::Value ifCond, async, waitDevnum;
535+
SmallVector<Value, 2> copyoutOperands, deleteOperands, detachOperands,
536+
waitOperands;
537+
538+
// Async and wait clause have optional values but can be present with
539+
// no value as well. When there is no value, the op has an attribute to
540+
// represent the clause.
541+
bool addAsyncAttr = false;
542+
bool addWaitAttr = false;
543+
bool addFinalizeAttr = false;
544+
545+
auto &firOpBuilder = converter.getFirOpBuilder();
546+
auto currentLocation = converter.getCurrentLocation();
547+
548+
// Lower clauses values mapped to operands.
549+
// Keep track of each group of operands separatly as clauses can appear
550+
// more than once.
551+
for (const auto &clause : accClauseList.v) {
552+
if (const auto *ifClause =
553+
std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
554+
Value cond = fir::getBase(
555+
converter.genExprValue(*Fortran::semantics::GetExpr(ifClause->v)));
556+
ifCond = firOpBuilder.createConvert(currentLocation,
557+
firOpBuilder.getI1Type(), cond);
558+
} else if (const auto *asyncClause =
559+
std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
560+
const auto &asyncClauseValue = asyncClause->v;
561+
if (asyncClauseValue) { // async has a value.
562+
async = fir::getBase(converter.genExprValue(
563+
*Fortran::semantics::GetExpr(*asyncClauseValue)));
564+
} else {
565+
addAsyncAttr = true;
566+
}
567+
} else if (const auto *waitClause =
568+
std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
569+
const auto &waitClauseValue = waitClause->v;
570+
if (waitClauseValue) { // wait has a value.
571+
const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
572+
const std::list<Fortran::parser::ScalarIntExpr> &waitList =
573+
std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t);
574+
for (const Fortran::parser::ScalarIntExpr &value : waitList) {
575+
Value v = fir::getBase(
576+
converter.genExprValue(*Fortran::semantics::GetExpr(value)));
577+
waitOperands.push_back(v);
578+
}
579+
580+
const std::optional<Fortran::parser::ScalarIntExpr> &waitDevnumValue =
581+
std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t);
582+
if (waitDevnumValue)
583+
waitDevnum = fir::getBase(converter.genExprValue(
584+
*Fortran::semantics::GetExpr(*waitDevnumValue)));
585+
} else {
586+
addWaitAttr = true;
587+
}
588+
} else if (const auto *copyoutClause =
589+
std::get_if<Fortran::parser::AccClause::Copyout>(
590+
&clause.u)) {
591+
const Fortran::parser::AccObjectListWithModifier &listWithModifier =
592+
copyoutClause->v;
593+
const Fortran::parser::AccObjectList &accObjectList =
594+
std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
595+
genObjectList(accObjectList, converter, copyoutOperands);
596+
} else if (const auto *deleteClause =
597+
std::get_if<Fortran::parser::AccClause::Delete>(&clause.u)) {
598+
genObjectList(deleteClause->v, converter, deleteOperands);
599+
} else if (const auto *detachClause =
600+
std::get_if<Fortran::parser::AccClause::Detach>(&clause.u)) {
601+
genObjectList(detachClause->v, converter, detachOperands);
602+
} else if (std::get_if<Fortran::parser::AccClause::Finalize>(&clause.u)) {
603+
addFinalizeAttr = true;
604+
}
605+
}
606+
607+
// Prepare the operand segement size attribute and the operands value range.
608+
SmallVector<Value, 8> operands;
609+
SmallVector<int32_t, 8> operandSegments;
610+
addOperand(operands, operandSegments, ifCond);
611+
addOperand(operands, operandSegments, async);
612+
addOperand(operands, operandSegments, waitDevnum);
613+
addOperands(operands, operandSegments, waitOperands);
614+
addOperands(operands, operandSegments, copyoutOperands);
615+
addOperands(operands, operandSegments, deleteOperands);
616+
addOperands(operands, operandSegments, detachOperands);
617+
618+
auto exitDataOp = createSimpleOp<mlir::acc::ExitDataOp>(
619+
firOpBuilder, currentLocation, operands, operandSegments);
620+
621+
if (addAsyncAttr)
622+
exitDataOp.asyncAttr(firOpBuilder.getUnitAttr());
623+
if (addWaitAttr)
624+
exitDataOp.waitAttr(firOpBuilder.getUnitAttr());
625+
if (addFinalizeAttr)
626+
exitDataOp.finalizeAttr(firOpBuilder.getUnitAttr());
627+
}
628+
629+
static void
630+
genACC(Fortran::lower::AbstractConverter &converter,
631+
Fortran::lower::pft::Evaluation &eval,
632+
const Fortran::parser::OpenACCStandaloneConstruct &standaloneConstruct) {
633+
const auto &standaloneDirective =
634+
std::get<Fortran::parser::AccStandaloneDirective>(standaloneConstruct.t);
635+
const auto &accClauseList =
636+
std::get<Fortran::parser::AccClauseList>(standaloneConstruct.t);
637+
638+
if (standaloneDirective.v == llvm::acc::Directive::ACCD_enter_data) {
639+
TODO("OpenACC enter data directive not lowered yet!");
640+
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_exit_data) {
641+
genACCExitDataOp(converter, accClauseList);
642+
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_init) {
643+
TODO("OpenACC init directive not lowered yet!");
644+
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_shutdown) {
645+
TODO("OpenACC shutdown directive not lowered yet!");
646+
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_set) {
647+
TODO("OpenACC set directive not lowered yet!");
648+
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_update) {
649+
TODO("OpenACC update directive not lowered yet!");
650+
}
651+
}
652+
519653
void Fortran::lower::genOpenACCConstruct(
520654
Fortran::lower::AbstractConverter &converter,
521655
Fortran::lower::pft::Evaluation &eval,
@@ -535,7 +669,7 @@ void Fortran::lower::genOpenACCConstruct(
535669
},
536670
[&](const Fortran::parser::OpenACCStandaloneConstruct
537671
&standaloneConstruct) {
538-
TODO("OpenACC Standalone construct not lowered yet!");
672+
genACC(converter, eval, standaloneConstruct);
539673
},
540674
[&](const Fortran::parser::OpenACCRoutineConstruct
541675
&routineConstruct) {

0 commit comments

Comments
 (0)