blob: cebf6cd8ed0dfaecfb9c93474cb4acd973457f10 [file] [log] [blame]
//===- DoConcurrentConversion.cpp -- map `DO CONCURRENT` to OpenMP loops --===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/OpenMP/Passes.h"
#include "flang/Optimizer/OpenMP/Utils.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
#include "mlir/Transforms/DialectConversion.h"
namespace flangomp {
#define GEN_PASS_DEF_DOCONCURRENTCONVERSIONPASS
#include "flang/Optimizer/OpenMP/Passes.h.inc"
} // namespace flangomp
#define DEBUG_TYPE "do-concurrent-conversion"
#define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE << "]: ")
namespace {
class DoConcurrentConversion : public mlir::OpConversionPattern<fir::DoLoopOp> {
public:
using mlir::OpConversionPattern<fir::DoLoopOp>::OpConversionPattern;
DoConcurrentConversion(mlir::MLIRContext *context, bool mapToDevice)
: OpConversionPattern(context), mapToDevice(mapToDevice) {}
mlir::LogicalResult
matchAndRewrite(fir::DoLoopOp doLoop, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
// TODO This will be filled in with the next PRs that upstreams the rest of
// the ROCm implementaion.
return mlir::success();
}
bool mapToDevice;
};
class DoConcurrentConversionPass
: public flangomp::impl::DoConcurrentConversionPassBase<
DoConcurrentConversionPass> {
public:
DoConcurrentConversionPass() = default;
DoConcurrentConversionPass(
const flangomp::DoConcurrentConversionPassOptions &options)
: DoConcurrentConversionPassBase(options) {}
void runOnOperation() override {
mlir::func::FuncOp func = getOperation();
if (func.isDeclaration())
return;
mlir::MLIRContext *context = &getContext();
if (mapTo != flangomp::DoConcurrentMappingKind::DCMK_Host &&
mapTo != flangomp::DoConcurrentMappingKind::DCMK_Device) {
mlir::emitWarning(mlir::UnknownLoc::get(context),
"DoConcurrentConversionPass: invalid `map-to` value. "
"Valid values are: `host` or `device`");
return;
}
mlir::RewritePatternSet patterns(context);
patterns.insert<DoConcurrentConversion>(
context, mapTo == flangomp::DoConcurrentMappingKind::DCMK_Device);
mlir::ConversionTarget target(*context);
target.addDynamicallyLegalOp<fir::DoLoopOp>([&](fir::DoLoopOp op) {
// The goal is to handle constructs that eventually get lowered to
// `fir.do_loop` with the `unordered` attribute (e.g. array expressions).
// Currently, this is only enabled for the `do concurrent` construct since
// the pass runs early in the pipeline.
return !op.getUnordered();
});
target.markUnknownOpDynamicallyLegal(
[](mlir::Operation *) { return true; });
if (mlir::failed(mlir::applyFullConversion(getOperation(), target,
std::move(patterns)))) {
mlir::emitError(mlir::UnknownLoc::get(context),
"error in converting do-concurrent op");
signalPassFailure();
}
}
};
} // namespace
std::unique_ptr<mlir::Pass>
flangomp::createDoConcurrentConversionPass(bool mapToDevice) {
DoConcurrentConversionPassOptions options;
options.mapTo = mapToDevice ? flangomp::DoConcurrentMappingKind::DCMK_Device
: flangomp::DoConcurrentMappingKind::DCMK_Host;
return std::make_unique<DoConcurrentConversionPass>(options);
}