MLIR 22.0.0git
OpenMPToLLVM.cpp
Go to the documentation of this file.
1//===- OpenMPToLLVM.cpp - conversion from OpenMP to LLVM dialect ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
20#include "mlir/Pass/Pass.h"
21
22namespace mlir {
23#define GEN_PASS_DEF_CONVERTOPENMPTOLLVMPASS
24#include "mlir/Conversion/Passes.h.inc"
25} // namespace mlir
26
27using namespace mlir;
28
29namespace {
30
31/// A pattern that converts the result and operand types, attributes, and region
32/// arguments of an OpenMP operation to the LLVM dialect.
33///
34/// Attributes are copied verbatim by default, and only translated if they are
35/// type attributes.
36///
37/// Region bodies, if any, are not modified and expected to either be processed
38/// by the conversion infrastructure or already contain ops compatible with LLVM
39/// dialect types.
40template <typename T>
41struct OpenMPOpConversion : public ConvertOpToLLVMPattern<T> {
42 using ConvertOpToLLVMPattern<T>::ConvertOpToLLVMPattern;
43
44 OpenMPOpConversion(LLVMTypeConverter &typeConverter,
45 PatternBenefit benefit = 1)
46 : ConvertOpToLLVMPattern<T>(typeConverter, benefit) {
47 // Operations using CanonicalLoopInfoType are lowered only by
48 // mlir::translateModuleToLLVMIR() using the OpenMPIRBuilder. Until then,
49 // the type and operations using it must be preserved.
50 typeConverter.addConversion(
51 [&](::mlir::omp::CanonicalLoopInfoType type) { return type; });
52 }
53
54 LogicalResult
55 matchAndRewrite(T op, typename T::Adaptor adaptor,
56 ConversionPatternRewriter &rewriter) const override {
57 // Translate result types.
58 const TypeConverter *converter = ConvertToLLVMPattern::getTypeConverter();
59 SmallVector<Type> resTypes;
60 if (failed(converter->convertTypes(op->getResultTypes(), resTypes)))
61 return failure();
62
63 // Translate type attributes.
64 // They are kept unmodified except if they are type attributes.
65 SmallVector<NamedAttribute> convertedAttrs;
66 for (NamedAttribute attr : op->getAttrs()) {
67 if (auto typeAttr = dyn_cast<TypeAttr>(attr.getValue())) {
68 Type convertedType = converter->convertType(typeAttr.getValue());
69 convertedAttrs.emplace_back(attr.getName(),
70 TypeAttr::get(convertedType));
71 } else {
72 convertedAttrs.push_back(attr);
73 }
74 }
75
76 // Translate operands.
77 SmallVector<Value> convertedOperands;
78 convertedOperands.reserve(op->getNumOperands());
79 for (auto [originalOperand, convertedOperand] :
80 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
81 if (!originalOperand)
82 return failure();
83
84 // TODO: Revisit whether we need to trigger an error specifically for this
85 // set of operations. Consider removing this check or updating the list.
86 if constexpr (llvm::is_one_of<T, omp::AtomicUpdateOp, omp::AtomicWriteOp,
87 omp::FlushOp, omp::MapBoundsOp,
88 omp::ThreadprivateOp>::value) {
89 if (isa<MemRefType>(originalOperand.getType())) {
90 // TODO: Support memref type in variable operands
91 return rewriter.notifyMatchFailure(op, "memref is not supported yet");
92 }
93 }
94 convertedOperands.push_back(convertedOperand);
95 }
96
97 // Create new operation.
98 auto newOp = T::create(rewriter, op.getLoc(), resTypes, convertedOperands,
99 convertedAttrs);
100
101 // Translate regions.
102 for (auto [originalRegion, convertedRegion] :
103 llvm::zip_equal(op->getRegions(), newOp->getRegions())) {
104 rewriter.inlineRegionBefore(originalRegion, convertedRegion,
105 convertedRegion.end());
106 if (failed(rewriter.convertRegionTypes(&convertedRegion,
107 *this->getTypeConverter())))
108 return failure();
109 }
110
111 // Delete old operation and replace result uses with those of the new one.
112 rewriter.replaceOp(op, newOp->getResults());
113 return success();
114 }
115};
116
117} // namespace
118
120 ConversionTarget &target, const LLVMTypeConverter &typeConverter) {
121 target.addDynamicallyLegalOp<
122#define GET_OP_LIST
123#include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
124 >([&](Operation *op) {
125 return typeConverter.isLegal(op->getOperandTypes()) &&
126 typeConverter.isLegal(op->getResultTypes()) &&
127 llvm::all_of(op->getRegions(),
128 [&](Region &region) {
129 return typeConverter.isLegal(&region);
130 }) &&
131 llvm::all_of(op->getAttrs(), [&](NamedAttribute attr) {
132 auto typeAttr = dyn_cast<TypeAttr>(attr.getValue());
133 return !typeAttr || typeConverter.isLegal(typeAttr.getValue());
134 });
135 });
136}
137
138/// Add an `OpenMPOpConversion<T>` conversion pattern for each operation type
139/// passed as template argument.
140template <typename... Ts>
141static inline RewritePatternSet &
144 return patterns.add<OpenMPOpConversion<Ts>...>(converter);
145}
146
149 // This type is allowed when converting OpenMP to LLVM Dialect, it carries
150 // bounds information for map clauses and the operation and type are
151 // discarded on lowering to LLVM-IR from the OpenMP dialect.
152 converter.addConversion(
153 [&](omp::MapBoundsType type) -> Type { return type; });
154
155 // Add conversions for all OpenMP operations.
157#define GET_OP_LIST
158#include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
159 >(converter, patterns);
160}
161
162namespace {
163struct ConvertOpenMPToLLVMPass
164 : public impl::ConvertOpenMPToLLVMPassBase<ConvertOpenMPToLLVMPass> {
165 using Base::Base;
166
167 void runOnOperation() override;
168};
169} // namespace
170
171void ConvertOpenMPToLLVMPass::runOnOperation() {
172 auto module = getOperation();
173
174 // Convert to OpenMP operations with LLVM IR dialect
175 RewritePatternSet patterns(&getContext());
176 LLVMTypeConverter converter(&getContext());
177 arith::populateArithToLLVMConversionPatterns(converter, patterns);
183
184 LLVMConversionTarget target(getContext());
185 target.addLegalOp<omp::BarrierOp, omp::FlushOp, omp::TaskwaitOp,
186 omp::TaskyieldOp, omp::TerminatorOp>();
188 if (failed(applyPartialConversion(module, target, std::move(patterns))))
189 signalPassFailure();
190}
191
192//===----------------------------------------------------------------------===//
193// ConvertToLLVMPatternInterface implementation
194//===----------------------------------------------------------------------===//
195namespace {
196/// Implement the interface to convert OpenMP to LLVM.
197struct OpenMPToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
199 void loadDependentDialects(MLIRContext *context) const final {
200 context->loadDialect<LLVM::LLVMDialect>();
201 }
202
203 /// Hook for derived dialect interface to provide conversion patterns
204 /// and mark dialect legal for the conversion target.
205 void populateConvertToLLVMConversionPatterns(
206 ConversionTarget &target, LLVMTypeConverter &typeConverter,
207 RewritePatternSet &patterns) const final {
210 }
211};
212} // namespace
213
215 registry.addExtension(+[](MLIRContext *ctx, omp::OpenMPDialect *dialect) {
216 dialect->addInterfaces<OpenMPToLLVMDialectInterface>();
217 });
218}
return success()
b getContext())
static RewritePatternSet & addOpenMPOpConversions(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Add an OpenMPOpConversion<T> conversion pattern for each operation type passed as template argument.
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
Definition Pattern.h:207
ConvertToLLVMPatternInterface(Dialect *dialect)
const LLVMTypeConverter * getTypeConverter() const
Definition Pattern.cpp:27
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Conversion from types to the LLVM IR dialect.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
void populateControlFlowToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns)
Collect the patterns to convert from the ControlFlow dialect to LLVM.
void populateAssertToLLVMConversionPattern(const LLVMTypeConverter &converter, RewritePatternSet &patterns, bool abortOnFailure=true, SymbolTableCollection *symbolTables=nullptr)
Populate the cf.assert to LLVM conversion pattern.
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:561
Include the generated interface declarations.
void populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Populate the given list with patterns that convert from OpenMP to LLVM.
void populateFuncToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect the patterns to convert from the Func dialect to LLVM.
void populateFinalizeMemRefToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns, SymbolTableCollection *symbolTables=nullptr)
Collect a set of patterns to convert memory-related operations from the MemRef dialect to the LLVM di...
const FrozenRewritePatternSet & patterns
void registerConvertOpenMPToLLVMInterface(DialectRegistry &registry)
Registers the ConvertToLLVMPatternInterface interface in the OpenMP dialect.
void configureOpenMPToLLVMConversionLegality(ConversionTarget &target, const LLVMTypeConverter &typeConverter)
Configure dynamic conversion legality of regionless operations from OpenMP to LLVM.