bool EliminateAvailableExternally::runOnModule(Module &M) { bool Changed = false; // Drop initializers of available externally global variables. for (GlobalVariable &GV : M.globals()) { if (!GV.hasAvailableExternallyLinkage()) continue; if (GV.hasInitializer()) { Constant *Init = GV.getInitializer(); GV.setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } GV.removeDeadConstantUsers(); GV.setLinkage(GlobalValue::ExternalLinkage); NumVariables++; Changed = true; } // Drop the bodies of available externally functions. for (Function &F : M) { if (!F.hasAvailableExternallyLinkage()) continue; if (!F.isDeclaration()) // This will set the linkage to external F.deleteBody(); F.removeDeadConstantUsers(); NumFunctions++; Changed = true; } return Changed; }
bool EliminateAvailableExternally::runOnModule(Module &M) { bool Changed = false; // Convert any aliases that alias with an available externally // value (which will be turned into declarations later on in this routine) // into declarations themselves. All aliases must be definitions, and // must alias with a definition. So this involves creating a declaration // equivalent to the alias's base object. for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) { // Increment the iterator first since we may delete the current alias. GlobalAlias &GA = *(I++); GlobalValue *GVal = GA.getBaseObject(); if (!GVal->hasAvailableExternallyLinkage()) continue; convertAliasToDeclaration(GA, M); Changed = true; } // Drop initializers of available externally global variables. for (GlobalVariable &GV : M.globals()) { if (!GV.hasAvailableExternallyLinkage()) continue; if (GV.hasInitializer()) { Constant *Init = GV.getInitializer(); GV.setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } GV.removeDeadConstantUsers(); GV.setLinkage(GlobalValue::ExternalLinkage); NumVariables++; Changed = true; } // Drop the bodies of available externally functions. for (Function &F : M) { if (!F.hasAvailableExternallyLinkage()) continue; if (!F.isDeclaration()) // This will set the linkage to external F.deleteBody(); F.removeDeadConstantUsers(); NumFunctions++; Changed = true; } return Changed; }
static int runCompilePasses(Module *ModuleRef, unsigned ModuleIndex, ThreadedFunctionQueue *FuncQueue, const Triple &TheTriple, TargetMachine &Target, StringRef ProgramName, raw_pwrite_stream &OS){ PNaClABIErrorReporter ABIErrorReporter; if (SplitModuleCount > 1 || ExternalizeAll) { // Add function and global names, and give them external linkage. // This relies on LLVM's consistent auto-generation of names, we could // maybe do our own in case something changes there. for (Function &F : *ModuleRef) { if (!F.hasName()) F.setName("Function"); if (F.hasInternalLinkage()) F.setLinkage(GlobalValue::ExternalLinkage); } for (Module::global_iterator GI = ModuleRef->global_begin(), GE = ModuleRef->global_end(); GI != GE; ++GI) { if (!GI->hasName()) GI->setName("Global"); if (GI->hasInternalLinkage()) GI->setLinkage(GlobalValue::ExternalLinkage); } if (ModuleIndex > 0) { // Remove the initializers for all global variables, turning them into // declarations. for (Module::global_iterator GI = ModuleRef->global_begin(), GE = ModuleRef->global_end(); GI != GE; ++GI) { assert(GI->hasInitializer() && "Global variable missing initializer"); Constant *Init = GI->getInitializer(); GI->setInitializer(nullptr); if (Init->getNumUses() == 0) Init->destroyConstant(); } } } // Make all non-weak symbols hidden for better code. We cannot do // this for weak symbols. The linker complains when some weak // symbols are not resolved. for (Function &F : *ModuleRef) { if (!F.isWeakForLinker() && !F.hasLocalLinkage()) F.setVisibility(GlobalValue::HiddenVisibility); } for (Module::global_iterator GI = ModuleRef->global_begin(), GE = ModuleRef->global_end(); GI != GE; ++GI) { if (!GI->isWeakForLinker() && !GI->hasLocalLinkage()) GI->setVisibility(GlobalValue::HiddenVisibility); } // Build up all of the passes that we want to do to the module. std::unique_ptr<legacy::PassManagerBase> PM; if (LazyBitcode) PM.reset(new legacy::FunctionPassManager(ModuleRef)); else PM.reset(new legacy::PassManager()); // Add the target data from the target machine, if it exists, or the module. if (const DataLayout *DL = Target.getDataLayout()) ModuleRef->setDataLayout(*DL); // For conformance with llc, we let the user disable LLVM IR verification with // -disable-verify. Unlike llc, when LLVM IR verification is enabled we only // run it once, before PNaCl ABI verification. if (!NoVerify) PM->add(createVerifierPass()); // Add the ABI verifier pass before the analysis and code emission passes. if (PNaClABIVerify) PM->add(createPNaClABIVerifyFunctionsPass(&ABIErrorReporter)); // Add the intrinsic resolution pass. It assumes ABI-conformant code. PM->add(createResolvePNaClIntrinsicsPass()); // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(TheTriple); // The -disable-simplify-libcalls flag actually disables all builtin optzns. if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); PM->add(new TargetLibraryInfoWrapperPass(TLII)); // Allow subsequent passes and the backend to better optimize instructions // that were simplified for PNaCl's ABI. This pass uses the TargetLibraryInfo // above. PM->add(createBackendCanonicalizePass()); // Ask the target to add backend passes as necessary. We explicitly ask it // not to add the verifier pass because we added it earlier. if (Target.addPassesToEmitFile(*PM, OS, FileType, /* DisableVerify */ true)) { errs() << ProgramName << ": target does not support generation of this file type!\n"; return 1; } if (LazyBitcode) { auto FPM = static_cast<legacy::FunctionPassManager *>(PM.get()); FPM->doInitialization(); unsigned FuncIndex = 0; switch (SplitModuleSched) { case SplitModuleStatic: for (Function &F : *ModuleRef) { if (FuncQueue->GrabFunctionStatic(FuncIndex, ModuleIndex)) { FPM->run(F); CheckABIVerifyErrors(ABIErrorReporter, "Function " + F.getName()); F.Dematerialize(); } ++FuncIndex; } break; case SplitModuleDynamic: unsigned ChunkSize = 0; unsigned NumFunctions = FuncQueue->Size(); Module::iterator I = ModuleRef->begin(); while (FuncIndex < NumFunctions) { ChunkSize = FuncQueue->RecommendedChunkSize(); unsigned NextIndex; bool grabbed = FuncQueue->GrabFunctionDynamic(FuncIndex, ChunkSize, NextIndex); if (grabbed) { while (FuncIndex < NextIndex) { if (!I->isMaterializable() && I->isDeclaration()) { ++I; continue; } FPM->run(*I); CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName()); I->Dematerialize(); ++FuncIndex; ++I; } } else { while (FuncIndex < NextIndex) { if (!I->isMaterializable() && I->isDeclaration()) { ++I; continue; } ++FuncIndex; ++I; } } } break; } FPM->doFinalization(); } else static_cast<legacy::PassManager *>(PM.get())->run(*ModuleRef); return 0; }
PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &) { bool Changed = false; // Remove empty functions from the global ctors list. Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); // Collect the set of members for each comdat. for (Function &F : M) if (Comdat *C = F.getComdat()) ComdatMembers.insert(std::make_pair(C, &F)); for (GlobalVariable &GV : M.globals()) if (Comdat *C = GV.getComdat()) ComdatMembers.insert(std::make_pair(C, &GV)); for (GlobalAlias &GA : M.aliases()) if (Comdat *C = GA.getComdat()) ComdatMembers.insert(std::make_pair(C, &GA)); // Loop over the module, adding globals which are obviously necessary. for (GlobalObject &GO : M.global_objects()) { Changed |= RemoveUnusedGlobalValue(GO); // Functions with external linkage are needed if they have a body. // Externally visible & appending globals are needed, if they have an // initializer. if (!GO.isDeclaration() && !GO.hasAvailableExternallyLinkage()) if (!GO.isDiscardableIfUnused()) GlobalIsNeeded(&GO); } for (GlobalAlias &GA : M.aliases()) { Changed |= RemoveUnusedGlobalValue(GA); // Externally visible aliases are needed. if (!GA.isDiscardableIfUnused()) GlobalIsNeeded(&GA); } for (GlobalIFunc &GIF : M.ifuncs()) { Changed |= RemoveUnusedGlobalValue(GIF); // Externally visible ifuncs are needed. if (!GIF.isDiscardableIfUnused()) GlobalIsNeeded(&GIF); } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals for (GlobalVariable &GV : M.globals()) if (!AliveGlobals.count(&GV)) { DeadGlobalVars.push_back(&GV); // Keep track of dead globals if (GV.hasInitializer()) { Constant *Init = GV.getInitializer(); GV.setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } } // The second pass drops the bodies of functions which are dead... std::vector<Function *> DeadFunctions; for (Function &F : M) if (!AliveGlobals.count(&F)) { DeadFunctions.push_back(&F); // Keep track of dead globals if (!F.isDeclaration()) F.deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (GlobalAlias &GA : M.aliases()) if (!AliveGlobals.count(&GA)) { DeadAliases.push_back(&GA); GA.setAliasee(nullptr); } // The third pass drops targets of ifuncs which are dead... std::vector<GlobalIFunc*> DeadIFuncs; for (GlobalIFunc &GIF : M.ifuncs()) if (!AliveGlobals.count(&GIF)) { DeadIFuncs.push_back(&GIF); GIF.setResolver(nullptr); } // Now that all interferences have been dropped, delete the actual objects // themselves. auto EraseUnusedGlobalValue = [&](GlobalValue *GV) { RemoveUnusedGlobalValue(*GV); GV->eraseFromParent(); Changed = true; }; NumFunctions += DeadFunctions.size(); for (Function *F : DeadFunctions) EraseUnusedGlobalValue(F); NumVariables += DeadGlobalVars.size(); for (GlobalVariable *GV : DeadGlobalVars) EraseUnusedGlobalValue(GV); NumAliases += DeadAliases.size(); for (GlobalAlias *GA : DeadAliases) EraseUnusedGlobalValue(GA); NumIFuncs += DeadIFuncs.size(); for (GlobalIFunc *GIF : DeadIFuncs) EraseUnusedGlobalValue(GIF); // Make sure that all memory is released AliveGlobals.clear(); SeenConstants.clear(); ComdatMembers.clear(); if (Changed) return PreservedAnalyses::none(); return PreservedAnalyses::all(); }
bool GlobalDCE::runOnModule(Module &M) { bool Changed = false; // Remove empty functions from the global ctors list. Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); // Loop over the module, adding globals which are obviously necessary. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Functions with external linkage are needed if they have a body if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); } } for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible & appending globals are needed, if they have an // initializer. if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { if (!I->isDiscardableIfUnused()) GlobalIsNeeded(I); } } for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { Changed |= RemoveUnusedGlobalValue(*I); // Externally visible aliases are needed. if (!I->isDiscardableIfUnused()) { GlobalIsNeeded(I); } } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable*> DeadGlobalVars; // Keep track of dead globals for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadGlobalVars.push_back(I); // Keep track of dead globals if (I->hasInitializer()) { Constant *Init = I->getInitializer(); I->setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } } // The second pass drops the bodies of functions which are dead... std::vector<Function*> DeadFunctions; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadFunctions.push_back(I); // Keep track of dead globals if (!I->isDeclaration()) I->deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) if (!AliveGlobals.count(I)) { DeadAliases.push_back(I); I->setAliasee(nullptr); } if (!DeadFunctions.empty()) { // Now that all interferences have been dropped, delete the actual objects // themselves. for (unsigned i = 0, e = DeadFunctions.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadFunctions[i]); M.getFunctionList().erase(DeadFunctions[i]); } NumFunctions += DeadFunctions.size(); Changed = true; } if (!DeadGlobalVars.empty()) { for (unsigned i = 0, e = DeadGlobalVars.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadGlobalVars[i]); M.getGlobalList().erase(DeadGlobalVars[i]); } NumVariables += DeadGlobalVars.size(); Changed = true; } // Now delete any dead aliases. if (!DeadAliases.empty()) { for (unsigned i = 0, e = DeadAliases.size(); i != e; ++i) { RemoveUnusedGlobalValue(*DeadAliases[i]); M.getAliasList().erase(DeadAliases[i]); } NumAliases += DeadAliases.size(); Changed = true; } // Make sure that all memory is released AliveGlobals.clear(); SeenConstants.clear(); return Changed; }
PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &MAM) { bool Changed = false; // The algorithm first computes the set L of global variables that are // trivially live. Then it walks the initialization of these variables to // compute the globals used to initialize them, which effectively builds a // directed graph where nodes are global variables, and an edge from A to B // means B is used to initialize A. Finally, it propagates the liveness // information through the graph starting from the nodes in L. Nodes note // marked as alive are discarded. // Remove empty functions from the global ctors list. Changed |= optimizeGlobalCtorsList(M, isEmptyFunction); // Collect the set of members for each comdat. for (Function &F : M) if (Comdat *C = F.getComdat()) ComdatMembers.insert(std::make_pair(C, &F)); for (GlobalVariable &GV : M.globals()) if (Comdat *C = GV.getComdat()) ComdatMembers.insert(std::make_pair(C, &GV)); for (GlobalAlias &GA : M.aliases()) if (Comdat *C = GA.getComdat()) ComdatMembers.insert(std::make_pair(C, &GA)); // Loop over the module, adding globals which are obviously necessary. for (GlobalObject &GO : M.global_objects()) { Changed |= RemoveUnusedGlobalValue(GO); // Functions with external linkage are needed if they have a body. // Externally visible & appending globals are needed, if they have an // initializer. if (!GO.isDeclaration() && !GO.hasAvailableExternallyLinkage()) if (!GO.isDiscardableIfUnused()) MarkLive(GO); UpdateGVDependencies(GO); } // Compute direct dependencies of aliases. for (GlobalAlias &GA : M.aliases()) { Changed |= RemoveUnusedGlobalValue(GA); // Externally visible aliases are needed. if (!GA.isDiscardableIfUnused()) MarkLive(GA); UpdateGVDependencies(GA); } // Compute direct dependencies of ifuncs. for (GlobalIFunc &GIF : M.ifuncs()) { Changed |= RemoveUnusedGlobalValue(GIF); // Externally visible ifuncs are needed. if (!GIF.isDiscardableIfUnused()) MarkLive(GIF); UpdateGVDependencies(GIF); } // Propagate liveness from collected Global Values through the computed // dependencies. SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(), AliveGlobals.end()}; while (!NewLiveGVs.empty()) { GlobalValue *LGV = NewLiveGVs.pop_back_val(); for (auto &&GVD : make_range(GVDependencies.equal_range(LGV))) MarkLive(*GVD.second, &NewLiveGVs); } // Now that all globals which are needed are in the AliveGlobals set, we loop // through the program, deleting those which are not alive. // // The first pass is to drop initializers of global variables which are dead. std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals for (GlobalVariable &GV : M.globals()) if (!AliveGlobals.count(&GV)) { DeadGlobalVars.push_back(&GV); // Keep track of dead globals if (GV.hasInitializer()) { Constant *Init = GV.getInitializer(); GV.setInitializer(nullptr); if (isSafeToDestroyConstant(Init)) Init->destroyConstant(); } } // The second pass drops the bodies of functions which are dead... std::vector<Function *> DeadFunctions; for (Function &F : M) if (!AliveGlobals.count(&F)) { DeadFunctions.push_back(&F); // Keep track of dead globals if (!F.isDeclaration()) F.deleteBody(); } // The third pass drops targets of aliases which are dead... std::vector<GlobalAlias*> DeadAliases; for (GlobalAlias &GA : M.aliases()) if (!AliveGlobals.count(&GA)) { DeadAliases.push_back(&GA); GA.setAliasee(nullptr); } // The fourth pass drops targets of ifuncs which are dead... std::vector<GlobalIFunc*> DeadIFuncs; for (GlobalIFunc &GIF : M.ifuncs()) if (!AliveGlobals.count(&GIF)) { DeadIFuncs.push_back(&GIF); GIF.setResolver(nullptr); } // Now that all interferences have been dropped, delete the actual objects // themselves. auto EraseUnusedGlobalValue = [&](GlobalValue *GV) { RemoveUnusedGlobalValue(*GV); GV->eraseFromParent(); Changed = true; }; NumFunctions += DeadFunctions.size(); for (Function *F : DeadFunctions) EraseUnusedGlobalValue(F); NumVariables += DeadGlobalVars.size(); for (GlobalVariable *GV : DeadGlobalVars) EraseUnusedGlobalValue(GV); NumAliases += DeadAliases.size(); for (GlobalAlias *GA : DeadAliases) EraseUnusedGlobalValue(GA); NumIFuncs += DeadIFuncs.size(); for (GlobalIFunc *GIF : DeadIFuncs) EraseUnusedGlobalValue(GIF); // Make sure that all memory is released AliveGlobals.clear(); ConstantDependenciesCache.clear(); GVDependencies.clear(); ComdatMembers.clear(); if (Changed) return PreservedAnalyses::none(); return PreservedAnalyses::all(); }
/// Once all constants are read, this method bulk resolves any forward /// references. The idea behind this is that we sometimes get constants (such /// as large arrays) which reference *many* forward ref constants. Replacing /// each of these causes a lot of thrashing when building/reuniquing the /// constant. Instead of doing this, we look at all the uses and rewrite all /// the place holders at once for any constant that uses a placeholder. void BitcodeReaderValueList::resolveConstantForwardRefs() { // Sort the values by-pointer so that they are efficient to look up with a // binary search. llvm::sort(ResolveConstants); SmallVector<Constant *, 64> NewOps; while (!ResolveConstants.empty()) { Value *RealVal = operator[](ResolveConstants.back().second); Constant *Placeholder = ResolveConstants.back().first; ResolveConstants.pop_back(); // Loop over all users of the placeholder, updating them to reference the // new value. If they reference more than one placeholder, update them all // at once. while (!Placeholder->use_empty()) { auto UI = Placeholder->user_begin(); User *U = *UI; // If the using object isn't uniqued, just update the operands. This // handles instructions and initializers for global variables. if (!isa<Constant>(U) || isa<GlobalValue>(U)) { UI.getUse().set(RealVal); continue; } // Otherwise, we have a constant that uses the placeholder. Replace that // constant with a new constant that has *all* placeholder uses updated. Constant *UserC = cast<Constant>(U); for (User::op_iterator I = UserC->op_begin(), E = UserC->op_end(); I != E; ++I) { Value *NewOp; if (!isa<ConstantPlaceHolder>(*I)) { // Not a placeholder reference. NewOp = *I; } else if (*I == Placeholder) { // Common case is that it just references this one placeholder. NewOp = RealVal; } else { // Otherwise, look up the placeholder in ResolveConstants. ResolveConstantsTy::iterator It = llvm::lower_bound( ResolveConstants, std::pair<Constant *, unsigned>(cast<Constant>(*I), 0)); assert(It != ResolveConstants.end() && It->first == *I); NewOp = operator[](It->second); } NewOps.push_back(cast<Constant>(NewOp)); } // Make the new constant. Constant *NewC; if (ConstantArray *UserCA = dyn_cast<ConstantArray>(UserC)) { NewC = ConstantArray::get(UserCA->getType(), NewOps); } else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) { NewC = ConstantStruct::get(UserCS->getType(), NewOps); } else if (isa<ConstantVector>(UserC)) { NewC = ConstantVector::get(NewOps); } else { assert(isa<ConstantExpr>(UserC) && "Must be a ConstantExpr."); NewC = cast<ConstantExpr>(UserC)->getWithOperands(NewOps); } UserC->replaceAllUsesWith(NewC); UserC->destroyConstant(); NewOps.clear(); } // Update all ValueHandles, they should be the only users at this point. Placeholder->replaceAllUsesWith(RealVal); Placeholder->deleteValue(); } }