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