1 //===- TestPrintNesting.cpp - Passes to illustrate the IR nesting ---------===// 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 #include "mlir/IR/BuiltinOps.h" 10 #include "mlir/Pass/Pass.h" 11 12 using namespace mlir; 13 14 namespace { 15 /// This pass illustrates the IR nesting through printing. 16 struct TestPrintNestingPass 17 : public PassWrapper<TestPrintNestingPass, OperationPass<>> { MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID__anonb6b2ab1a0111::TestPrintNestingPass18 MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(TestPrintNestingPass) 19 20 StringRef getArgument() const final { return "test-print-nesting"; } getDescription__anonb6b2ab1a0111::TestPrintNestingPass21 StringRef getDescription() const final { return "Test various printing."; } 22 // Entry point for the pass. runOnOperation__anonb6b2ab1a0111::TestPrintNestingPass23 void runOnOperation() override { 24 Operation *op = getOperation(); 25 resetIndent(); 26 printOperation(op); 27 } 28 29 /// The three methods below are mutually recursive and follow the nesting of 30 /// the IR: operation->region->block->operation->... 31 printOperation__anonb6b2ab1a0111::TestPrintNestingPass32 void printOperation(Operation *op) { 33 // Print the operation itself and some of its properties 34 printIndent() << "visiting op: '" << op->getName() << "' with " 35 << op->getNumOperands() << " operands and " 36 << op->getNumResults() << " results\n"; 37 // Print the operation attributes 38 if (!op->getAttrs().empty()) { 39 printIndent() << op->getAttrs().size() << " attributes:\n"; 40 for (NamedAttribute attr : op->getAttrs()) 41 printIndent() << " - '" << attr.getName().getValue() << "' : '" 42 << attr.getValue() << "'\n"; 43 } 44 45 // Recurse into each of the regions attached to the operation. 46 printIndent() << " " << op->getNumRegions() << " nested regions:\n"; 47 auto indent = pushIndent(); 48 for (Region ®ion : op->getRegions()) 49 printRegion(region); 50 } 51 printRegion__anonb6b2ab1a0111::TestPrintNestingPass52 void printRegion(Region ®ion) { 53 // A region does not hold anything by itself other than a list of blocks. 54 printIndent() << "Region with " << region.getBlocks().size() 55 << " blocks:\n"; 56 auto indent = pushIndent(); 57 for (Block &block : region.getBlocks()) 58 printBlock(block); 59 } 60 printBlock__anonb6b2ab1a0111::TestPrintNestingPass61 void printBlock(Block &block) { 62 // Print the block intrinsics properties (basically: argument list) 63 printIndent() 64 << "Block with " << block.getNumArguments() << " arguments, " 65 << block.getNumSuccessors() 66 << " successors, and " 67 // Note, this `.size()` is traversing a linked-list and is O(n). 68 << block.getOperations().size() << " operations\n"; 69 70 // Block main role is to hold a list of Operations: let's recurse. 71 auto indent = pushIndent(); 72 for (Operation &op : block.getOperations()) 73 printOperation(&op); 74 } 75 76 /// Manages the indentation as we traverse the IR nesting. 77 int indent; 78 struct IdentRAII { 79 int &indent; IdentRAII__anonb6b2ab1a0111::TestPrintNestingPass::IdentRAII80 IdentRAII(int &indent) : indent(indent) {} ~IdentRAII__anonb6b2ab1a0111::TestPrintNestingPass::IdentRAII81 ~IdentRAII() { --indent; } 82 }; resetIndent__anonb6b2ab1a0111::TestPrintNestingPass83 void resetIndent() { indent = 0; } pushIndent__anonb6b2ab1a0111::TestPrintNestingPass84 IdentRAII pushIndent() { return IdentRAII(++indent); } 85 printIndent__anonb6b2ab1a0111::TestPrintNestingPass86 llvm::raw_ostream &printIndent() { 87 for (int i = 0; i < indent; ++i) 88 llvm::outs() << " "; 89 return llvm::outs(); 90 } 91 }; 92 } // namespace 93 94 namespace mlir { registerTestPrintNestingPass()95void registerTestPrintNestingPass() { 96 PassRegistration<TestPrintNestingPass>(); 97 } 98 } // namespace mlir 99