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 
18*b8cd0c14STres Popp #include "TestDialect.h"
19ac91e673SRiver Riddle #include "mlir/IR/Function.h"
20ac91e673SRiver Riddle #include "mlir/Pass/Pass.h"
21ac91e673SRiver Riddle 
22ac91e673SRiver Riddle using namespace mlir;
23ac91e673SRiver Riddle 
24ac91e673SRiver Riddle namespace {
25ac91e673SRiver Riddle /// This is a symbol test pass that tests the symbol uselist functionality
26*b8cd0c14STres Popp /// provided by the symbol table along with erasing from the symbol table.
27ac91e673SRiver Riddle struct SymbolUsesPass : public ModulePass<SymbolUsesPass> {
28ac91e673SRiver Riddle   void runOnModule() override {
29ac91e673SRiver Riddle     auto module = getModule();
30*b8cd0c14STres Popp     std::vector<FuncOp> ops_to_delete;
31ac91e673SRiver Riddle 
32ac91e673SRiver Riddle     for (FuncOp func : module.getOps<FuncOp>()) {
33ac91e673SRiver Riddle       // Test computing uses on a non symboltable op.
34b3a6ae83SRiver Riddle       Optional<SymbolTable::UseRange> symbolUses =
35b3a6ae83SRiver Riddle           SymbolTable::getSymbolUses(func);
36b3a6ae83SRiver Riddle 
37b3a6ae83SRiver Riddle       // Test the conservative failure case.
38b3a6ae83SRiver Riddle       if (!symbolUses) {
39b3a6ae83SRiver Riddle         func.emitRemark() << "function contains an unknown nested operation "
40b3a6ae83SRiver Riddle                              "that 'may' define a new symbol table";
41b3a6ae83SRiver Riddle         return;
42b3a6ae83SRiver Riddle       }
43b3a6ae83SRiver Riddle       if (unsigned numUses = llvm::size(*symbolUses))
44ac91e673SRiver Riddle         func.emitRemark() << "function contains " << numUses
45ac91e673SRiver Riddle                           << " nested references";
46ac91e673SRiver Riddle 
47b3a6ae83SRiver Riddle       // Test the functionality of symbolKnownUseEmpty.
489ac459e8SRiver Riddle       if (func.symbolKnownUseEmpty(module)) {
49ac91e673SRiver Riddle         func.emitRemark() << "function has no uses";
50*b8cd0c14STres Popp         if (func.getBody().empty())
51*b8cd0c14STres Popp           ops_to_delete.push_back(func);
52ac91e673SRiver Riddle         continue;
53ac91e673SRiver Riddle       }
54ac91e673SRiver Riddle 
55b3a6ae83SRiver Riddle       // Test the functionality of getSymbolUses.
569ac459e8SRiver Riddle       symbolUses = func.getSymbolUses(module);
57b3a6ae83SRiver Riddle       assert(symbolUses.hasValue() && "expected no unknown operations");
58b3a6ae83SRiver Riddle       for (SymbolTable::SymbolUse symbolUse : *symbolUses) {
59ac91e673SRiver Riddle         symbolUse.getUser()->emitRemark()
60ac91e673SRiver Riddle             << "found use of function : " << symbolUse.getSymbolRef();
61b3a6ae83SRiver Riddle       }
62b3a6ae83SRiver Riddle       func.emitRemark() << "function has " << llvm::size(*symbolUses)
63b3a6ae83SRiver Riddle                         << " uses";
64ac91e673SRiver Riddle     }
65*b8cd0c14STres Popp 
66*b8cd0c14STres Popp     for (FuncOp func : ops_to_delete) {
67*b8cd0c14STres Popp       // In order to test the SymbolTable::erase method, also erase completely
68*b8cd0c14STres Popp       // useless functions.
69*b8cd0c14STres Popp       SymbolTable table(module);
70*b8cd0c14STres Popp       auto func_name = func.getName();
71*b8cd0c14STres Popp       assert(table.lookup(func_name) && "expected no unknown operations");
72*b8cd0c14STres Popp       table.erase(func);
73*b8cd0c14STres Popp       assert(!table.lookup(func_name) &&
74*b8cd0c14STres Popp              "expected erased operation to be unknown now");
75*b8cd0c14STres Popp       module.emitRemark() << func_name << " function successfully erased";
76*b8cd0c14STres Popp     }
77ac91e673SRiver Riddle   }
78ac91e673SRiver Riddle };
79ef43b565SRiver Riddle 
80ef43b565SRiver Riddle /// This is a symbol test pass that tests the symbol use replacement
81ef43b565SRiver Riddle /// functionality provided by the symbol table.
82ef43b565SRiver Riddle struct SymbolReplacementPass : public ModulePass<SymbolReplacementPass> {
83ef43b565SRiver Riddle   void runOnModule() override {
84ef43b565SRiver Riddle     auto module = getModule();
85ef43b565SRiver Riddle 
86ef43b565SRiver Riddle     for (FuncOp func : module.getOps<FuncOp>()) {
87ef43b565SRiver Riddle       StringAttr newName = func.getAttrOfType<StringAttr>("sym.new_name");
88ef43b565SRiver Riddle       if (!newName)
89ef43b565SRiver Riddle         continue;
90ef43b565SRiver Riddle       if (succeeded(func.replaceAllSymbolUses(newName.getValue(), module)))
91ef43b565SRiver Riddle         func.setName(newName.getValue());
92ef43b565SRiver Riddle     }
93ef43b565SRiver Riddle   }
94ef43b565SRiver Riddle };
95ac91e673SRiver Riddle } // end anonymous namespace
96ac91e673SRiver Riddle 
97ac91e673SRiver Riddle static PassRegistration<SymbolUsesPass> pass("test-symbol-uses",
98ac91e673SRiver Riddle                                              "Test detection of symbol uses");
99ef43b565SRiver Riddle 
100ef43b565SRiver Riddle static PassRegistration<SymbolReplacementPass>
101ef43b565SRiver Riddle     rauwPass("test-symbol-rauw", "Test replacement of symbol uses");
102