Skip to content

Commit b4b6569

Browse files
committed
[flang][OpenMP] Add basic support to lower loop to MLIR
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`
1 parent d74127e commit b4b6569

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,
@@ -2051,6 +2063,40 @@ static void genStandaloneDo(lower::AbstractConverter &converter,
20512063
llvm::omp::Directive::OMPD_do, dsp);
20522064
}
20532065

2066+
static void genLoopOp(lower::AbstractConverter &converter,
2067+
lower::SymMap &symTable,
2068+
semantics::SemanticsContext &semaCtx,
2069+
lower::pft::Evaluation &eval, mlir::Location loc,
2070+
const ConstructQueue &queue,
2071+
ConstructQueue::const_iterator item) {
2072+
mlir::omp::LoopOperands loopClauseOps;
2073+
llvm::SmallVector<const semantics::Symbol *> loopReductionSyms;
2074+
genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps,
2075+
loopReductionSyms);
2076+
2077+
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
2078+
/*shouldCollectPreDeterminedSymbols=*/true,
2079+
/*useDelayedPrivatization=*/true, &symTable);
2080+
dsp.processStep1(&loopClauseOps);
2081+
2082+
mlir::omp::LoopNestOperands loopNestClauseOps;
2083+
llvm::SmallVector<const semantics::Symbol *> iv;
2084+
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
2085+
loopNestClauseOps, iv);
2086+
2087+
EntryBlockArgs loopArgs;
2088+
loopArgs.priv.syms = dsp.getDelayedPrivSymbols();
2089+
loopArgs.priv.vars = loopClauseOps.privateVars;
2090+
loopArgs.reduction.syms = loopReductionSyms;
2091+
loopArgs.reduction.vars = loopClauseOps.reductionVars;
2092+
2093+
auto loopOp =
2094+
genWrapperOp<mlir::omp::LoopOp>(converter, loc, loopClauseOps, loopArgs);
2095+
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
2096+
loopNestClauseOps, iv, {{loopOp, loopArgs}},
2097+
llvm::omp::Directive::OMPD_loop, dsp);
2098+
}
2099+
20542100
static void genStandaloneParallel(lower::AbstractConverter &converter,
20552101
lower::SymMap &symTable,
20562102
semantics::SemanticsContext &semaCtx,
@@ -2479,7 +2525,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
24792525
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item);
24802526
break;
24812527
case llvm::omp::Directive::OMPD_loop:
2482-
TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
2528+
genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item);
24832529
break;
24842530
case llvm::omp::Directive::OMPD_masked:
24852531
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: 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: 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: 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: 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
@@ -1952,6 +1952,17 @@ LogicalResult LoopWrapperInterface::verifyImpl() {
19521952
// LoopOp
19531953
//===----------------------------------------------------------------------===//
19541954

1955+
void LoopOp::build(OpBuilder &builder, OperationState &state,
1956+
const LoopOperands &clauses) {
1957+
MLIRContext *ctx = builder.getContext();
1958+
1959+
LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
1960+
makeArrayAttr(ctx, clauses.privateSyms), clauses.order,
1961+
clauses.orderMod, clauses.reductionVars,
1962+
makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
1963+
makeArrayAttr(ctx, clauses.reductionSyms));
1964+
}
1965+
19551966
LogicalResult LoopOp::verify() {
19561967
return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
19571968
getReductionByref());

0 commit comments

Comments
 (0)