Fixed a bug in memory debugger (...) Fixed a stupid bug while releasing FunctionDAG
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Sat, 17 Mar 2012 11:07:37 +0000 (04:07 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:15:44 +0000 (16:15 -0700)
backend/src/ir/value.cpp
backend/src/ir/value.hpp
backend/src/sys/alloc.cpp
backend/src/sys/alloc.hpp
backend/src/sys/hash_map.hpp
backend/src/sys/map.hpp
backend/src/sys/set.hpp
backend/src/sys/vector.hpp
backend/src/utest/utest_llvm.cpp

index a4fd89b..2c8c3f3 100644 (file)
@@ -90,6 +90,16 @@ namespace ir {
                                const BasicBlock &bb,
                                const Register &reg)
   {
+    // We add all the definitions here
+    RegDefSet &defs = this->getDefSet(&bb, reg);
+
+    // Iterate over all the predecessors
+    const auto &preds = bb.getPredecessorSet();
+    for (auto pred = preds.begin(); pred != preds.end(); ++pred) {
+      RegDefSet &predDef = this->getDefSet(*pred, reg);
+      for (auto def = predDef.begin(); def != predDef.end(); ++def)
+        defs.insert(*def);
+    }
   }
 
   void LiveOutSet::initializeInstructionDst(void) {
@@ -257,8 +267,72 @@ namespace ir {
       duGraph.insert(std::make_pair(*valueDef, duEmpty));
     }
 
+#if 1
     // We create the liveOutSet to help us transfer the definitions
-    const LiveOutSet liveOutSet(liveness, *this);
+    LiveOutSet liveOutSet(liveness, *this);
+
+    // Build UD chains traversing the blocks top to bottom
+    fn.foreachBlock([&](const BasicBlock &bb) {
+      // Track the allocated chains to be able to reuse them
+      map<Register, UDChain*> allocated;
+      // Some chains may be not used (ie they are dead). We track them to be
+      // able to deallocate them later
+      // set<UDChain*> unused;
+
+      // For each instruction build the UD chains
+      bb.foreach([&](const Instruction &insn) {
+        // Instruction sources consumes definitions
+#if 1
+        const uint32_t srcNum = insn.getSrcNum();
+        for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
+          const Register src = insn.getSrcIndex(fn, srcID);
+          const ValueUse use(&insn, srcID);
+          // auto ud = udGraph.find(use);
+          //GBE_ASSERT(ud != udGraph.end());
+
+          // We already allocate the ud chain for this register
+          auto it = allocated.find(src);
+          if (it != allocated.end()) {
+            // udGraph.erase(ud);
+            udGraph.insert(std::make_pair(use, it->second));
+            //if (unused.contains(it->second))
+            //  unused.erase(it->second);
+
+          // Create a new one from the predecessor chains (upward used value)
+          } else {
+    //        UDChain *udChain = this->newUDChain();
+    //        liveOutSet.fillUDChain(*udChain, bb, src);
+    //        allocated.insert(std::make_pair(src, udChain));
+    //        ud->second = udChain;
+          }
+        }
+#endif
+        // Instruction destinations create new chains
+        const uint32_t dstNum = insn.getDstNum();
+        for (uint32_t dstID = 0; dstID < dstNum; ++dstID) {
+          const Register dst = insn.getDstIndex(fn, dstID);
+          // ValueDef *def = (ValueDef *) this->getDefAddress(&insn, dstID);
+
+          UDChain *udChain = this->newUDChain();
+          // udChain->insert(def);
+          udChain->insert(NULL);
+          // unused.insert(udChain);
+          allocated.insert(std::make_pair(dst, udChain));
+#endif
+        }
+      });
+
+      // Deallocate unused chains
+//      for (auto it = unused.begin(); it != unused.end(); ++it)
+//        this->deleteUDChain(*it);
+    });
+
+    // Build the DU chains from the UD ones
+    fn.foreachInstruction([&](const Instruction &insn) {
+
+
+    });
+
   }
 
 /*! Helper to deallocate objects */
@@ -282,6 +356,7 @@ namespace ir {
     // We free all the ud-chains
     for (auto it = udGraph.begin(); it != udGraph.end(); ++it) {
       auto defs = it->second;
+      if (destroyed.contains(defs)) continue;
       for (auto def = defs->begin(); def != defs->end(); ++def)
         PTR_RELEASE(ValueDef, *def);
       PTR_RELEASE(UDChain, defs);
@@ -290,6 +365,7 @@ namespace ir {
     // We free all the du-chains
     for (auto it = duGraph.begin(); it != duGraph.end(); ++it) {
       auto uses = it->second;
+      if (destroyed.contains(uses)) continue;
       for (auto use = uses->begin(); use != uses->end(); ++use)
         PTR_RELEASE(ValueUse, *use);
       PTR_RELEASE(DUChain, uses);
@@ -303,14 +379,12 @@ namespace ir {
     GBE_ASSERT(it != duGraph.end());
     return *it->second;
   }
-
   const DUChain &FunctionDAG::getUse(const FunctionInput *input) const {
     const ValueDef def(input);
     auto it = duGraph.find(def);
     GBE_ASSERT(it != duGraph.end());
     return *it->second;
   }
-
   const UDChain &FunctionDAG::getDef(const Instruction *insn, uint32_t srcID) const {
     const ValueUse use(insn, srcID);
     auto it = udGraph.find(use);
index 9b3ec63..f40a71a 100644 (file)
@@ -89,6 +89,7 @@ namespace ir {
     } data;
     /*!< Function argument or instruction dst? */
     Type type;
+    GBE_CLASS(ValueDef); // Use gbe allocators
   };
 
   /*! Compare two value definitions (used in maps) */
@@ -126,6 +127,7 @@ namespace ir {
   private:
     const Instruction *insn; //!< Instruction where the value is used
     uint32_t srcID;          //!< Index of the source in the instruction
+    GBE_CLASS(ValueUse);     // Use gbe allocators
   };
 
   /*! Compare two value uses (used in maps) */
@@ -141,7 +143,7 @@ namespace ir {
   /*! All uses of a definition */
   typedef set<ValueUse*> DUChain;
   /*! All possible definitions for a use */
-  typedef set<ValueDef*> UDChain;
+  typedef std::set<ValueDef*> UDChain;
 
   /*! Get the chains (in both directions) for the complete program */
   class FunctionDAG
@@ -172,6 +174,7 @@ namespace ir {
     DUGraph duGraph;                   //!< All the DU chains
     UDChain *udEmpty;                  //!< Void use set
     DUChain *duEmpty;                  //!< Void def set
+    ValueDef *undefined;               //!< Undefined value
     map<ValueUse, ValueUse*> useName;  //!< Get the ValueUse pointer from the value
     map<ValueDef, ValueDef*> defName;  //!< Get the ValueDef pointer from the value
     DECL_POOL(ValueDef, valueDefPool); //!< Fast ValueDef allocation
index c7305c2..f048ee0 100644 (file)
@@ -141,18 +141,19 @@ namespace gbe
   static MemDebugger *memDebugger = NULL;
 
   /*! Monitor maximum memory requirement in the compiler */
-  static size_t memDebuggerCurrSize = 0;
-  static size_t memDebuggerMaxSize = 0;
+  static MutexSys sizeMutex;
+  static size_t memDebuggerCurrSize(0u);
+  static size_t memDebuggerMaxSize(0u);
 
   /*! Stop the memory debugger */
   static void MemDebuggerEnd(void) {
     MemDebugger *_debug = memDebugger;
     memDebugger = NULL;
-    GBE_ASSERT(memDebuggerCurrSize == 0);
     std::cout << "Maximum memory consumption: "
               << std::setprecision(2) << std::fixed
               << float(memDebuggerMaxSize) / 1024. << "KB" << std::endl;
     delete _debug;
+    GBE_ASSERT(memDebuggerCurrSize == 0);
   }
 
   /*! Bring up the debugger at pre-main */
@@ -201,8 +202,10 @@ namespace gbe
     void *ptr = std::malloc(size + sizeof(size_t));
     *(size_t *) ptr = size;
     MemDebuggerInitializeMem((char*) ptr + sizeof(size_t), size);
+    sizeMutex.lock();
     memDebuggerCurrSize += size;
     memDebuggerMaxSize = std::max(memDebuggerCurrSize, memDebuggerMaxSize);
+    sizeMutex.unlock();
     return (char *) ptr + sizeof(size_t);
   }
   void memFree(void *ptr) {
@@ -210,7 +213,9 @@ namespace gbe
       char *toFree = (char*) ptr - sizeof(size_t);
       const size_t size = *(size_t *) toFree;
       MemDebuggerInitializeMem(ptr, size);
+      sizeMutex.lock();
       memDebuggerCurrSize -= size;
+      sizeMutex.unlock();
       std::free(toFree);
     }
   }
@@ -226,15 +231,17 @@ namespace gbe
 namespace gbe
 {
   void* alignedMalloc(size_t size, size_t align) {
-    void* mem = malloc(size+(align-1)+sizeof(uintptr_t) + sizeof(void*));
+    void* mem = malloc(size+align+sizeof(uintptr_t) + sizeof(void*));
     FATAL_IF (!mem && size, "memory allocation failed");
     char* aligned = (char*) mem + sizeof(uintptr_t) + sizeof(void*);
     aligned += align - ((uintptr_t)aligned & (align - 1));
     ((void**)aligned)[-1] = mem;
     ((uintptr_t*)aligned)[-2] = uintptr_t(size);
     MemDebuggerInitializeMem(aligned, size);
+    sizeMutex.lock();
     memDebuggerCurrSize += size;
     memDebuggerMaxSize = std::max(memDebuggerCurrSize, memDebuggerMaxSize);
+    sizeMutex.unlock();
     return aligned;
   }
 
@@ -243,7 +250,9 @@ namespace gbe
       const size_t size = ((uintptr_t*)ptr)[-2];
       MemDebuggerInitializeMem(ptr, size);
       free(((void**)ptr)[-1]);
+      sizeMutex.lock();
       memDebuggerCurrSize -= size;
+      sizeMutex.unlock();
     }
   }
 } /* namespace gbe */
@@ -310,7 +319,7 @@ namespace gbe
 namespace gbe
 {
   void* alignedMalloc(size_t size, size_t align) {
-    void* mem = malloc(size+(align-1)+sizeof(void*));
+    void* mem = malloc(size+align+sizeof(void*));
     FATAL_IF (!mem && size, "memory allocation failed");
     char* aligned = ((char*)mem) + sizeof(void*);
     aligned += align - ((uintptr_t)aligned & (align - 1));
index 5e5d2ca..8e9fabf 100644 (file)
@@ -226,10 +226,10 @@ namespace gbe
 #define DECL_POOL(TYPE, POOL)                     \
   GrowingPool<TYPE> POOL;                         \
   template <typename... Args>                     \
-  INLINE TYPE *new##TYPE(Args... args) {          \
+  TYPE *new##TYPE(Args... args) {          \
     return new (POOL.allocate()) TYPE(args...);   \
   }                                               \
-  INLINE void delete##TYPE(TYPE *ptr) {           \
+  void delete##TYPE(TYPE *ptr) {           \
     ptr->~TYPE();                                 \
     POOL.deallocate(ptr);                         \
   }
index cddd811..f7a63c2 100644 (file)
@@ -40,7 +40,8 @@ namespace gbe
             class T,
             class Hash = std::hash<Key>,
             class Pred = std::equal_to<Key>>
-  class hash_map : public std::tr1::unordered_map<Key,T,Hash,Pred,Allocator<std::pair<const Key,T>>>
+  class hash_map : public std::tr1::unordered_map<Key,T,Hash,Pred,Allocator<std::pair<const Key,T>>>,
+                   public NonCopyable
   {
   public:
     // Typedefs
@@ -68,8 +69,10 @@ namespace gbe
                     const key_equal& eql = key_equal(),
                     const allocator_type& a = allocator_type()) :
       parent_type(first,last,n,hf,eql,a) {}
+#if 0
     /*! Copy constructor */
     INLINE hash_map(const hash_map &other) : parent_type(other) {}
+#endif
     GBE_CLASS(hash_map);
   };
 } /* namespace gbe */
index 6e9d8dd..1c72400 100644 (file)
@@ -32,7 +32,8 @@ namespace gbe
 {
   /*! Use custom allocator instead of std one */
   template<class Key, class T, class Pred = std::less<Key>>
-  class map : public std::map<Key,T,Pred,Allocator<std::pair<const Key, T>>>
+  class map : public std::map<Key,T,Pred,Allocator<std::pair<const Key, T>>>,
+              public NonCopyable
   {
   public:
     // Typedefs
@@ -58,8 +59,10 @@ namespace gbe
                const key_compare &comp = key_compare(),
                const allocator_type& a = allocator_type()) :
       parent_type(first, last, comp, a) {}
+#if 0
     /*! Copy constructor */
     INLINE map(const map& x) : parent_type(x) {}
+#endif
     /*! Better than using find if we do not care about the iterator itself */
     INLINE bool contains(const Key &key) const {
       return this->find(key) != this->end();
index bf1da2d..db68807 100644 (file)
@@ -32,7 +32,7 @@ namespace gbe
 {
   /*! Add our custom allocator to std::set */
   template<class Key, class Pred = std::less<Key>>
-  class set : public std::set<Key,Pred,Allocator<Key>>
+  class set : public std::set<Key,Pred,Allocator<Key>>, public NonCopyable
   {
   public:
     // Typedefs
@@ -53,8 +53,10 @@ namespace gbe
                const key_compare &comp = key_compare(),
                const allocator_type& a = allocator_type()) :
       parent_type(first, last, comp, a) {}
+#if 0
     /*! Copy constructor */
     INLINE set(const set& x) : parent_type(x) {}
+#endif
     /*! Better than using find if we do not care about the iterator itself */
     INLINE bool contains(const Key &key) const {
       return this->find(key) != this->end();
index 6632d19..7f23c8f 100644 (file)
@@ -34,7 +34,7 @@ namespace gbe
    *  allocator
    */
   template<class T>
-  class vector : public std::vector<T, Allocator<T>>
+  class vector : public std::vector<T, Allocator<T>>, public NonCopyable
   {
   public:
     // Typedefs
@@ -46,8 +46,10 @@ namespace gbe
     /*! Default constructor */
     INLINE explicit vector(const allocator_type &a = allocator_type()) :
       parent_type(a) {}
+#if 0
     /*! Copy constructor */
     INLINE vector(const vector &x) : parent_type(x) {}
+#endif
     /*! Repetitive sequence constructor */
     INLINE explicit vector(size_type n,
                            const T& value= T(),
index d368c35..37f8dd7 100644 (file)
@@ -54,7 +54,7 @@ namespace gbe
     unit.apply([](ir::Function &fn) {
       ir::Liveness liveness(fn);
       ir::FunctionDAG dag(liveness);
-      std::cout << liveness << std::endl;
+  //    std::cout << liveness << std::endl;
     });
   }
 } /* namespace gbe */