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 
22 namespace mlir {
23 #define GEN_PASS_DEF_CONVERTOPENMPTOLLVMPASS
24 #include "mlir/Conversion/Passes.h.inc"
25 } // namespace mlir
26 
27 using namespace mlir;
28 
29 namespace {
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.
40 template <typename T>
41 struct OpenMPOpConversion : public ConvertOpToLLVMPattern<T> {
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.
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.
140 template <typename... Ts>
141 static 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 
162 namespace {
163 struct ConvertOpenMPToLLVMPass
164  : public impl::ConvertOpenMPToLLVMPassBase<ConvertOpenMPToLLVMPass> {
165  using Base::Base;
166 
167  void runOnOperation() override;
168 };
169 } // namespace
170 
171 void ConvertOpenMPToLLVMPass::runOnOperation() {
172  auto module = getOperation();
173 
174  // Convert to OpenMP operations with LLVM IR dialect
176  LLVMTypeConverter converter(&getContext());
183 
185  target.addLegalOp<omp::BarrierOp, omp::FlushOp, omp::TaskwaitOp,
186  omp::TaskyieldOp, omp::TerminatorOp>();
187  configureOpenMPToLLVMConversionLegality(target, converter);
188  if (failed(applyPartialConversion(module, target, std::move(patterns))))
189  signalPassFailure();
190 }
191 
192 //===----------------------------------------------------------------------===//
193 // ConvertToLLVMPatternInterface implementation
194 //===----------------------------------------------------------------------===//
195 namespace {
196 /// Implement the interface to convert OpenMP to LLVM.
197 struct 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 {
208  configureOpenMPToLLVMConversionLegality(target, typeConverter);
210  }
211 };
212 } // namespace
213 
215  registry.addExtension(+[](MLIRContext *ctx, omp::OpenMPDialect *dialect) {
216  dialect->addInterfaces<OpenMPToLLVMDialectInterface>();
217  });
218 }
static MLIRContext * getContext(OpFoldResult val)
static RewritePatternSet & addOpenMPOpConversions(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Add an OpenMPOpConversion<T> conversion pattern for each operation type passed as template argument.
This class implements a pattern rewriter for use with ConversionPatterns.
void replaceOp(Operation *op, ValueRange newValues) override
Replace the given operation with the new values.
FailureOr< Block * > convertRegionTypes(Region *region, const TypeConverter &converter, TypeConverter::SignatureConversion *entryConversion=nullptr)
Apply a signature conversion to each block in the given region.
This class describes a specific conversion target.
void addDynamicallyLegalOp(OperationName op, const DynamicLegalityCallbackFn &callback)
Register the given operation as dynamically legal and set the dynamic legalization callback to the on...
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
Definition: Pattern.h:209
Base class for dialect interfaces providing translation to LLVM IR.
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.
Derived class that automatically populates legalization information for different LLVM ops.
Conversion from types to the LLVM IR dialect.
Definition: TypeConverter.h:35
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 represents the benefit of a pattern match in a unitless scheme that ranges from 0 (very li...
Definition: PatternMatch.h:34
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
std::enable_if_t<!std::is_convertible< CallbackT, Twine >::value, LogicalResult > notifyMatchFailure(Location loc, CallbackT &&reasonCallback)
Used to notify the listener that the IR failed to be rewritten because of a match failure,...
Definition: PatternMatch.h:716
void inlineRegionBefore(Region &region, Region &parent, Region::iterator before)
Move the blocks that belong to "region" before the given position in another region "parent".
Type conversion class.
void addConversion(FnT &&callback)
Register a conversion function.
bool isLegal(Type type) const
Return true if the given type is legal for this type converter, i.e.
LogicalResult convertType(Type t, SmallVectorImpl< Type > &results) const
Convert the given type.
LogicalResult convertTypes(TypeRange types, SmallVectorImpl< Type > &results) const
Convert the given types, filling 'results' as necessary.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
void populateArithToLLVMConversionPatterns(const LLVMTypeConverter &converter, RewritePatternSet &patterns)
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:491
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.
Definition: FuncToLLVM.cpp:788
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.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult applyPartialConversion(ArrayRef< Operation * > ops, const ConversionTarget &target, const FrozenRewritePatternSet &patterns, ConversionConfig config=ConversionConfig())
Below we define several entry points for operation conversion.