Represent sentinel slot indexes with a null pointer.

This is much faster than using a pointer to a ManagedStatic object accessed with
a function call. The greedy register allocator is 5% faster overall just from
the SlotIndex default constructor savings.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126925 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2011-03-03 05:40:04 +00:00
parent a97ff8a027
commit f37712f486
2 changed files with 8 additions and 85 deletions

View File

@ -34,77 +34,35 @@ namespace llvm {
/// SlotIndex & SlotIndexes classes for the public interface to this /// SlotIndex & SlotIndexes classes for the public interface to this
/// information. /// information.
class IndexListEntry { class IndexListEntry {
static const unsigned EMPTY_KEY_INDEX = ~0U & ~3U,
TOMBSTONE_KEY_INDEX = ~0U & ~7U;
IndexListEntry *next, *prev; IndexListEntry *next, *prev;
MachineInstr *mi; MachineInstr *mi;
unsigned index; unsigned index;
protected:
typedef enum { EMPTY_KEY, TOMBSTONE_KEY } ReservedEntryType;
// This constructor is only to be used by getEmptyKeyEntry
// & getTombstoneKeyEntry. It sets index to the given
// value and mi to zero.
IndexListEntry(ReservedEntryType r) : mi(0) {
switch(r) {
case EMPTY_KEY: index = EMPTY_KEY_INDEX; break;
case TOMBSTONE_KEY: index = TOMBSTONE_KEY_INDEX; break;
default: assert(false && "Invalid value for constructor.");
}
next = this;
prev = this;
}
public: public:
IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) { IndexListEntry(MachineInstr *mi, unsigned index) : mi(mi), index(index) {}
assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX &&
"Attempt to create invalid index. "
"Available indexes may have been exhausted?.");
}
bool isValid() const {
return (index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX);
}
MachineInstr* getInstr() const { return mi; } MachineInstr* getInstr() const { return mi; }
void setInstr(MachineInstr *mi) { void setInstr(MachineInstr *mi) {
assert(isValid() && "Attempt to modify reserved index.");
this->mi = mi; this->mi = mi;
} }
unsigned getIndex() const { return index; } unsigned getIndex() const { return index; }
void setIndex(unsigned index) { void setIndex(unsigned index) {
assert(index != EMPTY_KEY_INDEX && index != TOMBSTONE_KEY_INDEX &&
"Attempt to set index to invalid value.");
assert(isValid() && "Attempt to reset reserved index value.");
this->index = index; this->index = index;
} }
IndexListEntry* getNext() { return next; } IndexListEntry* getNext() { return next; }
const IndexListEntry* getNext() const { return next; } const IndexListEntry* getNext() const { return next; }
void setNext(IndexListEntry *next) { void setNext(IndexListEntry *next) {
assert(isValid() && "Attempt to modify reserved index.");
this->next = next; this->next = next;
} }
IndexListEntry* getPrev() { return prev; } IndexListEntry* getPrev() { return prev; }
const IndexListEntry* getPrev() const { return prev; } const IndexListEntry* getPrev() const { return prev; }
void setPrev(IndexListEntry *prev) { void setPrev(IndexListEntry *prev) {
assert(isValid() && "Attempt to modify reserved index.");
this->prev = prev; this->prev = prev;
} }
// This function returns the index list entry that is to be used for empty
// SlotIndex keys.
static IndexListEntry* getEmptyKeyEntry();
// This function returns the index list entry that is to be used for
// tombstone SlotIndex keys.
static IndexListEntry* getTombstoneKeyEntry();
}; };
// Specialize PointerLikeTypeTraits for IndexListEntry. // Specialize PointerLikeTypeTraits for IndexListEntry.
@ -130,9 +88,7 @@ namespace llvm {
PointerIntPair<IndexListEntry*, 2, unsigned> lie; PointerIntPair<IndexListEntry*, 2, unsigned> lie;
SlotIndex(IndexListEntry *entry, unsigned slot) SlotIndex(IndexListEntry *entry, unsigned slot)
: lie(entry, slot) { : lie(entry, slot) {}
assert(entry != 0 && "Attempt to construct index with 0 pointer.");
}
IndexListEntry& entry() const { IndexListEntry& entry() const {
assert(isValid() && "Attempt to compare reserved index."); assert(isValid() && "Attempt to compare reserved index.");
@ -149,22 +105,21 @@ namespace llvm {
} }
static inline unsigned getHashValue(const SlotIndex &v) { static inline unsigned getHashValue(const SlotIndex &v) {
IndexListEntry *ptrVal = &v.entry(); void *ptrVal = v.lie.getOpaqueValue();
return (unsigned((intptr_t)ptrVal) >> 4) ^ return (unsigned((intptr_t)ptrVal)) ^ (unsigned((intptr_t)ptrVal) >> 9);
(unsigned((intptr_t)ptrVal) >> 9);
} }
public: public:
static inline SlotIndex getEmptyKey() { static inline SlotIndex getEmptyKey() {
return SlotIndex(IndexListEntry::getEmptyKeyEntry(), 0); return SlotIndex(0, 1);
} }
static inline SlotIndex getTombstoneKey() { static inline SlotIndex getTombstoneKey() {
return SlotIndex(IndexListEntry::getTombstoneKeyEntry(), 0); return SlotIndex(0, 2);
} }
/// Construct an invalid index. /// Construct an invalid index.
SlotIndex() : lie(IndexListEntry::getEmptyKeyEntry(), 0) {} SlotIndex() : lie(0, 0) {}
// Construct a new slot index from the given one, and set the slot. // Construct a new slot index from the given one, and set the slot.
SlotIndex(const SlotIndex &li, Slot s) SlotIndex(const SlotIndex &li, Slot s)
@ -176,8 +131,7 @@ namespace llvm {
/// Returns true if this is a valid index. Invalid indicies do /// Returns true if this is a valid index. Invalid indicies do
/// not point into an index table, and cannot be compared. /// not point into an index table, and cannot be compared.
bool isValid() const { bool isValid() const {
IndexListEntry *entry = lie.getPointer(); return lie.getPointer();
return ((entry!= 0) && (entry->isValid()));
} }
/// Print this index to the given raw_ostream. /// Print this index to the given raw_ostream.

View File

@ -13,45 +13,14 @@
#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetInstrInfo.h"
using namespace llvm; using namespace llvm;
// Yep - these are thread safe. See the header for details.
namespace {
class EmptyIndexListEntry : public IndexListEntry {
public:
EmptyIndexListEntry() : IndexListEntry(EMPTY_KEY) {}
};
class TombstoneIndexListEntry : public IndexListEntry {
public:
TombstoneIndexListEntry() : IndexListEntry(TOMBSTONE_KEY) {}
};
// The following statics are thread safe. They're read only, and you
// can't step from them to any other list entries.
ManagedStatic<EmptyIndexListEntry> IndexListEntryEmptyKey;
ManagedStatic<TombstoneIndexListEntry> IndexListEntryTombstoneKey;
}
char SlotIndexes::ID = 0; char SlotIndexes::ID = 0;
INITIALIZE_PASS(SlotIndexes, "slotindexes", INITIALIZE_PASS(SlotIndexes, "slotindexes",
"Slot index numbering", false, false) "Slot index numbering", false, false)
IndexListEntry* IndexListEntry::getEmptyKeyEntry() {
return &*IndexListEntryEmptyKey;
}
IndexListEntry* IndexListEntry::getTombstoneKeyEntry() {
return &*IndexListEntryTombstoneKey;
}
void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const { void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const {
au.setPreservesAll(); au.setPreservesAll();
MachineFunctionPass::getAnalysisUsage(au); MachineFunctionPass::getAnalysisUsage(au);