Skip to content

Commit a716cc0

Browse files
authored
[flang] Support do concurrent ... reduce for associating names (#148597)
Extends reduction support for `do concurrent`, in particular, for associating names. Consider the following input: ```fortran subroutine dc_associate_reduce integer :: i real, allocatable, dimension(:) :: x associate(x_associate => x) do concurrent (i = 1:10) reduce(+: x_associate) end do end associate end subroutine ``` The declaration of `x_associate` is emitted as follows: ```mlir %13:2 = hlfir.declare %10(%12) {uniq_name = "...."} : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>) -> (!fir.box<!fir.array<?xf32>>, !fir.heap<!fir.array<?xf32>>) ``` where the HLFIR base type is an array descriptor (i.e. the allocatable/heap attribute is dropped as stipulated by the spec; section 11.1.3.3). The problem here is that `declare_reduction` ops accept only reference types. This restriction is already partially handled for `fir::BaseBoxType`'s by allocating a stack slot for the descriptor and storing the box in that stack allocation. We have to modify this a littble bit for `associate` since the HLFIR and FIR base types are different (unlike most scenarios).
1 parent 1b4a1a0 commit a716cc0

7 files changed

+48
-13
lines changed

flang/lib/Lower/Support/ReductionProcessor.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -633,13 +633,25 @@ void ReductionProcessor::processReductionArguments(
633633
}
634634
}
635635

636-
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
637-
638636
// Reduction variable processing common to both intrinsic operators and
639637
// procedure designators
640638
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
639+
mlir::OpBuilder::InsertPoint dcIP;
640+
constexpr bool isDoConcurrent =
641+
std::is_same_v<OpType, fir::DeclareReductionOp>;
642+
643+
if (isDoConcurrent) {
644+
dcIP = builder.saveInsertionPoint();
645+
builder.setInsertionPoint(
646+
builder.getRegion().getParentOfType<fir::DoConcurrentOp>());
647+
}
648+
641649
for (const semantics::Symbol *symbol : reductionSymbols) {
642650
mlir::Value symVal = converter.getSymbolAddress(*symbol);
651+
652+
if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>())
653+
symVal = declOp.getBase();
654+
643655
mlir::Type eleType;
644656
auto refType = mlir::dyn_cast_or_null<fir::ReferenceType>(symVal.getType());
645657
if (refType)
@@ -667,13 +679,13 @@ void ReductionProcessor::processReductionArguments(
667679
// boxed arrays are passed as values not by reference. Unfortunately,
668680
// we can't pass a box by value to omp.redution_declare, so turn it
669681
// into a reference
670-
682+
auto oldIP = builder.saveInsertionPoint();
683+
builder.setInsertionPointToStart(builder.getAllocaBlock());
671684
auto alloca =
672685
builder.create<fir::AllocaOp>(currentLocation, symVal.getType());
686+
builder.restoreInsertionPoint(oldIP);
673687
builder.create<fir::StoreOp>(currentLocation, symVal, alloca);
674688
symVal = alloca;
675-
} else if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) {
676-
symVal = declOp.getBase();
677689
}
678690

679691
// this isn't the same as the by-val and by-ref passing later in the
@@ -693,7 +705,7 @@ void ReductionProcessor::processReductionArguments(
693705
unsigned idx = 0;
694706
for (auto [symVal, isByRef] : llvm::zip(reductionVars, reduceVarByRef)) {
695707
auto redType = mlir::cast<fir::ReferenceType>(symVal.getType());
696-
const auto &kindMap = firOpBuilder.getKindMap();
708+
const auto &kindMap = builder.getKindMap();
697709
std::string reductionName;
698710
ReductionIdentifier redId;
699711

@@ -745,9 +757,12 @@ void ReductionProcessor::processReductionArguments(
745757
OpType decl = createDeclareReduction<OpType>(
746758
converter, reductionName, redId, redType, currentLocation, isByRef);
747759
reductionDeclSymbols.push_back(
748-
mlir::SymbolRefAttr::get(firOpBuilder.getContext(), decl.getSymName()));
760+
mlir::SymbolRefAttr::get(builder.getContext(), decl.getSymName()));
749761
++idx;
750762
}
763+
764+
if (isDoConcurrent)
765+
builder.restoreInsertionPoint(dcIP);
751766
}
752767

753768
const semantics::SourceName

flang/test/Lower/OpenMP/parallel-reduction-array-lb.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,14 @@ program reduce
6969
! CHECK: }
7070

7171
! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "reduce"} {
72+
! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.box<!fir.array<3x2xi32>>
7273
! CHECK: %[[VAL_0:.*]] = fir.address_of(@_QFEi) : !fir.ref<!fir.array<3x2xi32>>
7374
! CHECK: %[[VAL_1:.*]] = arith.constant 2 : index
7475
! CHECK: %[[VAL_2:.*]] = arith.constant 3 : index
7576
! CHECK: %[[VAL_3:.*]] = arith.constant 1 : index
7677
! CHECK: %[[VAL_4:.*]] = arith.constant 2 : index
7778
! CHECK: %[[VAL_5:.*]] = fir.shape_shift %[[VAL_1]], %[[VAL_2]], %[[VAL_3]], %[[VAL_4]] : (index, index, index, index) -> !fir.shapeshift<2>
7879
! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_5]]) {uniq_name = "_QFEi"} : (!fir.ref<!fir.array<3x2xi32>>, !fir.shapeshift<2>) -> (!fir.box<!fir.array<3x2xi32>>, !fir.ref<!fir.array<3x2xi32>>)
79-
! CHECK: %[[VAL_7:.*]] = fir.alloca !fir.box<!fir.array<3x2xi32>>
8080
! CHECK: fir.store %[[VAL_6]]#0 to %[[VAL_7]] : !fir.ref<!fir.box<!fir.array<3x2xi32>>>
8181
! CHECK: omp.parallel reduction(byref @add_reduction_byref_box_3x2xi32 %[[VAL_7]] -> %[[VAL_8:.*]] : !fir.ref<!fir.box<!fir.array<3x2xi32>>>) {
8282
! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFEi"} : (!fir.ref<!fir.box<!fir.array<3x2xi32>>>) -> (!fir.ref<!fir.box<!fir.array<3x2xi32>>>, !fir.ref<!fir.box<!fir.array<3x2xi32>>>)

flang/test/Lower/OpenMP/reduction-array-intrinsic.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ subroutine max_array_reduction(l, r)
6464
! CHECK-LABEL: func.func @_QPmax_array_reduction(
6565
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "l"},
6666
! CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xi32>> {fir.bindc_name = "r"}) {
67+
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<?xi32>>
6768
! CHECK: %[[VAL_2:.*]] = fir.dummy_scope : !fir.dscope
6869
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_2]] {uniq_name = "_QFmax_array_reductionEl"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
6970
! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_1]] dummy_scope %[[VAL_2]] {uniq_name = "_QFmax_array_reductionEr"} : (!fir.box<!fir.array<?xi32>>, !fir.dscope) -> (!fir.box<!fir.array<?xi32>>, !fir.box<!fir.array<?xi32>>)
70-
! CHECK: %[[VAL_5:.*]] = fir.alloca !fir.box<!fir.array<?xi32>>
71-
! CHECK: fir.store %[[VAL_3]]#1 to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
71+
! CHECK: fir.store %[[VAL_3]]#0 to %[[VAL_5]] : !fir.ref<!fir.box<!fir.array<?xi32>>>
7272
! CHECK: omp.parallel reduction(byref @max_byref_box_Uxi32 %[[VAL_5]] -> %[[VAL_6:.*]] : !fir.ref<!fir.box<!fir.array<?xi32>>>) {
7373
! CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]] {uniq_name = "_QFmax_array_reductionEl"} : (!fir.ref<!fir.box<!fir.array<?xi32>>>) -> (!fir.ref<!fir.box<!fir.array<?xi32>>>, !fir.ref<!fir.box<!fir.array<?xi32>>>)
7474
! CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]]#0 : !fir.ref<!fir.box<!fir.array<?xi32>>>

flang/test/Lower/OpenMP/sections-array-reduction.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ subroutine sectionsReduction(x)
3434
! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %[[VAL_1]] {uniq_name = "_QFsectionsreductionEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
3535
! CHECK: omp.parallel {
3636
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<?xf32>>
37-
! CHECK: fir.store %[[VAL_2]]#1 to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
37+
! CHECK: fir.store %[[VAL_2]]#0 to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
3838
! CHECK: omp.sections reduction(byref @add_reduction_byref_box_Uxf32 %[[VAL_3]] -> %[[VAL_4:.*]] : !fir.ref<!fir.box<!fir.array<?xf32>>>) {
3939
! CHECK: omp.section {
4040
! CHECK: ^bb0(%[[VAL_5:.*]]: !fir.ref<!fir.box<!fir.array<?xf32>>>):

flang/test/Lower/OpenMP/taskgroup-task-array-reduction.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
! CHECK-SAME: {uniq_name = "_QFtask_reductionEx"} : (!fir.box<!fir.array<?xf32>>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.box<!fir.array<?xf32>>)
2323
! CHECK: omp.parallel {
2424
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.box<!fir.array<?xf32>>
25-
! CHECK: fir.store %[[VAL_2]]#1 to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
25+
! CHECK: fir.store %[[VAL_2]]#0 to %[[VAL_3]] : !fir.ref<!fir.box<!fir.array<?xf32>>>
2626
! CHECK: omp.taskgroup task_reduction(byref @add_reduction_byref_box_Uxf32 %[[VAL_3]] -> %[[VAL_4:.*]]: !fir.ref<!fir.box<!fir.array<?xf32>>>) {
2727
! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_4]]
2828
! CHECK-SAME: {uniq_name = "_QFtask_reductionEx"} : (!fir.ref<!fir.box<!fir.array<?xf32>>>) -> (!fir.ref<!fir.box<!fir.array<?xf32>>>, !fir.ref<!fir.box<!fir.array<?xf32>>>)

flang/test/Lower/OpenMP/wsloop-reduction-array-assumed-shape.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ subroutine reduce(r)
8181
! CHECK: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_0]] dummy_scope %{{[0-9]+}} {fortran_attrs = {{.*}}, uniq_name = "_QFFreduceEr"} : (!fir.box<!fir.array<?xf64>>, !fir.dscope) -> (!fir.box<!fir.array<?xf64>>, !fir.box<!fir.array<?xf64>>)
8282
! CHECK: omp.parallel {
8383
! CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.array<?xf64>>
84-
! CHECK: fir.store %[[VAL_3]]#1 to %[[VAL_4]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
84+
! CHECK: fir.store %[[VAL_3]]#0 to %[[VAL_4]] : !fir.ref<!fir.box<!fir.array<?xf64>>>
8585
! CHECK: %[[VAL_7:.*]] = arith.constant 0 : i32
8686
! CHECK: %[[VAL_8:.*]] = arith.constant 10 : i32
8787
! CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck %s
2+
3+
subroutine dc_associate_reduce
4+
integer :: i
5+
real, allocatable, dimension(:) :: x
6+
7+
associate(x_associate => x)
8+
do concurrent (i = 1:10) reduce(+: x_associate)
9+
end do
10+
end associate
11+
end subroutine
12+
13+
! CHECK-LABEL: func.func @_QPdc_associate_reduce() {
14+
! CHECK: %[[BOX_ALLOC:.*]] = fir.alloca !fir.box<!fir.array<?xf32>>
15+
! CHECK: %[[ASSOC_DECL:.*]]:2 = hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "{{.*}}x_associate"}
16+
! CHECK: fir.store %[[ASSOC_DECL]]#0 to %[[BOX_ALLOC]]
17+
! CHECK-NEXT: fir.do_concurrent {
18+
! CHECK: fir.do_concurrent.loop {{.*}} reduce(byref @{{.*}} #fir.reduce_attr<add> %[[BOX_ALLOC]] -> %{{.*}} : !{{.*}}) {
19+
! CHECK: }
20+
! CHECK: }

0 commit comments

Comments
 (0)