/// AnalyzeGlobals - Scan through the users of all of the internal /// GlobalValue's in the program. If none of them have their "address taken" /// (really, their address passed to something nontrivial), record this fact, /// and record the functions that they are used directly in. void GlobalsModRef::AnalyzeGlobals(Module &M) { std::vector<Function*> Readers, Writers; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->hasLocalLinkage()) { if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { // Remember that we are tracking this global. NonAddressTakenGlobals.insert(I); ++NumNonAddrTakenFunctions; } Readers.clear(); Writers.clear(); } for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (I->hasLocalLinkage()) { if (!AnalyzeUsesOfPointer(I, Readers, Writers)) { // Remember that we are tracking this global, and the mod/ref fns NonAddressTakenGlobals.insert(I); for (unsigned i = 0, e = Readers.size(); i != e; ++i) FunctionInfo[Readers[i]].GlobalInfo[I] |= Ref; if (!I->isConstant()) // No need to keep track of writers to constants for (unsigned i = 0, e = Writers.size(); i != e; ++i) FunctionInfo[Writers[i]].GlobalInfo[I] |= Mod; ++NumNonAddrTakenGlobalVars; // If this global holds a pointer type, see if it is an indirect global. if (I->getType()->getElementType()->isPointerTy() && AnalyzeIndirectGlobalMemory(I)) ++NumIndirectGlobalVars; } Readers.clear(); Writers.clear(); } }
bool GlobalMerge::doInitialization(Module &M) { DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, BSSGlobals; const DataLayout *TD = TLI->getDataLayout(); unsigned MaxOffset = TLI->getMaximalGlobalOffset(); bool Changed = false; // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal globals only if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) continue; PointerType *PT = dyn_cast<PointerType>(I->getType()); assert(PT && "Global variable is not a pointer!"); unsigned AddressSpace = PT->getAddressSpace(); // Ignore fancy-aligned globals for now. unsigned Alignment = TD->getPreferredAlignment(I); Type *Ty = I->getType()->getElementType(); if (Alignment > TD->getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; if (TD->getTypeAllocSize(Ty) < MaxOffset) { if (TargetLoweringObjectFile::getKindForGlobal(I, TLI->getTargetMachine()) .isBSSLocal()) BSSGlobals[AddressSpace].push_back(I); else if (I->isConstant()) ConstGlobals[AddressSpace].push_back(I); else Globals[AddressSpace].push_back(I); } } for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = Globals.begin(), E = Globals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); // FIXME: This currently breaks the EH processing due to way how the // typeinfo detection works. We might want to detect the TIs and ignore // them in the future. // if (ConstGlobals.size() > 1) // Changed |= doMerge(ConstGlobals, M, true); return Changed; }
bool ARMGlobalMerge::doInitialization(Module &M) { SmallVector<GlobalVariable*, 16> Globals, ConstGlobals, BSSGlobals; const TargetData *TD = TLI->getTargetData(); unsigned MaxOffset = TLI->getMaximalGlobalOffset(); bool Changed = false; // Disable this pass on darwin. The debugger is not yet ready to extract // variable's info from a merged global. if (TLI->getTargetMachine().getSubtarget<ARMSubtarget>().isTargetDarwin()) return false; // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal globals only if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) continue; // Ignore fancy-aligned globals for now. if (I->getAlignment() != 0) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; if (TD->getTypeAllocSize(I->getType()->getElementType()) < MaxOffset) { const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering(); if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal()) BSSGlobals.push_back(I); else if (I->isConstant()) ConstGlobals.push_back(I); else Globals.push_back(I); } } if (Globals.size() > 1) Changed |= doMerge(Globals, M, false); if (BSSGlobals.size() > 1) Changed |= doMerge(BSSGlobals, M, false); // FIXME: This currently breaks the EH processing due to way how the // typeinfo detection works. We might want to detect the TIs and ignore // them in the future. // if (ConstGlobals.size() > 1) // Changed |= doMerge(ConstGlobals, M, true); return Changed; }
// Create shadow information for all global variables. void LLPEAnalysisPass::initShadowGlobals(Module& M, uint32_t extraSlots) { uint32_t i = 0; uint32_t nGlobals = std::distance(M.global_begin(), M.global_end()); // extraSlots are reserved for new globals we know will be introduced between now and specialisation start. nGlobals += extraSlots; shadowGlobals = new ShadowGV[nGlobals]; // Assign them all numbers before computing initialisers, because the initialiser can // reference another global, and getValPB will then lookup in shadowGlobalsIdx. for(Module::global_iterator it = M.global_begin(), itend = M.global_end(); it != itend; ++it, ++i) { shadowGlobals[i].G = it; shadowGlobalsIdx[it] = i; } i = 0; for(Module::global_iterator it = M.global_begin(), itend = M.global_end(); it != itend; ++it, ++i) { // getTypeStoreSize can be expensive, so do it once here. if(it->isConstant()) { shadowGlobals[i].storeSize = GlobalAA->getTypeStoreSize(shadowGlobals[i].G->getType()); continue; } // Non-constant global -- assign it a heap slot. shadowGlobals[i].allocIdx = (int32_t)heap.size(); heap.push_back(AllocData()); AllocData& AD = heap.back(); AD.allocIdx = heap.size() - 1; AD.storeSize = GlobalAA->getTypeStoreSize(it->getType()->getElementType()); AD.isCommitted = true; // This usually points to a malloc instruction -- here the global itself. AD.allocValue = ShadowValue(&(shadowGlobals[i])); AD.allocType = shadowGlobals[i].G->getType(); //errs() << "Init store for " << *it << " -> "; //printPB(errs(), *Init); //errs() << "\n"; shadowGlobals[i].storeSize = AD.storeSize; } }
/// OptimizeGlobals - This method uses information taken from DSA to optimize /// global variables. /// bool DSOpt::OptimizeGlobals(Module &M) { DSGraph* GG = TD->getGlobalsGraph(); const DSGraph::ScalarMapTy &SM = GG->getScalarMap(); bool Changed = false; for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!I->isDeclaration()) { // Loop over all of the non-external globals... // Look up the node corresponding to this global, if it exists. DSNode *GNode = 0; DSGraph::ScalarMapTy::const_iterator SMI = SM.find(I); if (SMI != SM.end()) GNode = SMI->second.getNode(); if (GNode == 0 && I->hasInternalLinkage()) { // If there is no entry in the scalar map for this global, it was never // referenced in the program. If it has internal linkage, that means we // can delete it. We don't ACTUALLY want to delete the global, just // remove anything that references the global: later passes will take // care of nuking it. if (!I->use_empty()) { I->replaceAllUsesWith(ConstantPointerNull::get(I->getType())); ++NumGlobalsIsolated; } } else if (GNode && GNode->NodeType.isCompleteNode()) { // If the node has not been read or written, and it is not externally // visible, kill any references to it so it can be DCE'd. if (!GNode->NodeType.isModifiedNode() && !GNode->NodeType.isReadNode() &&I->hasInternalLinkage()){ if (!I->use_empty()) { I->replaceAllUsesWith(ConstantPointerNull::get(I->getType())); ++NumGlobalsIsolated; } } // We expect that there will almost always be a node for this global. // If there is, and the node doesn't have the M bit set, we can set the // 'constant' bit on the global. if (!GNode->NodeType.isModifiedNode() && !I->isConstant()) { I->setConstant(true); ++NumGlobalsConstanted; Changed = true; } } } return Changed; }
bool ARMGlobalMerge::doInitialization(Module &M) { SmallVector<GlobalVariable*, 16> Globals, ConstGlobals; const TargetData *TD = TLI->getTargetData(); unsigned MaxOffset = TLI->getMaximalGlobalOffset(); bool Changed = false; // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal globals only if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) continue; // Ignore fancy-aligned globals for now. if (I->getAlignment() != 0) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; if (TD->getTypeAllocSize(I->getType()) < MaxOffset) { if (I->isConstant()) ConstGlobals.push_back(I); else Globals.push_back(I); } } if (Globals.size() > 1) Changed |= doMerge(Globals, M, false); // FIXME: This currently breaks the EH processing due to way how the // typeinfo detection works. We might want to detect the TIs and ignore // them in the future. // if (ConstGlobals.size() > 1) // Changed |= doMerge(ConstGlobals, M, true); return Changed; }
bool GlobalMerge::doInitialization(Module &M) { if (!EnableGlobalMerge) return false; auto &DL = M.getDataLayout(); DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, BSSGlobals; bool Changed = false; setMustKeepGlobalVariables(M); // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal or external globals only if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) continue; if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && !I->hasInternalLinkage()) continue; PointerType *PT = dyn_cast<PointerType>(I->getType()); assert(PT && "Global variable is not a pointer!"); unsigned AddressSpace = PT->getAddressSpace(); // Ignore fancy-aligned globals for now. unsigned Alignment = DL.getPreferredAlignment(I); Type *Ty = I->getType()->getElementType(); if (Alignment > DL.getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; // Ignore all "required" globals: if (isMustKeepGlobalVariable(I)) continue; if (DL.getTypeAllocSize(Ty) < MaxOffset) { if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) BSSGlobals[AddressSpace].push_back(I); else if (I->isConstant()) ConstGlobals[AddressSpace].push_back(I); else Globals[AddressSpace].push_back(I); } } for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = Globals.begin(), E = Globals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); if (EnableGlobalMergeOnConst) for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, true, I->first); return Changed; }