@@ -725,6 +725,85 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
725
725
exitDataOp.finalizeAttr (firOpBuilder.getUnitAttr ());
726
726
}
727
727
728
+ static void
729
+ genACCUpdateOp (Fortran::lower::AbstractConverter &converter,
730
+ const Fortran::parser::AccClauseList &accClauseList) {
731
+ mlir::Value ifCond, async, waitDevnum;
732
+ SmallVector<Value, 2 > hostOperands, deviceOperands, waitOperands;
733
+
734
+ // Async and wait clause have optional values but can be present with
735
+ // no value as well. When there is no value, the op has an attribute to
736
+ // represent the clause.
737
+ bool addAsyncAttr = false ;
738
+ bool addWaitAttr = false ;
739
+ bool addIfPresentAttr = false ;
740
+
741
+ auto &firOpBuilder = converter.getFirOpBuilder ();
742
+ auto currentLocation = converter.getCurrentLocation ();
743
+
744
+ // Lower clauses values mapped to operands.
745
+ // Keep track of each group of operands separatly as clauses can appear
746
+ // more than once.
747
+ for (const auto &clause : accClauseList.v ) {
748
+ if (const auto *asyncClause =
749
+ std::get_if<Fortran::parser::AccClause::Async>(&clause.u )) {
750
+ const auto &asyncClauseValue = asyncClause->v ;
751
+ if (asyncClauseValue) { // async has a value.
752
+ async = fir::getBase (converter.genExprValue (
753
+ *Fortran::semantics::GetExpr (*asyncClauseValue)));
754
+ } else {
755
+ addAsyncAttr = true ;
756
+ }
757
+ } else if (const auto *waitClause =
758
+ std::get_if<Fortran::parser::AccClause::Wait>(&clause.u )) {
759
+ const auto &waitClauseValue = waitClause->v ;
760
+ if (waitClauseValue) { // wait has a value.
761
+ const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
762
+ const std::list<Fortran::parser::ScalarIntExpr> &waitList =
763
+ std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t );
764
+ for (const Fortran::parser::ScalarIntExpr &value : waitList) {
765
+ mlir::Value v = fir::getBase (
766
+ converter.genExprValue (*Fortran::semantics::GetExpr (value)));
767
+ waitOperands.push_back (v);
768
+ }
769
+
770
+ const std::optional<Fortran::parser::ScalarIntExpr> &waitDevnumValue =
771
+ std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t );
772
+ if (waitDevnumValue)
773
+ waitDevnum = fir::getBase (converter.genExprValue (
774
+ *Fortran::semantics::GetExpr (*waitDevnumValue)));
775
+ } else {
776
+ addWaitAttr = true ;
777
+ }
778
+ } else if (const auto *hostClause =
779
+ std::get_if<Fortran::parser::AccClause::Host>(&clause.u )) {
780
+ genObjectList (hostClause->v , converter, hostOperands);
781
+ } else if (const auto *deviceClause =
782
+ std::get_if<Fortran::parser::AccClause::Device>(&clause.u )) {
783
+ genObjectList (deviceClause->v , converter, deviceOperands);
784
+ }
785
+ }
786
+
787
+ // Prepare the operand segement size attribute and the operands value range.
788
+ SmallVector<mlir::Value, 10 > operands;
789
+ SmallVector<int32_t , 5 > operandSegments;
790
+ addOperand (operands, operandSegments, async);
791
+ addOperand (operands, operandSegments, waitDevnum);
792
+ addOperands (operands, operandSegments, waitOperands);
793
+ addOperands (operands, operandSegments, hostOperands);
794
+ addOperands (operands, operandSegments, deviceOperands);
795
+
796
+ auto updateOp = createSimpleOp<mlir::acc::UpdateOp>(
797
+ firOpBuilder, currentLocation, operands, operandSegments);
798
+
799
+ if (addAsyncAttr)
800
+ updateOp.asyncAttr (firOpBuilder.getUnitAttr ());
801
+ if (addWaitAttr)
802
+ updateOp.waitAttr (firOpBuilder.getUnitAttr ());
803
+ if (addIfPresentAttr)
804
+ updateOp.ifPresentAttr (firOpBuilder.getUnitAttr ());
805
+ }
806
+
728
807
static void
729
808
genACC (Fortran::lower::AbstractConverter &converter,
730
809
Fortran::lower::pft::Evaluation &eval,
@@ -745,7 +824,7 @@ genACC(Fortran::lower::AbstractConverter &converter,
745
824
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_set) {
746
825
TODO (" OpenACC set directive not lowered yet!" );
747
826
} else if (standaloneDirective.v == llvm::acc::Directive::ACCD_update) {
748
- TODO ( " OpenACC update directive not lowered yet! " );
827
+ genACCUpdateOp (converter, accClauseList );
749
828
}
750
829
}
751
830
0 commit comments