| //===- 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); |
| } |