@@ -2673,38 +2673,65 @@ getAtomicMemoryOrder(lower::AbstractConverter &converter,
2673
2673
static mlir::Operation * //
2674
2674
genAtomicRead (lower::AbstractConverter &converter, mlir::Location loc,
2675
2675
lower::StatementContext &stmtCtx, mlir::Value atomAddr,
2676
- const semantics::SomeExpr &atom, const semantics::SomeExpr &expr,
2677
- mlir::IntegerAttr hint,
2676
+ const semantics::SomeExpr &atom,
2677
+ const evaluate::Assignment &assign, mlir::IntegerAttr hint,
2678
2678
mlir::omp::ClauseMemoryOrderKindAttr memOrder,
2679
+ fir::FirOpBuilder::InsertPoint preAt,
2679
2680
fir::FirOpBuilder::InsertPoint atomicAt,
2680
- fir::FirOpBuilder::InsertPoint prepareAt ) {
2681
+ fir::FirOpBuilder::InsertPoint postAt ) {
2681
2682
fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
2682
2683
fir::FirOpBuilder::InsertPoint saved = builder.saveInsertionPoint ();
2683
- builder.restoreInsertionPoint (prepareAt );
2684
+ builder.restoreInsertionPoint (preAt );
2684
2685
2685
- mlir::Value toAddr = fir::getBase (converter.genExprAddr (expr, stmtCtx, &loc));
2686
+ mlir::Value storeAddr =
2687
+ fir::getBase (converter.genExprAddr (assign.lhs , stmtCtx, &loc));
2686
2688
mlir::Type atomType = fir::unwrapRefType (atomAddr.getType ());
2689
+ mlir::Type storeType = fir::unwrapRefType (storeAddr.getType ());
2690
+
2691
+ mlir::Value toAddr = [&]() {
2692
+ if (atomType == storeType)
2693
+ return storeAddr;
2694
+ return builder.createTemporary (loc, atomType, " .tmp.atomval" );
2695
+ }();
2687
2696
2688
2697
builder.restoreInsertionPoint (atomicAt);
2689
2698
mlir::Operation *op = builder.create <mlir::omp::AtomicReadOp>(
2690
2699
loc, atomAddr, toAddr, mlir::TypeAttr::get (atomType), hint, memOrder);
2700
+
2701
+ if (atomType != storeType) {
2702
+ lower::ExprToValueMap overrides;
2703
+ // The READ operation could be a part of UPDATE CAPTURE, so make sure
2704
+ // we don't emit extra code into the body of the atomic op.
2705
+ builder.restoreInsertionPoint (postAt);
2706
+ mlir::Value load = builder.create <fir::LoadOp>(loc, toAddr);
2707
+ overrides.try_emplace (&atom, load);
2708
+
2709
+ converter.overrideExprValues (&overrides);
2710
+ mlir::Value value =
2711
+ fir::getBase (converter.genExprValue (assign.rhs , stmtCtx, &loc));
2712
+ converter.resetExprOverrides ();
2713
+
2714
+ builder.create <fir::StoreOp>(loc, value, storeAddr);
2715
+ }
2691
2716
builder.restoreInsertionPoint (saved);
2692
2717
return op;
2693
2718
}
2694
2719
2695
2720
static mlir::Operation * //
2696
2721
genAtomicWrite (lower::AbstractConverter &converter, mlir::Location loc,
2697
2722
lower::StatementContext &stmtCtx, mlir::Value atomAddr,
2698
- const semantics::SomeExpr &atom, const semantics::SomeExpr &expr,
2699
- mlir::IntegerAttr hint,
2723
+ const semantics::SomeExpr &atom,
2724
+ const evaluate::Assignment &assign, mlir::IntegerAttr hint,
2700
2725
mlir::omp::ClauseMemoryOrderKindAttr memOrder,
2726
+ fir::FirOpBuilder::InsertPoint preAt,
2701
2727
fir::FirOpBuilder::InsertPoint atomicAt,
2702
- fir::FirOpBuilder::InsertPoint prepareAt ) {
2728
+ fir::FirOpBuilder::InsertPoint postAt ) {
2703
2729
fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
2704
2730
fir::FirOpBuilder::InsertPoint saved = builder.saveInsertionPoint ();
2705
- builder.restoreInsertionPoint (prepareAt );
2731
+ builder.restoreInsertionPoint (preAt );
2706
2732
2707
- mlir::Value value = fir::getBase (converter.genExprValue (expr, stmtCtx, &loc));
2733
+ mlir::Value value =
2734
+ fir::getBase (converter.genExprValue (assign.rhs , stmtCtx, &loc));
2708
2735
mlir::Type atomType = fir::unwrapRefType (atomAddr.getType ());
2709
2736
mlir::Value converted = builder.createConvert (loc, atomType, value);
2710
2737
@@ -2719,19 +2746,20 @@ static mlir::Operation *
2719
2746
genAtomicUpdate (lower::AbstractConverter &converter, mlir::Location loc,
2720
2747
lower::StatementContext &stmtCtx, mlir::Value atomAddr,
2721
2748
const semantics::SomeExpr &atom,
2722
- const semantics::SomeExpr &expr , mlir::IntegerAttr hint,
2749
+ const evaluate::Assignment &assign , mlir::IntegerAttr hint,
2723
2750
mlir::omp::ClauseMemoryOrderKindAttr memOrder,
2751
+ fir::FirOpBuilder::InsertPoint preAt,
2724
2752
fir::FirOpBuilder::InsertPoint atomicAt,
2725
- fir::FirOpBuilder::InsertPoint prepareAt ) {
2753
+ fir::FirOpBuilder::InsertPoint postAt ) {
2726
2754
lower::ExprToValueMap overrides;
2727
2755
lower::StatementContext naCtx;
2728
2756
fir::FirOpBuilder &builder = converter.getFirOpBuilder ();
2729
2757
fir::FirOpBuilder::InsertPoint saved = builder.saveInsertionPoint ();
2730
- builder.restoreInsertionPoint (prepareAt );
2758
+ builder.restoreInsertionPoint (preAt );
2731
2759
2732
2760
mlir::Type atomType = fir::unwrapRefType (atomAddr.getType ());
2733
2761
2734
- std::vector<SomeExpr> args{semantics::GetOpenMPTopLevelArguments (expr )};
2762
+ std::vector<SomeExpr> args{semantics::GetOpenMPTopLevelArguments (assign. rhs )};
2735
2763
assert (!args.empty () && " Update operation without arguments" );
2736
2764
for (auto &arg : args) {
2737
2765
if (!semantics::IsSameOrResizeOf (arg, atom)) {
@@ -2751,7 +2779,7 @@ genAtomicUpdate(lower::AbstractConverter &converter, mlir::Location loc,
2751
2779
2752
2780
converter.overrideExprValues (&overrides);
2753
2781
mlir::Value updated =
2754
- fir::getBase (converter.genExprValue (expr , stmtCtx, &loc));
2782
+ fir::getBase (converter.genExprValue (assign. rhs , stmtCtx, &loc));
2755
2783
mlir::Value converted = builder.createConvert (loc, atomType, updated);
2756
2784
builder.create <mlir::omp::YieldOp>(loc, converted);
2757
2785
converter.resetExprOverrides ();
@@ -2764,20 +2792,21 @@ static mlir::Operation *
2764
2792
genAtomicOperation (lower::AbstractConverter &converter, mlir::Location loc,
2765
2793
lower::StatementContext &stmtCtx, int action,
2766
2794
mlir::Value atomAddr, const semantics::SomeExpr &atom,
2767
- const semantics::SomeExpr &expr , mlir::IntegerAttr hint,
2795
+ const evaluate::Assignment &assign , mlir::IntegerAttr hint,
2768
2796
mlir::omp::ClauseMemoryOrderKindAttr memOrder,
2797
+ fir::FirOpBuilder::InsertPoint preAt,
2769
2798
fir::FirOpBuilder::InsertPoint atomicAt,
2770
- fir::FirOpBuilder::InsertPoint prepareAt ) {
2799
+ fir::FirOpBuilder::InsertPoint postAt ) {
2771
2800
switch (action) {
2772
2801
case parser::OpenMPAtomicConstruct::Analysis::Read:
2773
- return genAtomicRead (converter, loc, stmtCtx, atomAddr, atom, expr , hint,
2774
- memOrder, atomicAt, prepareAt );
2802
+ return genAtomicRead (converter, loc, stmtCtx, atomAddr, atom, assign , hint,
2803
+ memOrder, preAt, atomicAt, postAt );
2775
2804
case parser::OpenMPAtomicConstruct::Analysis::Write:
2776
- return genAtomicWrite (converter, loc, stmtCtx, atomAddr, atom, expr , hint,
2777
- memOrder, atomicAt, prepareAt );
2805
+ return genAtomicWrite (converter, loc, stmtCtx, atomAddr, atom, assign , hint,
2806
+ memOrder, preAt, atomicAt, postAt );
2778
2807
case parser::OpenMPAtomicConstruct::Analysis::Update:
2779
- return genAtomicUpdate (converter, loc, stmtCtx, atomAddr, atom, expr, hint ,
2780
- memOrder, atomicAt, prepareAt );
2808
+ return genAtomicUpdate (converter, loc, stmtCtx, atomAddr, atom, assign ,
2809
+ hint, memOrder, preAt, atomicAt, postAt );
2781
2810
default :
2782
2811
return nullptr ;
2783
2812
}
@@ -3724,6 +3753,15 @@ dumpAnalysis(const parser::OpenMPAtomicConstruct::Analysis &analysis) {
3724
3753
}
3725
3754
return " <null>" s;
3726
3755
};
3756
+ auto assignStr = [&](const parser::AssignmentStmt::TypedAssignment &assign) {
3757
+ if (auto *maybe = assign.get (); maybe && maybe->v ) {
3758
+ std::string str;
3759
+ llvm::raw_string_ostream os (str);
3760
+ maybe->v ->AsFortran (os);
3761
+ return str;
3762
+ }
3763
+ return " <null>" s;
3764
+ };
3727
3765
3728
3766
const SomeExpr &atom = *analysis.atom .get ()->v ;
3729
3767
@@ -3732,11 +3770,11 @@ dumpAnalysis(const parser::OpenMPAtomicConstruct::Analysis &analysis) {
3732
3770
llvm::errs () << " cond: " << exprStr (analysis.cond ) << " \n " ;
3733
3771
llvm::errs () << " op0 {\n " ;
3734
3772
llvm::errs () << " what: " << whatStr (analysis.op0 .what ) << " \n " ;
3735
- llvm::errs () << " expr : " << exprStr (analysis.op0 .expr ) << " \n " ;
3773
+ llvm::errs () << " assign : " << assignStr (analysis.op0 .assign ) << " \n " ;
3736
3774
llvm::errs () << " }\n " ;
3737
3775
llvm::errs () << " op1 {\n " ;
3738
3776
llvm::errs () << " what: " << whatStr (analysis.op1 .what ) << " \n " ;
3739
- llvm::errs () << " expr : " << exprStr (analysis.op1 .expr ) << " \n " ;
3777
+ llvm::errs () << " assign : " << assignStr (analysis.op1 .assign ) << " \n " ;
3740
3778
llvm::errs () << " }\n " ;
3741
3779
llvm::errs () << " }\n " ;
3742
3780
}
@@ -3745,8 +3783,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
3745
3783
semantics::SemanticsContext &semaCtx,
3746
3784
lower::pft::Evaluation &eval,
3747
3785
const parser::OpenMPAtomicConstruct &construct) {
3748
- auto get = [](const parser::TypedExpr &expr ) -> const semantics::SomeExpr * {
3749
- if (auto *maybe = expr .get (); maybe && maybe->v ) {
3786
+ auto get = [](auto &&typedWrapper ) -> decltype (&*typedWrapper. get ()-> v ) {
3787
+ if (auto *maybe = typedWrapper .get (); maybe && maybe->v ) {
3750
3788
return &*maybe->v ;
3751
3789
} else {
3752
3790
return nullptr ;
@@ -3774,8 +3812,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
3774
3812
int action0 = analysis.op0 .what & analysis.Action ;
3775
3813
int action1 = analysis.op1 .what & analysis.Action ;
3776
3814
mlir::Operation *captureOp = nullptr ;
3777
- fir::FirOpBuilder::InsertPoint atomicAt ;
3778
- fir::FirOpBuilder::InsertPoint prepareAt = builder. saveInsertionPoint () ;
3815
+ fir::FirOpBuilder::InsertPoint preAt = builder. saveInsertionPoint () ;
3816
+ fir::FirOpBuilder::InsertPoint atomicAt, postAt ;
3779
3817
3780
3818
if (construct.IsCapture ()) {
3781
3819
// Capturing operation.
@@ -3784,35 +3822,36 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
3784
3822
captureOp =
3785
3823
builder.create <mlir::omp::AtomicCaptureOp>(loc, hint, memOrder);
3786
3824
// Set the non-atomic insertion point to before the atomic.capture.
3787
- prepareAt = getInsertionPointBefore (captureOp);
3825
+ preAt = getInsertionPointBefore (captureOp);
3788
3826
3789
3827
mlir::Block *block = builder.createBlock (&captureOp->getRegion (0 ));
3790
3828
builder.setInsertionPointToEnd (block);
3791
3829
// Set the atomic insertion point to before the terminator inside
3792
3830
// atomic.capture.
3793
3831
mlir::Operation *term = builder.create <mlir::omp::TerminatorOp>(loc);
3794
3832
atomicAt = getInsertionPointBefore (term);
3833
+ postAt = getInsertionPointAfter (captureOp);
3795
3834
hint = nullptr ;
3796
3835
memOrder = nullptr ;
3797
3836
} else {
3798
3837
// Non-capturing operation.
3799
3838
assert (action0 != analysis.None && action1 == analysis.None &&
3800
3839
" Expexcing single action" );
3801
3840
assert (!(analysis.op0 .what & analysis.Condition ));
3802
- atomicAt = prepareAt ;
3841
+ postAt = atomicAt = preAt ;
3803
3842
}
3804
3843
3805
3844
mlir::Operation *firstOp = genAtomicOperation (
3806
3845
converter, loc, stmtCtx, analysis.op0 .what , atomAddr, atom,
3807
- *get (analysis.op0 .expr ), hint, memOrder, atomicAt, prepareAt );
3846
+ *get (analysis.op0 .assign ), hint, memOrder, preAt, atomicAt, postAt );
3808
3847
assert (firstOp && " Should have created an atomic operation" );
3809
3848
atomicAt = getInsertionPointAfter (firstOp);
3810
3849
3811
3850
mlir::Operation *secondOp = nullptr ;
3812
3851
if (analysis.op1 .what != analysis.None ) {
3813
3852
secondOp = genAtomicOperation (converter, loc, stmtCtx, analysis.op1 .what ,
3814
- atomAddr, atom, *get (analysis.op1 .expr ),
3815
- hint, memOrder, atomicAt, prepareAt );
3853
+ atomAddr, atom, *get (analysis.op1 .assign ),
3854
+ hint, memOrder, preAt, atomicAt, postAt );
3816
3855
}
3817
3856
3818
3857
if (secondOp) {
0 commit comments