1875074c8SKiran Chandramohan //===- OpenMPToLLVM.cpp - conversion from OpenMP to LLVM dialect ----------===//
2875074c8SKiran Chandramohan //
3875074c8SKiran Chandramohan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4875074c8SKiran Chandramohan // See https://llvm.org/LICENSE.txt for license information.
5875074c8SKiran Chandramohan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6875074c8SKiran Chandramohan //
7875074c8SKiran Chandramohan //===----------------------------------------------------------------------===//
8875074c8SKiran Chandramohan 
9875074c8SKiran Chandramohan #include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
10875074c8SKiran Chandramohan 
11875074c8SKiran Chandramohan #include "../PassDetail.h"
12*a54f4eaeSMogball #include "mlir/Conversion/ArithmeticToLLVM/ArithmeticToLLVM.h"
1375e5f0aaSAlex Zinenko #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
14684dfe8aSAlex Zinenko #include "mlir/Conversion/LLVMCommon/Pattern.h"
1575e5f0aaSAlex Zinenko #include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h"
16875074c8SKiran Chandramohan #include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
17684dfe8aSAlex Zinenko #include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
18875074c8SKiran Chandramohan #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
19875074c8SKiran Chandramohan #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
20875074c8SKiran Chandramohan 
21875074c8SKiran Chandramohan using namespace mlir;
22875074c8SKiran Chandramohan 
23875074c8SKiran Chandramohan namespace {
24f7d033f4SAlex Zinenko /// A pattern that converts the region arguments in a single-region OpenMP
25f7d033f4SAlex Zinenko /// operation to the LLVM dialect. The body of the region is not modified and is
26f7d033f4SAlex Zinenko /// expected to either be processed by the conversion infrastructure or already
27f7d033f4SAlex Zinenko /// contain ops compatible with LLVM dialect types.
28f7d033f4SAlex Zinenko template <typename OpType>
29563879b6SRahul Joshi struct RegionOpConversion : public ConvertOpToLLVMPattern<OpType> {
30563879b6SRahul Joshi   using ConvertOpToLLVMPattern<OpType>::ConvertOpToLLVMPattern;
31875074c8SKiran Chandramohan 
32875074c8SKiran Chandramohan   LogicalResult
33ef976337SRiver Riddle   matchAndRewrite(OpType curOp, typename OpType::Adaptor adaptor,
34875074c8SKiran Chandramohan                   ConversionPatternRewriter &rewriter) const override {
35ef976337SRiver Riddle     auto newOp = rewriter.create<OpType>(
36ef976337SRiver Riddle         curOp.getLoc(), TypeRange(), adaptor.getOperands(), curOp->getAttrs());
37875074c8SKiran Chandramohan     rewriter.inlineRegionBefore(curOp.region(), newOp.region(),
38875074c8SKiran Chandramohan                                 newOp.region().end());
39563879b6SRahul Joshi     if (failed(rewriter.convertRegionTypes(&newOp.region(),
40563879b6SRahul Joshi                                            *this->getTypeConverter())))
41875074c8SKiran Chandramohan       return failure();
42875074c8SKiran Chandramohan 
43563879b6SRahul Joshi     rewriter.eraseOp(curOp);
44875074c8SKiran Chandramohan     return success();
45875074c8SKiran Chandramohan   }
46875074c8SKiran Chandramohan };
47875074c8SKiran Chandramohan } // namespace
48875074c8SKiran Chandramohan 
49dc4e913bSChris Lattner void mlir::populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter,
50dc4e913bSChris Lattner                                                   RewritePatternSet &patterns) {
51187d9f8cSKiran Chandramohan   patterns.add<RegionOpConversion<omp::MasterOp>,
52187d9f8cSKiran Chandramohan                RegionOpConversion<omp::ParallelOp>,
53563879b6SRahul Joshi                RegionOpConversion<omp::WsLoopOp>>(converter);
54875074c8SKiran Chandramohan }
55875074c8SKiran Chandramohan 
56875074c8SKiran Chandramohan namespace {
57875074c8SKiran Chandramohan struct ConvertOpenMPToLLVMPass
58875074c8SKiran Chandramohan     : public ConvertOpenMPToLLVMBase<ConvertOpenMPToLLVMPass> {
59875074c8SKiran Chandramohan   void runOnOperation() override;
60875074c8SKiran Chandramohan };
61875074c8SKiran Chandramohan } // namespace
62875074c8SKiran Chandramohan 
63875074c8SKiran Chandramohan void ConvertOpenMPToLLVMPass::runOnOperation() {
64875074c8SKiran Chandramohan   auto module = getOperation();
65875074c8SKiran Chandramohan 
66875074c8SKiran Chandramohan   // Convert to OpenMP operations with LLVM IR dialect
67dc4e913bSChris Lattner   RewritePatternSet patterns(&getContext());
68875074c8SKiran Chandramohan   LLVMTypeConverter converter(&getContext());
69*a54f4eaeSMogball   mlir::arith::populateArithmeticToLLVMConversionPatterns(converter, patterns);
7075e5f0aaSAlex Zinenko   populateMemRefToLLVMConversionPatterns(converter, patterns);
71875074c8SKiran Chandramohan   populateStdToLLVMConversionPatterns(converter, patterns);
72563879b6SRahul Joshi   populateOpenMPToLLVMConversionPatterns(converter, patterns);
73875074c8SKiran Chandramohan 
74875074c8SKiran Chandramohan   LLVMConversionTarget target(getContext());
75187d9f8cSKiran Chandramohan   target.addDynamicallyLegalOp<omp::MasterOp, omp::ParallelOp, omp::WsLoopOp>(
76f7d033f4SAlex Zinenko       [&](Operation *op) { return converter.isLegal(&op->getRegion(0)); });
77875074c8SKiran Chandramohan   target.addLegalOp<omp::TerminatorOp, omp::TaskyieldOp, omp::FlushOp,
78875074c8SKiran Chandramohan                     omp::BarrierOp, omp::TaskwaitOp>();
793fffffa8SRiver Riddle   if (failed(applyPartialConversion(module, target, std::move(patterns))))
80875074c8SKiran Chandramohan     signalPassFailure();
81875074c8SKiran Chandramohan }
82875074c8SKiran Chandramohan 
83875074c8SKiran Chandramohan std::unique_ptr<OperationPass<ModuleOp>> mlir::createConvertOpenMPToLLVMPass() {
84875074c8SKiran Chandramohan   return std::make_unique<ConvertOpenMPToLLVMPass>();
85875074c8SKiran Chandramohan }
86