Skip to content

Commit 62ae549

Browse files
[flang][openacc] Add implicit copy for reduction in combined construct (#70148)
After PR#69417, lowering for combined constructs was updated to adhere to OpenACC 3.3, section 2.11: `A private or reduction clause on a combined construct is treated as if it appeared on the loop construct.` However, the second part of that paragraph notes `In addition, a reduction clause on a combined construct implies a copy clause`. Since the acc dialect decomposes combined constructs, it is important to distinguish between the case where an explicit data clause is required (as noted in section 2.6.2) and the case where an implicit data action must be generated by compiler.
1 parent 53705dd commit 62ae549

File tree

5 files changed

+53
-27
lines changed

5 files changed

+53
-27
lines changed

flang/lib/Lower/OpenACC.cpp

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static void genDeclareDataOperandOperationsWithModifier(
336336
template <typename EntryOp, typename ExitOp>
337337
static void genDataExitOperations(fir::FirOpBuilder &builder,
338338
llvm::SmallVector<mlir::Value> operands,
339-
bool structured, bool implicit) {
339+
bool structured) {
340340
for (mlir::Value operand : operands) {
341341
auto entryOp = mlir::dyn_cast_or_null<EntryOp>(operand.getDefiningOp());
342342
assert(entryOp && "data entry op expected");
@@ -346,7 +346,7 @@ static void genDataExitOperations(fir::FirOpBuilder &builder,
346346
varPtr = entryOp.getVarPtr();
347347
builder.create<ExitOp>(entryOp.getLoc(), entryOp.getAccPtr(), varPtr,
348348
entryOp.getBounds(), entryOp.getDataClause(),
349-
structured, implicit,
349+
structured, entryOp.getImplicit(),
350350
builder.getStringAttr(*entryOp.getName()));
351351
}
352352
}
@@ -1872,9 +1872,24 @@ createComputeOp(Fortran::lower::AbstractConverter &converter,
18721872
} else if (const auto *reductionClause =
18731873
std::get_if<Fortran::parser::AccClause::Reduction>(
18741874
&clause.u)) {
1875-
if (!outerCombined)
1875+
// A reduction clause on a combined construct is treated as if it appeared
1876+
// on the loop construct. So don't generate a reduction clause when it is
1877+
// combined - delay it to the loop. However, a reduction clause on a
1878+
// combined construct implies a copy clause so issue an implicit copy
1879+
// instead.
1880+
if (!outerCombined) {
18761881
genReductions(reductionClause->v, converter, semanticsContext, stmtCtx,
18771882
reductionOperands, reductionRecipes);
1883+
} else {
1884+
auto crtDataStart = dataClauseOperands.size();
1885+
genDataOperandOperations<mlir::acc::CopyinOp>(
1886+
std::get<Fortran::parser::AccObjectList>(reductionClause->v.t),
1887+
converter, semanticsContext, stmtCtx, dataClauseOperands,
1888+
mlir::acc::DataClause::acc_reduction,
1889+
/*structured=*/true, /*implicit=*/true);
1890+
copyEntryOperands.append(dataClauseOperands.begin() + crtDataStart,
1891+
dataClauseOperands.end());
1892+
}
18781893
} else if (const auto *defaultClause =
18791894
std::get_if<Fortran::parser::AccClause::Default>(
18801895
&clause.u)) {
@@ -1944,13 +1959,13 @@ createComputeOp(Fortran::lower::AbstractConverter &converter,
19441959

19451960
// Create the exit operations after the region.
19461961
genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
1947-
builder, copyEntryOperands, /*structured=*/true, /*implicit=*/false);
1962+
builder, copyEntryOperands, /*structured=*/true);
19481963
genDataExitOperations<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
1949-
builder, copyoutEntryOperands, /*structured=*/true, /*implicit=*/false);
1964+
builder, copyoutEntryOperands, /*structured=*/true);
19501965
genDataExitOperations<mlir::acc::AttachOp, mlir::acc::DetachOp>(
1951-
builder, attachEntryOperands, /*structured=*/true, /*implicit=*/false);
1966+
builder, attachEntryOperands, /*structured=*/true);
19521967
genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
1953-
builder, createEntryOperands, /*structured=*/true, /*implicit=*/false);
1968+
builder, createEntryOperands, /*structured=*/true);
19541969

19551970
builder.restoreInsertionPoint(insPt);
19561971
return computeOp;
@@ -2099,13 +2114,13 @@ static void genACCDataOp(Fortran::lower::AbstractConverter &converter,
20992114

21002115
// Create the exit operations after the region.
21012116
genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
2102-
builder, copyEntryOperands, /*structured=*/true, /*implicit=*/false);
2117+
builder, copyEntryOperands, /*structured=*/true);
21032118
genDataExitOperations<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
2104-
builder, copyoutEntryOperands, /*structured=*/true, /*implicit=*/false);
2119+
builder, copyoutEntryOperands, /*structured=*/true);
21052120
genDataExitOperations<mlir::acc::AttachOp, mlir::acc::DetachOp>(
2106-
builder, attachEntryOperands, /*structured=*/true, /*implicit=*/false);
2121+
builder, attachEntryOperands, /*structured=*/true);
21072122
genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
2108-
builder, createEntryOperands, /*structured=*/true, /*implicit=*/false);
2123+
builder, createEntryOperands, /*structured=*/true);
21092124

21102125
builder.restoreInsertionPoint(insPt);
21112126
}
@@ -2415,11 +2430,11 @@ genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
24152430
exitDataOp.setFinalizeAttr(builder.getUnitAttr());
24162431

24172432
genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::CopyoutOp>(
2418-
builder, copyoutOperands, /*structured=*/false, /*implicit=*/false);
2433+
builder, copyoutOperands, /*structured=*/false);
24192434
genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::DeleteOp>(
2420-
builder, deleteOperands, /*structured=*/false, /*implicit=*/false);
2435+
builder, deleteOperands, /*structured=*/false);
24212436
genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::DetachOp>(
2422-
builder, detachOperands, /*structured=*/false, /*implicit=*/false);
2437+
builder, detachOperands, /*structured=*/false);
24232438
}
24242439

24252440
template <typename Op>
@@ -2594,7 +2609,7 @@ genACCUpdateOp(Fortran::lower::AbstractConverter &converter,
25942609
builder, currentLocation, operands, operandSegments);
25952610

25962611
genDataExitOperations<mlir::acc::GetDevicePtrOp, mlir::acc::UpdateHostOp>(
2597-
builder, updateHostOperands, /*structured=*/false, /*implicit=*/false);
2612+
builder, updateHostOperands, /*structured=*/false);
25982613

25992614
if (addAsyncAttr)
26002615
updateOp.setAsyncAttr(builder.getUnitAttr());
@@ -3054,17 +3069,14 @@ genDeclareInFunction(Fortran::lower::AbstractConverter &converter,
30543069
builder.setInsertionPointAfter(declareOp);
30553070
}
30563071
genDataExitOperations<mlir::acc::CreateOp, mlir::acc::DeleteOp>(
3057-
builder, createEntryOperands, /*structured=*/true,
3058-
/*implicit=*/false);
3072+
builder, createEntryOperands, /*structured=*/true);
30593073
genDataExitOperations<mlir::acc::DeclareDeviceResidentOp,
30603074
mlir::acc::DeleteOp>(
3061-
builder, deviceResidentEntryOperands, /*structured=*/true,
3062-
/*implicit=*/false);
3075+
builder, deviceResidentEntryOperands, /*structured=*/true);
30633076
genDataExitOperations<mlir::acc::CopyinOp, mlir::acc::CopyoutOp>(
3064-
builder, copyEntryOperands, /*structured=*/true, /*implicit=*/false);
3077+
builder, copyEntryOperands, /*structured=*/true);
30653078
genDataExitOperations<mlir::acc::CreateOp, mlir::acc::CopyoutOp>(
3066-
builder, copyoutEntryOperands, /*structured=*/true,
3067-
/*implicit=*/false);
3079+
builder, copyoutEntryOperands, /*structured=*/true);
30683080
});
30693081
}
30703082

flang/test/Lower/OpenACC/acc-kernels-loop.f90

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,12 +751,16 @@ subroutine acc_kernels_loop
751751
reduction_i = 1
752752
end do
753753

754-
! CHECK: acc.kernels {
754+
! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"}
755+
! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"}
756+
! CHECK: acc.kernels dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) {
755757
! CHECK: acc.loop reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {
756758
! CHECK: fir.do_loop
757759
! CHECK: acc.yield
758760
! CHECK-NEXT: }{{$}}
759761
! CHECK: acc.terminator
760762
! CHECK-NEXT: }{{$}}
763+
! CHECK: acc.copyout accPtr(%[[COPYINREDR]] : !fir.ref<f32>) to varPtr(%{{.*}} : !fir.ref<f32>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"}
764+
! CHECK: acc.copyout accPtr(%[[COPYINREDI]] : !fir.ref<i32>) to varPtr(%{{.*}} : !fir.ref<i32>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"}
761765

762766
end subroutine

flang/test/Lower/OpenACC/acc-parallel-loop.f90

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,13 +770,17 @@ subroutine acc_parallel_loop
770770
reduction_i = 1
771771
end do
772772

773-
! CHECK: acc.parallel {
773+
! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"}
774+
! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"}
775+
! CHECK: acc.parallel dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) {
774776
! CHECK: acc.loop reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {
775777
! CHECK: fir.do_loop
776778
! CHECK: acc.yield
777779
! CHECK-NEXT: }{{$}}
778780
! CHECK: acc.yield
779781
! CHECK-NEXT: }{{$}}
782+
! CHECK: acc.copyout accPtr(%[[COPYINREDR]] : !fir.ref<f32>) to varPtr(%{{.*}} : !fir.ref<f32>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"}
783+
! CHECK: acc.copyout accPtr(%[[COPYINREDI]] : !fir.ref<i32>) to varPtr(%{{.*}} : !fir.ref<i32>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"}
780784

781785
!$acc parallel loop
782786
do 10 i=0, n

flang/test/Lower/OpenACC/acc-serial-loop.f90

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,12 +705,16 @@ subroutine acc_serial_loop
705705
reduction_i = 1
706706
end do
707707

708-
! CHECK: acc.serial {
708+
! CHECK: %[[COPYINREDR:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<f32>) -> !fir.ref<f32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"}
709+
! CHECK: %[[COPYINREDI:.*]] = acc.copyin varPtr(%{{.*}} : !fir.ref<i32>) -> !fir.ref<i32> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"}
710+
! CHECK: acc.serial dataOperands(%[[COPYINREDR]], %[[COPYINREDI]] : !fir.ref<f32>, !fir.ref<i32>) {
709711
! CHECK: acc.loop reduction(@reduction_add_ref_f32 -> %{{.*}} : !fir.ref<f32>, @reduction_mul_ref_i32 -> %{{.*}} : !fir.ref<i32>) {
710712
! CHECK: fir.do_loop
711713
! CHECK: acc.yield
712714
! CHECK-NEXT: }{{$}}
713715
! CHECK: acc.yield
714716
! CHECK-NEXT: }{{$}}
717+
! CHECK: acc.copyout accPtr(%[[COPYINREDR]] : !fir.ref<f32>) to varPtr(%{{.*}} : !fir.ref<f32>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_r"}
718+
! CHECK: acc.copyout accPtr(%[[COPYINREDI]] : !fir.ref<i32>) to varPtr(%{{.*}} : !fir.ref<i32>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "reduction_i"}
715719

716720
end subroutine acc_serial_loop

mlir/lib/Dialect/OpenACC/IR/OpenACC.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ LogicalResult acc::CopyinOp::verify() {
131131
// Test for all clauses this operation can be decomposed from:
132132
if (!getImplicit() && getDataClause() != acc::DataClause::acc_copyin &&
133133
getDataClause() != acc::DataClause::acc_copyin_readonly &&
134-
getDataClause() != acc::DataClause::acc_copy)
134+
getDataClause() != acc::DataClause::acc_copy &&
135+
getDataClause() != acc::DataClause::acc_reduction)
135136
return emitError(
136137
"data clause associated with copyin operation must match its intent"
137138
" or specify original clause this operation was decomposed from");
@@ -212,7 +213,8 @@ LogicalResult acc::CopyoutOp::verify() {
212213
// Test for all clauses this operation can be decomposed from:
213214
if (getDataClause() != acc::DataClause::acc_copyout &&
214215
getDataClause() != acc::DataClause::acc_copyout_zero &&
215-
getDataClause() != acc::DataClause::acc_copy)
216+
getDataClause() != acc::DataClause::acc_copy &&
217+
getDataClause() != acc::DataClause::acc_reduction)
216218
return emitError(
217219
"data clause associated with copyout operation must match its intent"
218220
" or specify original clause this operation was decomposed from");

0 commit comments

Comments
 (0)