Skip to content

Commit fd3ff20

Browse files
authored
[flang][OpenMP] Add basic support to lower loop directive to MLIR (#114199)
Adds initial support for lowering the `loop` directive to MLIR. The PR includes basic suport and testing for the following clauses: * `collapse` * `order` * `private` * `reduction` Parent PR: #113911, only the latest commit is relevant to this PR.
1 parent 1c4f335 commit fd3ff20

File tree

6 files changed

+159
-23
lines changed

6 files changed

+159
-23
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,6 +1176,18 @@ genLoopNestClauses(lower::AbstractConverter &converter,
11761176
clauseOps.loopInclusive = converter.getFirOpBuilder().getUnitAttr();
11771177
}
11781178

1179+
static void genLoopClauses(
1180+
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
1181+
const List<Clause> &clauses, mlir::Location loc,
1182+
mlir::omp::LoopOperands &clauseOps,
1183+
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
1184+
ClauseProcessor cp(converter, semaCtx, clauses);
1185+
cp.processOrder(clauseOps);
1186+
cp.processReduction(loc, clauseOps, reductionSyms);
1187+
cp.processTODO<clause::Bind, clause::Lastprivate>(
1188+
loc, llvm::omp::Directive::OMPD_loop);
1189+
}
1190+
11791191
static void genMaskedClauses(lower::AbstractConverter &converter,
11801192
semantics::SemanticsContext &semaCtx,
11811193
lower::StatementContext &stmtCtx,
@@ -1473,6 +1485,40 @@ static mlir::omp::LoopNestOp genLoopNestOp(
14731485
queue, item, clauseOps);
14741486
}
14751487

1488+
static void genLoopOp(lower::AbstractConverter &converter,
1489+
lower::SymMap &symTable,
1490+
semantics::SemanticsContext &semaCtx,
1491+
lower::pft::Evaluation &eval, mlir::Location loc,
1492+
const ConstructQueue &queue,
1493+
ConstructQueue::const_iterator item) {
1494+
mlir::omp::LoopOperands loopClauseOps;
1495+
llvm::SmallVector<const semantics::Symbol *> loopReductionSyms;
1496+
genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps,
1497+
loopReductionSyms);
1498+
1499+
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
1500+
/*shouldCollectPreDeterminedSymbols=*/true,
1501+
/*useDelayedPrivatization=*/true, &symTable);
1502+
dsp.processStep1(&loopClauseOps);
1503+
1504+
mlir::omp::LoopNestOperands loopNestClauseOps;
1505+
llvm::SmallVector<const semantics::Symbol *> iv;
1506+
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
1507+
loopNestClauseOps, iv);
1508+
1509+
EntryBlockArgs loopArgs;
1510+
loopArgs.priv.syms = dsp.getDelayedPrivSymbols();
1511+
loopArgs.priv.vars = loopClauseOps.privateVars;
1512+
loopArgs.reduction.syms = loopReductionSyms;
1513+
loopArgs.reduction.vars = loopClauseOps.reductionVars;
1514+
1515+
auto loopOp =
1516+
genWrapperOp<mlir::omp::LoopOp>(converter, loc, loopClauseOps, loopArgs);
1517+
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
1518+
loopNestClauseOps, iv, {{loopOp, loopArgs}},
1519+
llvm::omp::Directive::OMPD_loop, dsp);
1520+
}
1521+
14761522
static mlir::omp::MaskedOp
14771523
genMaskedOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
14781524
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
@@ -2505,7 +2551,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
25052551
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item);
25062552
break;
25072553
case llvm::omp::Directive::OMPD_loop:
2508-
TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
2554+
genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item);
25092555
break;
25102556
case llvm::omp::Directive::OMPD_masked:
25112557
genMaskedOp(converter, symTable, semaCtx, eval, loc, queue, item);

flang/test/Lower/OpenMP/Todo/loop-directive.f90

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
! This test checks lowering of OpenMP loop Directive.
2+
3+
! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
4+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
5+
6+
! CHECK: omp.declare_reduction @[[RED:add_reduction_i32]] : i32
7+
! CHECK: omp.private {type = private} @[[DUMMY_PRIV:.*test_privateEdummy_private.*]] : !fir.ref<i32>
8+
! CHECK: omp.private {type = private} @[[I_PRIV:.*test_no_clausesEi.*]] : !fir.ref<i32>
9+
10+
! CHECK-LABEL: func.func @_QPtest_no_clauses
11+
subroutine test_no_clauses()
12+
integer :: i, j, dummy = 1
13+
14+
! CHECK: omp.loop private(@[[I_PRIV]] %{{.*}}#0 -> %[[ARG:.*]] : !fir.ref<i32>) {
15+
! CHECK-NEXT: omp.loop_nest (%[[IV:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
16+
! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]]
17+
! CHECK: fir.store %[[IV]] to %[[ARG_DECL]]#1 : !fir.ref<i32>
18+
! CHECK: }
19+
! CHECK: }
20+
!$omp loop
21+
do i=1,10
22+
dummy = dummy + 1
23+
end do
24+
!$omp end loop
25+
end subroutine
26+
27+
! CHECK-LABEL: func.func @_QPtest_collapse
28+
subroutine test_collapse()
29+
integer :: i, j, dummy = 1
30+
! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
31+
! CHECK-NEXT: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 {{.*}} {
32+
! CHECK: }
33+
! CHECK: }
34+
!$omp loop collapse(2)
35+
do i=1,10
36+
do j=2,20
37+
dummy = dummy + 1
38+
end do
39+
end do
40+
!$omp end loop
41+
end subroutine
42+
43+
! CHECK-LABEL: func.func @_QPtest_private
44+
subroutine test_private()
45+
integer :: i, dummy = 1
46+
! CHECK: omp.loop private(@[[DUMMY_PRIV]] %{{.*}}#0 -> %[[DUMMY_ARG:.*]], @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
47+
! CHECK-NEXT: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
48+
! CHECK: %[[DUMMY_DECL:.*]]:2 = hlfir.declare %[[DUMMY_ARG]] {uniq_name = "_QFtest_privateEdummy"}
49+
! CHECK: %{{.*}} = fir.load %[[DUMMY_DECL]]#0
50+
! CHECK: hlfir.assign %{{.*}} to %[[DUMMY_DECL]]#0
51+
! CHECK: }
52+
! CHECK: }
53+
!$omp loop private(dummy)
54+
do i=1,10
55+
dummy = dummy + 1
56+
end do
57+
!$omp end loop
58+
end subroutine
59+
60+
61+
! CHECK-LABEL: func.func @_QPtest_order
62+
subroutine test_order()
63+
integer :: i, dummy = 1
64+
! CHECK: omp.loop order(reproducible:concurrent) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
65+
! CHECK: }
66+
!$omp loop order(concurrent)
67+
do i=1,10
68+
dummy = dummy + 1
69+
end do
70+
!$omp end loop
71+
end subroutine
72+
73+
! CHECK-LABEL: func.func @_QPtest_reduction
74+
subroutine test_reduction()
75+
integer :: i, dummy = 1
76+
77+
! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}} : !{{.*}}) reduction
78+
! CHECK-SAME: (@[[RED]] %{{.*}}#0 -> %[[DUMMY_ARG:.*]] : !{{.*}}) {
79+
! CHECK-NEXT: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
80+
! CHECK: %[[DUMMY_DECL:.*]]:2 = hlfir.declare %[[DUMMY_ARG]] {uniq_name = "_QFtest_reductionEdummy"}
81+
! CHECK: %{{.*}} = fir.load %[[DUMMY_DECL]]#0
82+
! CHECK: hlfir.assign %{{.*}} to %[[DUMMY_DECL]]#0
83+
! CHECK: }
84+
! CHECK: }
85+
!$omp loop reduction(+:dummy)
86+
do i=1,10
87+
dummy = dummy + 1
88+
end do
89+
!$omp end loop
90+
end subroutine

mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ def LoopOp : OpenMP_Op<"loop", traits = [
422422
$reduction_syms) attr-dict
423423
}];
424424

425+
let builders = [
426+
OpBuilder<(ins CArg<"const LoopOperands &">:$clauses)>
427+
];
428+
425429
let hasVerifier = 1;
426430
let hasRegionVerifier = 1;
427431
}

mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,11 @@ void mlir::configureOpenMPToLLVMConversionLegality(
234234
});
235235
target.addDynamicallyLegalOp<
236236
omp::AtomicUpdateOp, omp::CriticalOp, omp::DeclareReductionOp,
237-
omp::DistributeOp, omp::LoopNestOp, omp::MasterOp, omp::OrderedRegionOp,
238-
omp::ParallelOp, omp::PrivateClauseOp, omp::SectionOp, omp::SectionsOp,
239-
omp::SimdOp, omp::SingleOp, omp::TargetDataOp, omp::TargetOp,
240-
omp::TaskgroupOp, omp::TaskloopOp, omp::TaskOp, omp::TeamsOp,
241-
omp::WsloopOp>([&](Operation *op) {
237+
omp::DistributeOp, omp::LoopNestOp, omp::LoopOp, omp::MasterOp,
238+
omp::OrderedRegionOp, omp::ParallelOp, omp::PrivateClauseOp,
239+
omp::SectionOp, omp::SectionsOp, omp::SimdOp, omp::SingleOp,
240+
omp::TargetDataOp, omp::TargetOp, omp::TaskgroupOp, omp::TaskloopOp,
241+
omp::TaskOp, omp::TeamsOp, omp::WsloopOp>([&](Operation *op) {
242242
return std::all_of(op->getRegions().begin(), op->getRegions().end(),
243243
[&](Region &region) {
244244
return typeConverter.isLegal(&region);
@@ -275,8 +275,8 @@ void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter,
275275
RegionOpConversion<omp::AtomicCaptureOp>,
276276
RegionOpConversion<omp::CriticalOp>,
277277
RegionOpConversion<omp::DistributeOp>,
278-
RegionOpConversion<omp::LoopNestOp>, RegionOpConversion<omp::MaskedOp>,
279-
RegionOpConversion<omp::MasterOp>,
278+
RegionOpConversion<omp::LoopNestOp>, RegionOpConversion<omp::LoopOp>,
279+
RegionOpConversion<omp::MaskedOp>, RegionOpConversion<omp::MasterOp>,
280280
RegionOpConversion<omp::OrderedRegionOp>,
281281
RegionOpConversion<omp::ParallelOp>, RegionOpConversion<omp::SectionOp>,
282282
RegionOpConversion<omp::SectionsOp>, RegionOpConversion<omp::SimdOp>,

mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,6 +1928,17 @@ LogicalResult LoopWrapperInterface::verifyImpl() {
19281928
// LoopOp
19291929
//===----------------------------------------------------------------------===//
19301930

1931+
void LoopOp::build(OpBuilder &builder, OperationState &state,
1932+
const LoopOperands &clauses) {
1933+
MLIRContext *ctx = builder.getContext();
1934+
1935+
LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
1936+
makeArrayAttr(ctx, clauses.privateSyms), clauses.order,
1937+
clauses.orderMod, clauses.reductionVars,
1938+
makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
1939+
makeArrayAttr(ctx, clauses.reductionSyms));
1940+
}
1941+
19311942
LogicalResult LoopOp::verify() {
19321943
return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
19331944
getReductionByref());

0 commit comments

Comments
 (0)