bool MergeFunctions::runOnModule(Module &M) { typedef DenseSet<ComparableFunction *, MergeFunctionsEqualityInfo> FnSetType; bool Changed = false; TD = getAnalysisIfAvailable<TargetData>(); 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; 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); return Changed; }
// Insert - Insert a ComparableFunction into the FnSet, or merge it away if // equal to one that's already inserted. bool MergeFunctions::Insert(FnSetType &FnSet, ComparableFunction &NewF) { std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF); if (Result.second) return false; const ComparableFunction &OldF = *Result.first; // Never thunk a strong function to a weak function. assert(!OldF.getFunc()->mayBeOverridden() || NewF.getFunc()->mayBeOverridden()); DEBUG(dbgs() << " " << OldF.getFunc()->getName() << " == " << NewF.getFunc()->getName() << '\n'); Function *DeleteF = NewF.getFunc(); NewF.release(); MergeTwoFunctions(OldF.getFunc(), DeleteF); return true; }