1 //===- Pass.h - Base classes for compiler passes ----------------*- 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 #ifndef MLIR_PASS_PASS_H 10 #define MLIR_PASS_PASS_H 11 12 #include "mlir/IR/BuiltinOps.h" 13 #include "mlir/IR/Dialect.h" 14 #include "mlir/Pass/AnalysisManager.h" 15 #include "mlir/Pass/PassRegistry.h" 16 #include "mlir/Support/LogicalResult.h" 17 #include "llvm/ADT/PointerIntPair.h" 18 #include "llvm/ADT/Statistic.h" 19 20 namespace mlir { 21 namespace detail { 22 class OpToOpPassAdaptor; 23 24 /// The state for a single execution of a pass. This provides a unified 25 /// interface for accessing and initializing necessary state for pass execution. 26 struct PassExecutionState { PassExecutionStatePassExecutionState27 PassExecutionState(Operation *ir, AnalysisManager analysisManager, 28 function_ref<LogicalResult(OpPassManager &, Operation *)> 29 pipelineExecutor) 30 : irAndPassFailed(ir, false), analysisManager(analysisManager), 31 pipelineExecutor(pipelineExecutor) {} 32 33 /// The current operation being transformed and a bool for if the pass 34 /// signaled a failure. 35 llvm::PointerIntPair<Operation *, 1, bool> irAndPassFailed; 36 37 /// The analysis manager for the operation. 38 AnalysisManager analysisManager; 39 40 /// The set of preserved analyses for the current execution. 41 detail::PreservedAnalyses preservedAnalyses; 42 43 /// This is a callback in the PassManager that allows to schedule dynamic 44 /// pipelines that will be rooted at the provided operation. 45 function_ref<LogicalResult(OpPassManager &, Operation *)> pipelineExecutor; 46 }; 47 } // namespace detail 48 49 /// The abstract base pass class. This class contains information describing the 50 /// derived pass object, e.g its kind and abstract TypeID. 51 class Pass { 52 public: 53 virtual ~Pass() = default; 54 55 /// Returns the unique identifier that corresponds to this pass. getTypeID()56 TypeID getTypeID() const { return passID; } 57 58 /// Returns the pass info for the specified pass class or null if unknown. 59 static const PassInfo *lookupPassInfo(TypeID passID); lookupPassInfo()60 template <typename PassT> static const PassInfo *lookupPassInfo() { 61 return lookupPassInfo(TypeID::get<PassT>()); 62 } 63 64 /// Returns the pass info for this pass. lookupPassInfo()65 const PassInfo *lookupPassInfo() const { return lookupPassInfo(getTypeID()); } 66 67 /// Returns the derived pass name. 68 virtual StringRef getName() const = 0; 69 70 /// Register dependent dialects for the current pass. 71 /// A pass is expected to register the dialects it will create entities for 72 /// (Operations, Types, Attributes), other than dialect that exists in the 73 /// input. For example, a pass that converts from Linalg to Affine would 74 /// register the Affine dialect but does not need to register Linalg. getDependentDialects(DialectRegistry & registry)75 virtual void getDependentDialects(DialectRegistry ®istry) const {} 76 77 /// Returns the command line argument used when registering this pass. Return 78 /// an empty string if one does not exist. getArgument()79 virtual StringRef getArgument() const { 80 if (const PassInfo *passInfo = lookupPassInfo()) 81 return passInfo->getPassArgument(); 82 return ""; 83 } 84 85 /// Returns the name of the operation that this pass operates on, or None if 86 /// this is a generic OperationPass. getOpName()87 Optional<StringRef> getOpName() const { return opName; } 88 89 //===--------------------------------------------------------------------===// 90 // Options 91 //===--------------------------------------------------------------------===// 92 93 /// This class represents a specific pass option, with a provided data type. 94 template <typename DataType, 95 typename OptionParser = detail::PassOptions::OptionParser<DataType>> 96 struct Option : public detail::PassOptions::Option<DataType, OptionParser> { 97 template <typename... Args> OptionOption98 Option(Pass &parent, StringRef arg, Args &&... args) 99 : detail::PassOptions::Option<DataType, OptionParser>( 100 parent.passOptions, arg, std::forward<Args>(args)...) {} 101 using detail::PassOptions::Option<DataType, OptionParser>::operator=; 102 }; 103 /// This class represents a specific pass option that contains a list of 104 /// values of the provided data type. 105 template <typename DataType, 106 typename OptionParser = detail::PassOptions::OptionParser<DataType>> 107 struct ListOption 108 : public detail::PassOptions::ListOption<DataType, OptionParser> { 109 template <typename... Args> ListOptionListOption110 ListOption(Pass &parent, StringRef arg, Args &&... args) 111 : detail::PassOptions::ListOption<DataType, OptionParser>( 112 parent.passOptions, arg, std::forward<Args>(args)...) {} 113 using detail::PassOptions::ListOption<DataType, OptionParser>::operator=; 114 }; 115 116 /// Attempt to initialize the options of this pass from the given string. 117 LogicalResult initializeOptions(StringRef options); 118 119 /// Prints out the pass in the textual representation of pipelines. If this is 120 /// an adaptor pass, print with the op_name(sub_pass,...) format. 121 void printAsTextualPipeline(raw_ostream &os); 122 123 //===--------------------------------------------------------------------===// 124 // Statistics 125 //===--------------------------------------------------------------------===// 126 127 /// This class represents a single pass statistic. This statistic functions 128 /// similarly to an unsigned integer value, and may be updated and incremented 129 /// accordingly. This class can be used to provide additional information 130 /// about the transformations and analyses performed by a pass. 131 class Statistic : public llvm::Statistic { 132 public: 133 /// The statistic is initialized by the pass owner, a name, and a 134 /// description. 135 Statistic(Pass *owner, const char *name, const char *description); 136 137 /// Assign the statistic to the given value. 138 Statistic &operator=(unsigned value); 139 140 private: 141 /// Hide some of the details of llvm::Statistic that we don't use. 142 using llvm::Statistic::getDebugType; 143 }; 144 145 /// Returns the main statistics for this pass instance. getStatistics()146 ArrayRef<Statistic *> getStatistics() const { return statistics; } getStatistics()147 MutableArrayRef<Statistic *> getStatistics() { return statistics; } 148 149 protected: 150 explicit Pass(TypeID passID, Optional<StringRef> opName = llvm::None) passID(passID)151 : passID(passID), opName(opName) {} Pass(const Pass & other)152 Pass(const Pass &other) : Pass(other.passID, other.opName) {} 153 154 /// Returns the current pass state. getPassState()155 detail::PassExecutionState &getPassState() { 156 assert(passState && "pass state was never initialized"); 157 return *passState; 158 } 159 160 /// Return the MLIR context for the current function being transformed. getContext()161 MLIRContext &getContext() { return *getOperation()->getContext(); } 162 163 /// The polymorphic API that runs the pass over the currently held operation. 164 virtual void runOnOperation() = 0; 165 166 /// Schedule an arbitrary pass pipeline on the provided operation. 167 /// This can be invoke any time in a pass to dynamic schedule more passes. 168 /// The provided operation must be the current one or one nested below. runPipeline(OpPassManager & pipeline,Operation * op)169 LogicalResult runPipeline(OpPassManager &pipeline, Operation *op) { 170 return passState->pipelineExecutor(pipeline, op); 171 } 172 173 /// A clone method to create a copy of this pass. clone()174 std::unique_ptr<Pass> clone() const { 175 auto newInst = clonePass(); 176 newInst->copyOptionValuesFrom(this); 177 return newInst; 178 } 179 180 /// Return the current operation being transformed. getOperation()181 Operation *getOperation() { 182 return getPassState().irAndPassFailed.getPointer(); 183 } 184 185 /// Signal that some invariant was broken when running. The IR is allowed to 186 /// be in an invalid state. signalPassFailure()187 void signalPassFailure() { getPassState().irAndPassFailed.setInt(true); } 188 189 /// Query an analysis for the current ir unit. getAnalysis()190 template <typename AnalysisT> AnalysisT &getAnalysis() { 191 return getAnalysisManager().getAnalysis<AnalysisT>(); 192 } 193 194 /// Query an analysis for the current ir unit of a specific derived operation 195 /// type. 196 template <typename AnalysisT, typename OpT> getAnalysis()197 AnalysisT &getAnalysis() { 198 return getAnalysisManager().getAnalysis<AnalysisT, OpT>(); 199 } 200 201 /// Query a cached instance of an analysis for the current ir unit if one 202 /// exists. 203 template <typename AnalysisT> getCachedAnalysis()204 Optional<std::reference_wrapper<AnalysisT>> getCachedAnalysis() { 205 return getAnalysisManager().getCachedAnalysis<AnalysisT>(); 206 } 207 208 /// Mark all analyses as preserved. markAllAnalysesPreserved()209 void markAllAnalysesPreserved() { 210 getPassState().preservedAnalyses.preserveAll(); 211 } 212 213 /// Mark the provided analyses as preserved. markAnalysesPreserved()214 template <typename... AnalysesT> void markAnalysesPreserved() { 215 getPassState().preservedAnalyses.preserve<AnalysesT...>(); 216 } markAnalysesPreserved(TypeID id)217 void markAnalysesPreserved(TypeID id) { 218 getPassState().preservedAnalyses.preserve(id); 219 } 220 221 /// Returns the analysis for the given parent operation if it exists. 222 template <typename AnalysisT> 223 Optional<std::reference_wrapper<AnalysisT>> getCachedParentAnalysis(Operation * parent)224 getCachedParentAnalysis(Operation *parent) { 225 return getAnalysisManager().getCachedParentAnalysis<AnalysisT>(parent); 226 } 227 228 /// Returns the analysis for the parent operation if it exists. 229 template <typename AnalysisT> getCachedParentAnalysis()230 Optional<std::reference_wrapper<AnalysisT>> getCachedParentAnalysis() { 231 return getAnalysisManager().getCachedParentAnalysis<AnalysisT>( 232 getOperation()->getParentOp()); 233 } 234 235 /// Returns the analysis for the given child operation if it exists. 236 template <typename AnalysisT> 237 Optional<std::reference_wrapper<AnalysisT>> getCachedChildAnalysis(Operation * child)238 getCachedChildAnalysis(Operation *child) { 239 return getAnalysisManager().getCachedChildAnalysis<AnalysisT>(child); 240 } 241 242 /// Returns the analysis for the given child operation, or creates it if it 243 /// doesn't exist. getChildAnalysis(Operation * child)244 template <typename AnalysisT> AnalysisT &getChildAnalysis(Operation *child) { 245 return getAnalysisManager().getChildAnalysis<AnalysisT>(child); 246 } 247 248 /// Returns the analysis for the given child operation of specific derived 249 /// operation type, or creates it if it doesn't exist. 250 template <typename AnalysisT, typename OpTy> getChildAnalysis(OpTy child)251 AnalysisT &getChildAnalysis(OpTy child) { 252 return getAnalysisManager().getChildAnalysis<AnalysisT>(child); 253 } 254 255 /// Returns the current analysis manager. getAnalysisManager()256 AnalysisManager getAnalysisManager() { 257 return getPassState().analysisManager; 258 } 259 260 /// Create a copy of this pass, ignoring statistics and options. 261 virtual std::unique_ptr<Pass> clonePass() const = 0; 262 263 /// Copy the option values from 'other', which is another instance of this 264 /// pass. 265 void copyOptionValuesFrom(const Pass *other); 266 267 private: 268 269 /// Out of line virtual method to ensure vtables and metadata are emitted to a 270 /// single .o file. 271 virtual void anchor(); 272 273 /// Represents a unique identifier for the pass. 274 TypeID passID; 275 276 /// The name of the operation that this pass operates on, or None if this is a 277 /// generic OperationPass. 278 Optional<StringRef> opName; 279 280 /// The current execution state for the pass. 281 Optional<detail::PassExecutionState> passState; 282 283 /// The set of statistics held by this pass. 284 std::vector<Statistic *> statistics; 285 286 /// The pass options registered to this pass instance. 287 detail::PassOptions passOptions; 288 289 /// Allow access to 'clone'. 290 friend class OpPassManager; 291 292 /// Allow access to 'passState'. 293 friend detail::OpToOpPassAdaptor; 294 295 /// Allow access to 'passOptions'. 296 friend class PassInfo; 297 }; 298 299 //===----------------------------------------------------------------------===// 300 // Pass Model Definitions 301 //===----------------------------------------------------------------------===// 302 303 /// Pass to transform an operation of a specific type. 304 /// 305 /// Operation passes must not: 306 /// - modify any other operations within the parent region, as other threads 307 /// may be manipulating them concurrently. 308 /// - modify any state within the parent operation, this includes adding 309 /// additional operations. 310 /// 311 /// Derived function passes are expected to provide the following: 312 /// - A 'void runOnOperation()' method. 313 /// - A 'StringRef getName() const' method. 314 /// - A 'std::unique_ptr<Pass> clonePass() const' method. 315 template <typename OpT = void> class OperationPass : public Pass { 316 protected: OperationPass(TypeID passID)317 OperationPass(TypeID passID) : Pass(passID, OpT::getOperationName()) {} 318 319 /// Support isa/dyn_cast functionality. classof(const Pass * pass)320 static bool classof(const Pass *pass) { 321 return pass->getOpName() == OpT::getOperationName(); 322 } 323 324 /// Return the current operation being transformed. getOperation()325 OpT getOperation() { return cast<OpT>(Pass::getOperation()); } 326 327 /// Query an analysis for the current operation of the specific derived 328 /// operation type. 329 template <typename AnalysisT> getAnalysis()330 AnalysisT &getAnalysis() { 331 return Pass::getAnalysis<AnalysisT, OpT>(); 332 } 333 }; 334 335 /// Pass to transform an operation. 336 /// 337 /// Operation passes must not: 338 /// - modify any other operations within the parent region, as other threads 339 /// may be manipulating them concurrently. 340 /// - modify any state within the parent operation, this includes adding 341 /// additional operations. 342 /// 343 /// Derived function passes are expected to provide the following: 344 /// - A 'void runOnOperation()' method. 345 /// - A 'StringRef getName() const' method. 346 /// - A 'std::unique_ptr<Pass> clonePass() const' method. 347 template <> class OperationPass<void> : public Pass { 348 protected: OperationPass(TypeID passID)349 OperationPass(TypeID passID) : Pass(passID) {} 350 }; 351 352 /// A model for providing function pass specific utilities. 353 /// 354 /// Derived function passes are expected to provide the following: 355 /// - A 'void runOnFunction()' method. 356 /// - A 'StringRef getName() const' method. 357 /// - A 'std::unique_ptr<Pass> clonePass() const' method. 358 class FunctionPass : public OperationPass<FuncOp> { 359 public: 360 using OperationPass<FuncOp>::OperationPass; 361 362 /// The polymorphic API that runs the pass over the currently held function. 363 virtual void runOnFunction() = 0; 364 365 /// The polymorphic API that runs the pass over the currently held operation. runOnOperation()366 void runOnOperation() final { 367 if (!getFunction().isExternal()) 368 runOnFunction(); 369 } 370 371 /// Return the current function being transformed. getFunction()372 FuncOp getFunction() { return this->getOperation(); } 373 }; 374 375 /// This class provides a CRTP wrapper around a base pass class to define 376 /// several necessary utility methods. This should only be used for passes that 377 /// are not suitably represented using the declarative pass specification(i.e. 378 /// tablegen backend). 379 template <typename PassT, typename BaseT> class PassWrapper : public BaseT { 380 public: 381 /// Support isa/dyn_cast functionality for the derived pass class. classof(const Pass * pass)382 static bool classof(const Pass *pass) { 383 return pass->getTypeID() == TypeID::get<PassT>(); 384 } 385 386 protected: PassWrapper()387 PassWrapper() : BaseT(TypeID::get<PassT>()) {} 388 389 /// Returns the derived pass name. getName()390 StringRef getName() const override { return llvm::getTypeName<PassT>(); } 391 392 /// A clone method to create a copy of this pass. clonePass()393 std::unique_ptr<Pass> clonePass() const override { 394 return std::make_unique<PassT>(*static_cast<const PassT *>(this)); 395 } 396 }; 397 398 } // end namespace mlir 399 400 #endif // MLIR_PASS_PASS_H 401