diff options
Diffstat (limited to 'lib/Transforms/IPO/MergeFunctions.cpp')
-rw-r--r-- | lib/Transforms/IPO/MergeFunctions.cpp | 252 |
1 files changed, 136 insertions, 116 deletions
diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index 76b90391fbb1..139941127dee 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -90,7 +90,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/Argument.h" @@ -407,10 +407,10 @@ bool MergeFunctions::runOnModule(Module &M) { std::vector<WeakTrackingVH> Worklist; Deferred.swap(Worklist); - DEBUG(doSanityCheck(Worklist)); + LLVM_DEBUG(doSanityCheck(Worklist)); - DEBUG(dbgs() << "size of module: " << M.size() << '\n'); - DEBUG(dbgs() << "size of worklist: " << Worklist.size() << '\n'); + LLVM_DEBUG(dbgs() << "size of module: " << M.size() << '\n'); + LLVM_DEBUG(dbgs() << "size of worklist: " << Worklist.size() << '\n'); // Insert functions and merge them. for (WeakTrackingVH &I : Worklist) { @@ -421,7 +421,7 @@ bool MergeFunctions::runOnModule(Module &M) { Changed |= insert(F); } } - DEBUG(dbgs() << "size of FnTree: " << FnTree.size() << '\n'); + LLVM_DEBUG(dbgs() << "size of FnTree: " << FnTree.size() << '\n'); } while (!Deferred.empty()); FnTree.clear(); @@ -498,19 +498,20 @@ static Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy) { // parameter debug info, from the entry block. void MergeFunctions::eraseInstsUnrelatedToPDI( std::vector<Instruction *> &PDIUnrelatedWL) { - DEBUG(dbgs() << " Erasing instructions (in reverse order of appearance in " - "entry block) unrelated to parameter debug info from entry " - "block: {\n"); + LLVM_DEBUG( + dbgs() << " Erasing instructions (in reverse order of appearance in " + "entry block) unrelated to parameter debug info from entry " + "block: {\n"); while (!PDIUnrelatedWL.empty()) { Instruction *I = PDIUnrelatedWL.back(); - DEBUG(dbgs() << " Deleting Instruction: "); - DEBUG(I->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Deleting Instruction: "); + LLVM_DEBUG(I->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); I->eraseFromParent(); PDIUnrelatedWL.pop_back(); } - DEBUG(dbgs() << " } // Done erasing instructions unrelated to parameter " - "debug info from entry block. \n"); + LLVM_DEBUG(dbgs() << " } // Done erasing instructions unrelated to parameter " + "debug info from entry block. \n"); } // Reduce G to its entry block. @@ -543,99 +544,113 @@ void MergeFunctions::filterInstsUnrelatedToPDI( for (BasicBlock::iterator BI = GEntryBlock->begin(), BIE = GEntryBlock->end(); BI != BIE; ++BI) { if (auto *DVI = dyn_cast<DbgValueInst>(&*BI)) { - DEBUG(dbgs() << " Deciding: "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Deciding: "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); DILocalVariable *DILocVar = DVI->getVariable(); if (DILocVar->isParameter()) { - DEBUG(dbgs() << " Include (parameter): "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Include (parameter): "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); PDIRelated.insert(&*BI); } else { - DEBUG(dbgs() << " Delete (!parameter): "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Delete (!parameter): "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } else if (auto *DDI = dyn_cast<DbgDeclareInst>(&*BI)) { - DEBUG(dbgs() << " Deciding: "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Deciding: "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); DILocalVariable *DILocVar = DDI->getVariable(); if (DILocVar->isParameter()) { - DEBUG(dbgs() << " Parameter: "); - DEBUG(DILocVar->print(dbgs())); + LLVM_DEBUG(dbgs() << " Parameter: "); + LLVM_DEBUG(DILocVar->print(dbgs())); AllocaInst *AI = dyn_cast_or_null<AllocaInst>(DDI->getAddress()); if (AI) { - DEBUG(dbgs() << " Processing alloca users: "); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Processing alloca users: "); + LLVM_DEBUG(dbgs() << "\n"); for (User *U : AI->users()) { if (StoreInst *SI = dyn_cast<StoreInst>(U)) { if (Value *Arg = SI->getValueOperand()) { if (dyn_cast<Argument>(Arg)) { - DEBUG(dbgs() << " Include: "); - DEBUG(AI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Include: "); + LLVM_DEBUG(AI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); PDIRelated.insert(AI); - DEBUG(dbgs() << " Include (parameter): "); - DEBUG(SI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Include (parameter): "); + LLVM_DEBUG(SI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); PDIRelated.insert(SI); - DEBUG(dbgs() << " Include: "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Include: "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); PDIRelated.insert(&*BI); } else { - DEBUG(dbgs() << " Delete (!parameter): "); - DEBUG(SI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Delete (!parameter): "); + LLVM_DEBUG(SI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } } else { - DEBUG(dbgs() << " Defer: "); - DEBUG(U->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Defer: "); + LLVM_DEBUG(U->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } } else { - DEBUG(dbgs() << " Delete (alloca NULL): "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Delete (alloca NULL): "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } else { - DEBUG(dbgs() << " Delete (!parameter): "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Delete (!parameter): "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } else if (dyn_cast<TerminatorInst>(BI) == GEntryBlock->getTerminator()) { - DEBUG(dbgs() << " Will Include Terminator: "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Will Include Terminator: "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); PDIRelated.insert(&*BI); } else { - DEBUG(dbgs() << " Defer: "); - DEBUG(BI->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Defer: "); + LLVM_DEBUG(BI->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } - DEBUG(dbgs() - << " Report parameter debug info related/related instructions: {\n"); + LLVM_DEBUG( + dbgs() + << " Report parameter debug info related/related instructions: {\n"); for (BasicBlock::iterator BI = GEntryBlock->begin(), BE = GEntryBlock->end(); BI != BE; ++BI) { Instruction *I = &*BI; if (PDIRelated.find(I) == PDIRelated.end()) { - DEBUG(dbgs() << " !PDIRelated: "); - DEBUG(I->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " !PDIRelated: "); + LLVM_DEBUG(I->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); PDIUnrelatedWL.push_back(I); } else { - DEBUG(dbgs() << " PDIRelated: "); - DEBUG(I->print(dbgs())); - DEBUG(dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " PDIRelated: "); + LLVM_DEBUG(I->print(dbgs())); + LLVM_DEBUG(dbgs() << "\n"); } } - DEBUG(dbgs() << " }\n"); + 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) { + if (F->size() == 1) { + if (F->front().size() <= 2) { + LLVM_DEBUG(dbgs() << "isThunkProfitable: " << F->getName() + << " is too small to bother creating a thunk for\n"); + return false; + } + } + return true; } // Replace G with a simple tail call to bitcast(F). Also (unless @@ -647,51 +662,19 @@ void MergeFunctions::filterInstsUnrelatedToPDI( // For better debugability, under MergeFunctionsPDI, we do not modify G's // call sites to point to F even when within the same translation unit. void MergeFunctions::writeThunk(Function *F, Function *G) { - if (!G->isInterposable() && !MergeFunctionsPDI) { - if (G->hasGlobalUnnamedAddr()) { - // G might have been a key in our GlobalNumberState, and it's illegal - // to replace a key in ValueMap<GlobalValue *> with a non-global. - GlobalNumbers.erase(G); - // If G's address is not significant, replace it entirely. - Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); - G->replaceAllUsesWith(BitcastF); - } else { - // Redirect direct callers of G to F. (See note on MergeFunctionsPDI - // above). - replaceDirectCallers(G, F); - } - } - - // If G was internal then we may have replaced all uses of G with F. If so, - // stop here and delete G. There's no need for a thunk. (See note on - // MergeFunctionsPDI above). - if (G->hasLocalLinkage() && G->use_empty() && !MergeFunctionsPDI) { - G->eraseFromParent(); - return; - } - - // 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) { - DEBUG(dbgs() << "writeThunk: " << F->getName() - << " is too small to bother creating a thunk for\n"); - return; - } - } - BasicBlock *GEntryBlock = nullptr; std::vector<Instruction *> PDIUnrelatedWL; BasicBlock *BB = nullptr; Function *NewG = nullptr; if (MergeFunctionsPDI) { - DEBUG(dbgs() << "writeThunk: (MergeFunctionsPDI) Do not create a new " - "function as thunk; retain original: " - << G->getName() << "()\n"); + LLVM_DEBUG(dbgs() << "writeThunk: (MergeFunctionsPDI) Do not create a new " + "function as thunk; retain original: " + << G->getName() << "()\n"); GEntryBlock = &G->getEntryBlock(); - DEBUG(dbgs() << "writeThunk: (MergeFunctionsPDI) filter parameter related " - "debug info for " - << G->getName() << "() {\n"); + LLVM_DEBUG( + dbgs() << "writeThunk: (MergeFunctionsPDI) filter parameter related " + "debug info for " + << G->getName() << "() {\n"); filterInstsUnrelatedToPDI(GEntryBlock, PDIUnrelatedWL); GEntryBlock->getTerminator()->eraseFromParent(); BB = GEntryBlock; @@ -730,13 +713,15 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { CI->setDebugLoc(CIDbgLoc); RI->setDebugLoc(RIDbgLoc); } else { - DEBUG(dbgs() << "writeThunk: (MergeFunctionsPDI) No DISubprogram for " - << G->getName() << "()\n"); + LLVM_DEBUG( + dbgs() << "writeThunk: (MergeFunctionsPDI) No DISubprogram for " + << G->getName() << "()\n"); } eraseTail(G); eraseInstsUnrelatedToPDI(PDIUnrelatedWL); - DEBUG(dbgs() << "} // End of parameter related debug info filtering for: " - << G->getName() << "()\n"); + LLVM_DEBUG( + dbgs() << "} // End of parameter related debug info filtering for: " + << G->getName() << "()\n"); } else { NewG->copyAttributesFrom(G); NewG->takeName(G); @@ -745,7 +730,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { G->eraseFromParent(); } - DEBUG(dbgs() << "writeThunk: " << H->getName() << '\n'); + LLVM_DEBUG(dbgs() << "writeThunk: " << H->getName() << '\n'); ++NumThunksWritten; } @@ -754,6 +739,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { if (F->isInterposable()) { assert(G->isInterposable()); + if (!isThunkProfitable(F)) { + return; + } + // Make them both thunks to the same internal function. Function *H = Function::Create(F->getFunctionType(), F->getLinkage(), "", F->getParent()); @@ -770,11 +759,41 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { F->setAlignment(MaxAlignment); F->setLinkage(GlobalValue::PrivateLinkage); ++NumDoubleWeak; + ++NumFunctionsMerged; } else { + // For better debugability, under MergeFunctionsPDI, we do not modify G's + // call sites to point to F even when within the same translation unit. + if (!G->isInterposable() && !MergeFunctionsPDI) { + if (G->hasGlobalUnnamedAddr()) { + // G might have been a key in our GlobalNumberState, and it's illegal + // to replace a key in ValueMap<GlobalValue *> with a non-global. + GlobalNumbers.erase(G); + // If G's address is not significant, replace it entirely. + Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); + G->replaceAllUsesWith(BitcastF); + } else { + // Redirect direct callers of G to F. (See note on MergeFunctionsPDI + // above). + replaceDirectCallers(G, F); + } + } + + // If G was internal then we may have replaced all uses of G with F. If so, + // stop here and delete G. There's no need for a thunk. (See note on + // MergeFunctionsPDI above). + if (G->hasLocalLinkage() && G->use_empty() && !MergeFunctionsPDI) { + G->eraseFromParent(); + ++NumFunctionsMerged; + return; + } + + if (!isThunkProfitable(F)) { + return; + } + writeThunk(F, G); + ++NumFunctionsMerged; } - - ++NumFunctionsMerged; } /// Replace function F by function G. @@ -806,7 +825,8 @@ bool MergeFunctions::insert(Function *NewFunction) { if (Result.second) { assert(FNodesInTree.count(NewFunction) == 0); FNodesInTree.insert({NewFunction, Result.first}); - DEBUG(dbgs() << "Inserting as unique: " << NewFunction->getName() << '\n'); + LLVM_DEBUG(dbgs() << "Inserting as unique: " << NewFunction->getName() + << '\n'); return false; } @@ -827,8 +847,8 @@ bool MergeFunctions::insert(Function *NewFunction) { assert(OldF.getFunc() != F && "Must have swapped the functions."); } - DEBUG(dbgs() << " " << OldF.getFunc()->getName() - << " == " << NewFunction->getName() << '\n'); + LLVM_DEBUG(dbgs() << " " << OldF.getFunc()->getName() + << " == " << NewFunction->getName() << '\n'); Function *DeleteF = NewFunction; mergeTwoFunctions(OldF.getFunc(), DeleteF); @@ -840,7 +860,7 @@ bool MergeFunctions::insert(Function *NewFunction) { void MergeFunctions::remove(Function *F) { auto I = FNodesInTree.find(F); if (I != FNodesInTree.end()) { - DEBUG(dbgs() << "Deferred " << F->getName()<< ".\n"); + LLVM_DEBUG(dbgs() << "Deferred " << F->getName() << ".\n"); FnTree.erase(I->second); // I->second has been invalidated, remove it from the FNodesInTree map to // preserve the invariant. @@ -854,7 +874,7 @@ void MergeFunctions::remove(Function *F) { void MergeFunctions::removeUsers(Value *V) { std::vector<Value *> Worklist; Worklist.push_back(V); - SmallSet<Value*, 8> Visited; + SmallPtrSet<Value*, 8> Visited; Visited.insert(V); while (!Worklist.empty()) { Value *V = Worklist.back(); |