diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -175,7 +175,7 @@ for (auto &Buf : Buffers) { layoutBuffer(Buf, DL); GlobalVariable *GV = replaceBuffer(Buf); - M.getGlobalList().push_back(GV); + M.insertGlobalVariable(GV); llvm::hlsl::ResourceClass RC = Buf.IsCBuffer ? llvm::hlsl::ResourceClass::CBuffer : llvm::hlsl::ResourceClass::SRV; diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -7431,7 +7431,7 @@ GV->eraseFromParent(); } GV = NewGV; - CGM.getModule().getGlobalList().push_back(GV); + CGM.getModule().insertGlobalVariable(GV); } assert(GV->getLinkage() == L); diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -406,7 +406,7 @@ } }; - for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) { + for (llvm::GlobalVariable &global_var : m_module->globals()) { RegisterOneValue(global_var); } diff --git a/llvm/docs/ProgrammersManual.rst b/llvm/docs/ProgrammersManual.rst --- a/llvm/docs/ProgrammersManual.rst +++ b/llvm/docs/ProgrammersManual.rst @@ -3429,17 +3429,14 @@ * | ``Module::global_iterator`` - Typedef for global variable list iterator | ``Module::const_global_iterator`` - Typedef for const_iterator. + | ``Module::insertGlobalVariable()`` - Inserts a global variable to the list. + | ``Module::removeGlobalVariable()`` - Removes a global variable frome the list. + | ``Module::eraseGlobalVariable()`` - Removes a global variable frome the list and deletes it. | ``global_begin()``, ``global_end()``, ``global_size()``, ``global_empty()`` These are forwarding methods that make it easy to access the contents of a ``Module`` object's GlobalVariable_ list. -* ``Module::GlobalListType &getGlobalList()`` - - Returns the list of GlobalVariable_\ s. This is necessary to use when you - need to update the list or perform a complex action that doesn't have a - forwarding method. - ---------------- * ``SymbolTable *getSymbolTable()`` diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -542,6 +542,24 @@ llvm::Error materializeMetadata(); + /// Detach global variable \p GV from the list but don't delete it. + void removeGlobalVariable(GlobalVariable *GV) { GlobalList.remove(GV); } + /// Remove global variable \p GV from the list and delete it. + void eraseGlobalVariable(GlobalVariable *GV) { GlobalList.erase(GV); } + /// Insert global variable \p GV at the end of the global variable list and + /// take ownership. + void insertGlobalVariable(GlobalVariable *GV) { + insertGlobalVariable(GlobalList.end(), GV); + } + /// Insert global variable \p GV into the global variable list before \p + /// Where and take ownership. + void insertGlobalVariable(GlobalListType::iterator Where, GlobalVariable *GV) { + GlobalList.insert(Where, GV); + } + // Use global_size() to get the total number of global variables. + // Use globals() to get the range of all global variables. + +private: /// @} /// @name Direct access to the globals list, functions list, and symbol table /// @{ @@ -554,7 +572,9 @@ static GlobalListType Module::*getSublistAccess(GlobalVariable*) { return &Module::GlobalList; } + friend class llvm::SymbolTableListTraits; +public: /// Get the Module's list of functions (constant). const FunctionListType &getFunctionList() const { return FunctionList; } /// Get the Module's list of functions. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -3693,7 +3693,7 @@ UpgradedVariables.emplace_back(&GV, Upgraded); for (auto &Pair : UpgradedVariables) { Pair.first->eraseFromParent(); - TheModule->getGlobalList().push_back(Pair.second); + TheModule->insertGlobalVariable(Pair.second); } // Force deallocation of memory for these vectors to favor the client that diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -571,7 +571,7 @@ // Look for existing encoding of the location + flags, not needed but // minimizes the difference to the existing solution while we transition. - for (GlobalVariable &GV : M.getGlobalList()) + for (GlobalVariable &GV : M.globals()) if (GV.getValueType() == OpenMPIRBuilder::Ident && GV.hasInitializer()) if (GV.getInitializer() == Initializer) Ident = &GV; @@ -601,7 +601,7 @@ // Look for existing encoding of the location, not needed but minimizes the // difference to the existing solution while we transition. - for (GlobalVariable &GV : M.getGlobalList()) + for (GlobalVariable &GV : M.globals()) if (GV.isConstant() && GV.hasInitializer() && GV.getInitializer() == Initializer) return SrcLocStr = ConstantExpr::getPointerCast(&GV, Int8Ptr); diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -456,17 +456,17 @@ } if (Before) - Before->getParent()->getGlobalList().insert(Before->getIterator(), this); + Before->getParent()->insertGlobalVariable(Before->getIterator(), this); else - M.getGlobalList().push_back(this); + M.insertGlobalVariable(this); } void GlobalVariable::removeFromParent() { - getParent()->getGlobalList().remove(getIterator()); + getParent()->removeGlobalVariable(this); } void GlobalVariable::eraseFromParent() { - getParent()->getGlobalList().erase(getIterator()); + getParent()->eraseGlobalVariable(this); } void GlobalVariable::setInitializer(Constant *InitVal) { diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1671,15 +1671,16 @@ // Reorder the globals just added to the destination module to match their // original order in the source module. - Module::GlobalListType &Globals = DstM.getGlobalList(); for (GlobalVariable &GV : SrcM->globals()) { if (GV.hasAppendingLinkage()) continue; Value *NewValue = Mapper.mapValue(GV); if (NewValue) { auto *NewGV = dyn_cast(NewValue->stripPointerCasts()); - if (NewGV) - Globals.splice(Globals.end(), Globals, NewGV->getIterator()); + if (NewGV) { + NewGV->removeFromParent(); + DstM.insertGlobalVariable(NewGV); + } } } diff --git a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp --- a/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp +++ b/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp @@ -826,8 +826,7 @@ for (const GlobalVariable &I : M.globals()) VisitGlobalVariableForEmission(&I, Globals, GVVisited, GVVisiting); - assert(GVVisited.size() == M.getGlobalList().size() && - "Missed a global variable"); + assert(GVVisited.size() == M.global_size() && "Missed a global variable"); assert(GVVisiting.size() == 0 && "Did not fully process a global variable"); const NVPTXTargetMachine &NTM = static_cast(TM); diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -976,7 +976,7 @@ cast(InitBool->user_back())->eraseFromParent(); delete InitBool; } else - GV->getParent()->getGlobalList().insert(GV->getIterator(), InitBool); + GV->getParent()->insertGlobalVariable(GV->getIterator(), InitBool); // Now the GV is dead, nuke it and the allocation.. GV->eraseFromParent(); @@ -1158,7 +1158,7 @@ GV->getThreadLocalMode(), GV->getType()->getAddressSpace()); NewGV->copyAttributesFrom(GV); - GV->getParent()->getGlobalList().insert(GV->getIterator(), NewGV); + GV->getParent()->insertGlobalVariable(GV->getIterator(), NewGV); Constant *InitVal = GV->getInitializer(); assert(InitVal->getType() != Type::getInt1Ty(GV->getContext()) && diff --git a/llvm/lib/Transforms/IPO/SCCP.cpp b/llvm/lib/Transforms/IPO/SCCP.cpp --- a/llvm/lib/Transforms/IPO/SCCP.cpp +++ b/llvm/lib/Transforms/IPO/SCCP.cpp @@ -370,7 +370,7 @@ SI->eraseFromParent(); MadeChanges = true; } - M.getGlobalList().erase(GV); + M.eraseGlobalVariable(GV); ++NumGlobalConst; } @@ -407,3 +407,72 @@ PA.preserve(); return PA; } + +namespace { + +//===--------------------------------------------------------------------===// +// +/// IPSCCP Class - This class implements interprocedural Sparse Conditional +/// Constant Propagation. +/// +class IPSCCPLegacyPass : public ModulePass { +public: + static char ID; + + IPSCCPLegacyPass() : ModulePass(ID) { + initializeIPSCCPLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + if (skipModule(M)) + return false; + const DataLayout &DL = M.getDataLayout(); + auto GetTLI = [this](Function &F) -> const TargetLibraryInfo & { + return this->getAnalysis().getTLI(F); + }; + auto GetTTI = [this](Function &F) -> TargetTransformInfo & { + return this->getAnalysis().getTTI(F); + }; + auto GetAC = [this](Function &F) -> AssumptionCache & { + return this->getAnalysis().getAssumptionCache(F); + }; + auto getAnalysis = [this](Function &F) -> AnalysisResultsForFn { + DominatorTree &DT = + this->getAnalysis(F).getDomTree(); + return { + std::make_unique( + F, DT, + this->getAnalysis().getAssumptionCache( + F)), + nullptr, // We cannot preserve the LI, DT or PDT with the legacy pass + nullptr, // manager, so set them to nullptr. + nullptr}; + }; + + return runIPSCCP(M, DL, nullptr, GetTLI, GetTTI, GetAC, getAnalysis, false); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + } +}; + +} // end anonymous namespace + +char IPSCCPLegacyPass::ID = 0; + +INITIALIZE_PASS_BEGIN(IPSCCPLegacyPass, "ipsccp", + "Interprocedural Sparse Conditional Constant Propagation", + false, false) +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_END(IPSCCPLegacyPass, "ipsccp", + "Interprocedural Sparse Conditional Constant Propagation", + false, false) + +// createIPSCCPPass - This is the public interface to this file. +ModulePass *llvm::createIPSCCPPass() { return new IPSCCPLegacyPass(); } diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp --- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -958,7 +958,7 @@ std::vector &Bits, DenseMap> &TypeIdMap) { DenseMap GVToBits; - Bits.reserve(M.getGlobalList().size()); + Bits.reserve(M.global_size()); SmallVector Types; for (GlobalVariable &GV : M.globals()) { Types.clear(); diff --git a/llvm/lib/Transforms/Utils/CtorUtils.cpp b/llvm/lib/Transforms/Utils/CtorUtils.cpp --- a/llvm/lib/Transforms/Utils/CtorUtils.cpp +++ b/llvm/lib/Transforms/Utils/CtorUtils.cpp @@ -48,7 +48,7 @@ GlobalVariable *NGV = new GlobalVariable(CA->getType(), GCL->isConstant(), GCL->getLinkage(), CA, "", GCL->getThreadLocalMode()); - GCL->getParent()->getGlobalList().insert(GCL->getIterator(), NGV); + GCL->getParent()->insertGlobalVariable(GCL->getIterator(), NGV); NGV->takeName(GCL); // Nuke the old list, replacing any uses with the new one. diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp --- a/llvm/unittests/IR/ModuleTest.cpp +++ b/llvm/unittests/IR/ModuleTest.cpp @@ -46,8 +46,6 @@ // Sort the globals by name. EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare)); - M.getGlobalList().sort(compare); - EXPECT_TRUE(std::is_sorted(M.global_begin(), M.global_end(), compare)); } } @@ -273,4 +271,43 @@ EXPECT_EQ(M->named_metadata_size(), 2u); } +TEST(ModuleTest, GlobalList) { + // This tests all Module's functions that interact with Module::GlobalList. + LLVMContext C; + SMDiagnostic Err; + LLVMContext Context; + std::unique_ptr M = parseAssemblyString(R"( +@GV = external global i32 +)", + Err, Context); + auto *GV = cast(M->getNamedValue("GV")); + EXPECT_EQ(M->global_size(), 1u); + GlobalVariable *NewGV = new GlobalVariable( + Type::getInt32Ty(C), /*isConstant=*/true, GlobalValue::InternalLinkage, + /*Initializer=*/nullptr, "NewGV"); + EXPECT_EQ(M->global_size(), 1u); + // Insert before + M->insertGlobalVariable(M->globals().begin(), NewGV); + EXPECT_EQ(M->global_size(), 2u); + EXPECT_EQ(&*M->globals().begin(), NewGV); + // Insert at end() + M->removeGlobalVariable(NewGV); + EXPECT_EQ(M->global_size(), 1u); + M->insertGlobalVariable(NewGV); + EXPECT_EQ(M->global_size(), 2u); + EXPECT_EQ(&*std::prev(M->globals().end()), NewGV); + // Check globals() + auto Range = M->globals(); + EXPECT_EQ(&*Range.begin(), GV); + EXPECT_EQ(&*std::next(Range.begin()), NewGV); + EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); + // Check remove + M->removeGlobalVariable(NewGV); + EXPECT_EQ(M->global_size(), 1u); + // Check erase + M->insertGlobalVariable(NewGV); + M->eraseGlobalVariable(NewGV); + EXPECT_EQ(M->global_size(), 1u); +} + } // end namespace