@@ -528,6 +528,105 @@ genACC(Fortran::lower::AbstractConverter &converter,
528
528
}
529
529
}
530
530
531
+ static void
532
+ genACCEnterDataOp (Fortran::lower::AbstractConverter &converter,
533
+ const Fortran::parser::AccClauseList &accClauseList) {
534
+ mlir::Value ifCond, async, waitDevnum;
535
+ SmallVector<Value, 2 > copyinOperands, createOperands, createZeroOperands,
536
+ attachOperands, waitOperands;
537
+
538
+ // Async, wait and self 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
+
544
+ auto &firOpBuilder = converter.getFirOpBuilder ();
545
+ auto currentLocation = converter.getCurrentLocation ();
546
+
547
+ // Lower clauses values mapped to operands.
548
+ // Keep track of each group of operands separatly as clauses can appear
549
+ // more than once.
550
+ for (const auto &clause : accClauseList.v ) {
551
+ if (const auto *ifClause =
552
+ std::get_if<Fortran::parser::AccClause::If>(&clause.u )) {
553
+ mlir::Value cond = fir::getBase (
554
+ converter.genExprValue (*Fortran::semantics::GetExpr (ifClause->v )));
555
+ ifCond = firOpBuilder.createConvert (currentLocation,
556
+ firOpBuilder.getI1Type (), cond);
557
+ } else if (const auto *asyncClause =
558
+ std::get_if<Fortran::parser::AccClause::Async>(&clause.u )) {
559
+ const auto &asyncClauseValue = asyncClause->v ;
560
+ if (asyncClauseValue) { // async has a value.
561
+ async = fir::getBase (converter.genExprValue (
562
+ *Fortran::semantics::GetExpr (*asyncClauseValue)));
563
+ } else {
564
+ addAsyncAttr = true ;
565
+ }
566
+ } else if (const auto *waitClause =
567
+ std::get_if<Fortran::parser::AccClause::Wait>(&clause.u )) {
568
+ const auto &waitClauseValue = waitClause->v ;
569
+ if (waitClauseValue) { // wait has a value.
570
+ const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
571
+ const std::list<Fortran::parser::ScalarIntExpr> &waitList =
572
+ std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t );
573
+ for (const Fortran::parser::ScalarIntExpr &value : waitList) {
574
+ mlir::Value v = fir::getBase (
575
+ converter.genExprValue (*Fortran::semantics::GetExpr (value)));
576
+ waitOperands.push_back (v);
577
+ }
578
+
579
+ const std::optional<Fortran::parser::ScalarIntExpr> &waitDevnumValue =
580
+ std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t );
581
+ if (waitDevnumValue)
582
+ waitDevnum = fir::getBase (converter.genExprValue (
583
+ *Fortran::semantics::GetExpr (*waitDevnumValue)));
584
+ } else {
585
+ addWaitAttr = true ;
586
+ }
587
+ } else if (const auto *copyinClause =
588
+ std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u )) {
589
+ const Fortran::parser::AccObjectListWithModifier &listWithModifier =
590
+ copyinClause->v ;
591
+ const Fortran::parser::AccObjectList &accObjectList =
592
+ std::get<Fortran::parser::AccObjectList>(listWithModifier.t );
593
+ genObjectList (accObjectList, converter, copyinOperands);
594
+ } else if (const auto *createClause =
595
+ std::get_if<Fortran::parser::AccClause::Create>(&clause.u )) {
596
+ genObjectListWithModifier<Fortran::parser::AccClause::Create>(
597
+ createClause, converter,
598
+ Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands,
599
+ createOperands);
600
+ } else if (const auto *attachClause =
601
+ std::get_if<Fortran::parser::AccClause::Attach>(&clause.u )) {
602
+ genObjectList (attachClause->v , converter, attachOperands);
603
+ } else {
604
+ llvm::report_fatal_error (
605
+ " Unknown clause in ENTER DATA directive lowering" );
606
+ }
607
+ }
608
+
609
+ // Prepare the operand segement size attribute and the operands value range.
610
+ SmallVector<mlir::Value, 16 > operands;
611
+ SmallVector<int32_t , 8 > operandSegments;
612
+ addOperand (operands, operandSegments, ifCond);
613
+ addOperand (operands, operandSegments, async);
614
+ addOperand (operands, operandSegments, waitDevnum);
615
+ addOperands (operands, operandSegments, waitOperands);
616
+ addOperands (operands, operandSegments, copyinOperands);
617
+ addOperands (operands, operandSegments, createOperands);
618
+ addOperands (operands, operandSegments, createZeroOperands);
619
+ addOperands (operands, operandSegments, attachOperands);
620
+
621
+ auto enterDataOp = createSimpleOp<mlir::acc::EnterDataOp>(
622
+ firOpBuilder, currentLocation, operands, operandSegments);
623
+
624
+ if (addAsyncAttr)
625
+ enterDataOp.asyncAttr (firOpBuilder.getUnitAttr ());
626
+ if (addWaitAttr)
627
+ enterDataOp.waitAttr (firOpBuilder.getUnitAttr ());
628
+ }
629
+
531
630
static void
532
631
genACCExitDataOp (Fortran::lower::AbstractConverter &converter,
533
632
const Fortran::parser::AccClauseList &accClauseList) {
@@ -605,8 +704,8 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
605
704
}
606
705
607
706
// Prepare the operand segement size attribute and the operands value range.
608
- SmallVector<Value, 8 > operands;
609
- SmallVector<int32_t , 8 > operandSegments;
707
+ SmallVector<mlir:: Value, 14 > operands;
708
+ SmallVector<int32_t , 7 > operandSegments;
610
709
addOperand (operands, operandSegments, ifCond);
611
710
addOperand (operands, operandSegments, async);
612
711
addOperand (operands, operandSegments, waitDevnum);
@@ -636,7 +735,7 @@ genACC(Fortran::lower::AbstractConverter &converter,
636
735
std::get<Fortran::parser::AccClauseList>(standaloneConstruct.t );
637
736
638
737
if (standaloneDirective.v == llvm::acc::Directive::ACCD_enter_data) {
639
- TODO ( " OpenACC enter data directive not lowered yet! " );
738
+ genACCEnterDataOp (converter, accClauseList );
640
739
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_exit_data) {
641
740
genACCExitDataOp (converter, accClauseList);
642
741
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_init) {
0 commit comments