const BasicBlock &bb,
const Register ®)
{
+ // 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) {
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 */
// 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);
// 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);
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);
} data;
/*!< Function argument or instruction dst? */
Type type;
+ GBE_CLASS(ValueDef); // Use gbe allocators
};
/*! Compare two value definitions (used in maps) */
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) */
/*! 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
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
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 */
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) {
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);
}
}
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;
}
const size_t size = ((uintptr_t*)ptr)[-2];
MemDebuggerInitializeMem(ptr, size);
free(((void**)ptr)[-1]);
+ sizeMutex.lock();
memDebuggerCurrSize -= size;
+ sizeMutex.unlock();
}
}
} /* 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));
#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); \
}
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
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 */
{
/*! 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
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();
{
/*! 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
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();
* allocator
*/
template<class T>
- class vector : public std::vector<T, Allocator<T>>
+ class vector : public std::vector<T, Allocator<T>>, public NonCopyable
{
public:
// Typedefs
/*! 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(),
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 */