@@ -452,6 +452,145 @@ genOMP(Fortran::lower::AbstractConverter &converter,
452452 }
453453}
454454
455+ static void genOmpAtomicHintAndMemoryOrderClauses (
456+ Fortran::lower::AbstractConverter &converter,
457+ const Fortran::parser::OmpAtomicClauseList &clauseList,
458+ mlir::IntegerAttr &hint,
459+ mlir::omp::ClauseMemoryOrderKindAttr &memory_order) {
460+ auto &firOpBuilder = converter.getFirOpBuilder ();
461+ for (const auto &clause : clauseList.v ) {
462+ if (auto ompClause = std::get_if<Fortran::parser::OmpClause>(&clause.u )) {
463+ if (auto hintClause =
464+ std::get_if<Fortran::parser::OmpClause::Hint>(&ompClause->u )) {
465+ const auto *expr = Fortran::semantics::GetExpr (hintClause->v );
466+ uint64_t hintExprValue = *Fortran::evaluate::ToInt64 (*expr);
467+ hint = firOpBuilder.getI64IntegerAttr (hintExprValue);
468+ }
469+ } else if (auto ompMemoryOrderClause =
470+ std::get_if<Fortran::parser::OmpMemoryOrderClause>(
471+ &clause.u )) {
472+ if (std::get_if<Fortran::parser::OmpClause::Acquire>(
473+ &ompMemoryOrderClause->v .u )) {
474+ memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get (
475+ firOpBuilder.getContext (), omp::ClauseMemoryOrderKind::Acquire);
476+ } else if (std::get_if<Fortran::parser::OmpClause::Relaxed>(
477+ &ompMemoryOrderClause->v .u )) {
478+ memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get (
479+ firOpBuilder.getContext (), omp::ClauseMemoryOrderKind::Relaxed);
480+ } else if (std::get_if<Fortran::parser::OmpClause::SeqCst>(
481+ &ompMemoryOrderClause->v .u )) {
482+ memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get (
483+ firOpBuilder.getContext (), omp::ClauseMemoryOrderKind::Seq_cst);
484+ } else if (std::get_if<Fortran::parser::OmpClause::Release>(
485+ &ompMemoryOrderClause->v .u )) {
486+ memory_order = mlir::omp::ClauseMemoryOrderKindAttr::get (
487+ firOpBuilder.getContext (), omp::ClauseMemoryOrderKind::Release);
488+ }
489+ }
490+ }
491+ }
492+
493+ static void
494+ genOmpAtomicWrite (Fortran::lower::AbstractConverter &converter,
495+ Fortran::lower::pft::Evaluation &eval,
496+ const Fortran::parser::OmpAtomicWrite &atomicWrite) {
497+ auto &firOpBuilder = converter.getFirOpBuilder ();
498+ auto currentLocation = converter.getCurrentLocation ();
499+ mlir::Value address;
500+ // If no hint clause is specified, the effect is as if
501+ // hint(omp_sync_hint_none) had been specified.
502+ mlir::IntegerAttr hint = nullptr ;
503+ mlir::omp::ClauseMemoryOrderKindAttr memory_order = nullptr ;
504+ const Fortran::parser::OmpAtomicClauseList &rightHandClauseList =
505+ std::get<2 >(atomicWrite.t );
506+ const Fortran::parser::OmpAtomicClauseList &leftHandClauseList =
507+ std::get<0 >(atomicWrite.t );
508+ const auto &assignmentStmtExpr =
509+ std::get<Fortran::parser::Expr>(std::get<3 >(atomicWrite.t ).statement .t );
510+ const auto &assignmentStmtVariable = std::get<Fortran::parser::Variable>(
511+ std::get<3 >(atomicWrite.t ).statement .t );
512+ Fortran::lower::StatementContext stmtCtx;
513+ auto value = fir::getBase (converter.genExprValue (
514+ *Fortran::semantics::GetExpr (assignmentStmtExpr), stmtCtx));
515+ if (auto varDesignator = std::get_if<
516+ Fortran::common::Indirection<Fortran::parser::Designator>>(
517+ &assignmentStmtVariable.u )) {
518+ if (const auto *name = getDesignatorNameIfDataRef (varDesignator->value ())) {
519+ address = converter.getSymbolAddress (*name->symbol );
520+ }
521+ }
522+
523+ genOmpAtomicHintAndMemoryOrderClauses (converter, leftHandClauseList, hint,
524+ memory_order);
525+ genOmpAtomicHintAndMemoryOrderClauses (converter, rightHandClauseList, hint,
526+ memory_order);
527+ firOpBuilder.create <mlir::omp::AtomicWriteOp>(currentLocation, address, value,
528+ hint, memory_order);
529+ }
530+
531+ static void genOmpAtomicRead (Fortran::lower::AbstractConverter &converter,
532+ Fortran::lower::pft::Evaluation &eval,
533+ const Fortran::parser::OmpAtomicRead &atomicRead) {
534+ auto &firOpBuilder = converter.getFirOpBuilder ();
535+ auto currentLocation = converter.getCurrentLocation ();
536+ mlir::Value to_address;
537+ mlir::Value from_address;
538+ // If no hint clause is specified, the effect is as if
539+ // hint(omp_sync_hint_none) had been specified.
540+ mlir::IntegerAttr hint = nullptr ;
541+ mlir::omp::ClauseMemoryOrderKindAttr memory_order = nullptr ;
542+ const Fortran::parser::OmpAtomicClauseList &rightHandClauseList =
543+ std::get<2 >(atomicRead.t );
544+ const Fortran::parser::OmpAtomicClauseList &leftHandClauseList =
545+ std::get<0 >(atomicRead.t );
546+ const auto &assignmentStmtExpr =
547+ std::get<Fortran::parser::Expr>(std::get<3 >(atomicRead.t ).statement .t );
548+ const auto &assignmentStmtVariable = std::get<Fortran::parser::Variable>(
549+ std::get<3 >(atomicRead.t ).statement .t );
550+ if (auto exprDesignator = std::get_if<
551+ Fortran::common::Indirection<Fortran::parser::Designator>>(
552+ &assignmentStmtExpr.u )) {
553+ if (const auto *name =
554+ getDesignatorNameIfDataRef (exprDesignator->value ())) {
555+ from_address = converter.getSymbolAddress (*name->symbol );
556+ }
557+ }
558+
559+ if (auto varDesignator = std::get_if<
560+ Fortran::common::Indirection<Fortran::parser::Designator>>(
561+ &assignmentStmtVariable.u )) {
562+ if (const auto *name = getDesignatorNameIfDataRef (varDesignator->value ())) {
563+ to_address = converter.getSymbolAddress (*name->symbol );
564+ }
565+ }
566+
567+ genOmpAtomicHintAndMemoryOrderClauses (converter, leftHandClauseList, hint,
568+ memory_order);
569+ genOmpAtomicHintAndMemoryOrderClauses (converter, rightHandClauseList, hint,
570+ memory_order);
571+ firOpBuilder.create <mlir::omp::AtomicReadOp>(currentLocation, from_address,
572+ to_address, hint, memory_order);
573+ }
574+
575+ static void
576+ genOMP (Fortran::lower::AbstractConverter &converter,
577+ Fortran::lower::pft::Evaluation &eval,
578+ const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
579+ std::visit (Fortran::common::visitors{
580+ [&](const Fortran::parser::OmpAtomicRead &atomicRead) {
581+ genOmpAtomicRead (converter, eval, atomicRead);
582+ },
583+ [&](const Fortran::parser::OmpAtomicWrite &atomicWrite) {
584+ genOmpAtomicWrite (converter, eval, atomicWrite);
585+ },
586+ [&](const auto &) {
587+ TODO (converter.getCurrentLocation (),
588+ " Atomic update & capture" );
589+ },
590+ },
591+ atomicConstruct.u );
592+ }
593+
455594void Fortran::lower::genOpenMPConstruct (
456595 Fortran::lower::AbstractConverter &converter,
457596 Fortran::lower::pft::Evaluation &eval,
@@ -485,7 +624,7 @@ void Fortran::lower::genOpenMPConstruct(
485624 genOMP (converter, eval, blockConstruct);
486625 },
487626 [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
488- TODO (converter. getCurrentLocation (), " OpenMPAtomicConstruct " );
627+ genOMP (converter, eval, atomicConstruct );
489628 },
490629 [&](const Fortran::parser::OpenMPCriticalConstruct
491630 &criticalConstruct) {
0 commit comments