1ac91e673SRiver Riddle //===- TestSymbolUses.cpp - Pass to test symbol uselists ------------------===//
2ac91e673SRiver Riddle //
3ac91e673SRiver Riddle // Copyright 2019 The MLIR Authors.
4ac91e673SRiver Riddle //
5ac91e673SRiver Riddle // Licensed under the Apache License, Version 2.0 (the "License");
6ac91e673SRiver Riddle // you may not use this file except in compliance with the License.
7ac91e673SRiver Riddle // You may obtain a copy of the License at
8ac91e673SRiver Riddle //
9ac91e673SRiver Riddle //   http://www.apache.org/licenses/LICENSE-2.0
10ac91e673SRiver Riddle //
11ac91e673SRiver Riddle // Unless required by applicable law or agreed to in writing, software
12ac91e673SRiver Riddle // distributed under the License is distributed on an "AS IS" BASIS,
13ac91e673SRiver Riddle // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14ac91e673SRiver Riddle // See the License for the specific language governing permissions and
15ac91e673SRiver Riddle // limitations under the License.
16ac91e673SRiver Riddle // =============================================================================
17ac91e673SRiver Riddle 
18ac91e673SRiver Riddle #include "mlir/IR/Function.h"
19ac91e673SRiver Riddle #include "mlir/Pass/Pass.h"
20ac91e673SRiver Riddle 
21ac91e673SRiver Riddle using namespace mlir;
22ac91e673SRiver Riddle 
23ac91e673SRiver Riddle namespace {
24ac91e673SRiver Riddle /// This is a symbol test pass that tests the symbol uselist functionality
25ac91e673SRiver Riddle /// provided by the symbol table.
26ac91e673SRiver Riddle struct SymbolUsesPass : public ModulePass<SymbolUsesPass> {
27ac91e673SRiver Riddle   void runOnModule() override {
28ac91e673SRiver Riddle     auto module = getModule();
29ac91e673SRiver Riddle 
30ac91e673SRiver Riddle     for (FuncOp func : module.getOps<FuncOp>()) {
31ac91e673SRiver Riddle       // Test computing uses on a non symboltable op.
32b3a6ae83SRiver Riddle       Optional<SymbolTable::UseRange> symbolUses =
33b3a6ae83SRiver Riddle           SymbolTable::getSymbolUses(func);
34b3a6ae83SRiver Riddle 
35b3a6ae83SRiver Riddle       // Test the conservative failure case.
36b3a6ae83SRiver Riddle       if (!symbolUses) {
37b3a6ae83SRiver Riddle         func.emitRemark() << "function contains an unknown nested operation "
38b3a6ae83SRiver Riddle                              "that 'may' define a new symbol table";
39b3a6ae83SRiver Riddle         return;
40b3a6ae83SRiver Riddle       }
41b3a6ae83SRiver Riddle       if (unsigned numUses = llvm::size(*symbolUses))
42ac91e673SRiver Riddle         func.emitRemark() << "function contains " << numUses
43ac91e673SRiver Riddle                           << " nested references";
44ac91e673SRiver Riddle 
45b3a6ae83SRiver Riddle       // Test the functionality of symbolKnownUseEmpty.
469ac459e8SRiver Riddle       if (func.symbolKnownUseEmpty(module)) {
47ac91e673SRiver Riddle         func.emitRemark() << "function has no uses";
48ac91e673SRiver Riddle         continue;
49ac91e673SRiver Riddle       }
50ac91e673SRiver Riddle 
51b3a6ae83SRiver Riddle       // Test the functionality of getSymbolUses.
529ac459e8SRiver Riddle       symbolUses = func.getSymbolUses(module);
53b3a6ae83SRiver Riddle       assert(symbolUses.hasValue() && "expected no unknown operations");
54b3a6ae83SRiver Riddle       for (SymbolTable::SymbolUse symbolUse : *symbolUses) {
55ac91e673SRiver Riddle         symbolUse.getUser()->emitRemark()
56ac91e673SRiver Riddle             << "found use of function : " << symbolUse.getSymbolRef();
57b3a6ae83SRiver Riddle       }
58b3a6ae83SRiver Riddle       func.emitRemark() << "function has " << llvm::size(*symbolUses)
59b3a6ae83SRiver Riddle                         << " uses";
60ac91e673SRiver Riddle     }
61ac91e673SRiver Riddle   }
62ac91e673SRiver Riddle };
63*ef43b565SRiver Riddle 
64*ef43b565SRiver Riddle /// This is a symbol test pass that tests the symbol use replacement
65*ef43b565SRiver Riddle /// functionality provided by the symbol table.
66*ef43b565SRiver Riddle struct SymbolReplacementPass : public ModulePass<SymbolReplacementPass> {
67*ef43b565SRiver Riddle   void runOnModule() override {
68*ef43b565SRiver Riddle     auto module = getModule();
69*ef43b565SRiver Riddle 
70*ef43b565SRiver Riddle     for (FuncOp func : module.getOps<FuncOp>()) {
71*ef43b565SRiver Riddle       StringAttr newName = func.getAttrOfType<StringAttr>("sym.new_name");
72*ef43b565SRiver Riddle       if (!newName)
73*ef43b565SRiver Riddle         continue;
74*ef43b565SRiver Riddle       if (succeeded(func.replaceAllSymbolUses(newName.getValue(), module)))
75*ef43b565SRiver Riddle         func.setName(newName.getValue());
76*ef43b565SRiver Riddle     }
77*ef43b565SRiver Riddle   }
78*ef43b565SRiver Riddle };
79ac91e673SRiver Riddle } // end anonymous namespace
80ac91e673SRiver Riddle 
81ac91e673SRiver Riddle static PassRegistration<SymbolUsesPass> pass("test-symbol-uses",
82ac91e673SRiver Riddle                                              "Test detection of symbol uses");
83*ef43b565SRiver Riddle 
84*ef43b565SRiver Riddle static PassRegistration<SymbolReplacementPass>
85*ef43b565SRiver Riddle     rauwPass("test-symbol-rauw", "Test replacement of symbol uses");
86