diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:50:12 +0000 |
commit | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch) | |
tree | 599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/Transforms/IPO/MergeFunctions.cpp | |
parent | 1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff) |
Diffstat (limited to 'lib/Transforms/IPO/MergeFunctions.cpp')
-rw-r--r-- | lib/Transforms/IPO/MergeFunctions.cpp | 70 |
1 files changed, 27 insertions, 43 deletions
diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 11efe95b10d4..3a08069dcd4a 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -1,9 +1,8 @@ //===- MergeFunctions.cpp - Merge identical functions ---------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -190,8 +189,6 @@ public: void replaceBy(Function *G) const { F = G; } - - void release() { F = nullptr; } }; /// MergeFunctions finds functions which will generate identical machine code, @@ -281,8 +278,8 @@ private: // Replace G with an alias to F (deleting function G) void writeAlias(Function *F, Function *G); - // Replace G with an alias to F if possible, or a thunk to F if - // profitable. Returns false if neither is the case. + // Replace G with an alias to F if possible, or a thunk to F if possible. + // Returns false if neither is the case. bool writeThunkOrAlias(Function *F, Function *G); /// Replace function F with function G in the function tree. @@ -383,6 +380,11 @@ bool MergeFunctions::doSanityCheck(std::vector<WeakTrackingVH> &Worklist) { } #endif +/// Check whether \p F is eligible for function merging. +static bool isEligibleForMerging(Function &F) { + return !F.isDeclaration() && !F.hasAvailableExternallyLinkage(); +} + bool MergeFunctions::runOnModule(Module &M) { if (skipModule(M)) return false; @@ -394,17 +396,12 @@ bool MergeFunctions::runOnModule(Module &M) { std::vector<std::pair<FunctionComparator::FunctionHash, Function *>> HashedFuncs; for (Function &Func : M) { - if (!Func.isDeclaration() && !Func.hasAvailableExternallyLinkage()) { + if (isEligibleForMerging(Func)) { HashedFuncs.push_back({FunctionComparator::functionHash(Func), &Func}); } } - std::stable_sort( - HashedFuncs.begin(), HashedFuncs.end(), - [](const std::pair<FunctionComparator::FunctionHash, Function *> &a, - const std::pair<FunctionComparator::FunctionHash, Function *> &b) { - return a.first < b.first; - }); + llvm::stable_sort(HashedFuncs, less_first()); auto S = HashedFuncs.begin(); for (auto I = HashedFuncs.begin(), IE = HashedFuncs.end(); I != IE; ++I) { @@ -654,12 +651,16 @@ void MergeFunctions::filterInstsUnrelatedToPDI( LLVM_DEBUG(dbgs() << " }\n"); } -// Don't merge tiny functions using a thunk, since it can just end up -// making the function larger. -static bool isThunkProfitable(Function * F) { +/// Whether this function may be replaced by a forwarding thunk. +static bool canCreateThunkFor(Function *F) { + if (F->isVarArg()) + return false; + + // Don't merge tiny functions using a thunk, since it can just end up + // making the function larger. if (F->size() == 1) { if (F->front().size() <= 2) { - LLVM_DEBUG(dbgs() << "isThunkProfitable: " << F->getName() + LLVM_DEBUG(dbgs() << "canCreateThunkFor: " << F->getName() << " is too small to bother creating a thunk for\n"); return false; } @@ -695,6 +696,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { } else { NewG = Function::Create(G->getFunctionType(), G->getLinkage(), G->getAddressSpace(), "", G->getParent()); + NewG->setComdat(G->getComdat()); BB = BasicBlock::Create(F->getContext(), "", NewG); } @@ -787,7 +789,7 @@ bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) { writeAlias(F, G); return true; } - if (isThunkProfitable(F)) { + if (canCreateThunkFor(F)) { writeThunk(F, G); return true; } @@ -802,9 +804,9 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { // Both writeThunkOrAlias() calls below must succeed, either because we can // create aliases for G and NewF, or because a thunk for F is profitable. // F here has the same signature as NewF below, so that's what we check. - if (!isThunkProfitable(F) && (!canCreateAliasFor(F) || !canCreateAliasFor(G))) { + if (!canCreateThunkFor(F) && + (!canCreateAliasFor(F) || !canCreateAliasFor(G))) return; - } // Make them both thunks to the same internal function. Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(), @@ -944,25 +946,7 @@ void MergeFunctions::remove(Function *F) { // For each instruction used by the value, remove() the function that contains // the instruction. This should happen right before a call to RAUW. void MergeFunctions::removeUsers(Value *V) { - std::vector<Value *> Worklist; - Worklist.push_back(V); - SmallPtrSet<Value*, 8> Visited; - Visited.insert(V); - while (!Worklist.empty()) { - Value *V = Worklist.back(); - Worklist.pop_back(); - - for (User *U : V->users()) { - if (Instruction *I = dyn_cast<Instruction>(U)) { - remove(I->getFunction()); - } else if (isa<GlobalValue>(U)) { - // do nothing - } else if (Constant *C = dyn_cast<Constant>(U)) { - for (User *UU : C->users()) { - if (!Visited.insert(UU).second) - Worklist.push_back(UU); - } - } - } - } + for (User *U : V->users()) + if (auto *I = dyn_cast<Instruction>(U)) + remove(I->getFunction()); } |