Skip to content

[flang][OpenMP] Add basic support to lower loop directive to MLIR #114199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,18 @@ genLoopNestClauses(lower::AbstractConverter &converter,
clauseOps.loopInclusive = converter.getFirOpBuilder().getUnitAttr();
}

static void genLoopClauses(
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
const List<Clause> &clauses, mlir::Location loc,
mlir::omp::LoopOperands &clauseOps,
llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSyms) {
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processOrder(clauseOps);
cp.processReduction(loc, clauseOps, reductionSyms);
cp.processTODO<clause::Bind, clause::Lastprivate>(
loc, llvm::omp::Directive::OMPD_loop);
}

static void genMaskedClauses(lower::AbstractConverter &converter,
semantics::SemanticsContext &semaCtx,
lower::StatementContext &stmtCtx,
Expand Down Expand Up @@ -1473,6 +1485,40 @@ static mlir::omp::LoopNestOp genLoopNestOp(
queue, item, clauseOps);
}

static void genLoopOp(lower::AbstractConverter &converter,
lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval, mlir::Location loc,
const ConstructQueue &queue,
ConstructQueue::const_iterator item) {
mlir::omp::LoopOperands loopClauseOps;
llvm::SmallVector<const semantics::Symbol *> loopReductionSyms;
genLoopClauses(converter, semaCtx, item->clauses, loc, loopClauseOps,
loopReductionSyms);

DataSharingProcessor dsp(converter, semaCtx, item->clauses, eval,
/*shouldCollectPreDeterminedSymbols=*/true,
/*useDelayedPrivatization=*/true, &symTable);
dsp.processStep1(&loopClauseOps);

mlir::omp::LoopNestOperands loopNestClauseOps;
llvm::SmallVector<const semantics::Symbol *> iv;
genLoopNestClauses(converter, semaCtx, eval, item->clauses, loc,
loopNestClauseOps, iv);

EntryBlockArgs loopArgs;
loopArgs.priv.syms = dsp.getDelayedPrivSymbols();
loopArgs.priv.vars = loopClauseOps.privateVars;
loopArgs.reduction.syms = loopReductionSyms;
loopArgs.reduction.vars = loopClauseOps.reductionVars;

auto loopOp =
genWrapperOp<mlir::omp::LoopOp>(converter, loc, loopClauseOps, loopArgs);
genLoopNestOp(converter, symTable, semaCtx, eval, loc, queue, item,
loopNestClauseOps, iv, {{loopOp, loopArgs}},
llvm::omp::Directive::OMPD_loop, dsp);
}

static mlir::omp::MaskedOp
genMaskedOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
Expand Down Expand Up @@ -2505,7 +2551,7 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
genStandaloneDo(converter, symTable, semaCtx, eval, loc, queue, item);
break;
case llvm::omp::Directive::OMPD_loop:
TODO(loc, "Unhandled directive " + llvm::omp::getOpenMPDirectiveName(dir));
genLoopOp(converter, symTable, semaCtx, eval, loc, queue, item);
break;
case llvm::omp::Directive::OMPD_masked:
genMaskedOp(converter, symTable, semaCtx, eval, loc, queue, item);
Expand Down
15 changes: 0 additions & 15 deletions flang/test/Lower/OpenMP/Todo/loop-directive.f90

This file was deleted.

90 changes: 90 additions & 0 deletions flang/test/Lower/OpenMP/loop-directive.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
! This test checks lowering of OpenMP loop Directive.

! RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -o - %s 2>&1 | FileCheck %s

! CHECK: omp.declare_reduction @[[RED:add_reduction_i32]] : i32
! CHECK: omp.private {type = private} @[[DUMMY_PRIV:.*test_privateEdummy_private.*]] : !fir.ref<i32>
! CHECK: omp.private {type = private} @[[I_PRIV:.*test_no_clausesEi.*]] : !fir.ref<i32>

! CHECK-LABEL: func.func @_QPtest_no_clauses
subroutine test_no_clauses()
integer :: i, j, dummy = 1

! CHECK: omp.loop private(@[[I_PRIV]] %{{.*}}#0 -> %[[ARG:.*]] : !fir.ref<i32>) {
! CHECK-NEXT: omp.loop_nest (%[[IV:.*]]) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
! CHECK: %[[ARG_DECL:.*]]:2 = hlfir.declare %[[ARG]]
! CHECK: fir.store %[[IV]] to %[[ARG_DECL]]#1 : !fir.ref<i32>
! CHECK: }
! CHECK: }
!$omp loop
do i=1,10
dummy = dummy + 1
end do
!$omp end loop
end subroutine

! CHECK-LABEL: func.func @_QPtest_collapse
subroutine test_collapse()
integer :: i, j, dummy = 1
! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}}, @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK-NEXT: omp.loop_nest (%{{.*}}, %{{.*}}) : i32 {{.*}} {
! CHECK: }
! CHECK: }
!$omp loop collapse(2)
do i=1,10
do j=2,20
dummy = dummy + 1
end do
end do
!$omp end loop
end subroutine

! CHECK-LABEL: func.func @_QPtest_private
subroutine test_private()
integer :: i, dummy = 1
! CHECK: omp.loop private(@[[DUMMY_PRIV]] %{{.*}}#0 -> %[[DUMMY_ARG:.*]], @{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK-NEXT: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
! CHECK: %[[DUMMY_DECL:.*]]:2 = hlfir.declare %[[DUMMY_ARG]] {uniq_name = "_QFtest_privateEdummy"}
! CHECK: %{{.*}} = fir.load %[[DUMMY_DECL]]#0
! CHECK: hlfir.assign %{{.*}} to %[[DUMMY_DECL]]#0
! CHECK: }
! CHECK: }
!$omp loop private(dummy)
do i=1,10
dummy = dummy + 1
end do
!$omp end loop
end subroutine


! CHECK-LABEL: func.func @_QPtest_order
subroutine test_order()
integer :: i, dummy = 1
! CHECK: omp.loop order(reproducible:concurrent) private(@{{.*}} %{{.*}}#0 -> %{{.*}} : {{.*}}) {
! CHECK: }
!$omp loop order(concurrent)
do i=1,10
dummy = dummy + 1
end do
!$omp end loop
end subroutine

! CHECK-LABEL: func.func @_QPtest_reduction
subroutine test_reduction()
integer :: i, dummy = 1

! CHECK: omp.loop private(@{{.*}} %{{.*}}#0 -> %{{.*}} : !{{.*}}) reduction
! CHECK-SAME: (@[[RED]] %{{.*}}#0 -> %[[DUMMY_ARG:.*]] : !{{.*}}) {
! CHECK-NEXT: omp.loop_nest (%{{.*}}) : i32 = (%{{.*}}) to (%{{.*}}) {{.*}} {
! CHECK: %[[DUMMY_DECL:.*]]:2 = hlfir.declare %[[DUMMY_ARG]] {uniq_name = "_QFtest_reductionEdummy"}
! CHECK: %{{.*}} = fir.load %[[DUMMY_DECL]]#0
! CHECK: hlfir.assign %{{.*}} to %[[DUMMY_DECL]]#0
! CHECK: }
! CHECK: }
!$omp loop reduction(+:dummy)
do i=1,10
dummy = dummy + 1
end do
!$omp end loop
end subroutine
4 changes: 4 additions & 0 deletions mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ def LoopOp : OpenMP_Op<"loop", traits = [
$reduction_syms) attr-dict
}];

let builders = [
OpBuilder<(ins CArg<"const LoopOperands &">:$clauses)>
];

let hasVerifier = 1;
let hasRegionVerifier = 1;
}
Expand Down
14 changes: 7 additions & 7 deletions mlir/lib/Conversion/OpenMPToLLVM/OpenMPToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,11 +234,11 @@ void mlir::configureOpenMPToLLVMConversionLegality(
});
target.addDynamicallyLegalOp<
omp::AtomicUpdateOp, omp::CriticalOp, omp::DeclareReductionOp,
omp::DistributeOp, omp::LoopNestOp, omp::MasterOp, omp::OrderedRegionOp,
omp::ParallelOp, omp::PrivateClauseOp, omp::SectionOp, omp::SectionsOp,
omp::SimdOp, omp::SingleOp, omp::TargetDataOp, omp::TargetOp,
omp::TaskgroupOp, omp::TaskloopOp, omp::TaskOp, omp::TeamsOp,
omp::WsloopOp>([&](Operation *op) {
omp::DistributeOp, omp::LoopNestOp, omp::LoopOp, omp::MasterOp,
omp::OrderedRegionOp, omp::ParallelOp, omp::PrivateClauseOp,
omp::SectionOp, omp::SectionsOp, omp::SimdOp, omp::SingleOp,
omp::TargetDataOp, omp::TargetOp, omp::TaskgroupOp, omp::TaskloopOp,
omp::TaskOp, omp::TeamsOp, omp::WsloopOp>([&](Operation *op) {
return std::all_of(op->getRegions().begin(), op->getRegions().end(),
[&](Region &region) {
return typeConverter.isLegal(&region);
Expand Down Expand Up @@ -275,8 +275,8 @@ void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter,
RegionOpConversion<omp::AtomicCaptureOp>,
RegionOpConversion<omp::CriticalOp>,
RegionOpConversion<omp::DistributeOp>,
RegionOpConversion<omp::LoopNestOp>, RegionOpConversion<omp::MaskedOp>,
RegionOpConversion<omp::MasterOp>,
RegionOpConversion<omp::LoopNestOp>, RegionOpConversion<omp::LoopOp>,
RegionOpConversion<omp::MaskedOp>, RegionOpConversion<omp::MasterOp>,
RegionOpConversion<omp::OrderedRegionOp>,
RegionOpConversion<omp::ParallelOp>, RegionOpConversion<omp::SectionOp>,
RegionOpConversion<omp::SectionsOp>, RegionOpConversion<omp::SimdOp>,
Expand Down
11 changes: 11 additions & 0 deletions mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1928,6 +1928,17 @@ LogicalResult LoopWrapperInterface::verifyImpl() {
// LoopOp
//===----------------------------------------------------------------------===//

void LoopOp::build(OpBuilder &builder, OperationState &state,
const LoopOperands &clauses) {
MLIRContext *ctx = builder.getContext();

LoopOp::build(builder, state, clauses.bindKind, clauses.privateVars,
makeArrayAttr(ctx, clauses.privateSyms), clauses.order,
clauses.orderMod, clauses.reductionVars,
makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
makeArrayAttr(ctx, clauses.reductionSyms));
}

LogicalResult LoopOp::verify() {
return verifyReductionVarList(*this, getReductionSyms(), getReductionVars(),
getReductionByref());
Expand Down
Loading