163d1dc66SMehdi Amini //===- TestPrintNesting.cpp - Passes to illustrate the IR nesting ---------===// 263d1dc66SMehdi Amini // 363d1dc66SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 463d1dc66SMehdi Amini // See https://llvm.org/LICENSE.txt for license information. 563d1dc66SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 663d1dc66SMehdi Amini // 763d1dc66SMehdi Amini //===----------------------------------------------------------------------===// 863d1dc66SMehdi Amini 965fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h" 1063d1dc66SMehdi Amini #include "mlir/Pass/Pass.h" 1163d1dc66SMehdi Amini 1263d1dc66SMehdi Amini using namespace mlir; 1363d1dc66SMehdi Amini 1463d1dc66SMehdi Amini namespace { 1563d1dc66SMehdi Amini /// This pass illustrates the IR nesting through printing. 1663d1dc66SMehdi Amini struct TestPrintNestingPass 1763d1dc66SMehdi Amini : public PassWrapper<TestPrintNestingPass, OperationPass<>> { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anon7ab751170111::TestPrintNestingPass18*5e50dd04SRiver Riddle MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestPrintNestingPass) 19*5e50dd04SRiver Riddle 20b5e22e6dSMehdi Amini StringRef getArgument() const final { return "test-print-nesting"; } getDescription__anon7ab751170111::TestPrintNestingPass21b5e22e6dSMehdi Amini StringRef getDescription() const final { return "Test various printing."; } 2263d1dc66SMehdi Amini // Entry point for the pass. runOnOperation__anon7ab751170111::TestPrintNestingPass2363d1dc66SMehdi Amini void runOnOperation() override { 2463d1dc66SMehdi Amini Operation *op = getOperation(); 2563d1dc66SMehdi Amini resetIndent(); 2663d1dc66SMehdi Amini printOperation(op); 2763d1dc66SMehdi Amini } 2863d1dc66SMehdi Amini 2963d1dc66SMehdi Amini /// The three methods below are mutually recursive and follow the nesting of 3063d1dc66SMehdi Amini /// the IR: operation->region->block->operation->... 3163d1dc66SMehdi Amini printOperation__anon7ab751170111::TestPrintNestingPass3263d1dc66SMehdi Amini void printOperation(Operation *op) { 3363d1dc66SMehdi Amini // Print the operation itself and some of its properties 3463d1dc66SMehdi Amini printIndent() << "visiting op: '" << op->getName() << "' with " 3563d1dc66SMehdi Amini << op->getNumOperands() << " operands and " 3663d1dc66SMehdi Amini << op->getNumResults() << " results\n"; 3763d1dc66SMehdi Amini // Print the operation attributes 3863d1dc66SMehdi Amini if (!op->getAttrs().empty()) { 3963d1dc66SMehdi Amini printIndent() << op->getAttrs().size() << " attributes:\n"; 4063d1dc66SMehdi Amini for (NamedAttribute attr : op->getAttrs()) 410c7890c8SRiver Riddle printIndent() << " - '" << attr.getName().getValue() << "' : '" 420c7890c8SRiver Riddle << attr.getValue() << "'\n"; 4363d1dc66SMehdi Amini } 4463d1dc66SMehdi Amini 4563d1dc66SMehdi Amini // Recurse into each of the regions attached to the operation. 4663d1dc66SMehdi Amini printIndent() << " " << op->getNumRegions() << " nested regions:\n"; 4763d1dc66SMehdi Amini auto indent = pushIndent(); 4863d1dc66SMehdi Amini for (Region ®ion : op->getRegions()) 4963d1dc66SMehdi Amini printRegion(region); 5063d1dc66SMehdi Amini } 5163d1dc66SMehdi Amini printRegion__anon7ab751170111::TestPrintNestingPass5263d1dc66SMehdi Amini void printRegion(Region ®ion) { 5363d1dc66SMehdi Amini // A region does not hold anything by itself other than a list of blocks. 5463d1dc66SMehdi Amini printIndent() << "Region with " << region.getBlocks().size() 5563d1dc66SMehdi Amini << " blocks:\n"; 5663d1dc66SMehdi Amini auto indent = pushIndent(); 5763d1dc66SMehdi Amini for (Block &block : region.getBlocks()) 5863d1dc66SMehdi Amini printBlock(block); 5963d1dc66SMehdi Amini } 6063d1dc66SMehdi Amini printBlock__anon7ab751170111::TestPrintNestingPass6163d1dc66SMehdi Amini void printBlock(Block &block) { 6263d1dc66SMehdi Amini // Print the block intrinsics properties (basically: argument list) 6363d1dc66SMehdi Amini printIndent() 6463d1dc66SMehdi Amini << "Block with " << block.getNumArguments() << " arguments, " 6563d1dc66SMehdi Amini << block.getNumSuccessors() 6663d1dc66SMehdi Amini << " successors, and " 6763d1dc66SMehdi Amini // Note, this `.size()` is traversing a linked-list and is O(n). 6863d1dc66SMehdi Amini << block.getOperations().size() << " operations\n"; 6963d1dc66SMehdi Amini 7063d1dc66SMehdi Amini // Block main role is to hold a list of Operations: let's recurse. 7163d1dc66SMehdi Amini auto indent = pushIndent(); 7263d1dc66SMehdi Amini for (Operation &op : block.getOperations()) 7363d1dc66SMehdi Amini printOperation(&op); 7463d1dc66SMehdi Amini } 7563d1dc66SMehdi Amini 7663d1dc66SMehdi Amini /// Manages the indentation as we traverse the IR nesting. 7763d1dc66SMehdi Amini int indent; 7863d1dc66SMehdi Amini struct IdentRAII { 7963d1dc66SMehdi Amini int &indent; IdentRAII__anon7ab751170111::TestPrintNestingPass::IdentRAII8063d1dc66SMehdi Amini IdentRAII(int &indent) : indent(indent) {} ~IdentRAII__anon7ab751170111::TestPrintNestingPass::IdentRAII8163d1dc66SMehdi Amini ~IdentRAII() { --indent; } 8263d1dc66SMehdi Amini }; resetIndent__anon7ab751170111::TestPrintNestingPass8363d1dc66SMehdi Amini void resetIndent() { indent = 0; } pushIndent__anon7ab751170111::TestPrintNestingPass8463d1dc66SMehdi Amini IdentRAII pushIndent() { return IdentRAII(++indent); } 8563d1dc66SMehdi Amini printIndent__anon7ab751170111::TestPrintNestingPass8663d1dc66SMehdi Amini llvm::raw_ostream &printIndent() { 8763d1dc66SMehdi Amini for (int i = 0; i < indent; ++i) 8863d1dc66SMehdi Amini llvm::outs() << " "; 8963d1dc66SMehdi Amini return llvm::outs(); 9063d1dc66SMehdi Amini } 9163d1dc66SMehdi Amini }; 92be0a7e9fSMehdi Amini } // namespace 9363d1dc66SMehdi Amini 9463d1dc66SMehdi Amini namespace mlir { registerTestPrintNestingPass()9563d1dc66SMehdi Aminivoid registerTestPrintNestingPass() { 96b5e22e6dSMehdi Amini PassRegistration<TestPrintNestingPass>(); 9763d1dc66SMehdi Amini } 9863d1dc66SMehdi Amini } // namespace mlir 99