MLIR 23.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
54#include "mlir/IR/Remarks.h"
55#include "mlir/IR/Value.h"
57#include "llvm/ADT/StringRef.h"
58#include <memory>
59#include <string>
60
61namespace mlir {
62namespace acc {
63
64namespace detail {
65/// This class contains internal trait classes used by OpenACCSupport.
66/// It follows the Concept-Model pattern used throughout MLIR (e.g., in
67/// AliasAnalysis and interface definitions).
69 class Concept {
70 public:
71 virtual ~Concept() = default;
72
73 /// Get the variable name for a given MLIR value.
74 virtual std::string getVariableName(Value v) = 0;
75
76 /// Get the recipe name for a given kind, type and value.
77 virtual std::string getRecipeName(RecipeKind kind, Type type,
78 Value var) = 0;
79
80 // Used to report a case that is not supported by the implementation.
81 virtual InFlightDiagnostic emitNYI(Location loc, const Twine &message) = 0;
82
83 // Used to emit an OpenACC remark. The category is optional and is used to
84 // either capture the pass name or pipeline phase when the remark is
85 // emitted. When not provided, in the default implementation, the category
86 // is "openacc".
88 emitRemark(Operation *op, const Twine &message,
89 llvm::StringRef category) = 0;
90
91 /// Check if a symbol use is valid for use in an OpenACC region.
92 virtual bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
93 Operation **definingOpPtr) = 0;
94
95 /// Check if a value use is legal in an OpenACC region.
96 virtual bool isValidValueUse(Value v, mlir::Region &region) = 0;
97 };
98
99 /// SFINAE helpers to detect if implementation has optional methods
100 template <typename ImplT, typename... Args>
102 decltype(std::declval<ImplT>().isValidSymbolUse(std::declval<Args>()...));
103
104 template <typename ImplT>
106 llvm::is_detected<isValidSymbolUse_t, ImplT, Operation *, SymbolRefAttr,
107 Operation **>;
108
109 template <typename ImplT, typename... Args>
110
112 decltype(std::declval<ImplT>().isValidValueUse(std::declval<Args>()...));
113
114 template <typename ImplT>
116 llvm::is_detected<isValidValueUse_t, ImplT, Value, Region &>;
117
118 template <typename ImplT, typename... Args>
120 decltype(std::declval<ImplT>().emitRemark(std::declval<Args>()...));
121
122 template <typename ImplT>
123 using has_emitRemark = llvm::is_detected<emitRemark_t, ImplT, Operation *,
124 const Twine &, llvm::StringRef>;
125
126 /// This class wraps a concrete OpenACCSupport implementation and forwards
127 /// interface calls to it. This provides type erasure, allowing different
128 /// implementation types to be used interchangeably without inheritance.
129 /// Methods can be optionally implemented; if not present, default behavior
130 /// is used.
131 template <typename ImplT>
132 class Model final : public Concept {
133 public:
134 explicit Model(ImplT &&impl) : impl(std::forward<ImplT>(impl)) {}
135 ~Model() override = default;
136
137 std::string getVariableName(Value v) final {
138 return impl.getVariableName(v);
139 }
140
141 std::string getRecipeName(RecipeKind kind, Type type, Value var) final {
142 return impl.getRecipeName(kind, type, var);
143 }
144
145 InFlightDiagnostic emitNYI(Location loc, const Twine &message) final {
146 return impl.emitNYI(loc, message);
147 }
148
150 const Twine &message,
151 llvm::StringRef category) final {
152 if constexpr (has_emitRemark<ImplT>::value)
153 return impl.emitRemark(op, message, category);
154 else
155 return acc::emitRemark(op, message, category);
156 }
157
158 bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
159 Operation **definingOpPtr) final {
161 return impl.isValidSymbolUse(user, symbol, definingOpPtr);
162 else
163 return acc::isValidSymbolUse(user, symbol, definingOpPtr);
164 }
165
166 bool isValidValueUse(Value v, Region &region) final {
168 return impl.isValidValueUse(v, region);
169 else
170 return acc::isValidValueUse(v, region);
171 }
172
173 private:
174 ImplT impl;
175 };
176};
177} // namespace detail
178
179//===----------------------------------------------------------------------===//
180// OpenACCSupport
181//===----------------------------------------------------------------------===//
182
185 template <typename ImplT>
187
188public:
189 OpenACCSupport() = default;
191
192 /// Register a custom OpenACCSupport implementation. Only one implementation
193 /// can be registered at a time; calling this replaces any existing
194 /// implementation.
195 template <typename AnalysisT>
196 void setImplementation(AnalysisT &&analysis) {
197 impl =
198 std::make_unique<Model<AnalysisT>>(std::forward<AnalysisT>(analysis));
199 }
200
201 /// Get the variable name for a given value.
202 ///
203 /// \param v The MLIR value to get the variable name for.
204 /// \return The variable name, or an empty string if unavailable.
205 std::string getVariableName(Value v);
206
207 /// Get the recipe name for a given type and value.
208 ///
209 /// \param kind The kind of recipe to get the name for.
210 /// \param type The type to get the recipe name for. Can be null if the
211 /// var is provided instead.
212 /// \param var The MLIR value to get the recipe name for. Can be null if
213 /// the type is provided instead.
214 /// \return The recipe name, or an empty string if not available.
215 std::string getRecipeName(RecipeKind kind, Type type, Value var);
216
217 /// Report a case that is not yet supported by the implementation.
218 ///
219 /// \param loc The location to report the unsupported case at.
220 /// \param message The message to report.
221 /// \return An in-flight diagnostic object that can be used to report the
222 /// unsupported case.
223 InFlightDiagnostic emitNYI(Location loc, const Twine &message);
224
225 /// Emit an OpenACC remark.
226 ///
227 /// \param op The operation to emit the remark for.
228 /// \param message The remark message.
229 /// \param category Optional category for the remark. Defaults to "openacc".
230 /// \return An in-flight remark object that can be used to append
231 /// additional information to the remark.
233 emitRemark(Operation *op, const Twine &message,
234 llvm::StringRef category = "openacc");
235
236 /// Check if a symbol use is valid for use in an OpenACC region.
237 ///
238 /// \param user The operation using the symbol.
239 /// \param symbol The symbol reference being used.
240 /// \param definingOpPtr Optional output parameter to receive the defining op.
241 /// \return true if the symbol use is valid, false otherwise.
242 bool isValidSymbolUse(Operation *user, SymbolRefAttr symbol,
243 Operation **definingOpPtr = nullptr);
244
245 /// Check if a value use is legal in an OpenACC region.
246 ///
247 /// \param v The MLIR value to check for legality.
248 /// \param region The MLIR region in which the legality is checked.
249 bool isValidValueUse(Value v, Region &region);
250
251 /// Signal that this analysis should always be preserved so that
252 /// underlying implementation registration is not lost.
254 return false;
255 }
256
257private:
258 /// The registered custom implementation (if any).
259 std::unique_ptr<Concept> impl;
260};
261
262} // namespace acc
263} // namespace mlir
264
265#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
bool isValidSymbolUse(mlir::Operation *user, mlir::SymbolRefAttr symbol, mlir::Operation **definingOpPtr=nullptr)
Check if a symbol use is valid for use in an OpenACC region.
remark::detail::InFlightRemark emitRemark(mlir::Operation *op, const llvm::Twine &message, llvm::StringRef category="openacc")
Emit an OpenACC remark for the given operation with the given message.
bool isValidValueUse(mlir::Value val, mlir::Region &region)
Check if a value use is valid in an OpenACC region.
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.