|
| 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/Value.h" |
| 54 | +#include "mlir/Pass/AnalysisManager.h" |
| 55 | +#include <memory> |
| 56 | +#include <string> |
| 57 | + |
| 58 | +namespace mlir { |
| 59 | +namespace acc { |
| 60 | + |
| 61 | +namespace detail { |
| 62 | +/// This class contains internal trait classes used by OpenACCSupport. |
| 63 | +/// It follows the Concept-Model pattern used throughout MLIR (e.g., in |
| 64 | +/// AliasAnalysis and interface definitions). |
| 65 | +struct OpenACCSupportTraits { |
| 66 | + class Concept { |
| 67 | + public: |
| 68 | + virtual ~Concept() = default; |
| 69 | + |
| 70 | + /// Get the variable name for a given MLIR value. |
| 71 | + virtual std::string getVariableName(Value v) = 0; |
| 72 | + }; |
| 73 | + |
| 74 | + /// This class wraps a concrete OpenACCSupport implementation and forwards |
| 75 | + /// interface calls to it. This provides type erasure, allowing different |
| 76 | + /// implementation types to be used interchangeably without inheritance. |
| 77 | + template <typename ImplT> |
| 78 | + class Model final : public Concept { |
| 79 | + public: |
| 80 | + explicit Model(ImplT &&impl) : impl(std::forward<ImplT>(impl)) {} |
| 81 | + ~Model() override = default; |
| 82 | + |
| 83 | + std::string getVariableName(Value v) final { |
| 84 | + return impl.getVariableName(v); |
| 85 | + } |
| 86 | + |
| 87 | + private: |
| 88 | + ImplT impl; |
| 89 | + }; |
| 90 | +}; |
| 91 | +} // namespace detail |
| 92 | + |
| 93 | +//===----------------------------------------------------------------------===// |
| 94 | +// OpenACCSupport |
| 95 | +//===----------------------------------------------------------------------===// |
| 96 | + |
| 97 | +class OpenACCSupport { |
| 98 | + using Concept = detail::OpenACCSupportTraits::Concept; |
| 99 | + template <typename ImplT> |
| 100 | + using Model = detail::OpenACCSupportTraits::Model<ImplT>; |
| 101 | + |
| 102 | +public: |
| 103 | + OpenACCSupport() = default; |
| 104 | + OpenACCSupport(Operation *op) {} |
| 105 | + |
| 106 | + /// Register a custom OpenACCSupport implementation. Only one implementation |
| 107 | + /// can be registered at a time; calling this replaces any existing |
| 108 | + /// implementation. |
| 109 | + template <typename AnalysisT> |
| 110 | + void setImplementation(AnalysisT &&analysis) { |
| 111 | + impl = |
| 112 | + std::make_unique<Model<AnalysisT>>(std::forward<AnalysisT>(analysis)); |
| 113 | + } |
| 114 | + |
| 115 | + /// Get the variable name for a given value. |
| 116 | + /// |
| 117 | + /// \param v The MLIR value to get the variable name for. |
| 118 | + /// \return The variable name, or an empty string if unavailable. |
| 119 | + std::string getVariableName(Value v); |
| 120 | + |
| 121 | + /// Signal that this analysis should always be preserved so that |
| 122 | + /// underlying implementation registration is not lost. |
| 123 | + bool isInvalidated(const AnalysisManager::PreservedAnalyses &pa) { |
| 124 | + return false; |
| 125 | + } |
| 126 | + |
| 127 | +private: |
| 128 | + /// The registered custom implementation (if any). |
| 129 | + std::unique_ptr<Concept> impl; |
| 130 | +}; |
| 131 | + |
| 132 | +} // namespace acc |
| 133 | +} // namespace mlir |
| 134 | + |
| 135 | +#endif // MLIR_DIALECT_OPENACC_ANALYSIS_OPENACCSUPPORT_H |
0 commit comments