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/Dialect/StandardOps/IR/Ops.h" 10 #include "mlir/IR/BuiltinOps.h" 11 #include "mlir/Pass/Pass.h" 12 13 using namespace mlir; 14 15 namespace { 16 /// This pass illustrates the IR nesting through printing. 17 struct TestPrintNestingPass 18 : public PassWrapper<TestPrintNestingPass, OperationPass<>> { 19 // Entry point for the pass. runOnOperation__anon3176e55e0111::TestPrintNestingPass20 void runOnOperation() override { 21 Operation *op = getOperation(); 22 resetIndent(); 23 printOperation(op); 24 } 25 26 /// The three methods below are mutually recursive and follow the nesting of 27 /// the IR: operation->region->block->operation->... 28 printOperation__anon3176e55e0111::TestPrintNestingPass29 void printOperation(Operation *op) { 30 // Print the operation itself and some of its properties 31 printIndent() << "visiting op: '" << op->getName() << "' with " 32 << op->getNumOperands() << " operands and " 33 << op->getNumResults() << " results\n"; 34 // Print the operation attributes 35 if (!op->getAttrs().empty()) { 36 printIndent() << op->getAttrs().size() << " attributes:\n"; 37 for (NamedAttribute attr : op->getAttrs()) 38 printIndent() << " - '" << attr.first << "' : '" << attr.second 39 << "'\n"; 40 } 41 42 // Recurse into each of the regions attached to the operation. 43 printIndent() << " " << op->getNumRegions() << " nested regions:\n"; 44 auto indent = pushIndent(); 45 for (Region ®ion : op->getRegions()) 46 printRegion(region); 47 } 48 printRegion__anon3176e55e0111::TestPrintNestingPass49 void printRegion(Region ®ion) { 50 // A region does not hold anything by itself other than a list of blocks. 51 printIndent() << "Region with " << region.getBlocks().size() 52 << " blocks:\n"; 53 auto indent = pushIndent(); 54 for (Block &block : region.getBlocks()) 55 printBlock(block); 56 } 57 printBlock__anon3176e55e0111::TestPrintNestingPass58 void printBlock(Block &block) { 59 // Print the block intrinsics properties (basically: argument list) 60 printIndent() 61 << "Block with " << block.getNumArguments() << " arguments, " 62 << block.getNumSuccessors() 63 << " successors, and " 64 // Note, this `.size()` is traversing a linked-list and is O(n). 65 << block.getOperations().size() << " operations\n"; 66 67 // Block main role is to hold a list of Operations: let's recurse. 68 auto indent = pushIndent(); 69 for (Operation &op : block.getOperations()) 70 printOperation(&op); 71 } 72 73 /// Manages the indentation as we traverse the IR nesting. 74 int indent; 75 struct IdentRAII { 76 int &indent; IdentRAII__anon3176e55e0111::TestPrintNestingPass::IdentRAII77 IdentRAII(int &indent) : indent(indent) {} ~IdentRAII__anon3176e55e0111::TestPrintNestingPass::IdentRAII78 ~IdentRAII() { --indent; } 79 }; resetIndent__anon3176e55e0111::TestPrintNestingPass80 void resetIndent() { indent = 0; } pushIndent__anon3176e55e0111::TestPrintNestingPass81 IdentRAII pushIndent() { return IdentRAII(++indent); } 82 printIndent__anon3176e55e0111::TestPrintNestingPass83 llvm::raw_ostream &printIndent() { 84 for (int i = 0; i < indent; ++i) 85 llvm::outs() << " "; 86 return llvm::outs(); 87 } 88 }; 89 } // end anonymous namespace 90 91 namespace mlir { registerTestPrintNestingPass()92void registerTestPrintNestingPass() { 93 PassRegistration<TestPrintNestingPass>("test-print-nesting", 94 "Test various printing."); 95 } 96 } // namespace mlir 97