uint32_t Overlaps; // Overlapping registers, described above
uint32_t SubRegs; // Sub-register set, described above
uint32_t SuperRegs; // Super-register set, described above
+
+ // RegUnits - Points to the list of register units. The low 4 bits holds the
+ // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator.
+ uint32_t RegUnits;
};
/// MCRegisterInfo base class - We assume that the target defines a static
unsigned RAReg; // Return address register
const MCRegisterClass *Classes; // Pointer to the regclass array
unsigned NumClasses; // Number of entries in the array
+ unsigned NumRegUnits; // Number of regunits.
const uint16_t *RegLists; // Pointer to the reglists array
+ const uint16_t *DiffLists; // Pointer to the difflists array
const char *RegStrings; // Pointer to the string table.
const uint16_t *SubRegIndices; // Pointer to the subreg lookup
// array.
const DwarfLLVMRegPair *EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH
DenseMap<unsigned, int> L2SEHRegs; // LLVM to SEH regs mapping
+ /// DiffListIterator - Base iterator class that can traverse the
+ /// differentially encoded register and regunit lists in DiffLists.
+ /// Don't use this class directly, use one of the specialized sub-classes
+ /// defined below.
+ class DiffListIterator {
+ uint16_t Val;
+ const uint16_t *List;
+
+ protected:
+ /// Create an invalid iterator. Call init() to point to something useful.
+ DiffListIterator() : Val(0), List(0) {}
+
+ /// init - Point the iterator to InitVal, decoding subsequent values from
+ /// DiffList. The iterator will initially point to InitVal, sub-classes are
+ /// responsible for skipping the seed value if it is not part of the list.
+ void init(uint16_t InitVal, const uint16_t *DiffList) {
+ Val = InitVal;
+ List = DiffList;
+ }
+
+ /// advance - Move to the next list position, return the applied
+ /// differential. This function does not detect the end of the list, that
+ /// is the caller's responsibility (by checking for a 0 return value).
+ unsigned advance() {
+ assert(isValid() && "Cannot move off the end of the list.");
+ uint16_t D = *List++;
+ Val += D;
+ return D;
+ }
+
+ public:
+
+ /// isValid - returns true if this iterator is not yet at the end.
+ bool isValid() const { return List; }
+
+ /// Dereference the iterator to get the value at the current position.
+ unsigned operator*() const { return Val; }
+
+ /// Pre-increment to move to the next position.
+ void operator++() {
+ // The end of the list is encoded as a 0 differential.
+ if (!advance())
+ List = 0;
+ }
+ };
+
+ // These iterators are allowed to sub-class DiffListIterator and access
+ // internal list pointers.
+ friend class MCRegUnitIterator;
+
public:
/// InitMCRegisterInfo - Initialize MCRegisterInfo, called by TableGen
/// auto-generated routines. *DO NOT USE*.
void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA,
- const MCRegisterClass *C, unsigned NC,
+ const MCRegisterClass *C, unsigned NC, unsigned NRU,
const uint16_t *RL,
+ const uint16_t *DL,
const char *Strings,
const uint16_t *SubIndices,
unsigned NumIndices,
RAReg = RA;
Classes = C;
RegLists = RL;
+ DiffLists = DL;
RegStrings = Strings;
NumClasses = NC;
+ NumRegUnits = NRU;
SubRegIndices = SubIndices;
NumSubRegIndices = NumIndices;
RegEncodingTable = RET;
return NumRegs;
}
+ /// getNumRegUnits - Return the number of (native) register units in the
+ /// target. Register units are numbered from 0 to getNumRegUnits() - 1. They
+ /// can be accessed through MCRegUnitIterator defined below.
+ unsigned getNumRegUnits() const {
+ return NumRegUnits;
+ }
+
/// getDwarfRegNum - Map a target register to an equivalent dwarf register
/// number. Returns -1 if there is no equivalent value. The second
/// parameter allows targets to use different numberings for EH info and
};
+//===----------------------------------------------------------------------===//
+// Register Units
+//===----------------------------------------------------------------------===//
+
+// Register units are used to compute register aliasing. Every register has at
+// least one register unit, but it can have more. Two registers overlap if and
+// only if they have a common register unit.
+//
+// A target with a complicated sub-register structure will typically have many
+// fewer register units than actual registers. MCRI::getNumRegUnits() returns
+// the number of register units in the target.
+
+// MCRegUnitIterator enumerates a list of register units for Reg. The list is
+// in ascending numerical order.
+class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator {
+public:
+ /// MCRegUnitIterator - Create an iterator that traverses the register units
+ /// in Reg.
+ MCRegUnitIterator(unsigned Reg, const MCRegisterInfo *MCRI) {
+ // Decode the RegUnits MCRegisterDesc field.
+ unsigned RU = MCRI->get(Reg).RegUnits;
+ unsigned Scale = RU & 15;
+ unsigned Offset = RU >> 4;
+
+ // Initialize the iterator to Reg * Scale, and the List pointer to
+ // DiffLists + Offset.
+ init(Reg * Scale, MCRI->DiffLists + Offset);
+
+ // That may not be a valid unit, we need to advance by one to get the real
+ // unit number. The first differential can be 0 which would normally
+ // terminate the list, but since we know every register has at least one
+ // unit, we can allow a 0 differential here.
+ advance();
+ }
+};
+
} // End llvm namespace
#endif
EnumValue(Enum),
CostPerUse(R->getValueAsInt("CostPerUse")),
CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
+ NumNativeRegUnits(0),
SubRegsComplete(false),
SuperRegsComplete(false),
TopoSig(~0u)
if (RegUnits.empty())
RegUnits.push_back(RegBank.newRegUnit(this));
+ // We have now computed the native register units. More may be adopted later
+ // for balancing purposes.
+ NumNativeRegUnits = RegUnits.size();
+
return SubRegs;
}
// List of register units in ascending order.
typedef SmallVector<unsigned, 16> RegUnitList;
+ // How many entries in RegUnitList are native?
+ unsigned NumNativeRegUnits;
+
// Get the list of register units.
- // This is only valid after getSubRegs() completes.
+ // This is only valid after computeSubRegs() completes.
const RegUnitList &getRegUnits() const { return RegUnits; }
+ // Get the native register units. This is a prefix of getRegUnits().
+ ArrayRef<unsigned> getNativeRegUnits() const {
+ return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits);
+ }
+
// Inherit register units from subregisters.
// Return true if the RegUnits changed.
bool inheritRegUnits(CodeGenRegBank &RegBank);
return RUID < NumNativeRegUnits;
}
+ unsigned getNumNativeRegUnits() const {
+ return NumNativeRegUnits;
+ };
+
RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; }
const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; }
OS << Idx->getQualifiedName();
}
+// Differentially encoded register and regunit lists allow for better
+// compression on regular register banks. The sequence is computed from the
+// differential list as:
+//
+// out[0] = InitVal;
+// out[n+1] = out[n] + diff[n]; // n = 0, 1, ...
+//
+// The initial value depends on the specific list. The list is terminated by a
+// 0 differential which means we can't encode repeated elements.
+
+typedef SmallVector<uint16_t, 4> DiffVec;
+
+// Differentially encode a sequence of numbers into V. The starting value and
+// terminating 0 are not added to V, so it will have the same size as List.
+DiffVec &diffEncode(DiffVec &V, unsigned InitVal, ArrayRef<unsigned> List) {
+ assert(V.empty() && "Clear DiffVec before diffEncode.");
+ uint16_t Val = uint16_t(InitVal);
+ for (unsigned i = 0; i != List.size(); ++i) {
+ uint16_t Cur = List[i];
+ V.push_back(Cur - Val);
+ Val = Cur;
+ }
+ return V;
+}
+
+static void printDiff16(raw_ostream &OS, uint16_t Val) {
+ OS << SignExtend32<16>(Val);
+}
+
//
// runMCDesc - Print out MC register descriptions.
//
SmallVector<RegVec, 4> OverlapLists(Regs.size());
SequenceToOffsetTable<RegVec, CodeGenRegister::Less> RegSeqs;
+ // Differentially encoded lists.
+ SequenceToOffsetTable<DiffVec> DiffSeqs;
+ SmallVector<DiffVec, 4> RegUnitLists(Regs.size());
+ SmallVector<unsigned, 4> RegUnitInitScale(Regs.size());
+
SequenceToOffsetTable<std::string> RegStrings;
// Precompute register lists for the SequenceToOffsetTable.
// Finally, Suffix itself.
OverlapList.insert(OverlapList.end(), Suffix.begin(), Suffix.end());
RegSeqs.add(OverlapList);
+
+ // Differentially encode the register unit list, seeded by register number.
+ // First compute a scale factor that allows more diff-lists to be reused:
+ //
+ // D0 -> (S0, S1)
+ // D1 -> (S2, S3)
+ //
+ // A scale factor of 2 allows D0 and D1 to share a diff-list. The initial
+ // value for the differential decoder is the register number multiplied by
+ // the scale.
+ //
+ // Check the neighboring registers for arithmetic progressions.
+ unsigned ScaleA = ~0u, ScaleB = ~0u;
+ ArrayRef<unsigned> RUs = Reg->getNativeRegUnits();
+ if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size())
+ ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front();
+ if (i+1 != Regs.size() &&
+ Regs[i+1]->getNativeRegUnits().size() == RUs.size())
+ ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front();
+ unsigned Scale = std::min(ScaleB, ScaleA);
+ // Default the scale to 0 if it can't be encoded in 4 bits.
+ if (Scale >= 16)
+ Scale = 0;
+ RegUnitInitScale[i] = Scale;
+ DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs));
}
// Compute the final layout of the sequence table.
RegSeqs.layout();
+ DiffSeqs.layout();
OS << "namespace llvm {\n\n";
RegSeqs.emit(OS, printRegister);
OS << "};\n\n";
+ // Emit the shared table of differential lists.
+ OS << "extern const uint16_t " << TargetName << "RegDiffLists[] = {\n";
+ DiffSeqs.emit(OS, printDiff16);
+ OS << "};\n\n";
+
// Emit the string table.
RegStrings.layout();
OS << "extern const char " << TargetName << "RegStrings[] = {\n";
OS << "extern const MCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
- OS << " { " << RegStrings.get("") << ", 0, 0, 0 },\n";
+ OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n";
// Emit the register descriptors now.
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
OS << " { " << RegStrings.get(Reg->getName()) << ", "
<< RegSeqs.get(OverlapLists[i]) << ", "
<< RegSeqs.get(SubRegLists[i]) << ", "
- << RegSeqs.get(Reg->getSuperRegs()) << " },\n";
+ << RegSeqs.get(Reg->getSuperRegs()) << ", "
+ << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n";
}
OS << "};\n\n"; // End of register descriptors...
<< "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n";
OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
<< Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
- << RegisterClasses.size() << ", " << TargetName << "RegLists, "
+ << RegisterClasses.size() << ", "
+ << RegBank.getNumNativeRegUnits() << ", "
+ << TargetName << "RegLists, "
+ << TargetName << "RegDiffLists, "
<< TargetName << "RegStrings, ";
if (SubRegIndices.size() != 0)
OS << "(uint16_t*)" << TargetName << "SubRegTable, "
// Emit the constructor of the class...
OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";
OS << "extern const uint16_t " << TargetName << "RegLists[];\n";
+ OS << "extern const uint16_t " << TargetName << "RegDiffLists[];\n";
OS << "extern const char " << TargetName << "RegStrings[];\n";
if (SubRegIndices.size() != 0)
OS << "extern const uint16_t *get" << TargetName
<< " InitMCRegisterInfo(" << TargetName << "RegDesc, "
<< Regs.size()+1 << ", RA,\n " << TargetName
<< "MCRegisterClasses, " << RegisterClasses.size() << ",\n"
+ << " " << RegBank.getNumNativeRegUnits() << ",\n"
<< " " << TargetName << "RegLists,\n"
+ << " " << TargetName << "RegDiffLists,\n"
<< " " << TargetName << "RegStrings,\n"
<< " ";
if (SubRegIndices.size() != 0)