MLIR 23.0.0git
DuplicateFunctionElimination.cpp
Go to the documentation of this file.
1//===- DuplicateFunctionElimination.cpp - Duplicate function elimination --===//
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
11
12namespace mlir {
13namespace func {
14#define GEN_PASS_DEF_DUPLICATEFUNCTIONELIMINATIONPASS
15#include "mlir/Dialect/Func/Transforms/Passes.h.inc"
16} // namespace func
17
18namespace {
20// Define a notion of function equivalence that allows for reuse. Ignore the
21// symbol name for this purpose.
22struct DuplicateFuncOpEquivalenceInfo
23 : public llvm::DenseMapInfo<func::FuncOp> {
24
25 static unsigned getHashValue(const func::FuncOp cFunc) {
26 if (!cFunc) {
28 }
30 // Aggregate attributes, ignoring the symbol name.
31 llvm::hash_code hash = {};
32 func::FuncOp func = const_cast<func::FuncOp &>(cFunc);
33 StringAttr symNameAttrName = func.getSymNameAttrName();
34 for (NamedAttribute namedAttr : cFunc->getAttrs()) {
35 StringAttr attrName = namedAttr.getName();
36 if (attrName == symNameAttrName)
37 continue;
38 hash = llvm::hash_combine(hash, namedAttr);
39 }
41 // Also hash the func body.
42 func.getBody().walk([&](Operation *op) {
43 hash = llvm::hash_combine(
48 });
49
50 return hash;
51 }
52
53 static bool isEqual(func::FuncOp lhs, func::FuncOp rhs) {
54 if (lhs == rhs)
55 return true;
56 if (lhs.isDeclaration() || rhs.isDeclaration())
57 return false;
58
59 // Check discardable attributes equivalence
60 if (lhs->getDiscardableAttrDictionary() !=
61 rhs->getDiscardableAttrDictionary())
62 return false;
63
64 // Check properties equivalence, ignoring the symbol name.
65 // Make a copy, so that we can erase the symbol name and perform the
66 // comparison.
67 auto pLhs = lhs.getProperties();
68 auto pRhs = rhs.getProperties();
69 pLhs.sym_name = nullptr;
70 pRhs.sym_name = nullptr;
71 if (pLhs != pRhs)
72 return false;
74 // Compare inner workings.
76 &lhs.getBody(), &rhs.getBody(), OperationEquivalence::IgnoreLocations);
77 }
78};
80struct DuplicateFunctionEliminationPass
82 DuplicateFunctionEliminationPass> {
83
84 using DuplicateFunctionEliminationPassBase<
85 DuplicateFunctionEliminationPass>::DuplicateFunctionEliminationPassBase;
86
87 void runOnOperation() override {
88 auto module = getOperation();
89
90 // Find unique representant per equivalent func ops.
93 DenseSet<func::FuncOp> toBeErased;
94 module.walk([&](func::FuncOp f) {
95 auto [repr, inserted] = uniqueFuncOps.insert(f);
96 getRepresentant[f.getSymNameAttr()] = *repr;
97 if (!inserted) {
98 toBeErased.insert(f);
99 }
100 });
101
102 // Update all symbol uses to reference unique func op
103 // representants and erase redundant func ops.
104 SymbolTableCollection symbolTable;
105 SymbolUserMap userMap(symbolTable, module);
106 for (auto it : toBeErased) {
107 StringAttr oldSymbol = it.getSymNameAttr();
108 StringAttr newSymbol = getRepresentant[oldSymbol].getSymNameAttr();
109 userMap.replaceAllUsesWith(it, newSymbol);
110 it.erase();
111 }
112 }
113};
114
115} // namespace
116} // namespace mlir
static size_t hash(const T &value)
Local helper to compute std::hash for a value.
Definition IRCore.cpp:56
lhs
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
Operation is the basic unit of execution within MLIR.
Definition Operation.h:87
This class represents a collection of SymbolTables.
This class represents a map of symbols to users, and provides efficient implementations of symbol que...
void replaceAllUsesWith(Operation *symbol, StringAttr newSymbolName)
Replace all of the uses of the given symbol with newSymbolName.
Include the generated interface declarations.
llvm::DenseMapInfo< T, Enable > DenseMapInfo
Definition LLVM.h:116
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
Definition LLVM.h:122
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:120
static llvm::hash_code ignoreHashValue(Value)
Helper that can be used with computeHash above to ignore operation operands/result mapping.
static bool isRegionEquivalentTo(Region *lhs, Region *rhs, function_ref< LogicalResult(Value, Value)> checkEquivalent, function_ref< void(Value, Value)> markEquivalent, OperationEquivalence::Flags flags, function_ref< LogicalResult(ValueRange, ValueRange)> checkCommutativeEquivalent=nullptr)
Compare two regions (including their subregions) and return if they are equivalent.
static llvm::hash_code computeHash(Operation *op, function_ref< llvm::hash_code(Value)> hashOperands=[](Value v) { return hash_value(v);}, function_ref< llvm::hash_code(Value)> hashResults=[](Value v) { return hash_value(v);}, Flags flags=Flags::None)
Compute a hash for the given operation.