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:
parent
a95bd86b3c
commit
9a1e884e09
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
Loading…
x
Reference in New Issue
Block a user