This patch lower `!OMP PARALLEL` construct from PFT to OpenMPDialect operations. This is first patch in this direction(lowering parallel construct). OpenMP parallel construct can have multiple clauses and parameters. This patch only implements lowering of an empty(contains no code in body) parallel construct without any clauses or parameters. Patch is carved out of following approved PR: https://github.com/flang-compiler/f18-llvm-project/pull/322 Reviewed By: kiranchandramohan, DavidTruby Differential Revision: https://reviews.llvm.org/D84965
141 lines
5.3 KiB
C++
141 lines
5.3 KiB
C++
//===-- OpenMP.cpp -- Open MP directive lowering --------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Lower/OpenMP.h"
|
|
#include "flang/Lower/Bridge.h"
|
|
#include "flang/Lower/FIRBuilder.h"
|
|
#include "flang/Lower/PFTBuilder.h"
|
|
#include "flang/Parser/parse-tree.h"
|
|
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
|
|
#include "llvm/Frontend/OpenMP/OMPConstants.h"
|
|
|
|
#define TODO() llvm_unreachable("not yet implemented")
|
|
|
|
static void genOMP(Fortran::lower::AbstractConverter &absConv,
|
|
Fortran::lower::pft::Evaluation &eval,
|
|
const Fortran::parser::OpenMPSimpleStandaloneConstruct
|
|
&simpleStandaloneConstruct) {
|
|
const auto &directive =
|
|
std::get<Fortran::parser::OmpSimpleStandaloneDirective>(
|
|
simpleStandaloneConstruct.t);
|
|
switch (directive.v) {
|
|
default:
|
|
break;
|
|
case llvm::omp::Directive::OMPD_barrier:
|
|
absConv.getFirOpBuilder().create<mlir::omp::BarrierOp>(
|
|
absConv.getCurrentLocation());
|
|
break;
|
|
case llvm::omp::Directive::OMPD_taskwait:
|
|
absConv.getFirOpBuilder().create<mlir::omp::TaskwaitOp>(
|
|
absConv.getCurrentLocation());
|
|
break;
|
|
case llvm::omp::Directive::OMPD_taskyield:
|
|
absConv.getFirOpBuilder().create<mlir::omp::TaskyieldOp>(
|
|
absConv.getCurrentLocation());
|
|
break;
|
|
case llvm::omp::Directive::OMPD_target_enter_data:
|
|
TODO();
|
|
case llvm::omp::Directive::OMPD_target_exit_data:
|
|
TODO();
|
|
case llvm::omp::Directive::OMPD_target_update:
|
|
TODO();
|
|
case llvm::omp::Directive::OMPD_ordered:
|
|
TODO();
|
|
}
|
|
}
|
|
|
|
static void
|
|
genOMP(Fortran::lower::AbstractConverter &absConv,
|
|
Fortran::lower::pft::Evaluation &eval,
|
|
const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) {
|
|
std::visit(
|
|
Fortran::common::visitors{
|
|
[&](const Fortran::parser::OpenMPSimpleStandaloneConstruct
|
|
&simpleStandaloneConstruct) {
|
|
genOMP(absConv, eval, simpleStandaloneConstruct);
|
|
},
|
|
[&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) {
|
|
TODO();
|
|
},
|
|
[&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) {
|
|
TODO();
|
|
},
|
|
[&](const Fortran::parser::OpenMPCancellationPointConstruct
|
|
&cancellationPointConstruct) { TODO(); },
|
|
},
|
|
standaloneConstruct.u);
|
|
}
|
|
|
|
static void
|
|
genOMP(Fortran::lower::AbstractConverter &absConv,
|
|
Fortran::lower::pft::Evaluation &eval,
|
|
const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
|
|
const auto &blockDirective =
|
|
std::get<Fortran::parser::OmpBeginBlockDirective>(blockConstruct.t);
|
|
const auto ¶llelDirective =
|
|
std::get<Fortran::parser::OmpBlockDirective>(blockDirective.t);
|
|
if (parallelDirective.v == llvm::omp::OMPD_parallel) {
|
|
auto &firOpBuilder = absConv.getFirOpBuilder();
|
|
auto currentLocation = absConv.getCurrentLocation();
|
|
auto insertPt = firOpBuilder.saveInsertionPoint();
|
|
llvm::ArrayRef<mlir::Type> argTy;
|
|
mlir::ValueRange range;
|
|
llvm::SmallVector<int32_t, 6> operandSegmentSizes(6 /*Size=*/,
|
|
0 /*Value=*/);
|
|
// create and insert the operation.
|
|
auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>(
|
|
currentLocation, argTy, range);
|
|
parallelOp.setAttr(mlir::omp::ParallelOp::getOperandSegmentSizeAttr(),
|
|
firOpBuilder.getI32VectorAttr(operandSegmentSizes));
|
|
parallelOp.getRegion().push_back(new Block{});
|
|
auto &block = parallelOp.getRegion().back();
|
|
firOpBuilder.setInsertionPointToStart(&block);
|
|
// ensure the block is well-formed.
|
|
firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation);
|
|
firOpBuilder.restoreInsertionPoint(insertPt);
|
|
}
|
|
}
|
|
|
|
void Fortran::lower::genOpenMPConstruct(
|
|
Fortran::lower::AbstractConverter &absConv,
|
|
Fortran::lower::pft::Evaluation &eval,
|
|
const Fortran::parser::OpenMPConstruct &ompConstruct) {
|
|
|
|
std::visit(
|
|
common::visitors{
|
|
[&](const Fortran::parser::OpenMPStandaloneConstruct
|
|
&standaloneConstruct) {
|
|
genOMP(absConv, eval, standaloneConstruct);
|
|
},
|
|
[&](const Fortran::parser::OpenMPSectionsConstruct
|
|
§ionsConstruct) { TODO(); },
|
|
[&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
|
|
TODO();
|
|
},
|
|
[&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
|
|
genOMP(absConv, eval, blockConstruct);
|
|
},
|
|
[&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
|
|
TODO();
|
|
},
|
|
[&](const Fortran::parser::OpenMPCriticalConstruct
|
|
&criticalConstruct) { TODO(); },
|
|
},
|
|
ompConstruct.u);
|
|
}
|
|
|
|
void Fortran::lower::genOpenMPEndLoop(
|
|
Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &,
|
|
const Fortran::parser::OmpEndLoopDirective &) {
|
|
TODO();
|
|
}
|