patch-r274442-llvm-r221709-debug-oom.diff revision 274696
1Pull in r221709 from upstream llvm trunk (by Fr��d��ric Riss):
2
3  Totally forget deallocated SDNodes in SDDbgInfo.
4
5  What would happen before that commit is that the SDDbgValues associated with
6  a deallocated SDNode would be marked Invalidated, but SDDbgInfo would keep
7  a map entry keyed by the SDNode pointer pointing to this list of invalidated
8  SDDbgNodes. As the memory gets reused, the list might get wrongly associated
9  with another new SDNode. As the SDDbgValues are cloned when they are transfered,
10  this can lead to an exponential number of SDDbgValues being produced during
11  DAGCombine like in http://llvm.org/bugs/show_bug.cgi?id=20893
12
13  Note that the previous behavior wasn't really buggy as the invalidation made
14  sure that the SDDbgValues won't be used. This commit can be considered a
15  memory optimization and as such is really hard to validate in a unit-test.
16
17This should fix abnormally large memory usage and resulting OOM crashes
18when compiling certain ports with debug information.
19
20Reported by:	Dmitry Marakasov <amdmi3@amdmi3.ru>
21Upstream PRs:	http://llvm.org/PR19031 http://llvm.org/PR20893
22
23Introduced here: http://svnweb.freebsd.org/changeset/base/274442
24
25Index: include/llvm/CodeGen/SelectionDAG.h
26===================================================================
27--- include/llvm/CodeGen/SelectionDAG.h
28+++ include/llvm/CodeGen/SelectionDAG.h
29@@ -127,6 +127,10 @@ class SDDbgInfo {
30       DbgValMap[Node].push_back(V);
31   }
32 
33+  /// \brief Invalidate all DbgValues attached to the node and remove
34+  /// it from the Node-to-DbgValues map.
35+  void erase(const SDNode *Node);
36+
37   void clear() {
38     DbgValMap.clear();
39     DbgValues.clear();
40Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp
41===================================================================
42--- lib/CodeGen/SelectionDAG/SelectionDAG.cpp
43+++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp
44@@ -625,6 +625,15 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *
45   DeallocateNode(N);
46 }
47 
48+void SDDbgInfo::erase(const SDNode *Node) {
49+  DbgValMapType::iterator I = DbgValMap.find(Node);
50+  if (I == DbgValMap.end())
51+    return;
52+  for (unsigned J = 0, N = I->second.size(); J != N; ++J)
53+    I->second[J]->setIsInvalidated();
54+  DbgValMap.erase(I);
55+}
56+
57 void SelectionDAG::DeallocateNode(SDNode *N) {
58   if (N->OperandsNeedDelete)
59     delete[] N->OperandList;
60@@ -635,10 +644,9 @@ void SelectionDAG::DeallocateNode(SDNode *N) {
61 
62   NodeAllocator.Deallocate(AllNodes.remove(N));
63 
64-  // If any of the SDDbgValue nodes refer to this SDNode, invalidate them.
65-  ArrayRef<SDDbgValue*> DbgVals = DbgInfo->getSDDbgValues(N);
66-  for (unsigned i = 0, e = DbgVals.size(); i != e; ++i)
67-    DbgVals[i]->setIsInvalidated();
68+  // If any of the SDDbgValue nodes refer to this SDNode, invalidate
69+  // them and forget about that node.
70+  DbgInfo->erase(N);
71 }
72 
73 /// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that
74