Add function that translates subregister lane masks to other subregs.

This works like the composeSubRegisterIndices() function but transforms
a subregister lane mask instead of a subregister index.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223874 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matthias Braun 2014-12-10 01:12:00 +00:00
parent 2d1536af06
commit 6fed9cabfd
4 changed files with 190 additions and 1 deletions

View File

@ -510,6 +510,15 @@ public:
return composeSubRegIndicesImpl(a, b);
}
/// Transforms a LaneMask computed for one subregister to the lanemask that
/// would have been computed when composing the subsubregisters with IdxA
/// first. @sa composeSubRegIndices()
unsigned composeSubRegIndexLaneMask(unsigned IdxA, unsigned LaneMask) const {
if (!IdxA)
return LaneMask;
return composeSubRegIndexLaneMaskImpl(IdxA, LaneMask);
}
/// Debugging helper: dump register in human readable form to dbgs() stream.
static void dumpReg(unsigned Reg, unsigned SubRegIndex = 0,
const TargetRegisterInfo* TRI = nullptr);
@ -520,6 +529,12 @@ protected:
llvm_unreachable("Target has no sub-registers");
}
/// Overridden by TableGen in targets that have sub-registers.
virtual unsigned
composeSubRegIndexLaneMaskImpl(unsigned, unsigned) const {
llvm_unreachable("Target has no sub-registers");
}
public:
/// getCommonSuperRegClass - Find a common super-register class if it exists.
///

View File

@ -1192,6 +1192,70 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
}
}
// Compute transformation sequences for composeSubRegIndexLaneMask. The idea
// here is that for each possible target subregister we look at the leafs
// in the subregister graph that compose for this target and create
// transformation sequences for the lanemasks. Each step in the sequence
// consists of a bitmask and a bitrotate operation. As the rotation amounts
// are usually the same for many subregisters we can easily combine the steps
// by combining the masks.
for (const auto &Idx : SubRegIndices) {
const auto &Composites = Idx.getComposites();
auto &LaneTransforms = Idx.CompositionLaneMaskTransform;
// Go through all leaf subregisters and find the ones that compose with Idx.
// These make out all possible valid bits in the lane mask we want to
// transform. Looking only at the leafs ensure that only a single bit in
// the mask is set.
unsigned NextBit = 0;
for (auto &Idx2 : SubRegIndices) {
// Skip non-leaf subregisters.
if (!Idx2.getComposites().empty())
continue;
// Replicate the behaviour from the lane mask generation loop above.
unsigned SrcBit = NextBit;
unsigned SrcMask = 1u << SrcBit;
if (NextBit < 31)
++NextBit;
assert(Idx2.LaneMask == SrcMask);
// Get the composed subregister if there is any.
auto C = Composites.find(&Idx2);
if (C == Composites.end())
continue;
const CodeGenSubRegIndex *Composite = C->second;
// The Composed subreg should be a leaf subreg too
assert(Composite->getComposites().empty());
// Create Mask+Rotate operation and merge with existing ops if possible.
unsigned DstBit = Log2_32(Composite->LaneMask);
int Shift = DstBit - SrcBit;
uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift;
for (auto &I : LaneTransforms) {
if (I.RotateLeft == RotateLeft) {
I.Mask |= SrcMask;
SrcMask = 0;
}
}
if (SrcMask != 0) {
MaskRolPair MaskRol = { SrcMask, RotateLeft };
LaneTransforms.push_back(MaskRol);
}
}
// Optimize if the transformation consists of one step only: Set mask to
// 0xffffffff (including some irrelevant invalid bits) so that it should
// merge with more entries later while compressing the table.
if (LaneTransforms.size() == 1)
LaneTransforms[0].Mask = ~0u;
// Further compression optimization: For invalid compositions resulting
// in a sequence with 0 entries we can just pick any other. Choose
// Mask 0xffffffff with Rotation 0.
if (LaneTransforms.size() == 0) {
MaskRolPair P = { ~0u, 0 };
LaneTransforms.push_back(P);
}
}
// FIXME: What if ad-hoc aliasing introduces overlaps that aren't represented
// by the sub-register graph? This doesn't occur in any known targets.

View File

@ -34,6 +34,20 @@
namespace llvm {
class CodeGenRegBank;
/// Used to encode a step in a register lane mask transformation.
/// Mask the bits specified in Mask, then rotate them Rol bits to the left
/// assuming a wraparound at 32bits.
struct MaskRolPair {
unsigned Mask;
uint8_t RotateLeft;
bool operator==(const MaskRolPair Other) {
return Mask == Other.Mask && RotateLeft == Other.RotateLeft;
}
bool operator!=(const MaskRolPair Other) {
return Mask != Other.Mask || RotateLeft != Other.RotateLeft;
}
};
/// CodeGenSubRegIndex - Represents a sub-register index.
class CodeGenSubRegIndex {
Record *const TheDef;
@ -45,6 +59,7 @@ namespace llvm {
uint16_t Offset;
const unsigned EnumValue;
mutable unsigned LaneMask;
mutable SmallVector<MaskRolPair,1> CompositionLaneMaskTransform;
// Are all super-registers containing this SubRegIndex covered by their
// sub-registers?

View File

@ -62,6 +62,8 @@ private:
const std::string &ClassName);
void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank,
const std::string &ClassName);
void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank,
const std::string &ClassName);
};
} // End anonymous namespace
@ -687,6 +689,95 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
OS << "}\n\n";
}
void
RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
CodeGenRegBank &RegBank,
const std::string &ClName) {
// See the comments in computeSubRegLaneMasks() for our goal here.
const auto &SubRegIndices = RegBank.getSubRegIndices();
// Create a list of Mask+Rotate operations, with equivalent entries merged.
SmallVector<unsigned, 4> SubReg2SequenceIndexMap;
SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences;
for (const auto &Idx : SubRegIndices) {
const SmallVector<MaskRolPair, 1> &IdxSequence
= Idx.CompositionLaneMaskTransform;
unsigned Found = ~0u;
unsigned SIdx = 0;
unsigned NextSIdx;
for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) {
SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
NextSIdx = SIdx + Sequence.size() + 1;
if (Sequence.size() != IdxSequence.size())
continue;
bool Identical = true;
for (size_t o = 0, oe = Sequence.size(); o != oe; ++o) {
if (Sequence[o] != IdxSequence[o]) {
Identical = false;
break;
}
}
if (Identical) {
Found = SIdx;
break;
}
}
if (Found == ~0u) {
Sequences.push_back(IdxSequence);
Found = SIdx;
}
SubReg2SequenceIndexMap.push_back(Found);
}
OS << "unsigned " << ClName
<< "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, unsigned LaneMask)"
" const {\n";
OS << " struct MaskRolOp {\n"
" unsigned Mask;\n"
" uint8_t RotateLeft;\n"
" };\n"
" static const MaskRolOp Seqs[] = {\n";
unsigned Idx = 0;
for (size_t s = 0, se = Sequences.size(); s != se; ++s) {
OS << " ";
const SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) {
const MaskRolPair &P = Sequence[p];
OS << format("{ 0x%08X, %2u }, ", P.Mask, P.RotateLeft);
}
OS << "{ 0, 0 }";
if (s+1 != se)
OS << ", ";
OS << " // Sequence " << Idx << "\n";
Idx += Sequence.size() + 1;
}
OS << " };\n"
" static const MaskRolOp *CompositeSequences[] = {\n";
for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) {
OS << " ";
unsigned Idx = SubReg2SequenceIndexMap[i];
OS << format("&Seqs[%u]", Idx);
if (i+1 != e)
OS << ",";
OS << " // to " << SubRegIndices[i].getName() << "\n";
}
OS << " };\n\n";
OS << " --IdxA; assert(IdxA < " << SubRegIndices.size()
<< " && \"Subregister index out of bounds\");\n"
" unsigned Result = 0;\n"
" for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)"
" {\n"
" unsigned Masked = LaneMask & Ops->Mask;\n"
" Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n"
" Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n"
" }\n"
" return Result;\n"
"}\n";
}
//
// runMCDesc - Print out MC register descriptions.
//
@ -966,6 +1057,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
<< " { return false; }\n";
if (!RegBank.getSubRegIndices().empty()) {
OS << " unsigned composeSubRegIndicesImpl"
<< "(unsigned, unsigned) const override;\n"
<< " unsigned composeSubRegIndexLaneMaskImpl"
<< "(unsigned, unsigned) const override;\n"
<< " const TargetRegisterClass *getSubClassWithSubReg"
<< "(const TargetRegisterClass*, unsigned) const override;\n";
@ -1214,8 +1307,10 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
auto SubRegIndicesSize =
std::distance(SubRegIndices.begin(), SubRegIndices.end());
if (!SubRegIndices.empty())
if (!SubRegIndices.empty()) {
emitComposeSubRegIndices(OS, RegBank, ClassName);
emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName);
}
// Emit getSubClassWithSubReg.
if (!SubRegIndices.empty()) {