xref: /llvm-project/mlir/test/lib/IR/TestPrintNesting.cpp (revision 5e50dd048e3a20cde5da5d7a754dfee775ef35d6)
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 &region : op->getRegions())
49       printRegion(region);
50   }
51 
printRegion__anonb6b2ab1a0111::TestPrintNestingPass52   void printRegion(Region &region) {
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()95 void registerTestPrintNestingPass() {
96   PassRegistration<TestPrintNestingPass>();
97 }
98 } // namespace mlir
99