MLIR 24.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
15
16using namespace mlir;
17
18namespace {
19
20static LogicalResult convertTypeAttr(Attribute &attr,
21 const TypeConverter &typeConverter) {
22 auto typeAttr = dyn_cast<TypeAttr>(attr);
23 if (!typeAttr)
24 return success();
25 Type convertedType = typeConverter.convertType(typeAttr.getValue());
26 if (!convertedType)
27 return failure();
28 attr = TypeAttr::get(convertedType);
29 return success();
30}
31
32static bool areTypeAttrsLegal(Operation *op,
33 const TypeConverter &typeConverter) {
34 bool inherentAttrsLegal = true;
35 op->getName().walkInherentAttrs(op, [&](StringRef, Attribute &attr) {
36 if (auto typeAttr = dyn_cast<TypeAttr>(attr))
37 inherentAttrsLegal &= typeConverter.isLegal(typeAttr.getValue());
38 });
39 return inherentAttrsLegal &&
40 llvm::all_of(op->getDiscardableAttrs(), [&](NamedAttribute attr) {
41 auto typeAttr = dyn_cast<TypeAttr>(attr.getValue());
42 return !typeAttr || typeConverter.isLegal(typeAttr.getValue());
43 });
44}
45
46/// A pattern that converts the result and operand types, attributes, and region
47/// arguments of an OpenMP operation to the LLVM dialect.
48///
49/// Attributes are copied verbatim by default, and only translated if they are
50/// type attributes.
51///
52/// Region bodies, if any, are not modified and expected to either be processed
53/// by the conversion infrastructure or already contain ops compatible with LLVM
54/// dialect types.
55template <typename T>
56struct OpenMPOpConversion : public ConvertOpToLLVMPattern<T> {
57 using ConvertOpToLLVMPattern<T>::ConvertOpToLLVMPattern;
58
59 OpenMPOpConversion(LLVMTypeConverter &typeConverter,
60 PatternBenefit benefit = 1)
61 : ConvertOpToLLVMPattern<T>(typeConverter, benefit) {
62 // Operations using CanonicalLoopInfoType are lowered only by
63 // mlir::translateModuleToLLVMIR() using the OpenMPIRBuilder. Until then,
64 // the type and operations using it must be preserved.
65 typeConverter.addConversion(
66 [&](::mlir::omp::CanonicalLoopInfoType type) { return type; });
67 }
68
69 LogicalResult
70 matchAndRewrite(T op, typename T::Adaptor adaptor,
71 ConversionPatternRewriter &rewriter) const override {
72 // Translate result types.
73 const TypeConverter *converter = ConvertToLLVMPattern::getTypeConverter();
74 SmallVector<Type> resTypes;
75 if (failed(converter->convertTypes(op->getResultTypes(), resTypes)))
76 return failure();
77
78 // Translate type attributes in the properties and discardable attributes.
79 // They are kept unmodified except if they are type attributes.
80 typename T::Properties convertedProperties = op.getProperties();
81 LogicalResult attrConversionResult = success();
82 T::walkInherentAttrs(
83 op.getContext(), convertedProperties, [&](StringRef, Attribute &attr) {
84 if (succeeded(attrConversionResult))
85 attrConversionResult = convertTypeAttr(attr, *converter);
86 });
87 if (failed(attrConversionResult))
88 return rewriter.notifyMatchFailure(op,
89 "failed to convert type in attribute");
90
91 SmallVector<NamedAttribute> convertedDiscardableAttrs;
92 for (NamedAttribute attr : op->getDiscardableAttrs()) {
93 Attribute convertedAttr = attr.getValue();
94 if (failed(convertTypeAttr(convertedAttr, *converter)))
95 return rewriter.notifyMatchFailure(
96 op, "failed to convert type in attribute");
97 convertedDiscardableAttrs.emplace_back(attr.getName(), convertedAttr);
98 }
99
100 // Translate operands.
101 SmallVector<Value> convertedOperands;
102 convertedOperands.reserve(op->getNumOperands());
103 for (auto [originalOperand, convertedOperand] :
104 llvm::zip_equal(op->getOperands(), adaptor.getOperands())) {
105 if (!originalOperand)
106 return failure();
107
108 // TODO: Revisit whether we need to trigger an error specifically for this
109 // set of operations. Consider removing this check or updating the list.
110 if constexpr (llvm::is_one_of<T, omp::AtomicUpdateOp, omp::AtomicWriteOp,
111 omp::FlushOp, omp::MapBoundsOp,
112 omp::ThreadprivateOp>::value) {
113 if (isa<MemRefType>(originalOperand.getType())) {
114 // TODO: Support memref type in variable operands
115 return rewriter.notifyMatchFailure(op, "memref is not supported yet");
116 }
117 }
118 convertedOperands.push_back(convertedOperand);
119 }
120
121 // Create new operation.
122 auto newOp = T::create(rewriter, op.getLoc(), resTypes, convertedOperands,
123 convertedProperties, convertedDiscardableAttrs);
124
125 // Translate regions.
126 for (auto [originalRegion, convertedRegion] :
127 llvm::zip_equal(op->getRegions(), newOp->getRegions())) {
128 rewriter.inlineRegionBefore(originalRegion, convertedRegion,
129 convertedRegion.end());
130 if (failed(rewriter.convertRegionTypes(&convertedRegion,
131 *this->getTypeConverter())))
132 return failure();
133 }
134
135 // Delete old operation and replace result uses with those of the new one.
136 rewriter.replaceOp(op, newOp->getResults());
137 return success();
138 }
139};
140
141} // namespace
142
144 ConversionTarget &target, const LLVMTypeConverter &typeConverter) {
145 target.addDynamicallyLegalOp<
146#define GET_OP_LIST
147#include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
148 >([&](Operation *op) {
149 return typeConverter.isLegal(op->getOperandTypes()) &&
150 typeConverter.isLegal(op->getResultTypes()) &&
151 llvm::all_of(op->getRegions(),
152 [&](Region &region) {
153 return typeConverter.isLegal(&region);
154 }) &&
155 areTypeAttrsLegal(op, typeConverter);
156 });
157}
158
159/// Add an `OpenMPOpConversion<T>` conversion pattern for each operation type
160/// passed as template argument.
161template <typename... Ts>
162static inline RewritePatternSet &
164 RewritePatternSet &patterns) {
165 return patterns.add<OpenMPOpConversion<Ts>...>(converter);
166}
167
169 RewritePatternSet &patterns) {
170 // This type is allowed when converting OpenMP to LLVM Dialect, it carries
171 // bounds information for map clauses and the operation and type are
172 // discarded on lowering to LLVM-IR from the OpenMP dialect.
173 converter.addConversion(
174 [&](omp::MapBoundsType type) -> Type { return type; });
175 converter.addConversion(
176 [&](omp::AffinityEntryType type) -> Type { return type; });
177 converter.addConversion([&](omp::IteratedType type) -> Type { return type; });
178
179 // Add conversions for all OpenMP operations.
181#define GET_OP_LIST
182#include "mlir/Dialect/OpenMP/OpenMPOps.cpp.inc"
183 >(converter, patterns);
184}
185
186//===----------------------------------------------------------------------===//
187// ConvertToLLVMPatternInterface implementation
188//===----------------------------------------------------------------------===//
189namespace {
190/// Implement the interface to convert OpenMP to LLVM.
191struct OpenMPToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
192 OpenMPToLLVMDialectInterface(Dialect *dialect)
193 : ConvertToLLVMPatternInterface(dialect) {}
194
195 void loadDependentDialects(MLIRContext *context) const final {
196 context->loadDialect<LLVM::LLVMDialect>();
197 }
198
199 /// Hook for derived dialect interface to provide conversion patterns
200 /// and mark dialect legal for the conversion target.
201 void populateConvertToLLVMConversionPatterns(
202 ConversionTarget &target, LLVMTypeConverter &typeConverter,
203 RewritePatternSet &patterns) const final {
205 populateOpenMPToLLVMConversionPatterns(typeConverter, patterns);
206 }
207};
208} // namespace
209
211 registry.addExtension(+[](MLIRContext *ctx, omp::OpenMPDialect *dialect) {
212 dialect->addInterfaces<OpenMPToLLVMDialectInterface>();
213 });
214}
return success()
static RewritePatternSet & addOpenMPOpConversions(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Add an OpenMPOpConversion<T> conversion pattern for each operation type passed as template argument.
Attributes are known-constant values of operations.
Definition Attributes.h:25
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
Definition Pattern.h:233
const LLVMTypeConverter * getTypeConverter() const
Definition Pattern.cpp:29
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.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition Dialect.h:38
Conversion from types to the LLVM IR dialect.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:64
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
auto getDiscardableAttrs()
Return a range of all of discardable attributes on this operation.
Definition Operation.h:538
OperationName getName()
The name of an operation is the key identifier for it.
Definition Operation.h:115
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition Region.h:26
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:734
Include the generated interface declarations.
void populateOpenMPToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Populate the given list with patterns that convert from OpenMP to LLVM.
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.