X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FIPO%2FExtractGV.cpp;h=b9462f2ffc722d118d1f466e49700a6f648f20e4;hb=848219ca612e5488982f23c37c7459aeedff77e3;hp=a230dd1db881f96135dde8fc308ae1a2873c5398;hpb=d245a8ae470e2ee84d138379f793095646c590e5;p=oota-llvm.git diff --git a/lib/Transforms/IPO/ExtractGV.cpp b/lib/Transforms/IPO/ExtractGV.cpp index a230dd1db88..b9462f2ffc7 100644 --- a/lib/Transforms/IPO/ExtractGV.cpp +++ b/lib/Transforms/IPO/ExtractGV.cpp @@ -11,20 +11,52 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Constants.h" #include "llvm/Transforms/IPO.h" -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" +#include using namespace llvm; +/// Make sure GV is visible from both modules. Delete is true if it is +/// being deleted from this module. +/// This also makes sure GV cannot be dropped so that references from +/// the split module remain valid. +static void makeVisible(GlobalValue &GV, bool Delete) { + bool Local = GV.hasLocalLinkage(); + if (Local || Delete) { + GV.setLinkage(GlobalValue::ExternalLinkage); + if (Local) + GV.setVisibility(GlobalValue::HiddenVisibility); + return; + } + + if (!GV.hasLinkOnceLinkage()) { + assert(!GV.isDiscardableIfUnused()); + return; + } + + // Map linkonce* to weak* so that llvm doesn't drop this GV. + switch(GV.getLinkage()) { + default: + llvm_unreachable("Unexpected linkage"); + case GlobalValue::LinkOnceAnyLinkage: + GV.setLinkage(GlobalValue::WeakAnyLinkage); + return; + case GlobalValue::LinkOnceODRLinkage: + GV.setLinkage(GlobalValue::WeakODRLinkage); + return; + } +} + namespace { /// @brief A pass to extract specific functions and their dependencies. - class VISIBILITY_HIDDEN GVExtractorPass : public ModulePass { - std::vector Named; + class GVExtractorPass : public ModulePass { + SetVector Named; bool deleteStuff; - bool reLink; public: static char ID; // Pass identification, replacement for typeid @@ -32,133 +64,87 @@ namespace { /// specified function. Otherwise, it deletes as much of the module as /// possible, except for the function specified. /// - explicit GVExtractorPass(std::vector& GVs, bool deleteS = true, - bool relinkCallees = false) - : ModulePass((intptr_t)&ID), Named(GVs), deleteStuff(deleteS), - reLink(relinkCallees) {} - - bool runOnModule(Module &M) { - if (Named.size() == 0) { - return false; // Nothing to extract - } - - if (deleteStuff) - return deleteGV(); - M.setModuleInlineAsm(""); - return isolateGV(M); - } - - bool deleteGV() { - for (std::vector::iterator GI = Named.begin(), - GE = Named.end(); GI != GE; ++GI) { - if (Function* NamedFunc = dyn_cast(&*GI)) { - // If we're in relinking mode, set linkage of all internal callees to - // external. This will allow us extract function, and then - link - // everything together - if (reLink) { - for (Function::iterator B = NamedFunc->begin(), BE = NamedFunc->end(); - B != BE; ++B) { - for (BasicBlock::iterator I = B->begin(), E = B->end(); - I != E; ++I) { - if (CallInst* callInst = dyn_cast(&*I)) { - Function* Callee = callInst->getCalledFunction(); - if (Callee && Callee->hasInternalLinkage()) - Callee->setLinkage(GlobalValue::ExternalLinkage); - } - } - } - } - - NamedFunc->setLinkage(GlobalValue::ExternalLinkage); - NamedFunc->deleteBody(); - assert(NamedFunc->isDeclaration() && "This didn't make the function external!"); - } else { - if (!(*GI)->isDeclaration()) { - cast(*GI)->setInitializer(0); //clear the initializer - (*GI)->setLinkage(GlobalValue::ExternalLinkage); - } + explicit GVExtractorPass(std::vector& GVs, bool deleteS = true) + : ModulePass(ID), Named(GVs.begin(), GVs.end()), deleteStuff(deleteS) {} + + bool runOnModule(Module &M) override { + // Visit the global inline asm. + if (!deleteStuff) + M.setModuleInlineAsm(""); + + // For simplicity, just give all GlobalValues ExternalLinkage. A trickier + // implementation could figure out which GlobalValues are actually + // referenced by the Named set, and which GlobalValues in the rest of + // the module are referenced by the NamedSet, and get away with leaving + // more internal and private things internal and private. But for now, + // be conservative and simple. + + // Visit the GlobalVariables. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + bool Delete = + deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); + if (!Delete) { + if (I->hasAvailableExternallyLinkage()) + continue; + if (I->getName() == "llvm.global_ctors") + continue; } - } - return true; - } - bool isolateGV(Module &M) { - // Mark all globals internal - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (!I->isDeclaration()) { - I->setLinkage(GlobalValue::InternalLinkage); - } - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration()) { - I->setLinkage(GlobalValue::InternalLinkage); - } + makeVisible(*I, Delete); - // Make sure our result is globally accessible... - // by putting them in the used array - { - std::vector AUGs; - const Type *SBP= PointerType::getUnqual(Type::Int8Ty); - for (std::vector::iterator GI = Named.begin(), - GE = Named.end(); GI != GE; ++GI) { - (*GI)->setLinkage(GlobalValue::ExternalLinkage); - AUGs.push_back(ConstantExpr::getBitCast(*GI, SBP)); + if (Delete) { + // Make this a declaration and drop it's comdat. + I->setInitializer(nullptr); + I->setComdat(nullptr); } - ArrayType *AT = ArrayType::get(SBP, AUGs.size()); - Constant *Init = ConstantArray::get(AT, AUGs); - GlobalValue *gv = new GlobalVariable(AT, false, - GlobalValue::AppendingLinkage, - Init, "llvm.used", &M); - gv->setSection("llvm.metadata"); } - // All of the functions may be used by global variables or the named - // globals. Loop through them and create a new, external functions that - // can be "used", instead of ones with bodies. - std::vector NewFunctions; - - Function *Last = --M.end(); // Figure out where the last real fn is. - - for (Module::iterator I = M.begin(); ; ++I) { - if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { - Function *New = new Function(I->getFunctionType(), - GlobalValue::ExternalLinkage); - New->setCallingConv(I->getCallingConv()); - New->setParamAttrs(I->getParamAttrs()); - if (I->hasCollector()) - New->setCollector(I->getCollector()); + // Visit the Functions. + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + bool Delete = + deleteStuff == (bool)Named.count(I) && !I->isDeclaration(); + if (!Delete) { + if (I->hasAvailableExternallyLinkage()) + continue; + } - // If it's not the named function, delete the body of the function - I->dropAllReferences(); + makeVisible(*I, Delete); - M.getFunctionList().push_back(New); - NewFunctions.push_back(New); - New->takeName(I); + if (Delete) { + // Make this a declaration and drop it's comdat. + I->deleteBody(); + I->setComdat(nullptr); } - - if (&*I == Last) break; // Stop after processing the last function } - // Now that we have replacements all set up, loop through the module, - // deleting the old functions, replacing them with the newly created - // functions. - if (!NewFunctions.empty()) { - unsigned FuncNum = 0; - Module::iterator I = M.begin(); - do { - if (std::find(Named.begin(), Named.end(), &*I) == Named.end()) { - // Make everything that uses the old function use the new dummy fn - I->replaceAllUsesWith(NewFunctions[FuncNum++]); + // Visit the Aliases. + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E;) { + Module::alias_iterator CurI = I; + ++I; + + bool Delete = deleteStuff == (bool)Named.count(CurI); + makeVisible(*CurI, Delete); - Function *Old = I; - ++I; // Move the iterator to the new function + if (Delete) { + Type *Ty = CurI->getType()->getElementType(); - // Delete the old function! - M.getFunctionList().erase(Old); + CurI->removeFromParent(); + llvm::Value *Declaration; + if (FunctionType *FTy = dyn_cast(Ty)) { + Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage, + CurI->getName(), &M); } else { - ++I; // Skip the function we are extracting + Declaration = + new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, + nullptr, CurI->getName()); + } - } while (&*I != NewFunctions[0]); + CurI->replaceAllUsesWith(Declaration); + delete CurI; + } } return true; @@ -168,7 +154,7 @@ namespace { char GVExtractorPass::ID = 0; } -ModulePass *llvm::createGVExtractionPass(std::vector& GVs, - bool deleteFn, bool relinkCallees) { - return new GVExtractorPass(GVs, deleteFn, relinkCallees); +ModulePass *llvm::createGVExtractionPass(std::vector &GVs, + bool deleteFn) { + return new GVExtractorPass(GVs, deleteFn); }