1 //===- MergeFunctions.cpp - Merge identical functions ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This pass looks for equivalent functions that are mergable and folds them.
12 // A Function will not be analyzed if:
13 // * it is overridable at runtime (except for weak linkage), or
14 // * it is used by anything other than the callee parameter of a call/invoke
16 // A hash is computed from the function, based on its type and number of
19 // Once all hashes are computed, we perform an expensive equality comparison
20 // on each function pair. This takes n^2/2 comparisons per bucket, so it's
21 // important that the hash function be high quality. The equality comparison
22 // iterates through each instruction in each basic block.
24 // When a match is found, the functions are folded. We can only fold two
25 // functions when we know that the definition of one of them is not
27 // * fold a function marked internal by replacing all of its users.
28 // * fold extern or weak functions by replacing them with a global alias
30 //===----------------------------------------------------------------------===//
34 // * fold vector<T*>::push_back and vector<S*>::push_back.
36 // These two functions have different types, but in a way that doesn't matter
37 // to us. As long as we never see an S or T itself, using S* and S** is the
38 // same as using a T* and T**.
40 // * virtual functions.
42 // Many functions have their address taken by the virtual function table for
43 // the object they belong to. However, as long as it's only used for a lookup
44 // and call, this is irrelevant, and we'd like to fold such implementations.
46 //===----------------------------------------------------------------------===//
48 #define DEBUG_TYPE "mergefunc"
49 #include "llvm/Transforms/IPO.h"
50 #include "llvm/ADT/DenseMap.h"
51 #include "llvm/ADT/Statistic.h"
52 #include "llvm/Constants.h"
53 #include "llvm/InlineAsm.h"
54 #include "llvm/Instructions.h"
55 #include "llvm/Module.h"
56 #include "llvm/Pass.h"
57 #include "llvm/Support/CallSite.h"
58 #include "llvm/Support/Compiler.h"
59 #include "llvm/Support/Debug.h"
64 STATISTIC(NumFunctionsMerged
, "Number of functions merged");
65 STATISTIC(NumMergeFails
, "Number of identical function pairings not merged");
68 struct VISIBILITY_HIDDEN MergeFunctions
: public ModulePass
{
69 static char ID
; // Pass identification, replacement for typeid
70 MergeFunctions() : ModulePass((intptr_t)&ID
) {}
72 bool runOnModule(Module
&M
);
76 char MergeFunctions::ID
= 0;
77 static RegisterPass
<MergeFunctions
>
78 X("mergefunc", "Merge Functions");
80 ModulePass
*llvm::createMergeFunctionsPass() {
81 return new MergeFunctions();
84 static unsigned long hash(const Function
*F
) {
85 return F
->size() ^ reinterpret_cast<unsigned long>(F
->getType());
86 //return F->size() ^ F->arg_size() ^ F->getReturnType();
89 static bool compare(const Value
*V
, const Value
*U
) {
90 assert(!isa
<BasicBlock
>(V
) && !isa
<BasicBlock
>(U
) &&
91 "Must not compare basic blocks.");
93 assert(V
->getType() == U
->getType() &&
94 "Two of the same operation have operands of different type.");
96 // TODO: If the constant is an expression of F, we should accept that it's
97 // equal to the same expression in terms of G.
101 // The caller has ensured that ValueMap[V] != U. Since Arguments are
102 // pre-loaded into the ValueMap, and Instructions are added as we go, we know
103 // that this can only be a mis-match.
104 if (isa
<Instruction
>(V
) || isa
<Argument
>(V
))
107 if (isa
<InlineAsm
>(V
) && isa
<InlineAsm
>(U
)) {
108 const InlineAsm
*IAF
= cast
<InlineAsm
>(V
);
109 const InlineAsm
*IAG
= cast
<InlineAsm
>(U
);
110 return IAF
->getAsmString() == IAG
->getAsmString() &&
111 IAF
->getConstraintString() == IAG
->getConstraintString();
117 static bool equals(const BasicBlock
*BB1
, const BasicBlock
*BB2
,
118 DenseMap
<const Value
*, const Value
*> &ValueMap
,
119 DenseMap
<const Value
*, const Value
*> &SpeculationMap
) {
120 // Specutively add it anyways. If it's false, we'll notice a difference later, and
121 // this won't matter.
124 BasicBlock::const_iterator FI
= BB1
->begin(), FE
= BB1
->end();
125 BasicBlock::const_iterator GI
= BB2
->begin(), GE
= BB2
->end();
128 if (!FI
->isSameOperationAs(const_cast<Instruction
*>(&*GI
)))
131 if (FI
->getNumOperands() != GI
->getNumOperands())
134 if (ValueMap
[FI
] == GI
) {
139 if (ValueMap
[FI
] != NULL
)
142 for (unsigned i
= 0, e
= FI
->getNumOperands(); i
!= e
; ++i
) {
143 Value
*OpF
= FI
->getOperand(i
);
144 Value
*OpG
= GI
->getOperand(i
);
146 if (ValueMap
[OpF
] == OpG
)
149 if (ValueMap
[OpF
] != NULL
)
152 assert(OpF
->getType() == OpG
->getType() &&
153 "Two of the same operation has operands of different type.");
155 if (OpF
->getValueID() != OpG
->getValueID())
158 if (isa
<PHINode
>(FI
)) {
159 if (SpeculationMap
[OpF
] == NULL
)
160 SpeculationMap
[OpF
] = OpG
;
161 else if (SpeculationMap
[OpF
] != OpG
)
164 } else if (isa
<BasicBlock
>(OpF
)) {
165 assert(isa
<TerminatorInst
>(FI
) &&
166 "BasicBlock referenced by non-Terminator non-PHI");
167 // This call changes the ValueMap, hence we can't use
168 // Value *& = ValueMap[...]
169 if (!equals(cast
<BasicBlock
>(OpF
), cast
<BasicBlock
>(OpG
), ValueMap
,
173 if (!compare(OpF
, OpG
))
182 } while (FI
!= FE
&& GI
!= GE
);
184 return FI
== FE
&& GI
== GE
;
187 static bool equals(const Function
*F
, const Function
*G
) {
188 // We need to recheck everything, but check the things that weren't included
189 // in the hash first.
191 if (F
->getAttributes() != G
->getAttributes())
194 if (F
->hasGC() != G
->hasGC())
197 if (F
->hasGC() && F
->getGC() != G
->getGC())
200 if (F
->hasSection() != G
->hasSection())
203 if (F
->hasSection() && F
->getSection() != G
->getSection())
206 // TODO: if it's internal and only used in direct calls, we could handle this
208 if (F
->getCallingConv() != G
->getCallingConv())
211 // TODO: We want to permit cases where two functions take T* and S* but
212 // only load or store them into T** and S**.
213 if (F
->getType() != G
->getType())
216 DenseMap
<const Value
*, const Value
*> ValueMap
;
217 DenseMap
<const Value
*, const Value
*> SpeculationMap
;
220 assert(F
->arg_size() == G
->arg_size() &&
221 "Identical functions have a different number of args.");
223 for (Function::const_arg_iterator fi
= F
->arg_begin(), gi
= G
->arg_begin(),
224 fe
= F
->arg_end(); fi
!= fe
; ++fi
, ++gi
)
227 if (!equals(&F
->getEntryBlock(), &G
->getEntryBlock(), ValueMap
,
231 for (DenseMap
<const Value
*, const Value
*>::iterator
232 I
= SpeculationMap
.begin(), E
= SpeculationMap
.end(); I
!= E
; ++I
) {
233 if (ValueMap
[I
->first
] != I
->second
)
240 static bool fold(std::vector
<Function
*> &FnVec
, unsigned i
, unsigned j
) {
241 if (FnVec
[i
]->mayBeOverridden() && !FnVec
[j
]->mayBeOverridden())
242 std::swap(FnVec
[i
], FnVec
[j
]);
244 Function
*F
= FnVec
[i
];
245 Function
*G
= FnVec
[j
];
247 if (!F
->mayBeOverridden()) {
248 if (G
->hasLocalLinkage()) {
249 F
->setAlignment(std::max(F
->getAlignment(), G
->getAlignment()));
250 G
->replaceAllUsesWith(F
);
251 G
->eraseFromParent();
252 ++NumFunctionsMerged
;
256 if (G
->hasExternalLinkage() || G
->hasWeakLinkage()) {
257 GlobalAlias
*GA
= new GlobalAlias(G
->getType(), G
->getLinkage(), "",
259 F
->setAlignment(std::max(F
->getAlignment(), G
->getAlignment()));
261 GA
->setVisibility(G
->getVisibility());
262 G
->replaceAllUsesWith(GA
);
263 G
->eraseFromParent();
264 ++NumFunctionsMerged
;
269 if (F
->hasWeakLinkage() && G
->hasWeakLinkage()) {
270 GlobalAlias
*GA_F
= new GlobalAlias(F
->getType(), F
->getLinkage(), "",
273 GA_F
->setVisibility(F
->getVisibility());
274 F
->setAlignment(std::max(F
->getAlignment(), G
->getAlignment()));
275 F
->replaceAllUsesWith(GA_F
);
276 F
->setName("folded." + GA_F
->getName());
277 F
->setLinkage(GlobalValue::ExternalLinkage
);
280 GlobalAlias
*GA_G
= new GlobalAlias(G
->getType(), G
->getLinkage(), "",
283 GA_G
->setVisibility(G
->getVisibility());
284 G
->replaceAllUsesWith(GA_G
);
285 G
->eraseFromParent();
287 ++NumFunctionsMerged
;
291 DOUT
<< "Failed on " << F
->getName() << " and " << G
->getName() << "\n";
297 static bool hasAddressTaken(User
*U
) {
298 for (User::use_iterator I
= U
->use_begin(), E
= U
->use_end(); I
!= E
; ++I
) {
301 // 'call (bitcast @F to ...)' happens a lot.
302 while (isa
<ConstantExpr
>(Use
) && Use
->hasOneUse()) {
303 Use
= *Use
->use_begin();
306 if (isa
<ConstantExpr
>(Use
)) {
307 if (hasAddressTaken(Use
))
311 if (!isa
<CallInst
>(Use
) && !isa
<InvokeInst
>(Use
))
314 // Make sure we aren't passing U as a parameter to call instead of the
316 if (CallSite(cast
<Instruction
>(Use
)).hasArgument(U
))
323 bool MergeFunctions::runOnModule(Module
&M
) {
324 bool Changed
= false;
326 std::map
<unsigned long, std::vector
<Function
*> > FnMap
;
328 for (Module::iterator F
= M
.begin(), E
= M
.end(); F
!= E
; ++F
) {
329 if (F
->isDeclaration() || F
->isIntrinsic())
332 if (!F
->hasLocalLinkage() && !F
->hasExternalLinkage() &&
333 !F
->hasWeakLinkage())
336 if (hasAddressTaken(F
))
339 FnMap
[hash(F
)].push_back(F
);
342 // TODO: instead of running in a loop, we could also fold functions in callgraph
343 // order. Constructing the CFG probably isn't cheaper than just running in a loop.
347 LocalChanged
= false;
348 for (std::map
<unsigned long, std::vector
<Function
*> >::iterator
349 I
= FnMap
.begin(), E
= FnMap
.end(); I
!= E
; ++I
) {
350 DOUT
<< "size: " << FnMap
.size() << "\n";
351 std::vector
<Function
*> &FnVec
= I
->second
;
352 DOUT
<< "hash (" << I
->first
<< "): " << FnVec
.size() << "\n";
354 for (int i
= 0, e
= FnVec
.size(); i
!= e
; ++i
) {
355 for (int j
= i
+ 1; j
!= e
; ++j
) {
356 bool isEqual
= equals(FnVec
[i
], FnVec
[j
]);
358 DOUT
<< " " << FnVec
[i
]->getName()
359 << (isEqual
? " == " : " != ")
360 << FnVec
[j
]->getName() << "\n";
363 if (fold(FnVec
, i
, j
)) {
365 FnVec
.erase(FnVec
.begin() + j
);
373 Changed
|= LocalChanged
;
374 } while (LocalChanged
);