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 &region : op->getRegions())
4963d1dc66SMehdi Amini       printRegion(region);
5063d1dc66SMehdi Amini   }
5163d1dc66SMehdi Amini 
printRegion__anon7ab751170111::TestPrintNestingPass5263d1dc66SMehdi Amini   void printRegion(Region &region) {
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 Amini void registerTestPrintNestingPass() {
96b5e22e6dSMehdi Amini   PassRegistration<TestPrintNestingPass>();
9763d1dc66SMehdi Amini }
9863d1dc66SMehdi Amini } // namespace mlir
99