Allocate AtomicSDNode operands in SelectionDAG's allocator to stop leakage.
authorBenjamin Kramer <benny.kra@googlemail.com>
Sun, 29 Sep 2013 11:18:56 +0000 (11:18 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sun, 29 Sep 2013 11:18:56 +0000 (11:18 +0000)
SDNode destructors are never called. As an optimization use AtomicSDNode's
internal storage if we have a small number of operands.

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

include/llvm/CodeGen/SelectionDAGNodes.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp

index 4166340f3023fd30e78ac336aed19ee9f4416721..13f5d4ecac55bb273542c1e53820eabc3bd5099f 100644 (file)
@@ -1073,7 +1073,6 @@ public:
 ///
 class AtomicSDNode : public MemSDNode {
   SDUse Ops[4];
-  SDUse* DynOps;
 
   void InitAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope) {
     // This must match encodeMemSDNodeFlags() in SelectionDAG.cpp.
@@ -1101,7 +1100,7 @@ public:
                SDValue Chain, SDValue Ptr,
                SDValue Cmp, SDValue Swp, MachineMemOperand *MMO,
                AtomicOrdering Ordering, SynchronizationScope SynchScope)
-    : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO), DynOps(NULL) {
+    : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(Ordering, SynchScope);
     InitOperands(Ops, Chain, Ptr, Cmp, Swp);
   }
@@ -1110,7 +1109,7 @@ public:
                SDValue Chain, SDValue Ptr,
                SDValue Val, MachineMemOperand *MMO,
                AtomicOrdering Ordering, SynchronizationScope SynchScope)
-    : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO), DynOps(NULL) {
+    : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(Ordering, SynchScope);
     InitOperands(Ops, Chain, Ptr, Val);
   }
@@ -1119,21 +1118,19 @@ public:
                SDValue Chain, SDValue Ptr,
                MachineMemOperand *MMO,
                AtomicOrdering Ordering, SynchronizationScope SynchScope)
-    : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO), DynOps(NULL) {
+    : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
     InitAtomic(Ordering, SynchScope);
     InitOperands(Ops, Chain, Ptr);
   }
   AtomicSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTL, EVT MemVT,
-               SDValue* AllOps, unsigned NumOps,
+               SDValue* AllOps, SDUse *DynOps, unsigned NumOps,
                MachineMemOperand *MMO,
                AtomicOrdering Ordering, SynchronizationScope SynchScope)
     : MemSDNode(Opc, Order, dl, VTL, MemVT, MMO) {
-    DynOps = new SDUse[NumOps];
     InitAtomic(Ordering, SynchScope);
-    InitOperands(DynOps, AllOps, NumOps);
-  }
-  ~AtomicSDNode() {
-    delete[] DynOps;
+    assert((DynOps || NumOps <= array_lengthof(Ops)) &&
+           "Too many ops for internal storage!");
+    InitOperands(DynOps ? DynOps : Ops, AllOps, NumOps);
   }
 
   const SDValue &getBasePtr() const { return getOperand(1); }
index b96c4b18d11392dd159a4702a9e365f4902c109c..62ceb8b3a2556fb0631ca5b3cc777254824b5f02 100644 (file)
@@ -4125,10 +4125,18 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT,
     cast<AtomicSDNode>(E)->refineAlignment(MMO);
     return SDValue(E, 0);
   }
+
+  // Allocate the operands array for the node out of the BumpPtrAllocator, since
+  // SDNode doesn't have access to it.  This memory will be "leaked" when
+  // the node is deallocated, but recovered when the allocator is released.
+  // If the number of operands is less than 5 we use AtomicSDNode's internal
+  // storage.
+  SDUse *DynOps = NumOps > 4 ? OperandAllocator.Allocate<SDUse>(NumOps) : 0;
+
   SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl.getIROrder(),
                                                dl.getDebugLoc(), VTList, MemVT,
-                                               Ops, NumOps, MMO, Ordering,
-                                               SynchScope);
+                                               Ops, DynOps, NumOps, MMO,
+                                               Ordering, SynchScope);
   CSEMap.InsertNode(N, IP);
   AllNodes.push_back(N);
   return SDValue(N, 0);