Kept on implementing full function DAG Added a monitor for the memory consumption
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Fri, 16 Mar 2012 19:26:45 +0000 (19:26 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:15:42 +0000 (16:15 -0700)
backend/src/ir/liveness.cpp
backend/src/ir/liveness.hpp
backend/src/ir/value.cpp
backend/src/ir/value.hpp
backend/src/sys/alloc.cpp

index 0b9b560..8e5b9ec 100644 (file)
@@ -69,7 +69,7 @@ namespace ir {
 
   void Liveness::computeLiveOut(void) {
     // First insert the UEVar from the successors
-    forEachSuccessor([](BlockInfo &info, const BlockInfo &succ) {
+    foreach<DF_SUCC>([](BlockInfo &info, const BlockInfo &succ) {
       const UEVar &ueVarSet = succ.upwardUsed;
       // Iterate over all the registers in the UEVar of our successor
       for (auto ueVar = ueVarSet.begin(); ueVar != ueVarSet.end(); ++ueVar)
@@ -79,7 +79,7 @@ namespace ir {
     bool changed = true;
     while (changed) {
       changed = false;
-      forEachSuccessor([&changed](BlockInfo &info, const BlockInfo &succ) {
+      foreach<DF_SUCC>([&changed](BlockInfo &info, const BlockInfo &succ) {
         const UEVar &killSet = succ.varKill;
         const LiveOut &liveOut = succ.liveOut;
         // Iterate over all the registers in the UEVar of our successor
@@ -247,7 +247,7 @@ namespace ir {
 
     // Print liveness in each block
     fn.foreachBlock([&out, &liveness] (const BasicBlock &bb) {
-      const Liveness::Info &info = liveness.getLiveness();
+      const Liveness::Info &info = liveness.getLivenessInfo();
       auto it = info.find(&bb);
       GBE_ASSERT(it != info.end());
       printBlock(out, *it->second);
index ba34d89..6d97b1c 100644 (file)
@@ -35,6 +35,14 @@ namespace ir {
   // Liveness is computed per function
   class Function;
 
+  /*! To choose the iteration direction, we either look at predecessors or
+   *  successors
+   */
+  enum DataFlowDirection {
+    DF_PRED = 0,
+    DF_SUCC = 1
+  };
+
   /*! Compute liveness of each register */
   class Liveness : public NonCopyable
   {
@@ -67,7 +75,7 @@ namespace ir {
     /*! Gives for each block the variables alive at entry / exit */
     typedef map<const BasicBlock*, BlockInfo*> Info;
     /*! Return the complete liveness info */
-    INLINE const Info &getLiveness(void) const { return liveness; }
+    INLINE const Info &getLivenessInfo(void) const { return liveness; }
     /*! Return the complete block info */
     INLINE const BlockInfo &getBlockInfo(const BasicBlock &bb) const {
       auto it = liveness.find(&bb);
@@ -76,33 +84,37 @@ namespace ir {
     }
     /*! Return the function the liveness was computed on */
     INLINE const Function &getFunction(void) const { return fn; }
-  private:
-    /*! Store the liveness of all blocks */
-    Info liveness;
-    /*! Compute the liveness for this function */
-    Function &fn;
-    /*! Initialize UEVar and VarKill per block */
-    void initBlock(const BasicBlock &bb);
-    /*! Initialize UEVar and VarKill per instruction */
-    void initInstruction(BlockInfo &info, const Instruction &insn);
-    /*! Now really compute LiveOut based on UEVar and VarKill */
-    void computeLiveOut(void);
-    /*! Actually do something for each successor of *all* blocks */
-    template <typename T>
-    void forEachSuccessor(const T &functor) {
+    /*! Actually do something for each successor / predecessor of *all* blocks */
+    template <DataFlowDirection dir, typename T>
+    void foreach(const T &functor) {
       // Iterate on all blocks
       for (auto it = liveness.begin(); it != liveness.end(); ++it) {
         BlockInfo &info = *it->second;
         const BasicBlock &bb = info.bb;
-        const BlockSet set = bb.getSuccessorSet();
+        const BlockSet *set = NULL;
+        if (dir == DF_SUCC)
+          set = &bb.getSuccessorSet();
+        else
+          set = &bb.getPredecessorSet();
         // Iterate over all successors
-        for (auto other = set.begin(); other != set.end(); ++other) {
+        for (auto other = set->begin(); other != set->end(); ++other) {
           auto otherInfo = liveness.find(*other);
           GBE_ASSERT(otherInfo != liveness.end() && otherInfo->second != NULL);
           functor(info, *otherInfo->second);
         }
       }
     }
+  private:
+    /*! Store the liveness of all blocks */
+    Info liveness;
+    /*! Compute the liveness for this function */
+    Function &fn;
+    /*! Initialize UEVar and VarKill per block */
+    void initBlock(const BasicBlock &bb);
+    /*! Initialize UEVar and VarKill per instruction */
+    void initInstruction(BlockInfo &info, const Instruction &insn);
+    /*! Now really compute LiveOut based on UEVar and VarKill */
+    void computeLiveOut(void);
   };
 
   /*! Output a nice ASCII reprensation of the liveness */
index 8d0cb1e..4de5c40 100644 (file)
@@ -40,7 +40,7 @@ namespace ir {
   class LiveOutSet
   {
   public:
-    LiveOutSet(const Liveness &liveness, const FunctionDAG &dag);
+    LiveOutSet(Liveness &liveness, const FunctionDAG &dag);
     ~LiveOutSet(void);
     /*! One set per register */
     typedef set<const ValueDef*> RegDefSet;
@@ -48,19 +48,44 @@ namespace ir {
     typedef map<Register, RegDefSet*> BlockDefMap;
     /*! All the block definitions map in the functions */
     typedef map<const BasicBlock*, BlockDefMap*> FunctionDefMap;
-    FunctionDefMap defMap;    //!< All per-block data
-    const Liveness &liveness; //!< Contains LiveOut information
-    const FunctionDAG &dag;   //!< Structure we are building
+    /*! Performs the double look-up to get the set of defs per register */
+    RegDefSet &getDefSet(const BasicBlock *bb, const Register &reg) {
+      auto bbIt = defMap.find(bb);
+      GBE_ASSERT(bbIt != defMap.end());
+      auto defIt = bbIt->second->find(reg);
+      GBE_ASSERT(defIt != bbIt->second->end() && defIt->second != NULL);
+      return *defIt->second;
+    }
+    /*! Build a UD-chain as the union of the predecessor chains */
+    void fillUDChain(UDChain &udChain, const BasicBlock &bb, const Register &reg);
+    /*! Fast per register definition set allocation */
     DECL_POOL(RegDefSet, regDefSetPool);
+    /*! Fast register sets allocation */
     DECL_POOL(BlockDefMap, blockDefMapPool);
+    FunctionDefMap defMap;    //!< All per-block data
+    Liveness &liveness;       //!< Contains LiveOut information
+    const FunctionDAG &dag;   //!< Structure we are building
+  private:
+    /*! Initialize liveOut with the instruction destination values */
+    void initializeInstructionDst(void);
+    /*! Initialize liveOut with the function argument */
+    void initializeFunctionInput(void);
+    /*! Iterate to completely transfer the liveness and get the def sets */
+    void iterateLiveOut(void);
   };
 
-  LiveOutSet::LiveOutSet(const Liveness &liveness, const FunctionDAG &dag) :
+  LiveOutSet::LiveOutSet(Liveness &liveness, const FunctionDAG &dag) :
     liveness(liveness), dag(dag)
   {
+    this->initializeInstructionDst();
+    this->initializeFunctionInput();
+    this->iterateLiveOut();
+  }
+
+  void LiveOutSet::initializeInstructionDst(void) {
     const Function &fn = liveness.getFunction();
 
-    // Iterate over each block
+    // Iterate over each block and initialize the liveOut data
     fn.foreachBlock([&](const BasicBlock &bb) {
       GBE_ASSERT(defMap.find(&bb) == defMap.end());
 
@@ -85,17 +110,98 @@ namespace ir {
         for (uint32_t dstID = 0; dstID < dstNum; ++dstID) {
           const Register reg = insn.getDstIndex(fn, dstID);
           // We only take the most recent definition
-          if (defined.contains(reg) == false) continue;
+          if (defined.contains(reg) == true) continue;
           // Not in LiveOut, so does not matter
           if (info.inLiveOut(reg) == false) continue;
+          defined.insert(reg);
           // Insert the outgoing definition for this register
           auto regDefSet = blockDefMap->find(reg);
-          const ValueDef *def = this->dag.getDefAddress(insn, dstID);
+          const ValueDef *def = this->dag.getDefAddress(&insn, dstID);
           GBE_ASSERT(regDefSet != blockDefMap->end() && def != NULL);
+          // May be NULL if there is no definition
           regDefSet->second->insert(def);
         }
       });
     });
+
+    // The first block must also transfer the function arguments
+    const BasicBlock &top = fn.getBlock(0);
+    auto info = this->liveness.getBlockInfo(top);
+    auto blockDefMapIt = defMap.find(&top);
+    GBE_ASSERT(blockDefMapIt != defMap.end());
+    auto blockDefMap = blockDefMapIt->second;
+    const uint32_t inputNum = fn.inputNum();
+    for (uint32_t inputID = 0; inputID < inputNum; ++inputID) {
+      const FunctionInput &input = fn.getInput(inputID);
+      const Register reg = input.reg;
+      // Do not transfer dead values
+      if (info.inLiveOut(reg) == false) continue;
+      // If we overwrite it, do not transfer the initial value
+      if (info.inVarKill(reg) == false) continue;
+      const ValueDef *def = this->dag.getDefAddress(&input);
+      GBE_ASSERT(blockDefMap->contains(reg) == false);
+      auto regDefSet = this->newRegDefSet();
+      regDefSet->insert(def);
+      blockDefMap->insert(std::make_pair(reg, regDefSet));
+    }
+  }
+
+  void LiveOutSet::initializeFunctionInput(void) {
+    const Function &fn = liveness.getFunction();
+    const uint32_t inputNum = fn.inputNum();
+
+    // The first block must also transfer the function arguments
+    const BasicBlock &top = fn.getBlock(0);
+    const Liveness::BlockInfo &info = this->liveness.getBlockInfo(top);
+    GBE_ASSERT(defMap.contains(&top) == true);
+    auto blockDefMap = defMap.find(&top)->second;
+
+    // Insert all the values that are not overwritten in the block and alive at
+    // the end of it
+    for (uint32_t inputID = 0; inputID < inputNum; ++inputID) {
+      const FunctionInput &input = fn.getInput(inputID);
+      const Register reg = input.reg;
+      // Do not transfer dead values
+      if (info.inLiveOut(reg) == false) continue;
+      // If we overwrite it, do not transfer the initial value
+      if (info.inVarKill(reg) == false) continue;
+      const ValueDef *def = this->dag.getDefAddress(&input);
+      GBE_ASSERT(blockDefMap->contains(reg) == false);
+      auto regDefSet = this->newRegDefSet();
+      regDefSet->insert(def);
+      blockDefMap->insert(std::make_pair(reg, regDefSet));
+    }
+  }
+
+  void LiveOutSet::iterateLiveOut(void) {
+    bool changed = true;
+
+    while (changed) {
+      changed = false;
+
+      // Compute the union of the current liveout definitions with the previous
+      // ones. Do not take into account the killed values though
+      liveness.foreach<DF_PRED>([&](Liveness::BlockInfo &curr,
+                                    const Liveness::BlockInfo &pred)
+      {
+        const BasicBlock &bb = curr.bb;
+        const BasicBlock &pbb = pred.bb;
+        for (auto it = curr.liveOut.begin(); it != curr.liveOut.end(); ++it) {
+          const Register reg = *it;
+          if (pred.inLiveOut(reg) == false) continue;
+          if (curr.inVarKill(reg) == true) continue;
+          RegDefSet &currSet = this->getDefSet(&bb, reg);
+          RegDefSet &predSet = this->getDefSet(&pbb, reg);
+
+          // Transfer the values
+          for (auto it = predSet.begin(); it != predSet.end(); ++it) {
+            if (currSet.contains(*it)) continue;
+            changed = true;
+            currSet.insert(*it);
+          }
+        }
+      });
+    }
   }
 
   LiveOutSet::~LiveOutSet(void) {
@@ -107,26 +213,27 @@ namespace ir {
     }
   }
 
-  FunctionDAG::FunctionDAG(const Liveness &liveness) {
+  FunctionDAG::FunctionDAG(Liveness &liveness) {
     const Function &fn = liveness.getFunction();
-    LiveOutSet p(liveness, *this);
+
     // We first start with empty chains
-    udEmpty = this->newUDChain(); udEmpty->second = NULL;
-    duEmpty = this->newDUChain(); duEmpty->second = NULL;
+    udEmpty = this->newUDChain();
+    duEmpty = this->newDUChain();
 
     // First create the chains and insert them in their respective maps
     fn.foreachInstruction([this, udEmpty, duEmpty](const Instruction &insn) {
-
       // sources == value uses
       const uint32_t srcNum = insn.getSrcNum();
       for (uint32_t srcID = 0; srcID < srcNum; ++srcID) {
-        ValueUse *valueUse = this->newValueUse(insn, srcID);
+        ValueUse *valueUse = this->newValueUse(&insn, srcID);
+        useName.insert(std::make_pair(*valueUse, valueUse));
         udGraph.insert(std::make_pair(*valueUse, udEmpty));
       }
       // destinations == value defs
       const uint32_t dstNum = insn.getDstNum();
       for (uint32_t dstID = 0; dstID < dstNum; ++dstID) {
-        ValueDef *valueDef = this->newValueDef(insn, dstID);
+        ValueDef *valueDef = this->newValueDef(&insn, dstID);
+        defName.insert(std::make_pair(*valueDef, valueDef));
         duGraph.insert(std::make_pair(*valueDef, duEmpty));
       }
     });
@@ -135,9 +242,13 @@ namespace ir {
     const uint32_t inputNum = fn.inputNum();
     for (uint32_t inputID = 0; inputID < inputNum; ++inputID) {
       const FunctionInput &input = fn.getInput(inputID);
-      ValueDef *valueDef = this->newValueDef(input);
+      ValueDef *valueDef = this->newValueDef(&input);
+      defName.insert(std::make_pair(*valueDef, valueDef));
       duGraph.insert(std::make_pair(*valueDef, duEmpty));
     }
+
+    // We create the liveOutSet to help us transfer the definitions
+    const LiveOutSet liveOutSet(liveness, *this);
   }
 
 /*! Helper to deallocate objects */
@@ -155,76 +266,64 @@ namespace ir {
     set<void*> destroyed;
 
     // Release the empty ud-chains and du-chains
-    PTR_RELEASE(ValueUse, udEmpty->second);
-    PTR_RELEASE(ValueDef, duEmpty->second);
     PTR_RELEASE(UDChain, udEmpty);
     PTR_RELEASE(DUChain, duEmpty);
 
     // We free all the ud-chains
     for (auto it = udGraph.begin(); it != udGraph.end(); ++it) {
-      auto udChain = it->second;
-      auto defs = udChain->first;
-      for (auto def = defs.begin(); def != defs.end(); ++def)
+      auto defs = it->second;
+      for (auto def = defs->begin(); def != defs->end(); ++def)
         PTR_RELEASE(ValueDef, *def);
-      PTR_RELEASE(ValueUse, udChain->second);
-      PTR_RELEASE(UDChain, udChain);
+      PTR_RELEASE(UDChain, defs);
     }
 
     // We free all the du-chains
     for (auto it = duGraph.begin(); it != duGraph.end(); ++it) {
-      auto duChain = it->second;
-      auto uses = duChain->first;
-      for (auto use = uses.begin(); use != uses.end(); ++use)
+      auto uses = it->second;
+      for (auto use = uses->begin(); use != uses->end(); ++use)
         PTR_RELEASE(ValueUse, *use);
-      PTR_RELEASE(ValueDef, duChain->second);
-      PTR_RELEASE(DUChain, duChain);
+      PTR_RELEASE(DUChain, uses);
     }
   }
 #undef PTR_RELEASE
 
-  const DUChain &FunctionDAG::getDUChain(const Instruction &insn, uint32_t dstID) const {
+  const DUChain &FunctionDAG::getUse(const Instruction *insn, uint32_t dstID) const {
     const ValueDef def(insn, dstID);
     auto it = duGraph.find(def);
     GBE_ASSERT(it != duGraph.end());
     return *it->second;
   }
 
-  const DUChain &FunctionDAG::getDUChain(const FunctionInput &input) const {
+  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::getUDChain(const Instruction &insn, uint32_t srcID) const {
+  const UDChain &FunctionDAG::getDef(const Instruction *insn, uint32_t srcID) const {
     const ValueUse use(insn, srcID);
     auto it = udGraph.find(use);
     GBE_ASSERT(it != udGraph.end());
     return *it->second;
   }
-  const ValueUseSet &FunctionDAG::getUse(const Instruction &insn, uint32_t dstID) const {
-    const DUChain &chain = this->getDUChain(insn, dstID);
-    return chain.first;
-  }
-  const ValueUseSet &FunctionDAG::getUse(const FunctionInput &input) const {
-    const DUChain &chain = this->getDUChain(input);
-    return chain.first;
-  }
-  const ValueDefSet &FunctionDAG::getDef(const Instruction &insn, uint32_t srcID) const {
-    const UDChain &chain = this->getUDChain(insn, srcID);
-    return chain.first;
-  }
-  const ValueDef *FunctionDAG::getDefAddress(const Instruction &insn, uint32_t dstID) const {
-    const DUChain &chain = this->getDUChain(insn, dstID);
-    return chain.second;
+  const ValueDef *FunctionDAG::getDefAddress(const Instruction *insn, uint32_t dstID) const {
+    const ValueDef def(insn, dstID);
+    auto it = defName.find(def);
+    GBE_ASSERT(it != defName.end() && it->second != NULL);
+    return it->second;
   }
-  const ValueDef *FunctionDAG::getDefAddress(const FunctionInput &input) const {
-    const DUChain &chain = this->getDUChain(input);
-    return chain.second;
+  const ValueDef *FunctionDAG::getDefAddress(const FunctionInput *input) const {
+    const ValueDef def(input);
+    auto it = defName.find(def);
+    GBE_ASSERT(it != defName.end() && it->second != NULL);
+    return it->second;
   }
-  const ValueUse *FunctionDAG::getUseAddress(const Instruction &insn, uint32_t srcID) const {
-    const UDChain &chain = this->getUDChain(insn, srcID);
-    return chain.second;
+  const ValueUse *FunctionDAG::getUseAddress(const Instruction *insn, uint32_t srcID) const {
+    const ValueUse use(insn, srcID);
+    auto it = useName.find(use);
+    GBE_ASSERT(it != useName.end() && it->second != NULL);
+    return it->second;
   }
 } /* namespace ir */
 } /* namespace gbe */
index 3704b26..9b3ec63 100644 (file)
@@ -48,22 +48,22 @@ namespace ir {
       INSTRUCTION_DST = 1
     };
     /*! Build a value from an instruction destination */
-    ValueDef(const Instruction &insn, uint32_t dstID = 0u) :
+    ValueDef(const Instruction *insn, uint32_t dstID = 0u) :
       type(INSTRUCTION_DST)
     {
-      this->data.insn = &insn;
+      this->data.insn = insn;
       this->data.dstID = dstID;
     }
     /*! Build a value from a function argument */
-    ValueDef(const FunctionInput &input) : type(FUNCTION_INPUT) {
-      this->data.input = &input;
+    ValueDef(const FunctionInput *input) : type(FUNCTION_INPUT) {
+      this->data.input = input;
     }
     /*! Get the type of the value */
     INLINE Type getType(void) const { return type; }
     /*! Get the instruction (only if this is a instruction value) */
-    INLINE const Instruction &getInstruction(void) const {
+    INLINE const Instruction *getInstruction(void) const {
       GBE_ASSERT(type == INSTRUCTION_DST);
-      return *data.insn;
+      return data.insn;
     }
     /*! Get the destination ID (only if this is a instruction value) */
     INLINE uint32_t getDstID(void) const {
@@ -71,9 +71,9 @@ namespace ir {
       return data.dstID;
     }
     /*! Get the function input (only if this is a function argument) */
-    INLINE const FunctionInput &getFunctionInput(void) const {
+    INLINE const FunctionInput *getFunctionInput(void) const {
       GBE_ASSERT(type == FUNCTION_INPUT);
-      return *data.input;
+      return data.input;
     }
 
   private:
@@ -97,12 +97,12 @@ namespace ir {
     const ValueDef::Type type1 = def1.getType();
     if (type0 != type1) return uint32_t(type0) < uint32_t(type1);
     if (type0 == ValueDef::FUNCTION_INPUT) {
-      const FunctionInput *in0 = &def0.getFunctionInput();
-      const FunctionInput *in1 = &def1.getFunctionInput();
+      const FunctionInput *in0 = def0.getFunctionInput();
+      const FunctionInput *in1 = def1.getFunctionInput();
       return uintptr_t(in0) < uintptr_t(in1);
     } else {
-      const Instruction *insn0 = &def0.getInstruction();
-      const Instruction *insn1 = &def1.getInstruction();
+      const Instruction *insn0 = def0.getInstruction();
+      const Instruction *insn1 = def1.getInstruction();
       if (insn0 != insn1) return uintptr_t(insn0) < uintptr_t(insn1);
       const uint32_t dst0 = def0.getDstID();
       const uint32_t dst1 = def1.getDstID();
@@ -117,10 +117,10 @@ namespace ir {
   {
   public:
     /*! Build a value use */
-    ValueUse(const Instruction &insn, uint32_t srcID = 0u) :
-      insn(&insn), srcID(srcID) {}
+    ValueUse(const Instruction *insn, uint32_t srcID = 0u) :
+      insn(insn), srcID(srcID) {}
     /*! Get the instruction of the use */
-    const Instruction &getInstruction(void) const { return *insn; }
+    const Instruction *getInstruction(void) const { return insn; }
     /*! Get the source index for this use */
     uint32_t getSrcID(void) const { return srcID; }
   private:
@@ -130,8 +130,8 @@ namespace ir {
 
   /*! Compare two value uses (used in maps) */
   INLINE bool operator< (const ValueUse &use0, const ValueUse &use1) {
-    const Instruction *insn0 = &use0.getInstruction();
-    const Instruction *insn1 = &use1.getInstruction();
+    const Instruction *insn0 = use0.getInstruction();
+    const Instruction *insn1 = use1.getInstruction();
     if (insn0 != insn1) return uintptr_t(insn0) < uintptr_t(insn1);
     const uint32_t src0 = use0.getSrcID();
     const uint32_t src1 = use1.getSrcID();
@@ -139,38 +139,30 @@ namespace ir {
   }
 
   /*! All uses of a definition */
-  typedef set<ValueUse*> ValueUseSet;
-  typedef std::pair<ValueUseSet, ValueDef*> DUChain;
+  typedef set<ValueUse*> DUChain;
   /*! All possible definitions for a use */
-  typedef set<ValueDef*> ValueDefSet;
-  typedef std::pair<ValueDefSet, ValueUse*> UDChain;
+  typedef set<ValueDef*> UDChain;
 
   /*! Get the chains (in both directions) for the complete program */
   class FunctionDAG
   {
   public:
     /*! Build the complete DU/UD graphs for the program included in liveness */
-    FunctionDAG(const Liveness &liveness);
+    FunctionDAG(Liveness &liveness);
     /*! Free all the resources */
     ~FunctionDAG(void);
     /*! Get the du-chain for the given instruction and destination */
-    const DUChain &getDUChain(const Instruction &insn, uint32_t dstID) const;
+    const DUChain &getUse(const Instruction *insn, uint32_t dstID) const;
     /*! Get the du-chain for the given function input */
-    const DUChain &getDUChain(const FunctionInput &input) const;
+    const DUChain &getUse(const FunctionInput *input) const;
     /*! Get the ud-chain for the instruction and source */
-    const UDChain &getUDChain(const Instruction &insn, uint32_t srcID) const;
-    /*! Get the use set for the given definition */
-    const ValueUseSet &getUse(const Instruction &insn, uint32_t dstID) const;
-    /*! Get the use set for the function argument */
-    const ValueUseSet &getUse(const FunctionInput &input) const;
-    /*! Get the definition set for the given source */
-    const ValueDefSet &getDef(const Instruction &insn, uint32_t srcID) const;
+    const UDChain &getDef(const Instruction *insn, uint32_t srcID) const;
     /*! Get the pointer to the definition *as stored in the DAG* */
-    const ValueDef *getDefAddress(const Instruction &insn, uint32_t dstID) const;
+    const ValueDef *getDefAddress(const Instruction *insn, uint32_t dstID) const;
     /*! Get the pointer to the definition *as stored in the DAG* */
-    const ValueDef *getDefAddress(const FunctionInput &input) const;
+    const ValueDef *getDefAddress(const FunctionInput *input) const;
     /*! Get the pointer to the use *as stored in the DAG* */
-    const ValueUse *getUseAddress(const Instruction &insn, uint32_t srcID) const;
+    const ValueUse *getUseAddress(const Instruction *insn, uint32_t srcID) const;
     /*! The UDChain for each definition use */
     typedef map<ValueUse, UDChain*> UDGraph;
     /*! The DUChain for each definition */
@@ -178,8 +170,10 @@ namespace ir {
   private:
     UDGraph udGraph;                   //!< All the UD chains
     DUGraph duGraph;                   //!< All the DU chains
-    UDChain *udEmpty;                  //!< For all empty ud chains
-    DUChain *duEmpty;                  //!< For all empty du chains
+    UDChain *udEmpty;                  //!< Void use set
+    DUChain *duEmpty;                  //!< Void def set
+    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
     DECL_POOL(ValueUse, valueUsePool); //!< Fast ValueUse allocation
     DECL_POOL(UDChain, udChainPool);   //!< Fast UDChain allocation
index af4d390..c7305c2 100644 (file)
@@ -42,6 +42,7 @@
 #endif /* __ICC__ */
 #include <map>
 #include <vector>
+#include <iomanip>
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Memory debugger
@@ -139,10 +140,18 @@ namespace gbe
   /*! Declare C like interface functions here */
   static MemDebugger *memDebugger = NULL;
 
+  /*! Monitor maximum memory requirement in the compiler */
+  static size_t memDebuggerCurrSize = 0;
+  static size_t memDebuggerMaxSize = 0;
+
   /*! 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;
   }
 
@@ -192,6 +201,8 @@ namespace gbe
     void *ptr = std::malloc(size + sizeof(size_t));
     *(size_t *) ptr = size;
     MemDebuggerInitializeMem((char*) ptr + sizeof(size_t), size);
+    memDebuggerCurrSize += size;
+    memDebuggerMaxSize = std::max(memDebuggerCurrSize, memDebuggerMaxSize);
     return (char *) ptr + sizeof(size_t);
   }
   void memFree(void *ptr) {
@@ -199,6 +210,7 @@ namespace gbe
       char *toFree = (char*) ptr - sizeof(size_t);
       const size_t size = *(size_t *) toFree;
       MemDebuggerInitializeMem(ptr, size);
+      memDebuggerCurrSize -= size;
       std::free(toFree);
     }
   }
@@ -221,6 +233,8 @@ namespace gbe
     ((void**)aligned)[-1] = mem;
     ((uintptr_t*)aligned)[-2] = uintptr_t(size);
     MemDebuggerInitializeMem(aligned, size);
+    memDebuggerCurrSize += size;
+    memDebuggerMaxSize = std::max(memDebuggerCurrSize, memDebuggerMaxSize);
     return aligned;
   }
 
@@ -229,6 +243,7 @@ namespace gbe
       const size_t size = ((uintptr_t*)ptr)[-2];
       MemDebuggerInitializeMem(ptr, size);
       free(((void**)ptr)[-1]);
+      memDebuggerCurrSize -= size;
     }
   }
 } /* namespace gbe */