@@ -416,7 +416,8 @@ static inline void genAtomicUpdateStatement(
416416    Fortran::lower::AbstractConverter &converter, mlir::Value lhsAddr,
417417    mlir::Type varType, const  Fortran::parser::Variable &assignmentStmtVariable,
418418    const  Fortran::parser::Expr &assignmentStmtExpr, mlir::Location loc,
419-     mlir::Operation *atomicCaptureOp = nullptr ) {
419+     mlir::Operation *atomicCaptureOp = nullptr ,
420+     Fortran::lower::StatementContext *atomicCaptureStmtCtx = nullptr ) {
420421  //  Generate `atomic.update` operation for atomic assignment statements
421422  fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
422423  mlir::Location currentLocation = converter.getCurrentLocation ();
@@ -496,15 +497,24 @@ static inline void genAtomicUpdateStatement(
496497      },
497498      assignmentStmtExpr.u );
498499  Fortran::lower::StatementContext nonAtomicStmtCtx;
500+   Fortran::lower::StatementContext *stmtCtxPtr = &nonAtomicStmtCtx;
499501  if  (!nonAtomicSubExprs.empty ()) {
500502    //  Generate non atomic part before all the atomic operations.
501503    auto  insertionPoint = firOpBuilder.saveInsertionPoint ();
502-     if  (atomicCaptureOp)
504+     if  (atomicCaptureOp) {
505+       assert (atomicCaptureStmtCtx && " must specify statement context"  );
503506      firOpBuilder.setInsertionPoint (atomicCaptureOp);
507+       //  Any clean-ups associated with the expression lowering
508+       //  must also be generated outside of the atomic update operation
509+       //  and after the atomic capture operation.
510+       //  The atomicCaptureStmtCtx will be finalized at the end
511+       //  of the atomic capture operation generation.
512+       stmtCtxPtr = atomicCaptureStmtCtx;
513+     }
504514    mlir::Value nonAtomicVal;
505515    for  (auto  *nonAtomicSubExpr : nonAtomicSubExprs) {
506516      nonAtomicVal = fir::getBase (converter.genExprValue (
507-           currentLocation, *nonAtomicSubExpr, nonAtomicStmtCtx ));
517+           currentLocation, *nonAtomicSubExpr, *stmtCtxPtr ));
508518      exprValueOverrides.try_emplace (nonAtomicSubExpr, nonAtomicVal);
509519    }
510520    if  (atomicCaptureOp)
@@ -652,7 +662,7 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter,
652662      genAtomicCaptureStatement (converter, stmt2LHSArg, stmt1LHSArg,
653663                                elementType, loc);
654664      genAtomicUpdateStatement (converter, stmt2LHSArg, stmt2VarType, stmt2Var,
655-                                stmt2Expr, loc, atomicCaptureOp);
665+                                stmt2Expr, loc, atomicCaptureOp, &stmtCtx );
656666    } else  {
657667      //  Atomic capture construct is of the form [capture-stmt, write-stmt]
658668      firOpBuilder.setInsertionPoint (atomicCaptureOp);
@@ -672,13 +682,15 @@ void genAtomicCapture(Fortran::lower::AbstractConverter &converter,
672682        *Fortran::semantics::GetExpr (stmt2Expr);
673683    mlir::Type elementType = converter.genType (fromExpr);
674684    genAtomicUpdateStatement (converter, stmt1LHSArg, stmt1VarType, stmt1Var,
675-                              stmt1Expr, loc, atomicCaptureOp);
685+                              stmt1Expr, loc, atomicCaptureOp, &stmtCtx );
676686    genAtomicCaptureStatement (converter, stmt1LHSArg, stmt2LHSArg, elementType,
677687                              loc);
678688  }
679689  firOpBuilder.setInsertionPointToEnd (&block);
680690  firOpBuilder.create <mlir::acc::TerminatorOp>(loc);
681-   firOpBuilder.setInsertionPointToStart (&block);
691+   //  The clean-ups associated with the statements inside the capture
692+   //  construct must be generated after the AtomicCaptureOp.
693+   firOpBuilder.setInsertionPointAfter (atomicCaptureOp);
682694}
683695
684696template  <typename  Op>
0 commit comments