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; }
bool MergeFunctions::runOnModule(Module &M) { bool Changed = false; TD = getAnalysisIfAvailable<TargetData>(); bool LocalChanged; do { DEBUG(dbgs() << "size of module: " << M.size() << '\n'); LocalChanged = false; FnSetType FnSet; // Insert only strong functions and merge them. Strong function merging // always deletes one of them. for (Module::iterator I = M.begin(), E = M.end(); I != E;) { Function *F = I++; if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() && !F->mayBeOverridden() && !IsThunk(F)) { ComparableFunction CF = ComparableFunction(F, TD); LocalChanged |= Insert(FnSet, 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 (Module::iterator I = M.begin(), E = M.end(); I != E;) { Function *F = I++; if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() && F->mayBeOverridden() && !IsThunk(F)) { ComparableFunction CF = ComparableFunction(F, TD); LocalChanged |= Insert(FnSet, CF); } } DEBUG(dbgs() << "size of FnSet: " << FnSet.size() << '\n'); Changed |= LocalChanged; } 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; }