diff options
author | Erik Eckstein <eeckstein@apple.com> | 2016-05-31 17:20:23 +0000 |
---|---|---|
committer | Erik Eckstein <eeckstein@apple.com> | 2016-05-31 17:20:23 +0000 |
commit | 0c48dd8ca53f3a962ffa408908b03f4cf45bddcb (patch) | |
tree | 6a6b56378415477e0b0350f98d3601728db1fe8c /llvm/lib/Transforms/IPO/MergeFunctions.cpp | |
parent | 1762eef57240d261e0fc0ec7ad64aafc3e1b3fc6 (diff) | |
download | llvm-0c48dd8ca53f3a962ffa408908b03f4cf45bddcb.zip llvm-0c48dd8ca53f3a962ffa408908b03f4cf45bddcb.tar.gz llvm-0c48dd8ca53f3a962ffa408908b03f4cf45bddcb.tar.bz2 |
Fix a crash in MergeFunctions related to ordering of weak/strong functions
The assumption, made in insert() that weak functions are always inserted after strong functions,
is only true in the first round of adding functions.
In subsequent rounds this is no longer guaranteed , because we might remove a strong function from the tree (because it's modified) and add it later,
where an equivalent weak function already exists in the tree.
This change removes the assert in insert() and explicitly enforces a weak->strong order.
This also removes the need of two separate loops in runOnModule().
llvm-svn: 271299
Diffstat (limited to 'llvm/lib/Transforms/IPO/MergeFunctions.cpp')
-rw-r--r-- | llvm/lib/Transforms/IPO/MergeFunctions.cpp | 44 |
1 files changed, 12 insertions, 32 deletions
diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp index bb0ab84..27caa07 100644 --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -1577,28 +1577,12 @@ bool MergeFunctions::runOnModule(Module &M) { 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. + // Insert functions and merge 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->isInterposable()) { - Changed |= insert(F); - } - } - - // 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->isInterposable()) { + if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage()) { Changed |= insert(F); } } @@ -1838,20 +1822,16 @@ bool MergeFunctions::insert(Function *NewFunction) { // important when operating on more than one module independently to prevent // cycles of thunks calling each other when the modules are linked together. // - // When one function is weak and the other is strong there is an order imposed - // already. We process strong functions before weak functions. - if ((OldF.getFunc()->isInterposable() && NewFunction->isInterposable()) || - (!OldF.getFunc()->isInterposable() && !NewFunction->isInterposable())) - if (OldF.getFunc()->getName() > NewFunction->getName()) { - // Swap the two functions. - Function *F = OldF.getFunc(); - replaceFunctionInTree(*Result.first, NewFunction); - NewFunction = F; - assert(OldF.getFunc() != F && "Must have swapped the functions."); - } - - // Never thunk a strong function to a weak function. - assert(!OldF.getFunc()->isInterposable() || NewFunction->isInterposable()); + // First of all, we process strong functions before weak functions. + if ((OldF.getFunc()->isInterposable() && !NewFunction->isInterposable()) || + (OldF.getFunc()->isInterposable() == NewFunction->isInterposable() && + OldF.getFunc()->getName() > NewFunction->getName())) { + // Swap the two functions. + Function *F = OldF.getFunc(); + replaceFunctionInTree(*Result.first, NewFunction); + NewFunction = F; + assert(OldF.getFunc() != F && "Must have swapped the functions."); + } DEBUG(dbgs() << " " << OldF.getFunc()->getName() << " == " << NewFunction->getName() << '\n'); |