Commit 7bb9cab3 by John Porto

Subzero. Liveness memory management.

Creates a local arena allocator for holding liveness data structures. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4366 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1838973005 .
parent 23866e7b
...@@ -246,9 +246,9 @@ private: ...@@ -246,9 +246,9 @@ private:
} }
}; };
class BitVector { template <template <typename> class AT> class BitVectorTmpl {
typedef unsigned long BitWord; typedef unsigned long BitWord;
using Allocator = CfgLocalAllocator<BitWord>; using Allocator = AT<BitWord>;
enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT }; enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT };
...@@ -264,7 +264,7 @@ public: ...@@ -264,7 +264,7 @@ public:
typedef unsigned size_type; typedef unsigned size_type;
// Encapsulation of a single bit. // Encapsulation of a single bit.
class reference { class reference {
friend class BitVector; friend class BitVectorTmpl;
BitWord *WordRef; BitWord *WordRef;
unsigned BitPos; unsigned BitPos;
...@@ -272,7 +272,7 @@ public: ...@@ -272,7 +272,7 @@ public:
reference(); // Undefined reference(); // Undefined
public: public:
reference(BitVector &b, unsigned Idx) { reference(BitVectorTmpl &b, unsigned Idx) {
WordRef = &b.Bits[Idx / BITWORD_SIZE]; WordRef = &b.Bits[Idx / BITWORD_SIZE];
BitPos = Idx % BITWORD_SIZE; BitPos = Idx % BITWORD_SIZE;
} }
...@@ -297,15 +297,15 @@ public: ...@@ -297,15 +297,15 @@ public:
} }
}; };
/// BitVector default ctor - Creates an empty bitvector. /// BitVectorTmpl default ctor - Creates an empty bitvector.
BitVector(Allocator A = Allocator()) BitVectorTmpl(Allocator A = Allocator())
: Size(0), Capacity(0), Alloc(std::move(A)) { : Size(0), Capacity(0), Alloc(std::move(A)) {
Bits = nullptr; Bits = nullptr;
} }
/// BitVector ctor - Creates a bitvector of specified number of bits. All /// BitVectorTmpl ctor - Creates a bitvector of specified number of bits. All
/// bits are initialized to the specified value. /// bits are initialized to the specified value.
explicit BitVector(unsigned s, bool t = false, Allocator A = Allocator()) explicit BitVectorTmpl(unsigned s, bool t = false, Allocator A = Allocator())
: Size(s), Alloc(std::move(A)) { : Size(s), Alloc(std::move(A)) {
Capacity = NumBitWords(s); Capacity = NumBitWords(s);
Bits = Alloc.allocate(Capacity); Bits = Alloc.allocate(Capacity);
...@@ -314,8 +314,8 @@ public: ...@@ -314,8 +314,8 @@ public:
clear_unused_bits(); clear_unused_bits();
} }
/// BitVector copy ctor. /// BitVectorTmpl copy ctor.
BitVector(const BitVector &RHS) : Size(RHS.size()), Alloc(RHS.Alloc) { BitVectorTmpl(const BitVectorTmpl &RHS) : Size(RHS.size()), Alloc(RHS.Alloc) {
if (Size == 0) { if (Size == 0) {
Bits = nullptr; Bits = nullptr;
Capacity = 0; Capacity = 0;
...@@ -327,13 +327,13 @@ public: ...@@ -327,13 +327,13 @@ public:
std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord)); std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
} }
BitVector(BitVector &&RHS) BitVectorTmpl(BitVectorTmpl &&RHS)
: Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity), : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity),
Alloc(std::move(RHS.Alloc)) { Alloc(std::move(RHS.Alloc)) {
RHS.Bits = nullptr; RHS.Bits = nullptr;
} }
~BitVector() { ~BitVectorTmpl() {
if (Bits != nullptr) { if (Bits != nullptr) {
Alloc.deallocate(Bits, Capacity); Alloc.deallocate(Bits, Capacity);
} }
...@@ -420,7 +420,7 @@ public: ...@@ -420,7 +420,7 @@ public:
init_words(&Bits[OldCapacity], (Capacity - OldCapacity), t); init_words(&Bits[OldCapacity], (Capacity - OldCapacity), t);
} }
// Set any old unused bits that are now included in the BitVector. This // Set any old unused bits that are now included in the BitVectorTmpl. This
// may set bits that are not included in the new vector, but we will clear // may set bits that are not included in the new vector, but we will clear
// them back out below. // them back out below.
if (N > Size) if (N > Size)
...@@ -439,20 +439,20 @@ public: ...@@ -439,20 +439,20 @@ public:
} }
// Set, reset, flip // Set, reset, flip
BitVector &set() { BitVectorTmpl &set() {
init_words(Bits, Capacity, true); init_words(Bits, Capacity, true);
clear_unused_bits(); clear_unused_bits();
return *this; return *this;
} }
BitVector &set(unsigned Idx) { BitVectorTmpl &set(unsigned Idx) {
assert(Bits && "Bits never allocated"); assert(Bits && "Bits never allocated");
Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE);
return *this; return *this;
} }
/// set - Efficiently set a range of bits in [I, E) /// set - Efficiently set a range of bits in [I, E)
BitVector &set(unsigned I, unsigned E) { BitVectorTmpl &set(unsigned I, unsigned E) {
assert(I <= E && "Attempted to set backwards range!"); assert(I <= E && "Attempted to set backwards range!");
assert(E <= size() && "Attempted to set out-of-bounds range!"); assert(E <= size() && "Attempted to set out-of-bounds range!");
...@@ -481,18 +481,18 @@ public: ...@@ -481,18 +481,18 @@ public:
return *this; return *this;
} }
BitVector &reset() { BitVectorTmpl &reset() {
init_words(Bits, Capacity, false); init_words(Bits, Capacity, false);
return *this; return *this;
} }
BitVector &reset(unsigned Idx) { BitVectorTmpl &reset(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE)); Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE));
return *this; return *this;
} }
/// reset - Efficiently reset a range of bits in [I, E) /// reset - Efficiently reset a range of bits in [I, E)
BitVector &reset(unsigned I, unsigned E) { BitVectorTmpl &reset(unsigned I, unsigned E) {
assert(I <= E && "Attempted to reset backwards range!"); assert(I <= E && "Attempted to reset backwards range!");
assert(E <= size() && "Attempted to reset out-of-bounds range!"); assert(E <= size() && "Attempted to reset out-of-bounds range!");
...@@ -521,14 +521,14 @@ public: ...@@ -521,14 +521,14 @@ public:
return *this; return *this;
} }
BitVector &flip() { BitVectorTmpl &flip() {
for (unsigned i = 0; i < NumBitWords(size()); ++i) for (unsigned i = 0; i < NumBitWords(size()); ++i)
Bits[i] = ~Bits[i]; Bits[i] = ~Bits[i];
clear_unused_bits(); clear_unused_bits();
return *this; return *this;
} }
BitVector &flip(unsigned Idx) { BitVectorTmpl &flip(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE); Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE);
return *this; return *this;
} }
...@@ -548,7 +548,7 @@ public: ...@@ -548,7 +548,7 @@ public:
bool test(unsigned Idx) const { return (*this)[Idx]; } bool test(unsigned Idx) const { return (*this)[Idx]; }
/// Test if any common bits are set. /// Test if any common bits are set.
bool anyCommon(const BitVector &RHS) const { bool anyCommon(const BitVectorTmpl &RHS) const {
unsigned ThisWords = NumBitWords(size()); unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size()); unsigned RHSWords = NumBitWords(RHS.size());
for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i) for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i)
...@@ -558,7 +558,7 @@ public: ...@@ -558,7 +558,7 @@ public:
} }
// Comparison operators. // Comparison operators.
bool operator==(const BitVector &RHS) const { bool operator==(const BitVectorTmpl &RHS) const {
unsigned ThisWords = NumBitWords(size()); unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size()); unsigned RHSWords = NumBitWords(RHS.size());
unsigned i; unsigned i;
...@@ -579,10 +579,10 @@ public: ...@@ -579,10 +579,10 @@ public:
return true; return true;
} }
bool operator!=(const BitVector &RHS) const { return !(*this == RHS); } bool operator!=(const BitVectorTmpl &RHS) const { return !(*this == RHS); }
/// Intersection, union, disjoint union. /// Intersection, union, disjoint union.
BitVector &operator&=(const BitVector &RHS) { BitVectorTmpl &operator&=(const BitVectorTmpl &RHS) {
unsigned ThisWords = NumBitWords(size()); unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size()); unsigned RHSWords = NumBitWords(RHS.size());
unsigned i; unsigned i;
...@@ -599,7 +599,7 @@ public: ...@@ -599,7 +599,7 @@ public:
} }
/// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
BitVector &reset(const BitVector &RHS) { BitVectorTmpl &reset(const BitVectorTmpl &RHS) {
unsigned ThisWords = NumBitWords(size()); unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size()); unsigned RHSWords = NumBitWords(RHS.size());
unsigned i; unsigned i;
...@@ -610,7 +610,7 @@ public: ...@@ -610,7 +610,7 @@ public:
/// test - Check if (This - RHS) is zero. /// test - Check if (This - RHS) is zero.
/// This is the same as reset(RHS) and any(). /// This is the same as reset(RHS) and any().
bool test(const BitVector &RHS) const { bool test(const BitVectorTmpl &RHS) const {
unsigned ThisWords = NumBitWords(size()); unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size()); unsigned RHSWords = NumBitWords(RHS.size());
unsigned i; unsigned i;
...@@ -625,7 +625,7 @@ public: ...@@ -625,7 +625,7 @@ public:
return false; return false;
} }
BitVector &operator|=(const BitVector &RHS) { BitVectorTmpl &operator|=(const BitVectorTmpl &RHS) {
if (size() < RHS.size()) if (size() < RHS.size())
resize(RHS.size()); resize(RHS.size());
for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
...@@ -633,7 +633,7 @@ public: ...@@ -633,7 +633,7 @@ public:
return *this; return *this;
} }
BitVector &operator^=(const BitVector &RHS) { BitVectorTmpl &operator^=(const BitVectorTmpl &RHS) {
if (size() < RHS.size()) if (size() < RHS.size())
resize(RHS.size()); resize(RHS.size());
for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i) for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
...@@ -642,7 +642,7 @@ public: ...@@ -642,7 +642,7 @@ public:
} }
// Assignment operator. // Assignment operator.
const BitVector &operator=(const BitVector &RHS) { const BitVectorTmpl &operator=(const BitVectorTmpl &RHS) {
if (this == &RHS) if (this == &RHS)
return *this; return *this;
...@@ -655,10 +655,10 @@ public: ...@@ -655,10 +655,10 @@ public:
return *this; return *this;
} }
// Currently, BitVector is only used by liveness analysis. With the // Currently, BitVectorTmpl is only used by liveness analysis. With the
// following assert, we make sure BitVectors grow in a single step from 0 to // following assert, we make sure BitVectorTmpls grow in a single step from
// their final capacity, rather than growing slowly and "leaking" memory in // 0 to their final capacity, rather than growing slowly and "leaking"
// the process. // memory in the process.
assert(Capacity == 0); assert(Capacity == 0);
// Grow the bitvector to have enough elements. // Grow the bitvector to have enough elements.
...@@ -675,7 +675,7 @@ public: ...@@ -675,7 +675,7 @@ public:
return *this; return *this;
} }
const BitVector &operator=(BitVector &&RHS) { const BitVectorTmpl &operator=(BitVectorTmpl &&RHS) {
if (this == &RHS) if (this == &RHS)
return *this; return *this;
...@@ -689,7 +689,7 @@ public: ...@@ -689,7 +689,7 @@ public:
return *this; return *this;
} }
void swap(BitVector &RHS) { void swap(BitVectorTmpl &RHS) {
std::swap(Bits, RHS.Bits); std::swap(Bits, RHS.Bits);
std::swap(Size, RHS.Size); std::swap(Size, RHS.Size);
std::swap(Capacity, RHS.Capacity); std::swap(Capacity, RHS.Capacity);
...@@ -705,7 +705,7 @@ public: ...@@ -705,7 +705,7 @@ public:
// //
// The LSB in each word is the lowest numbered bit. The size of a portable // The LSB in each word is the lowest numbered bit. The size of a portable
// bit mask is always a whole multiple of 32 bits. If no bit mask size is // bit mask is always a whole multiple of 32 bits. If no bit mask size is
// given, the bit mask is assumed to cover the entire BitVector. // given, the bit mask is assumed to cover the entire BitVectorTmpl.
/// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize. /// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
/// This computes "*this |= Mask". /// This computes "*this |= Mask".
...@@ -807,11 +807,16 @@ private: ...@@ -807,11 +807,16 @@ private:
} }
}; };
using BitVector = BitVectorTmpl<CfgLocalAllocator>;
} // end of namespace Ice } // end of namespace Ice
namespace std { namespace std {
/// Implement std::swap in terms of BitVector swap. /// Implement std::swap in terms of BitVectorTmpl swap.
inline void swap(Ice::BitVector &LHS, Ice::BitVector &RHS) { LHS.swap(RHS); } template <template <typename> class AT>
inline void swap(Ice::BitVectorTmpl<AT> &LHS, Ice::BitVectorTmpl<AT> &RHS) {
LHS.swap(RHS);
}
} }
#endif // SUBZERO_SRC_ICEBITVECTOR_H #endif // SUBZERO_SRC_ICEBITVECTOR_H
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include "IceOperand.h" #include "IceOperand.h"
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include <memory>
#include <utility>
namespace Ice { namespace Ice {
Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber) Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
...@@ -819,9 +822,14 @@ void Cfg::livenessLightweight() { ...@@ -819,9 +822,14 @@ void Cfg::livenessLightweight() {
void Cfg::liveness(LivenessMode Mode) { void Cfg::liveness(LivenessMode Mode) {
TimerMarker T(TimerStack::TT_liveness, this); TimerMarker T(TimerStack::TT_liveness, this);
Live.reset(new Liveness(this, Mode)); // Destroying the previous (if any) Liveness information clears the Liveness
// allocator TLS pointer.
Live = nullptr;
Live = Liveness::create(this, Mode);
getVMetadata()->init(VMK_Uses); getVMetadata()->init(VMK_Uses);
Live->init(); Live->init();
// Initialize with all nodes needing to be processed. // Initialize with all nodes needing to be processed.
BitVector NeedToProcess(Nodes.size(), true); BitVector NeedToProcess(Nodes.size(), true);
while (NeedToProcess.any()) { while (NeedToProcess.any()) {
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
namespace Ice { namespace Ice {
class Assembler; class Assembler;
class BitVector; template <template <typename> class> class BitVectorTmpl;
class Cfg; class Cfg;
class CfgNode; class CfgNode;
class Constant; class Constant;
...@@ -272,9 +272,11 @@ using InstNumberT = int32_t; ...@@ -272,9 +272,11 @@ using InstNumberT = int32_t;
/// A LiveBeginEndMapEntry maps a Variable::Number value to an Inst::Number /// A LiveBeginEndMapEntry maps a Variable::Number value to an Inst::Number
/// value, giving the instruction number that begins or ends a variable's live /// value, giving the instruction number that begins or ends a variable's live
/// range. /// range.
template <typename T>
using LivenessVector = std::vector<T, LivenessAllocator<T>>;
using LiveBeginEndMapEntry = std::pair<SizeT, InstNumberT>; using LiveBeginEndMapEntry = std::pair<SizeT, InstNumberT>;
using LiveBeginEndMap = CfgVector<LiveBeginEndMapEntry>; using LiveBeginEndMap = LivenessVector<LiveBeginEndMapEntry>;
using LivenessBV = BitVector; using LivenessBV = BitVectorTmpl<LivenessAllocator>;
using TimerStackIdT = uint32_t; using TimerStackIdT = uint32_t;
using TimerIdT = uint32_t; using TimerIdT = uint32_t;
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "IceDefs.h" #include "IceDefs.h"
#include "IceELFObjectWriter.h" #include "IceELFObjectWriter.h"
#include "IceGlobalInits.h" #include "IceGlobalInits.h"
#include "IceLiveness.h"
#include "IceOperand.h" #include "IceOperand.h"
#include "IceTargetLowering.h" #include "IceTargetLowering.h"
#include "IceTimerTree.h" #include "IceTimerTree.h"
...@@ -304,6 +305,7 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError, ...@@ -304,6 +305,7 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
// free. // free.
GlobalContext::TlsInit(); GlobalContext::TlsInit();
Cfg::TlsInit(); Cfg::TlsInit();
Liveness::TlsInit();
// Create a new ThreadContext for the current thread. No need to // Create a new ThreadContext for the current thread. No need to
// lock AllThreadContexts at this point since no other threads have // lock AllThreadContexts at this point since no other threads have
// access yet to this GlobalContext object. // access yet to this GlobalContext object.
......
...@@ -106,8 +106,8 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode, ...@@ -106,8 +106,8 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode,
RangeMask[VarIndex] = false; RangeMask[VarIndex] = false;
} }
SizeT MaxLocals = 0;
// Process each node. // Process each node.
MaxLocals = 0;
for (auto I = FirstNode, E = Func->getNodes().end(); I != E; ++I) { for (auto I = FirstNode, E = Func->getNodes().end(); I != E; ++I) {
LivenessNode &Node = Nodes[(*I)->getIndex()]; LivenessNode &Node = Nodes[(*I)->getIndex()];
// NumLocals, LiveToVarMap already initialized // NumLocals, LiveToVarMap already initialized
......
...@@ -24,8 +24,12 @@ ...@@ -24,8 +24,12 @@
#include "IceDefs.h" #include "IceDefs.h"
#include "IceBitVector.h" #include "IceBitVector.h"
#include "IceCfgNode.h" #include "IceCfgNode.h"
#include "IceTLS.h"
#include "IceTypes.h" #include "IceTypes.h"
#include <memory>
#include <utility>
namespace Ice { namespace Ice {
class Liveness { class Liveness {
...@@ -49,7 +53,7 @@ class Liveness { ...@@ -49,7 +53,7 @@ class Liveness {
// LiveToVarMap maps a liveness bitvector index to a Variable. This is // LiveToVarMap maps a liveness bitvector index to a Variable. This is
// generally just for printing/dumping. The index should be less than // generally just for printing/dumping. The index should be less than
// NumLocals + Liveness::NumGlobals. // NumLocals + Liveness::NumGlobals.
CfgVector<Variable *> LiveToVarMap; LivenessVector<Variable *> LiveToVarMap;
// LiveIn and LiveOut track the in- and out-liveness of the global // LiveIn and LiveOut track the in- and out-liveness of the global
// variables. The size of each vector is LivenessNode::NumGlobals. // variables. The size of each vector is LivenessNode::NumGlobals.
LivenessBV LiveIn, LiveOut; LivenessBV LiveIn, LiveOut;
...@@ -60,7 +64,6 @@ class Liveness { ...@@ -60,7 +64,6 @@ class Liveness {
}; };
public: public:
Liveness(Cfg *Func, LivenessMode Mode) : Func(Func), Mode(Mode) {}
void init(); void init();
void initPhiEdgeSplits(NodeList::const_iterator FirstNode, void initPhiEdgeSplits(NodeList::const_iterator FirstNode,
VarList::const_iterator FirstVar); VarList::const_iterator FirstVar);
...@@ -102,32 +105,58 @@ public: ...@@ -102,32 +105,58 @@ public:
} }
bool getRangeMask(SizeT Index) const { return RangeMask[Index]; } bool getRangeMask(SizeT Index) const { return RangeMask[Index]; }
ArenaAllocator *getAllocator() const { return Alloc.get(); }
static std::unique_ptr<Liveness> create(Cfg *Func, LivenessMode Mode) {
return std::unique_ptr<Liveness>(new Liveness(Func, Mode));
}
static void TlsInit() { LivenessAllocatorTraits::init(); }
std::string dumpStr() const {
return "MaxLocals(" + std::to_string(MaxLocals) + "), "
"NumGlobals(" +
std::to_string(NumGlobals) + ")";
}
private: private:
Liveness(Cfg *Func, LivenessMode Mode)
: Alloc(new ArenaAllocator()), AllocScope(this), Func(Func), Mode(Mode) {}
void initInternal(NodeList::const_iterator FirstNode, void initInternal(NodeList::const_iterator FirstNode,
VarList::const_iterator FirstVar, bool IsFullInit); VarList::const_iterator FirstVar, bool IsFullInit);
/// Resize Nodes so that Nodes[Index] is valid. /// Resize Nodes so that Nodes[Index] is valid.
void resize(SizeT Index) { void resize(SizeT Index) {
if (Index >= Nodes.size()) if (Index >= Nodes.size()) {
assert(false && "The Nodes array is not expected to be resized.");
Nodes.resize(Index + 1); Nodes.resize(Index + 1);
}
} }
std::unique_ptr<ArenaAllocator> Alloc;
LivenessAllocatorScope AllocScope; // Must be declared after Alloc.
static constexpr SizeT InvalidLiveIndex = -1; static constexpr SizeT InvalidLiveIndex = -1;
Cfg *Func; Cfg *Func;
LivenessMode Mode; LivenessMode Mode;
SizeT NumGlobals = 0;
/// Size of Nodes is Cfg::Nodes.size(). /// Size of Nodes is Cfg::Nodes.size().
CfgVector<LivenessNode> Nodes; LivenessVector<LivenessNode> Nodes;
/// VarToLiveMap maps a Variable's Variable::Number to its live index within /// VarToLiveMap maps a Variable's Variable::Number to its live index within
/// its basic block. /// its basic block.
CfgVector<SizeT> VarToLiveMap; LivenessVector<SizeT> VarToLiveMap;
/// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for non-local /// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for non-local
/// variables. /// variables.
CfgVector<Variable *> LiveToVarMap; LivenessVector<Variable *> LiveToVarMap;
/// RangeMask[Variable::Number] indicates whether we want to track that /// RangeMask[Variable::Number] indicates whether we want to track that
/// Variable's live range. /// Variable's live range.
LivenessBV RangeMask; LivenessBV RangeMask;
/// ScratchBV is a bitvector that can be reused across CfgNode passes, to /// ScratchBV is a bitvector that can be reused across CfgNode passes, to
/// avoid having to allocate/deallocate memory so frequently. /// avoid having to allocate/deallocate memory so frequently.
LivenessBV ScratchBV; LivenessBV ScratchBV;
/// MaxLocals indicates what is the maximum number of local variables in a
/// single basic block, across all blocks in a function.
SizeT MaxLocals = 0;
/// NumGlobals indicates how many global variables (i.e., Multi Block) exist
/// for a function.
SizeT NumGlobals = 0;
}; };
} // end of namespace Ice } // end of namespace Ice
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "IceMemory.h" #include "IceMemory.h"
#include "IceCfg.h" #include "IceCfg.h"
#include "IceLiveness.h"
#include "IceTLS.h" #include "IceTLS.h"
#include <cassert> #include <cassert>
...@@ -33,4 +34,16 @@ void CfgAllocatorTraits::set_current(const manager_type *Manager) { ...@@ -33,4 +34,16 @@ void CfgAllocatorTraits::set_current(const manager_type *Manager) {
ICE_TLS_SET_FIELD(CfgAllocator, Allocator); ICE_TLS_SET_FIELD(CfgAllocator, Allocator);
} }
ICE_TLS_DEFINE_FIELD(ArenaAllocator *, LivenessAllocatorTraits,
LivenessAllocator);
LivenessAllocatorTraits::allocator_type LivenessAllocatorTraits::current() {
return ICE_TLS_GET_FIELD(LivenessAllocator);
}
void LivenessAllocatorTraits::set_current(const manager_type *Manager) {
ArenaAllocator *Allocator =
Manager == nullptr ? nullptr : Manager->getAllocator();
ICE_TLS_SET_FIELD(LivenessAllocator, Allocator);
}
} // end of namespace Ice } // end of namespace Ice
...@@ -27,6 +27,7 @@ namespace Ice { ...@@ -27,6 +27,7 @@ namespace Ice {
class Cfg; class Cfg;
class GlobalContext; class GlobalContext;
class Liveness;
using ArenaAllocator = using ArenaAllocator =
llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, /*SlabSize=*/1024 * 1024>; llvm::BumpPtrAllocatorImpl<llvm::MallocAllocator, /*SlabSize=*/1024 * 1024>;
...@@ -61,8 +62,10 @@ template <typename T, typename Traits> struct sz_allocator { ...@@ -61,8 +62,10 @@ template <typename T, typename Traits> struct sz_allocator {
using size_type = std::size_t; using size_type = std::size_t;
using difference_type = std::ptrdiff_t; using difference_type = std::ptrdiff_t;
sz_allocator() = default; sz_allocator() : Current() {}
template <class U> sz_allocator(const sz_allocator<U, Traits> &) {} template <class U>
sz_allocator(const sz_allocator<U, Traits> &)
: Current() {}
pointer address(reference x) const { pointer address(reference x) const {
return reinterpret_cast<pointer>(&reinterpret_cast<char &>(x)); return reinterpret_cast<pointer>(&reinterpret_cast<char &>(x));
...@@ -72,6 +75,7 @@ template <typename T, typename Traits> struct sz_allocator { ...@@ -72,6 +75,7 @@ template <typename T, typename Traits> struct sz_allocator {
} }
pointer allocate(size_type num) { pointer allocate(size_type num) {
assert(current() != nullptr);
return current()->template Allocate<T>(num); return current()->template Allocate<T>(num);
} }
...@@ -88,9 +92,20 @@ template <typename T, typename Traits> struct sz_allocator { ...@@ -88,9 +92,20 @@ template <typename T, typename Traits> struct sz_allocator {
/// Manages the current underlying allocator. /// Manages the current underlying allocator.
/// @{ /// @{
static typename Traits::allocator_type current() { return Traits::current(); } typename Traits::allocator_type current() {
if (!Traits::cache_allocator) {
// TODO(jpp): allocators should always be cacheable... maybe. Investigate.
return Traits::current();
}
if (Current == nullptr) {
Current = Traits::current();
}
assert(Current == Traits::current());
return Current;
}
static void init() { Traits::init(); } static void init() { Traits::init(); }
/// @} /// @}
typename Traits::allocator_type Current;
}; };
template <class Traits> struct sz_allocator_scope { template <class Traits> struct sz_allocator_scope {
...@@ -122,6 +137,7 @@ class CfgAllocatorTraits { ...@@ -122,6 +137,7 @@ class CfgAllocatorTraits {
public: public:
using allocator_type = ArenaAllocator *; using allocator_type = ArenaAllocator *;
using manager_type = Cfg; using manager_type = Cfg;
static constexpr bool cache_allocator = false;
static void init() { ICE_TLS_INIT_FIELD(CfgAllocator); }; static void init() { ICE_TLS_INIT_FIELD(CfgAllocator); };
...@@ -137,6 +153,31 @@ using CfgLocalAllocator = sz_allocator<T, CfgAllocatorTraits>; ...@@ -137,6 +153,31 @@ using CfgLocalAllocator = sz_allocator<T, CfgAllocatorTraits>;
using CfgLocalAllocatorScope = sz_allocator_scope<CfgAllocatorTraits>; using CfgLocalAllocatorScope = sz_allocator_scope<CfgAllocatorTraits>;
class LivenessAllocatorTraits {
LivenessAllocatorTraits() = delete;
LivenessAllocatorTraits(const LivenessAllocatorTraits &) = delete;
LivenessAllocatorTraits &operator=(const LivenessAllocatorTraits &) = delete;
~LivenessAllocatorTraits() = delete;
public:
using allocator_type = ArenaAllocator *;
using manager_type = Liveness;
static constexpr bool cache_allocator = true;
static void init() { ICE_TLS_INIT_FIELD(LivenessAllocator); };
static allocator_type current();
static void set_current(const manager_type *Manager);
private:
ICE_TLS_DECLARE_FIELD(ArenaAllocator *, LivenessAllocator);
};
template <typename T>
using LivenessAllocator = sz_allocator<T, LivenessAllocatorTraits>;
using LivenessAllocatorScope = sz_allocator_scope<LivenessAllocatorTraits>;
} // end of namespace Ice } // end of namespace Ice
#endif // SUBZERO_SRC_ICEMEMORY_H #endif // SUBZERO_SRC_ICEMEMORY_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment