1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

[RegisterBankInfo] Change the representation of the partial mappings.

Instead of holding a mask, hold two value: the start index and the
length of the mapping. This is a more compact representation, although
less powerful. That being said, arbitrary masks would not have worked
for the generic so do not allow them in the first place.

llvm-svn: 267025
This commit is contained in:
Quentin Colombet 2016-04-21 18:09:34 +00:00
parent a95bd86b3c
commit 9a1e884e09
3 changed files with 46 additions and 40 deletions

View File

@ -36,20 +36,33 @@ class RegisterBankInfo {
public:
/// Helper struct that represents how a value is partially mapped
/// into a register.
/// The Mask is used to represent this partial mapping. Ones represent
/// where the value lives in RegBank and the width of the Mask represents
/// the size of the whole value.
/// The StartIdx and Length represent what region of the orginal
/// value this partial mapping covers.
/// This can be represented as a Mask of contiguous bit starting
/// at StartIdx bit and spanning Length bits.
/// StartIdx is the number of bits from the less significant bits.
struct PartialMapping {
/// Mask where the partial value lives.
APInt Mask;
/// Number of bits at which this partial mapping starts in the
/// original value. The bits are counted from less significant
/// bits to most significant bits.
unsigned StartIdx;
/// Length of this mapping in bits. This is how many bits this
/// partial mapping covers in the original value:
/// from StartIdx to StartIdx + Length -1.
unsigned Length;
/// Register bank where the partial value lives.
const RegisterBank *RegBank;
PartialMapping() = default;
/// Provide a shortcut for quickly building PartialMapping.
PartialMapping(const APInt &Mask, const RegisterBank &RegBank)
: Mask(Mask), RegBank(&RegBank) {}
PartialMapping(unsigned StartIdx, unsigned Length,
const RegisterBank &RegBank)
: StartIdx(StartIdx), Length(Length), RegBank(&RegBank) {}
/// \return the index of in the original value of the most
/// significant bit that this partial mapping covers.
unsigned getHighBitIdx() const { return StartIdx + Length - 1; }
/// Print this partial mapping on dbgs() stream.
void dump() const;

View File

@ -63,7 +63,7 @@ RegBankSelect::repairReg(unsigned Reg,
assert(ValMapping.BreakDown.size() == 1 &&
"Support for complex break down not supported yet");
const RegisterBankInfo::PartialMapping &PartialMap = ValMapping.BreakDown[0];
assert(PartialMap.Mask.getBitWidth() ==
assert(PartialMap.Length ==
(TargetRegisterInfo::isPhysicalRegister(Reg)
? TRI->getMinimalPhysRegClass(Reg)->getSize() * 8
: MRI->getSize(Reg)) &&
@ -111,8 +111,7 @@ RegBankSelect::repairReg(unsigned Reg,
}
// Create a new temporary to hold the repaired value.
unsigned NewReg =
MRI->createGenericVirtualRegister(PartialMap.Mask.getBitWidth());
unsigned NewReg = MRI->createGenericVirtualRegister(PartialMap.Length);
// Set the registers for the source and destination of the copy.
unsigned Src = Reg, Dst = NewReg;
// If this is a definition that we repair, the copy will be

View File

@ -365,27 +365,14 @@ void RegisterBankInfo::PartialMapping::dump() const {
void RegisterBankInfo::PartialMapping::verify() const {
assert(RegBank && "Register bank not set");
// Check what is the minimum width that will live into RegBank.
// RegBank will have to, at least, accomodate all the bits between the first
// and last bits active in Mask.
// If Mask is zero, then ActiveWidth is 0.
unsigned ActiveWidth = 0;
// Otherwise, remove the trailing and leading zeros from the bitwidth.
// 0..0 ActiveWidth 0..0.
if (Mask.getBoolValue())
ActiveWidth = Mask.getBitWidth() - Mask.countLeadingZeros() -
Mask.countTrailingZeros();
(void)ActiveWidth;
assert(ActiveWidth <= Mask.getBitWidth() &&
"Wrong computation of ActiveWidth, overflow?");
assert(RegBank->getSize() >= ActiveWidth &&
"Register bank too small for Mask");
assert(Length && "Empty mapping");
assert((StartIdx < getHighBitIdx()) && "Overflow, switch to APInt?");
// Check if the minimum width fits into RegBank.
assert(RegBank->getSize() >= Length && "Register bank too small for Mask");
}
void RegisterBankInfo::PartialMapping::print(raw_ostream &OS) const {
SmallString<128> MaskStr;
Mask.toString(MaskStr, /*Radix*/ 16, /*Signed*/ 0, /*formatAsCLiteral*/ true);
OS << "Mask(" << Mask.getBitWidth() << ") = " << MaskStr << ", RegBank = ";
OS << "[" << StartIdx << ", " << getHighBitIdx() << "], RegBank = ";
if (RegBank)
OS << *RegBank;
else
@ -394,18 +381,27 @@ void RegisterBankInfo::PartialMapping::print(raw_ostream &OS) const {
void RegisterBankInfo::ValueMapping::verify(unsigned ExpectedBitWidth) const {
assert(!BreakDown.empty() && "Value mapped nowhere?!");
unsigned ValueBitWidth = BreakDown.back().Mask.getBitWidth();
assert(ValueBitWidth == ExpectedBitWidth && "BitWidth does not match");
APInt ValueMask(ValueBitWidth, 0);
unsigned OrigValueBitWidth = 0;
for (const RegisterBankInfo::PartialMapping &PartMap : BreakDown) {
// Check that all the partial mapping have the same bitwidth.
assert(PartMap.Mask.getBitWidth() == ValueBitWidth &&
"Value does not have the same size accross the partial mappings");
// Check that the union of the partial mappings covers the whole value.
ValueMask |= PartMap.Mask;
// Check that each register bank is big enough to hold the partial value:
// this check is done by PartialMapping::verify
PartMap.verify();
// The original value should completely be mapped.
// Thus the maximum accessed index + 1 is the size of the original value.
OrigValueBitWidth =
std::max(OrigValueBitWidth, PartMap.getHighBitIdx() + 1);
}
assert(OrigValueBitWidth == ExpectedBitWidth && "BitWidth does not match");
APInt ValueMask(OrigValueBitWidth, 0);
for (const RegisterBankInfo::PartialMapping &PartMap : BreakDown) {
// Check that the union of the partial mappings covers the whole value,
// without overlaps.
// The high bit is exclusive in the APInt API, thus getHighBitIdx + 1.
APInt PartMapMask = APInt::getBitsSet(OrigValueBitWidth, PartMap.StartIdx,
PartMap.getHighBitIdx() + 1);
ValueMask ^= PartMapMask;
assert((ValueMask & PartMapMask) == PartMapMask &&
"Some partial mappings overlap");
}
assert(ValueMask.isAllOnesValue() && "Value is not fully mapped");
}
@ -430,12 +426,10 @@ void RegisterBankInfo::InstructionMapping::setOperandMapping(
unsigned OpIdx, unsigned MaskSize, const RegisterBank &RegBank) {
// Build the value mapping.
assert(MaskSize <= RegBank.getSize() && "Register bank is too small");
APInt Mask(MaskSize, 0);
// The value is represented by all the bits.
Mask.flipAllBits();
// Create the mapping object.
getOperandMapping(OpIdx).BreakDown.push_back(PartialMapping(Mask, RegBank));
getOperandMapping(OpIdx).BreakDown.push_back(
PartialMapping(0, MaskSize, RegBank));
}
void RegisterBankInfo::InstructionMapping::verify(