// 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;
+
+ /// Index into list with lane mask sequences. The sequence contains a lanemask
+ /// for every register unit.
+ uint16_t RegUnitLaneMasks;
};
/// MCRegisterInfo base class - We assume that the target defines a static
unsigned NumRegUnits; // Number of regunits.
const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table.
const MCPhysReg *DiffLists; // Pointer to the difflists array
+ const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences
+ // for register units.
const char *RegStrings; // Pointer to the string table.
const char *RegClassStrings; // Pointer to the class strings.
const uint16_t *SubRegIndices; // Pointer to the subreg lookup
friend class MCSubRegIterator;
friend class MCSuperRegIterator;
friend class MCRegUnitIterator;
+ friend class MCRegUnitMaskIterator;
friend class MCRegUnitRootIterator;
/// \brief Initialize MCRegisterInfo, called by TableGen
const MCPhysReg (*RURoots)[2],
unsigned NRU,
const MCPhysReg *DL,
+ const unsigned *RUMS,
const char *Strings,
const char *ClassStrings,
const uint16_t *SubIndices,
PCReg = PC;
Classes = C;
DiffLists = DL;
+ RegUnitMaskSequences = RUMS;
RegStrings = Strings;
RegClassStrings = ClassStrings;
NumClasses = NC;
}
};
+/// MCRegUnitIterator enumerates a list of register units and their associated
+/// lane masks for Reg. The register units are in ascending numerical order.
+class MCRegUnitMaskIterator {
+ MCRegUnitIterator RUIter;
+ const unsigned *MaskListIter;
+public:
+ MCRegUnitMaskIterator() {}
+ /// Constructs an iterator that traverses the register units and their
+ /// associated LaneMasks in Reg.
+ MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI)
+ : RUIter(Reg, MCRI) {
+ uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks;
+ MaskListIter = &MCRI->RegUnitMaskSequences[Idx];
+ }
+
+ /// Returns a (RegUnit, LaneMask) pair.
+ std::pair<unsigned,unsigned> operator*() const {
+ return std::make_pair(*RUIter, *MaskListIter);
+ }
+
+ /// Returns true if this iterator is not yet at the end.
+ bool isValid() const { return RUIter.isValid(); }
+
+ /// Moves to the next position.
+ void operator++() {
+ ++MaskListIter;
+ ++RUIter;
+ }
+};
+
// Each register unit has one or two root registers. The complete set of
// registers containing a register unit is the union of the roots and their
// super-registers. All registers aliasing Unit can be visited like this:
}
}
+void CodeGenRegBank::computeRegUnitLaneMasks() {
+ for (auto &Register : Registers) {
+ // Create an initial lane mask for all register units.
+ const auto &RegUnits = Register.getRegUnits();
+ CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.size(), 0);
+ // Iterate through SubRegisters.
+ typedef CodeGenRegister::SubRegMap SubRegMap;
+ const SubRegMap &SubRegs = Register.getSubRegs();
+ for (SubRegMap::const_iterator S = SubRegs.begin(),
+ SE = SubRegs.end(); S != SE; ++S) {
+ CodeGenRegister *SubReg = S->second;
+ // Ignore non-leaf subregisters, their lane masks are fully covered by
+ // the leaf subregisters anyway.
+ if (SubReg->getSubRegs().size() != 0)
+ continue;
+ CodeGenSubRegIndex *SubRegIndex = S->first;
+ const CodeGenRegister *SubRegister = S->second;
+ unsigned LaneMask = SubRegIndex->LaneMask;
+ // Distribute LaneMask to Register Units touched.
+ for (const auto &SUI : SubRegister->getRegUnits()) {
+ bool Found = false;
+ for (size_t u = 0, ue = RegUnits.size(); u < ue; ++u) {
+ if (SUI == RegUnits[u]) {
+ RegUnitLaneMasks[u] |= LaneMask;
+ assert(!Found);
+ Found = true;
+ }
+ }
+ assert(Found);
+ }
+ }
+ Register.setRegUnitLaneMasks(RegUnitLaneMasks);
+ }
+}
+
void CodeGenRegBank::computeDerivedInfo() {
computeComposites();
computeSubRegLaneMasks();
// supersets for the union of overlapping sets.
computeRegUnitSets();
+ computeRegUnitLaneMasks();
+
// Get the weight of each set.
for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units);
// List of register units in ascending order.
typedef SmallVector<unsigned, 16> RegUnitList;
+ typedef SmallVector<unsigned, 16> RegUnitLaneMaskList;
// How many entries in RegUnitList are native?
unsigned NumNativeRegUnits;
// This is only valid after computeSubRegs() completes.
const RegUnitList &getRegUnits() const { return RegUnits; }
+ ArrayRef<unsigned> getRegUnitLaneMasks() const {
+ return makeArrayRef(RegUnitLaneMasks).slice(0, NumNativeRegUnits);
+ }
+
// Get the native register units. This is a prefix of getRegUnits().
ArrayRef<unsigned> getNativeRegUnits() const {
return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits);
}
+ void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) {
+ RegUnitLaneMasks = LaneMasks;
+ }
+
// Inherit register units from subregisters.
// Return true if the RegUnits changed.
bool inheritRegUnits(CodeGenRegBank &RegBank);
SuperRegList SuperRegs;
DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*> SubReg2Idx;
RegUnitList RegUnits;
+ RegUnitLaneMaskList RegUnitLaneMasks;
};
// Compute a lane mask for each sub-register index.
void computeSubRegLaneMasks();
+ /// Computes a lane mask for each register unit enumerated by a physical
+ /// register.
+ void computeRegUnitLaneMasks();
+
public:
CodeGenRegBank(RecordKeeper&);
// 0 differential which means we can't encode repeated elements.
typedef SmallVector<uint16_t, 4> DiffVec;
+typedef SmallVector<unsigned, 4> MaskVec;
// 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.
OS << Val;
}
+static void printMask(raw_ostream &OS, unsigned Val) {
+ OS << format("0x%08X", Val);
+}
+
// Try to combine Idx's compose map into Vec if it is compatible.
// Return false if it's not possible.
static bool combine(const CodeGenSubRegIndex *Idx,
SmallVector<DiffVec, 4> RegUnitLists(Regs.size());
SmallVector<unsigned, 4> RegUnitInitScale(Regs.size());
+ // List of lane masks accompanying register unit sequences.
+ SequenceToOffsetTable<MaskVec> LaneMaskSeqs;
+ SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size());
+
// Keep track of sub-register names as well. These are not differentially
// encoded.
typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec;
// Precompute register lists for the SequenceToOffsetTable.
unsigned i = 0;
- for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I) {
+ for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) {
const auto &Reg = *I;
RegStrings.add(Reg.getName());
Scale = 0;
RegUnitInitScale[i] = Scale;
DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg.EnumValue, RUs));
- ++i;
+
+ const auto &RUMasks = Reg.getRegUnitLaneMasks();
+ MaskVec &LaneMaskVec = RegUnitLaneMasks[i];
+ assert(LaneMaskVec.empty());
+ LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end());
+ // Terminator mask should not be used inside of the list.
+#ifndef NDEBUG
+ for (unsigned M : LaneMaskVec) {
+ assert(M != ~0u && "terminator mask should not be part of the list");
+ }
+#endif
+ LaneMaskSeqs.add(LaneMaskVec);
}
// Compute the final layout of the sequence table.
DiffSeqs.layout();
+ LaneMaskSeqs.layout();
SubRegIdxSeqs.layout();
OS << "namespace llvm {\n\n";
DiffSeqs.emit(OS, printDiff16);
OS << "};\n\n";
+ // Emit the shared table of regunit lane mask sequences.
+ OS << "extern const unsigned " << TargetName << "LaneMaskLists[] = {\n";
+ LaneMaskSeqs.emit(OS, printMask, "~0u");
+ OS << "};\n\n";
+
// Emit the table of sub-register indexes.
OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
SubRegIdxSeqs.emit(OS, printSubRegIndex);
OS << "extern const MCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
- OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n";
+ OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
// Emit the register descriptors now.
i = 0;
OS << " { " << RegStrings.get(Reg.getName()) << ", "
<< DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i])
<< ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "
- << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << " },\n";
+ << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", "
+ << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n";
++i;
}
OS << "};\n\n"; // End of register descriptors...
<< Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, "
<< RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, "
<< RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, "
- << TargetName << "RegStrings, " << TargetName << "RegClassStrings, "
- << TargetName << "SubRegIdxLists, "
+ << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, "
+ << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, "
<< (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n"
<< TargetName << "SubRegIdxRanges, " << TargetName
<< "RegEncodingTable);\n\n";
// Emit the constructor of the class...
OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n";
+ OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n";
OS << "extern const char " << TargetName << "RegStrings[];\n";
OS << "extern const char " << TargetName << "RegClassStrings[];\n";
OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n";
<< " " << TargetName << "RegUnitRoots,\n"
<< " " << RegBank.getNumNativeRegUnits() << ",\n"
<< " " << TargetName << "RegDiffLists,\n"
+ << " " << TargetName << "LaneMaskLists,\n"
<< " " << TargetName << "RegStrings,\n"
<< " " << TargetName << "RegClassStrings,\n"
<< " " << TargetName << "SubRegIdxLists,\n"