//
//===----------------------------------------------------------------------===//
//
-// InterferenceCache remembers per-block interference in LiveIntervalUnions.
+// InterferenceCache remembers per-block interference from LiveIntervalUnions,
+// fixed RegUnit interference, and register masks.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_INTERFERENCECACHE
-#define LLVM_CODEGEN_INTERFERENCECACHE
+#ifndef LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
+#define LLVM_LIB_CODEGEN_INTERFERENCECACHE_H
-#include "LiveIntervalUnion.h"
+#include "llvm/CodeGen/LiveIntervalUnion.h"
namespace llvm {
+class LiveIntervals;
+
class InterferenceCache {
const TargetRegisterInfo *TRI;
LiveIntervalUnion *LIUArray;
- SlotIndexes *Indexes;
MachineFunction *MF;
/// BlockInterference - information about the interference in a single basic
/// Indexes - Mapping block numbers to SlotIndex ranges.
SlotIndexes *Indexes;
+ /// LIS - Used for accessing register mask interference maps.
+ LiveIntervals *LIS;
+
/// PrevPos - The previous position the iterators were moved to.
SlotIndex PrevPos;
- /// AliasTags - A LiveIntervalUnion pointer and tag for each alias of
- /// PhysReg.
- SmallVector<std::pair<LiveIntervalUnion*, unsigned>, 8> Aliases;
+ /// RegUnitInfo - Information tracked about each RegUnit in PhysReg.
+ /// When PrevPos is set, the iterators are valid as if advanceTo(PrevPos)
+ /// had just been called.
+ struct RegUnitInfo {
+ /// Iterator pointing into the LiveIntervalUnion containing virtual
+ /// register interference.
+ LiveIntervalUnion::SegmentIter VirtI;
+
+ /// Tag of the LIU last time we looked.
+ unsigned VirtTag;
+
+ /// Fixed interference in RegUnit.
+ LiveRange *Fixed;
- typedef LiveIntervalUnion::SegmentIter Iter;
+ /// Iterator pointing into the fixed RegUnit interference.
+ LiveInterval::iterator FixedI;
- /// Iters - an iterator for each alias
- SmallVector<Iter, 8> Iters;
+ RegUnitInfo(LiveIntervalUnion &LIU)
+ : VirtTag(LIU.getTag()), Fixed(nullptr) {
+ VirtI.setMap(LIU.getMap());
+ }
+ };
+
+ /// Info for each RegUnit in PhysReg. It is very rare ofr a PHysReg to have
+ /// more than 4 RegUnits.
+ SmallVector<RegUnitInfo, 4> RegUnits;
/// Blocks - Interference for each block in the function.
SmallVector<BlockInterference, 8> Blocks;
void update(unsigned MBBNum);
public:
- Entry() : PhysReg(0), Tag(0), RefCount(0), Indexes(0) {}
+ Entry() : PhysReg(0), Tag(0), RefCount(0), Indexes(nullptr), LIS(nullptr) {}
- void clear(MachineFunction *mf, SlotIndexes *indexes) {
+ void clear(MachineFunction *mf, SlotIndexes *indexes, LiveIntervals *lis) {
assert(!hasRefs() && "Cannot clear cache entry with references");
PhysReg = 0;
MF = mf;
Indexes = indexes;
+ LIS = lis;
}
unsigned getPhysReg() const { return PhysReg; }
bool hasRefs() const { return RefCount > 0; }
- void revalidate();
+ void revalidate(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
/// valid - Return true if this is a valid entry for physReg.
bool valid(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
// Point to an entry for each physreg. The entry pointed to may not be up to
// date, and it may have been reused for a different physreg.
- SmallVector<unsigned char, 2> PhysRegEntries;
+ unsigned char* PhysRegEntries;
+ size_t PhysRegEntriesCount;
// Next round-robin entry to be picked.
unsigned RoundRobin;
Entry *get(unsigned PhysReg);
public:
- InterferenceCache() : TRI(0), LIUArray(0), Indexes(0), MF(0), RoundRobin(0) {}
+ InterferenceCache()
+ : TRI(nullptr), LIUArray(nullptr), MF(nullptr), PhysRegEntries(nullptr),
+ PhysRegEntriesCount(0), RoundRobin(0) {}
+
+ ~InterferenceCache() {
+ free(PhysRegEntries);
+ }
+
+ void reinitPhysRegEntries();
/// init - Prepare cache for a new function.
- void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*,
+ void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*, LiveIntervals*,
const TargetRegisterInfo *);
/// getMaxCursors - Return the maximum number of concurrent cursors that can
class Cursor {
Entry *CacheEntry;
BlockInterference *Current;
+ static BlockInterference NoInterference;
void setEntry(Entry *E) {
+ Current = nullptr;
// Update reference counts. Nothing happens when RefCount reaches 0, so
// we don't have to check for E == CacheEntry etc.
if (CacheEntry)
CacheEntry = E;
if (CacheEntry)
CacheEntry->addRef(+1);
- Current = 0;
}
public:
/// Cursor - Create a dangling cursor.
- Cursor() : CacheEntry(0), Current(0) {}
- ~Cursor() { setEntry(0); }
+ Cursor() : CacheEntry(nullptr), Current(nullptr) {}
+ ~Cursor() { setEntry(nullptr); }
- Cursor(const Cursor &O) {
+ Cursor(const Cursor &O) : CacheEntry(nullptr), Current(nullptr) {
setEntry(O.CacheEntry);
}
void setPhysReg(InterferenceCache &Cache, unsigned PhysReg) {
// Release reference before getting a new one. That guarantees we can
// actually have CacheEntries live cursors.
- setEntry(0);
+ setEntry(nullptr);
if (PhysReg)
setEntry(Cache.get(PhysReg));
}
/// moveTo - Move cursor to basic block MBBNum.
void moveToBlock(unsigned MBBNum) {
- Current = CacheEntry->get(MBBNum);
+ Current = CacheEntry ? CacheEntry->get(MBBNum) : &NoInterference;
}
/// hasInterference - Return true if the current block has any interference.