diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index b24023b05e4..62f41943be8 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -630,6 +630,15 @@ public: named_metadata_end()); } + /// Destroy ConstantArrays in LLVMContext if they are not used. + /// ConstantArrays constructed during linking can cause quadratic memory + /// explosion. Releasing all unused constants can cause a 20% LTO compile-time + /// slowdown for a large application. + /// + /// NOTE: Constants are currently owned by LLVMContext. This can then only + /// be called where all uses of the LLVMContext are understood. + void dropTriviallyDeadConstantArrays(); + /// @} /// @name Utility functions for printing and dumping Module objects /// @{ diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index aa7242af997..880e1c1bcad 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -163,6 +163,28 @@ LLVMContextImpl::~LLVMContextImpl() { MDStringCache.clear(); } +void LLVMContextImpl::dropTriviallyDeadConstantArrays() { + bool Changed; + do { + Changed = false; + + for (auto I = ArrayConstants.map_begin(), E = ArrayConstants.map_end(); + I != E; ) { + auto *C = I->first; + I++; + if (C->use_empty()) { + Changed = true; + C->destroyConstant(); + } + } + + } while (Changed); +} + +void Module::dropTriviallyDeadConstantArrays() { + Context.pImpl->dropTriviallyDeadConstantArrays(); +} + namespace llvm { /// \brief Make MDOperand transparent for hashing. /// diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 4604d9babb5..3b3be0f9982 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -474,6 +474,9 @@ public: LLVMContextImpl(LLVMContext &C); ~LLVMContextImpl(); + + /// Destroy the ConstantArrays if they are not used. + void dropTriviallyDeadConstantArrays(); }; } diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 767d465d1be..dc002d8a576 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -1721,7 +1721,9 @@ void Linker::deleteModule() { bool Linker::linkInModule(Module *Src) { ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, DiagnosticHandler); - return TheLinker.run(); + bool RetCode = TheLinker.run(); + Composite->dropTriviallyDeadConstantArrays(); + return RetCode; } //===----------------------------------------------------------------------===//