MLIR 22.0.0git
OpenACCSupport.h
Go to the documentation of this file.
1//===- OpenACCSupport.h - OpenACC Support Interface -------------*- C++ -*-===//
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//
9// This file defines the OpenACCSupport analysis interface, which provides
10// extensible support for OpenACC passes. Custom implementations
11// can be registered to provide pipeline and dialect-specific information
12// that cannot be adequately expressed through type or operation interfaces
13// alone.
14//
15// Usage Pattern:
16// ==============
17//
18// A pass that needs this functionality should call
19// getAnalysis<OpenACCSupport>(), which will provide either:
20// - A cached version if previously initialized, OR
21// - A default implementation if not previously initialized
22//
23// This analysis is never invalidated (isInvalidated returns false), so it only
24// needs to be initialized once and will persist throughout the pass pipeline.
25//
26// Registering a Custom Implementation:
27// =====================================
28//
29// If a custom implementation is needed, create a pass that runs BEFORE the pass
30// that needs the analysis. In this setup pass, use
31// getAnalysis<OpenACCSupport>() followed by setImplementation() to register
32// your custom implementation. The custom implementation will need to provide
33// implementation for all methods defined in the `OpenACCSupportTraits::Concept`
34// class.
35//
36// Example:
37// void MySetupPass::runOnOperation() {
38// OpenACCSupport &support = getAnalysis<OpenACCSupport>();
39// support.setImplementation(MyCustomImpl());
40// }
41//
42// void MyAnalysisConsumerPass::runOnOperation() {
43// OpenACCSupport &support = getAnalysis<OpenACCSupport>();
44// std::string name = support.getVariableName(someValue);
45// // ... use the analysis results
46// }
47//
48//===----------------------------------------------------------------------===//
49
50#ifndef MLIR_DIALECT_OPENACC_ANALYSIS_OPENACCSUPPORT_H
51#define MLIR_DIALECT_OPENACC_ANALYSIS_OPENACCSUPPORT_H
52
53#include "mlir/IR/Remarks.h"
54#include "mlir/IR/Value.h"
56#include "llvm/ADT/StringRef.h"
57#include <memory>
58#include <string>
59
60namespace mlir {
61namespace acc {
62
63// Forward declarations
64enum class RecipeKind : uint32_t;
65bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
66 Operation **definingOpPtr);
68 llvm::StringRef category);
69
70namespace detail {
71/// This class contains internal trait classes used by OpenACCSupport.
72/// It follows the Concept-Model pattern used throughout MLIR (e.g., in
73/// AliasAnalysis and interface definitions).
75 class Concept {
76 public:
77 virtual ~Concept() = default;
78
79 /// Get the variable name for a given MLIR value.
80 virtual std::string getVariableName(Value v) = 0;
81
82 /// Get the recipe name for a given kind, type and value.
83 virtual std::string getRecipeName(RecipeKind kind, Type type,
84 Value var) = 0;
85
86 // Used to report a case that is not supported by the implementation.
87 virtual InFlightDiagnostic emitNYI(Location loc, const Twine &message) = 0;
88
89 // Used to emit an OpenACC remark. The category is optional and is used to
90 // either capture the pass name or pipeline phase when the remark is
91 // emitted. When not provided, in the default implementation, the category
92 // is "openacc".
94 emitRemark(Operation *op, const Twine &message,
95 llvm::StringRef category) = 0;
96
97 /// Check if a symbol use is valid for use in an OpenACC region.
98 virtual bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
99 Operation **definingOpPtr) = 0;
100
101 /// Check if a value use is legal in an OpenACC region.
102 virtual bool isValidValueUse(Value v, mlir::Region &region) = 0;
103 };
104
105 /// SFINAE helpers to detect if implementation has optional methods
106 template <typename ImplT, typename... Args>
108 decltype(std::declval<ImplT>().isValidSymbolUse(std::declval<Args>()...));
109
110 template <typename ImplT>
112 llvm::is_detected<isValidSymbolUse_t, ImplT, Operation *, SymbolRefAttr,
113 Operation **>;
114
115 template <typename ImplT, typename... Args>
116
118 decltype(std::declval<ImplT>().isValidValueUse(std::declval<Args>()...));
119
120 template <typename ImplT>
122 llvm::is_detected<isValidValueUse_t, ImplT, Value, Region &>;
123
124 template <typename ImplT, typename... Args>
126 decltype(std::declval<ImplT>().emitRemark(std::declval<Args>()...));
127
128 template <typename ImplT>
129 using has_emitRemark = llvm::is_detected<emitRemark_t, ImplT, Operation *,
130 const Twine &, llvm::StringRef>;
131
132 /// This class wraps a concrete OpenACCSupport implementation and forwards
133 /// interface calls to it. This provides type erasure, allowing different
134 /// implementation types to be used interchangeably without inheritance.
135 /// Methods can be optionally implemented; if not present, default behavior
136 /// is used.
137 template <typename ImplT>
138 class Model final : public Concept {
139 public:
140 explicit Model(ImplT &&impl) : impl(std::forward<ImplT>(impl)) {}
141 ~Model() override = default;
142
143 std::string getVariableName(Value v) final {
144 return impl.getVariableName(v);
145 }
146
147 std::string getRecipeName(RecipeKind kind, Type type, Value var) final {
148 return impl.getRecipeName(kind, type, var);
149 }
150
151 InFlightDiagnostic emitNYI(Location loc, const Twine &message) final {
152 return impl.emitNYI(loc, message);
153 }
154
156 const Twine &message,
157 llvm::StringRef category) final {
158 if constexpr (has_emitRemark<ImplT>::value)
159 return impl.emitRemark(op, message, category);
160 else
161 return acc::emitRemark(op, message, category);
162 }
163
164 bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
165 Operation **definingOpPtr) final {
167 return impl.isValidSymbolUse(user, symbol, definingOpPtr);
168 else
169 return acc::isValidSymbolUse(user, symbol, definingOpPtr);
170 }
171
172 bool isValidValueUse(Value v, Region &region) final {
174 return impl.isValidValueUse(v, region);
175 else
176 return false;
177 }
178
179 private:
180 ImplT impl;
181 };
182};
183} // namespace detail
184
185//===----------------------------------------------------------------------===//
186// OpenACCSupport
187//===----------------------------------------------------------------------===//
188
191 template <typename ImplT>
193
194public:
195 OpenACCSupport() = default;
197
198 /// Register a custom OpenACCSupport implementation. Only one implementation
199 /// can be registered at a time; calling this replaces any existing
200 /// implementation.
201 template <typename AnalysisT>
202 void setImplementation(AnalysisT &&analysis) {
203 impl =
204 std::make_unique<Model<AnalysisT>>(std::forward<AnalysisT>(analysis));
205 }
206
207 /// Get the variable name for a given value.
208 ///
209 /// \param v The MLIR value to get the variable name for.
210 /// \return The variable name, or an empty string if unavailable.
211 std::string getVariableName(Value v);
212
213 /// Get the recipe name for a given type and value.
214 ///
215 /// \param kind The kind of recipe to get the name for.
216 /// \param type The type to get the recipe name for. Can be null if the
217 /// var is provided instead.
218 /// \param var The MLIR value to get the recipe name for. Can be null if
219 /// the type is provided instead.
220 /// \return The recipe name, or an empty string if not available.
221 std::string getRecipeName(RecipeKind kind, Type type, Value var);
222
223 /// Report a case that is not yet supported by the implementation.
224 ///
225 /// \param loc The location to report the unsupported case at.
226 /// \param message The message to report.
227 /// \return An in-flight diagnostic object that can be used to report the
228 /// unsupported case.
229 InFlightDiagnostic emitNYI(Location loc, const Twine &message);
230
231 /// Emit an OpenACC remark.
232 ///
233 /// \param op The operation to emit the remark for.
234 /// \param message The remark message.
235 /// \param category Optional category for the remark. Defaults to "openacc".
236 /// \return An in-flight remark object that can be used to append
237 /// additional information to the remark.
239 emitRemark(Operation *op, const Twine &message,
240 llvm::StringRef category = "openacc");
241
242 /// Check if a symbol use is valid for use in an OpenACC region.
243 ///
244 /// \param user The operation using the symbol.
245 /// \param symbol The symbol reference being used.
246 /// \param definingOpPtr Optional output parameter to receive the defining op.
247 /// \return true if the symbol use is valid, false otherwise.
248 bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
249 Operation **definingOpPtr = nullptr);
250
251 /// Check if a value use is legal in an OpenACC region.
252 ///
253 /// \param v The MLIR value to check for legality.
254 /// \param region The MLIR region in which the legality is checked.
255 bool isValidValueUse(Value v, Region &region);
256
257 /// Signal that this analysis should always be preserved so that
258 /// underlying implementation registration is not lost.
260 return false;
261 }
262
263private:
264 /// The registered custom implementation (if any).
265 std::unique_ptr<Concept> impl;
266};
267
268} // namespace acc
269} // namespace mlir
270
271#endif // MLIR_DIALECT_OPENACC_ANALYSIS_OPENACCSUPPORT_H
detail::PreservedAnalyses PreservedAnalyses
This class represents a diagnostic that is inflight and set to be reported.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
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
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
remark::detail::InFlightRemark emitRemark(Operation *op, const Twine &message, llvm::StringRef category="openacc")
Emit an OpenACC remark.
void setImplementation(AnalysisT &&analysis)
Register a custom OpenACCSupport implementation.
InFlightDiagnostic emitNYI(Location loc, const Twine &message)
Report a case that is not yet supported by the implementation.
bool isValidValueUse(Value v, Region &region)
Check if a value use is legal in an OpenACC region.
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr=nullptr)
Check if a symbol use is valid for use in an OpenACC region.
bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa)
Signal that this analysis should always be preserved so that underlying implementation registration i...
std::string getVariableName(Value v)
Get the variable name for a given value.
std::string getRecipeName(RecipeKind kind, Type type, Value var)
Get the recipe name for a given type and value.
virtual std::string getRecipeName(RecipeKind kind, Type type, Value var)=0
Get the recipe name for a given kind, type and value.
virtual std::string getVariableName(Value v)=0
Get the variable name for a given MLIR value.
virtual bool isValidValueUse(Value v, mlir::Region &region)=0
Check if a value use is legal in an OpenACC region.
virtual InFlightDiagnostic emitNYI(Location loc, const Twine &message)=0
virtual bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr)=0
Check if a symbol use is valid for use in an OpenACC region.
virtual remark::detail::InFlightRemark emitRemark(Operation *op, const Twine &message, llvm::StringRef category)=0
This class wraps a concrete OpenACCSupport implementation and forwards interface calls to it.
bool isValidValueUse(Value v, Region &region) final
Check if a value use is legal in an OpenACC region.
InFlightDiagnostic emitNYI(Location loc, const Twine &message) final
std::string getRecipeName(RecipeKind kind, Type type, Value var) final
Get the recipe name for a given kind, type and value.
remark::detail::InFlightRemark emitRemark(Operation *op, const Twine &message, llvm::StringRef category) final
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr) final
Check if a symbol use is valid for use in an OpenACC region.
std::string getVariableName(Value v) final
Get the variable name for a given MLIR value.
InFlightRemark is a RAII class that holds a reference to a Remark instance and allows to build the re...
Definition Remarks.h:292
remark::detail::InFlightRemark emitRemark(Operation *op, const Twine &message, llvm::StringRef category)
bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol, Operation **definingOpPtr)
Include the generated interface declarations.
This class contains internal trait classes used by OpenACCSupport.
decltype(std::declval< ImplT >().isValidValueUse(std::declval< Args >()...)) isValidValueUse_t
llvm::is_detected< emitRemark_t, ImplT, Operation *, const Twine &, llvm::StringRef > has_emitRemark
llvm::is_detected< isValidValueUse_t, ImplT, Value, Region & > has_isValidValueUse
llvm::is_detected< isValidSymbolUse_t, ImplT, Operation *, SymbolRefAttr, Operation ** > has_isValidSymbolUse
decltype(std::declval< ImplT >().emitRemark(std::declval< Args >()...)) emitRemark_t
decltype(std::declval< ImplT >().isValidSymbolUse(std::declval< Args >()...)) isValidSymbolUse_t
SFINAE helpers to detect if implementation has optional methods.