Skip to content

Commit 3babce1

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 0d8cbe4 commit 3babce1

File tree

6 files changed

+146
-17
lines changed

6 files changed

+146
-17
lines changed

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,52 @@ static void genStandaloneDo(lower::AbstractConverter &converter,
20342034
llvm::omp::Directive::OMPD_do, dsp);
20352035
}
20362036

2037+
static void genLoopClauses(
2038+
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
2039+
const List<Clause> &clauses, mlir::Location loc,
2040+
mlir::omp::LoopOperands &clauseOps,
2041+
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
2042+
ClauseProcessor cp(converter, semaCtx, clauses);
2043+
cp.processOrder(clauseOps);
2044+
cp.processReduction(loc, clauseOps, reductionSyms);
2045+
cp.processTODO<clause::Bind, clause::Lastprivate>(
2046+
loc, llvm::omp::Directive::OMPD_loop);
2047+
}
2048+
2049+
static void genLoopOp(lower::AbstractConverter &converter,
2050+
lower::SymMap &symTable,
2051+
semantics::SemanticsContext &semaCtx,
2052+
lower::pft::Evaluation &eval, mlir::Location loc,
2053+
const ConstructQueue &queue,
2054+
ConstructQueue::const_iterator item) {
2055+
mlir::omp::LoopOperands loopClauseOps;
2056+
llvm::SmallVector<const semantics::Symbol *> loopReductionSyms;
2057+
genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps,
2058+
loopReductionSyms);
2059+
2060+
DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
2061+
/*shouldCollectPreDeterminedSymbols=*/true,
2062+
/*useDelayedPrivatization=*/true, &symTable);
2063+
dsp.processStep1(&loopClauseOps);
2064+
2065+
mlir::omp::LoopNestOperands loopNestClauseOps;
2066+
llvm::SmallVector<const semantics::Symbol *> iv;
2067+
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
2068+
loopNestClauseOps, iv);
2069+
2070+
EntryBlockArgs loopArgs;
2071+
loopArgs.priv.syms = dsp.getDelayedPrivSymbols();
2072+
loopArgs.priv.vars = loopClauseOps.privateVars;
2073+
loopArgs.reduction.syms = loopReductionSyms;
2074+
loopArgs.reduction.vars = loopClauseOps.reductionVars;
2075+
2076+
auto loopOp =
2077+
genWrapperOp<mlir::omp::LoopOp>(converter, loc, loopClauseOps, loopArgs);
2078+
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
2079+
loopNestClauseOps, iv, {{loopOp, loopArgs}},
2080+
llvm::omp::Directive::OMPD_loop, dsp);
2081+
}
2082+
20372083
static void genStandaloneParallel(lower::AbstractConverter &converter,
20382084
lower::SymMap &symTable,
20392085
semantics::SemanticsContext &semaCtx,
@@ -2470,7 +2516,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
24702516
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item);
24712517
break;
24722518
case llvm::omp::Directive::OMPD_loop:
2473-
TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
2519+
genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item);
24742520
break;
24752521
case llvm::omp::Directive::OMPD_masked:
24762522
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: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
47+
! CHECK: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
48+
! CHECK: }
49+
! CHECK: }
50+
!$omp loop private(dummy)
51+
do i=1,10
52+
dummy = dummy + 1
53+
end do
54+
!$omp end loop
55+
end subroutine
56+
57+
58+
! CHECK-LABEL: func.func @_QPtest_order
59+
subroutine test_order()
60+
integer :: i, dummy = 1
61+
! CHECK: omp.loop order(reproducible:concurrent) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
62+
! CHECK: }
63+
!$omp loop order(concurrent)
64+
do i=1,10
65+
dummy = dummy + 1
66+
end do
67+
!$omp end loop
68+
end subroutine
69+
70+
! CHECK-LABEL: func.func @_QPtest_reduction
71+
subroutine test_reduction()
72+
integer :: i, dummy = 1
73+
74+
! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}} : !{{.*}}) reduction
75+
! CHECK-SAME: (@[[RED]] %{{.*}}#0 -> %{{.*}} : !{{.*}}) {
76+
! CHECK: }
77+
!$omp loop reduction(+:dummy)
78+
do i=1,10
79+
dummy = dummy + 1
80+
end do
81+
!$omp end loop
82+
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ void mlir::configureOpenMPToLLVMConversionLegality(
238238
omp::ParallelOp, omp::PrivateClauseOp, omp::SectionOp, omp::SectionsOp,
239239
omp::SimdOp, omp::SingleOp, omp::TargetDataOp, omp::TargetOp,
240240
omp::TaskgroupOp, omp::TaskloopOp, omp::TaskOp, omp::TeamsOp,
241-
omp::WsloopOp>([&](Operation *op) {
241+
omp::WsloopOp, omp::LoopOp>([&](Operation *op) {
242242
return std::all_of(op->getRegions().begin(), op->getRegions().end(),
243243
[&](Region &region) {
244244
return typeConverter.isLegal(&region);
@@ -284,6 +284,7 @@ void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter,
284284
RegionOpConversion<omp::TargetOp>, RegionOpConversion<omp::TaskgroupOp>,
285285
RegionOpConversion<omp::TaskloopOp>, RegionOpConversion<omp::TaskOp>,
286286
RegionOpConversion<omp::TeamsOp>, RegionOpConversion<omp::WsloopOp>,
287+
RegionOpConversion<omp::LoopOp>,
287288
RegionOpWithVarOperandsConversion<omp::AtomicUpdateOp>>(converter);
288289
}
289290

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)