summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/MergeFunctions.cpp
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2011-01-28 07:36:21 +0000
committerNick Lewycky <nicholas@mxc.ca>2011-01-28 07:36:21 +0000
commit285cf8040da6245d5dbc9ebfac8a8caf3647caf4 (patch)
tree38b28b2b1b007a1dae73a8b43f990017229c06fc /lib/Transforms/IPO/MergeFunctions.cpp
parent1b5c0cb71dd9d529a14cedb4bd89d544bf7e61c3 (diff)
downloadllvm-285cf8040da6245d5dbc9ebfac8a8caf3647caf4.tar.gz
llvm-285cf8040da6245d5dbc9ebfac8a8caf3647caf4.tar.bz2
llvm-285cf8040da6245d5dbc9ebfac8a8caf3647caf4.tar.xz
Reorder for readability. (Chris, is this what you meant?)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@124479 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO/MergeFunctions.cpp')
-rw-r--r--lib/Transforms/IPO/MergeFunctions.cpp298
1 files changed, 150 insertions, 148 deletions
diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp
index 30afaab47c..72047418ac 100644
--- a/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/lib/Transforms/IPO/MergeFunctions.cpp
@@ -157,80 +157,6 @@ namespace llvm {
namespace {
-/// MergeFunctions finds functions which will generate identical machine code,
-/// by considering all pointer types to be equivalent. Once identified,
-/// MergeFunctions will fold them by replacing a call to one to a call to a
-/// bitcast of the other.
-///
-class MergeFunctions : public ModulePass {
-public:
- static char ID;
- MergeFunctions()
- : ModulePass(ID), HasGlobalAliases(false) {
- initializeMergeFunctionsPass(*PassRegistry::getPassRegistry());
- }
-
- bool runOnModule(Module &M);
-
-private:
- typedef DenseSet<ComparableFunction> FnSetType;
-
- /// A work queue of functions that may have been modified and should be
- /// analyzed again.
- std::vector<WeakVH> Deferred;
-
- /// Insert a ComparableFunction into the FnSet, or merge it away if it's
- /// equal to one that's already present.
- bool Insert(ComparableFunction &NewF);
-
- /// Remove a Function from the FnSet and queue it up for a second sweep of
- /// analysis.
- void Remove(Function *F);
-
- /// Find the functions that use this Value and remove them from FnSet and
- /// queue the functions.
- void RemoveUsers(Value *V);
-
- /// Replace all direct calls of Old with calls of New. Will bitcast New if
- /// necessary to make types match.
- void replaceDirectCallers(Function *Old, Function *New);
-
- /// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G
- /// may be deleted, or may be converted into a thunk. In either case, it
- /// should never be visited again.
- void MergeTwoFunctions(Function *F, Function *G);
-
- /// WriteThunkOrAlias - Replace G with a thunk or an alias to F. Deletes G.
- void WriteThunkOrAlias(Function *F, Function *G);
-
- /// WriteThunk - Replace G with a simple tail call to bitcast(F). Also
- /// replace direct uses of G with bitcast(F). Deletes G.
- void WriteThunk(Function *F, Function *G);
-
- /// WriteAlias - Replace G with an alias to F. Deletes G.
- void WriteAlias(Function *F, Function *G);
-
- /// The set of all distinct functions. Use the Insert and Remove methods to
- /// modify it.
- FnSetType FnSet;
-
- /// TargetData for more accurate GEP comparisons. May be NULL.
- TargetData *TD;
-
- /// Whether or not the target supports global aliases.
- bool HasGlobalAliases;
-};
-
-} // end anonymous namespace
-
-char MergeFunctions::ID = 0;
-INITIALIZE_PASS(MergeFunctions, "mergefunc", "Merge Functions", false, false)
-
-ModulePass *llvm::createMergeFunctionsPass() {
- return new MergeFunctions();
-}
-
-namespace {
/// FunctionComparator - Compares two functions to determine whether or not
/// they will generate machine code with the same behaviour. TargetData is
/// used if available. The comparator always fails conservatively (erring on the
@@ -278,6 +204,7 @@ private:
IDMap Map1, Map2;
unsigned long IDMap1Count, IDMap2Count;
};
+
}
/// isEquivalentType - any two pointers in the same address space are
@@ -610,6 +537,155 @@ bool FunctionComparator::Compare() {
return true;
}
+namespace {
+
+/// MergeFunctions finds functions which will generate identical machine code,
+/// by considering all pointer types to be equivalent. Once identified,
+/// MergeFunctions will fold them by replacing a call to one to a call to a
+/// bitcast of the other.
+///
+class MergeFunctions : public ModulePass {
+public:
+ static char ID;
+ MergeFunctions()
+ : ModulePass(ID), HasGlobalAliases(false) {
+ initializeMergeFunctionsPass(*PassRegistry::getPassRegistry());
+ }
+
+ bool runOnModule(Module &M);
+
+private:
+ typedef DenseSet<ComparableFunction> FnSetType;
+
+ /// A work queue of functions that may have been modified and should be
+ /// analyzed again.
+ std::vector<WeakVH> Deferred;
+
+ /// Insert a ComparableFunction into the FnSet, or merge it away if it's
+ /// equal to one that's already present.
+ bool Insert(ComparableFunction &NewF);
+
+ /// Remove a Function from the FnSet and queue it up for a second sweep of
+ /// analysis.
+ void Remove(Function *F);
+
+ /// Find the functions that use this Value and remove them from FnSet and
+ /// queue the functions.
+ void RemoveUsers(Value *V);
+
+ /// Replace all direct calls of Old with calls of New. Will bitcast New if
+ /// necessary to make types match.
+ void replaceDirectCallers(Function *Old, Function *New);
+
+ /// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G
+ /// may be deleted, or may be converted into a thunk. In either case, it
+ /// should never be visited again.
+ void MergeTwoFunctions(Function *F, Function *G);
+
+ /// WriteThunkOrAlias - Replace G with a thunk or an alias to F. Deletes G.
+ void WriteThunkOrAlias(Function *F, Function *G);
+
+ /// WriteThunk - Replace G with a simple tail call to bitcast(F). Also
+ /// replace direct uses of G with bitcast(F). Deletes G.
+ void WriteThunk(Function *F, Function *G);
+
+ /// WriteAlias - Replace G with an alias to F. Deletes G.
+ void WriteAlias(Function *F, Function *G);
+
+ /// The set of all distinct functions. Use the Insert and Remove methods to
+ /// modify it.
+ FnSetType FnSet;
+
+ /// TargetData for more accurate GEP comparisons. May be NULL.
+ TargetData *TD;
+
+ /// Whether or not the target supports global aliases.
+ bool HasGlobalAliases;
+};
+
+} // end anonymous namespace
+
+char MergeFunctions::ID = 0;
+INITIALIZE_PASS(MergeFunctions, "mergefunc", "Merge Functions", false, false)
+
+ModulePass *llvm::createMergeFunctionsPass() {
+ return new MergeFunctions();
+}
+
+bool MergeFunctions::runOnModule(Module &M) {
+ bool Changed = false;
+ TD = getAnalysisIfAvailable<TargetData>();
+
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage())
+ Deferred.push_back(WeakVH(I));
+ }
+ FnSet.resize(Deferred.size());
+
+ do {
+ std::vector<WeakVH> Worklist;
+ Deferred.swap(Worklist);
+
+ DEBUG(dbgs() << "size of module: " << M.size() << '\n');
+ DEBUG(dbgs() << "size of worklist: " << Worklist.size() << '\n');
+
+ // Insert only strong functions and merge them. Strong function merging
+ // always deletes one of them.
+ for (std::vector<WeakVH>::iterator I = Worklist.begin(),
+ E = Worklist.end(); I != E; ++I) {
+ if (!*I) continue;
+ Function *F = cast<Function>(*I);
+ if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
+ !F->mayBeOverridden()) {
+ ComparableFunction CF = ComparableFunction(F, TD);
+ Changed |= Insert(CF);
+ }
+ }
+
+ // Insert only weak functions and merge them. By doing these second we
+ // create thunks to the strong function when possible. When two weak
+ // functions are identical, we create a new strong function with two weak
+ // weak thunks to it which are identical but not mergable.
+ for (std::vector<WeakVH>::iterator I = Worklist.begin(),
+ E = Worklist.end(); I != E; ++I) {
+ if (!*I) continue;
+ Function *F = cast<Function>(*I);
+ if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
+ F->mayBeOverridden()) {
+ ComparableFunction CF = ComparableFunction(F, TD);
+ Changed |= Insert(CF);
+ }
+ }
+ DEBUG(dbgs() << "size of FnSet: " << FnSet.size() << '\n');
+ } while (!Deferred.empty());
+
+ FnSet.clear();
+
+ return Changed;
+}
+
+bool DenseMapInfo<ComparableFunction>::isEqual(const ComparableFunction &LHS,
+ const ComparableFunction &RHS) {
+ if (LHS.getFunc() == RHS.getFunc() &&
+ LHS.getHash() == RHS.getHash())
+ return true;
+ if (!LHS.getFunc() || !RHS.getFunc())
+ return false;
+ assert(LHS.getTD() == RHS.getTD() &&
+ "Comparing functions for different targets");
+
+ bool inserted;
+ bool &result1 = LHS.getOrInsertCachedComparison(RHS, inserted);
+ if (!inserted)
+ return result1;
+ bool &result2 = RHS.getOrInsertCachedComparison(LHS, inserted);
+ if (!inserted)
+ return result1 = result2;
+
+ return result1 = result2 = FunctionComparator(LHS.getTD(), LHS.getFunc(),
+ RHS.getFunc()).Compare();
+}
+
/// Replace direct callers of Old with New.
void MergeFunctions::replaceDirectCallers(Function *Old, Function *New) {
Constant *BitcastNew = ConstantExpr::getBitCast(New, Old->getType());
@@ -792,77 +868,3 @@ void MergeFunctions::RemoveUsers(Value *V) {
}
}
}
-
-bool MergeFunctions::runOnModule(Module &M) {
- bool Changed = false;
- TD = getAnalysisIfAvailable<TargetData>();
-
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
- if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage())
- Deferred.push_back(WeakVH(I));
- }
- FnSet.resize(Deferred.size());
-
- do {
- std::vector<WeakVH> Worklist;
- Deferred.swap(Worklist);
-
- DEBUG(dbgs() << "size of module: " << M.size() << '\n');
- DEBUG(dbgs() << "size of worklist: " << Worklist.size() << '\n');
-
- // Insert only strong functions and merge them. Strong function merging
- // always deletes one of them.
- for (std::vector<WeakVH>::iterator I = Worklist.begin(),
- E = Worklist.end(); I != E; ++I) {
- if (!*I) continue;
- Function *F = cast<Function>(*I);
- if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
- !F->mayBeOverridden()) {
- ComparableFunction CF = ComparableFunction(F, TD);
- Changed |= Insert(CF);
- }
- }
-
- // Insert only weak functions and merge them. By doing these second we
- // create thunks to the strong function when possible. When two weak
- // functions are identical, we create a new strong function with two weak
- // weak thunks to it which are identical but not mergable.
- for (std::vector<WeakVH>::iterator I = Worklist.begin(),
- E = Worklist.end(); I != E; ++I) {
- if (!*I) continue;
- Function *F = cast<Function>(*I);
- if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
- F->mayBeOverridden()) {
- ComparableFunction CF = ComparableFunction(F, TD);
- Changed |= Insert(CF);
- }
- }
- DEBUG(dbgs() << "size of FnSet: " << FnSet.size() << '\n');
- } while (!Deferred.empty());
-
- FnSet.clear();
-
- return Changed;
-}
-
-bool DenseMapInfo<ComparableFunction>::isEqual(const ComparableFunction &LHS,
- const ComparableFunction &RHS) {
- if (LHS.getFunc() == RHS.getFunc() &&
- LHS.getHash() == RHS.getHash())
- return true;
- if (!LHS.getFunc() || !RHS.getFunc())
- return false;
- assert(LHS.getTD() == RHS.getTD() &&
- "Comparing functions for different targets");
-
- bool inserted;
- bool &result1 = LHS.getOrInsertCachedComparison(RHS, inserted);
- if (!inserted)
- return result1;
- bool &result2 = RHS.getOrInsertCachedComparison(LHS, inserted);
- if (!inserted)
- return result1 = result2;
-
- return result1 = result2 = FunctionComparator(LHS.getTD(), LHS.getFunc(),
- RHS.getFunc()).Compare();
-}