[llvm-commits] [llvm] r112595 - /llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
Nick Lewycky
nicholas at mxc.ca
Tue Aug 31 01:29:37 PDT 2010
Author: nicholas
Date: Tue Aug 31 03:29:37 2010
New Revision: 112595
URL: http://llvm.org/viewvc/llvm-project?rev=112595&view=rev
Log:
Fix an infinite loop; merging two functions will create a new function (if the
two are weak, we make them thunks to a new strong function) so don't iterate
through the function list as we're modifying it.
Also add back the outermost loop which got removed during the cleanups.
Modified:
llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
Modified: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp?rev=112595&r1=112594&r2=112595&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp Tue Aug 31 03:29:37 2010
@@ -63,6 +63,7 @@
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetData.h"
+#include <vector>
using namespace llvm;
STATISTIC(NumFunctionsMerged, "Number of functions merged");
@@ -82,7 +83,8 @@
private:
/// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G
- /// is deleted.
+ /// 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) const;
/// WriteThunk - Replace G with a simple tail call to bitcast(F). Also
@@ -598,41 +600,53 @@
};
bool MergeFunctions::runOnModule(Module &M) {
- bool Changed = false;
+ typedef DenseSet<ComparableFunction *, MergeFunctionsEqualityInfo> FnSetType;
+ bool Changed = false;
TD = getAnalysisIfAvailable<TargetData>();
- typedef DenseSet<ComparableFunction *, MergeFunctionsEqualityInfo> FnSetType;
- FnSetType FnSet;
- for (Module::iterator F = M.begin(), E = M.end(); F != E;) {
- if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
- ++F;
- continue;
- }
+ std::vector<Function *> Funcs;
+ for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
+ if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage())
+ Funcs.push_back(F);
+ }
+
+ bool LocalChanged;
+ do {
+ LocalChanged = false;
- ComparableFunction *NewF = new ComparableFunction(F, TD);
- ++F;
- std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF);
- if (!Result.second) {
- ComparableFunction *&OldF = *Result.first;
- assert(OldF && "Expected a hash collision");
-
- // NewF will be deleted in favour of OldF unless NewF is strong and OldF
- // is weak in which case swap them to keep the strong definition.
-
- if (OldF->Func->isWeakForLinker() && !NewF->Func->isWeakForLinker())
- std::swap(OldF, NewF);
-
- DEBUG(dbgs() << " " << OldF->Func->getName() << " == "
- << NewF->Func->getName() << '\n');
-
- Changed = true;
- Function *DeleteF = NewF->Func;
- delete NewF;
- MergeTwoFunctions(OldF->Func, DeleteF);
+ FnSetType FnSet;
+ for (unsigned i = 0, e = Funcs.size(); i != e;) {
+ Function *F = Funcs[i];
+ ComparableFunction *NewF = new ComparableFunction(F, TD);
+ std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF);
+ if (!Result.second) {
+ ComparableFunction *&OldF = *Result.first;
+ assert(OldF && "Expected a hash collision");
+
+ // NewF will be deleted in favour of OldF unless NewF is strong and
+ // OldF is weak in which case swap them to keep the strong definition.
+
+ if (OldF->Func->isWeakForLinker() && !NewF->Func->isWeakForLinker())
+ std::swap(OldF, NewF);
+
+ DEBUG(dbgs() << " " << OldF->Func->getName() << " == "
+ << NewF->Func->getName() << '\n');
+
+ Funcs.erase(Funcs.begin() + i);
+ --e;
+
+ Function *DeleteF = NewF->Func;
+ delete NewF;
+ MergeTwoFunctions(OldF->Func, DeleteF);
+ LocalChanged = true;
+ Changed = true;
+ } else {
+ ++i;
+ }
}
- }
+ DeleteContainerPointers(FnSet);
+ } while (LocalChanged);
- DeleteContainerPointers(FnSet);
return Changed;
}
More information about the llvm-commits
mailing list