[llvm link] Destroy ConstantArrays in LLVMContext if they are not used.
authorManman Ren <manman.ren@gmail.com>
Tue, 20 Jan 2015 19:24:59 +0000 (19:24 +0000)
committerManman Ren <manman.ren@gmail.com>
Tue, 20 Jan 2015 19:24:59 +0000 (19:24 +0000)
ConstantArrays constructed during linking can cause quadratic memory
explosion. An example is the ConstantArrays constructed when linking in
GlobalVariables with appending linkage.

Releasing all unused constants can cause a 20% LTO compile-time
slowdown for a large application. So this commit releases unused ConstantArrays
only.

rdar://19040716. It reduces memory footprint from 20+G to 6+G.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226592 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Module.h
lib/IR/LLVMContextImpl.cpp
lib/IR/LLVMContextImpl.h
lib/Linker/LinkModules.cpp

index b24023b05e4fad4cd032b043ccc2dfb6fc0142ab..62f41943be833c8ce2bcdf36ab4e8d1541ea4fa7 100644 (file)
@@ -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
 /// @{
index aa7242af997d7170db8d94b51c57f81ad9d8d62f..880e1c1bcad249219d79d6870d58be92dc9c6e25 100644 (file)
@@ -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.
 ///
index 4604d9babb54024a324cd5ef41b8e7a86e13ecf2..3b3be0f9982dd3b68198c139e487411c43d398b5 100644 (file)
@@ -474,6 +474,9 @@ public:
   
   LLVMContextImpl(LLVMContext &C);
   ~LLVMContextImpl();
+
+  /// Destroy the ConstantArrays if they are not used.
+  void dropTriviallyDeadConstantArrays();
 };
 
 }
index 767d465d1bee6da2d78e2e17cce041231bb53ddd..dc002d8a5766fbcb6e028834bb32a39465b4628c 100644 (file)
@@ -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;
 }
 
 //===----------------------------------------------------------------------===//