[RegisterBankInfo] Uniquely generate ValueMapping.

This is a step toward statically allocate ValueMapping. Like the
previous few commits, the goal is to move toward a TableGen'ed like
structure with no dynamic allocation at all.

llvm-svn: 282324
This commit is contained in:
Quentin Colombet 2016-09-24 04:53:52 +00:00
parent 8159de4de9
commit fd8c95adf4
3 changed files with 98 additions and 25 deletions

View File

@ -120,11 +120,11 @@ public:
unsigned Cost; unsigned Cost;
/// Mapping of all the operands. /// Mapping of all the operands.
/// Note: Use a SmallVector to avoid heap allocation in most cases. /// Note: Use a SmallVector to avoid heap allocation in most cases.
SmallVector<ValueMapping, 8> OperandsMapping; SmallVector<const ValueMapping *, 8> OperandsMapping;
/// Number of operands. /// Number of operands.
unsigned NumOperands; unsigned NumOperands;
ValueMapping &getOperandMapping(unsigned i) { const ValueMapping *&getOperandMapping(unsigned i) {
assert(i < getNumOperands() && "Out of bound operand"); assert(i < getNumOperands() && "Out of bound operand");
return OperandsMapping[i]; return OperandsMapping[i];
} }
@ -142,7 +142,7 @@ public:
: ID(ID), Cost(Cost), NumOperands(NumOperands) { : ID(ID), Cost(Cost), NumOperands(NumOperands) {
assert(getID() != InvalidMappingID && assert(getID() != InvalidMappingID &&
"Use the default constructor for invalid mapping"); "Use the default constructor for invalid mapping");
OperandsMapping.resize(getNumOperands()); OperandsMapping.resize(getNumOperands(), nullptr);
} }
/// Default constructor. /// Default constructor.
@ -159,13 +159,24 @@ public:
unsigned getNumOperands() const { return NumOperands; } unsigned getNumOperands() const { return NumOperands; }
/// Get the value mapping of the ith operand. /// Get the value mapping of the ith operand.
/// \pre The mapping for the ith operand has been set.
/// \pre The ith operand is a register.
const ValueMapping &getOperandMapping(unsigned i) const { const ValueMapping &getOperandMapping(unsigned i) const {
return const_cast<InstructionMapping *>(this)->getOperandMapping(i); const ValueMapping *&ValMapping =
const_cast<InstructionMapping *>(this)->getOperandMapping(i);
assert(ValMapping && "Trying to get the mapping for a non-reg operand?");
return *ValMapping;
}
/// Check if the value mapping of the ith operand has been set.
bool isOperandMappingSet(unsigned i) const {
return const_cast<InstructionMapping *>(this)->getOperandMapping(i) !=
nullptr;
} }
/// Get the value mapping of the ith operand. /// Get the value mapping of the ith operand.
void setOperandMapping(unsigned i, const ValueMapping &ValMapping) { void setOperandMapping(unsigned i, const ValueMapping &ValMapping) {
getOperandMapping(i) = ValMapping; getOperandMapping(i) = &ValMapping;
} }
/// Check whether this object is valid. /// Check whether this object is valid.
@ -300,6 +311,10 @@ protected:
/// This shouldn't be needed when everything gets TableGen'ed. /// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, PartialMapping *> MapOfPartialMappings; mutable DenseMap<unsigned, PartialMapping *> MapOfPartialMappings;
/// Keep dynamically allocated ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, ValueMapping *> MapOfValueMappings;
/// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks /// Create a RegisterBankInfo that can accomodate up to \p NumRegBanks
/// RegisterBank instances. /// RegisterBank instances.
/// ///
@ -373,6 +388,19 @@ protected:
const PartialMapping &getPartialMapping(unsigned StartIdx, unsigned Length, const PartialMapping &getPartialMapping(unsigned StartIdx, unsigned Length,
const RegisterBank &RegBank) const; const RegisterBank &RegBank) const;
/// Methods to get a uniquely generated ValueMapping.
/// @{
/// The most common ValueMapping consists of a single PartialMapping.
/// Feature a method for that.
const ValueMapping &getValueMapping(unsigned StartIdx, unsigned Length,
const RegisterBank &RegBank) const;
/// Get the ValueMapping for the given arguments.
const ValueMapping &getValueMapping(const PartialMapping *BreakDown,
unsigned NumBreakDowns) const;
/// @}
/// Get the register bank for the \p OpIdx-th operand of \p MI form /// Get the register bank for the \p OpIdx-th operand of \p MI form
/// the encoding constraints, if any. /// the encoding constraints, if any.
/// ///
@ -578,6 +606,10 @@ operator<<(raw_ostream &OS, const RegisterBankInfo::OperandsMapper &OpdMapper) {
OpdMapper.print(OS, /*ForDebug*/ false); OpdMapper.print(OS, /*ForDebug*/ false);
return OS; return OS;
} }
/// Hashing function for PartialMapping.
/// It is required for the hashing of ValueMapping.
hash_code hash_value(const RegisterBankInfo::PartialMapping &PartMapping);
} // End namespace llvm. } // End namespace llvm.
#endif #endif

View File

@ -57,6 +57,8 @@ RegisterBankInfo::RegisterBankInfo(RegisterBank **RegBanks,
RegisterBankInfo::~RegisterBankInfo() { RegisterBankInfo::~RegisterBankInfo() {
for (auto It : MapOfPartialMappings) for (auto It : MapOfPartialMappings)
delete It.second; delete It.second;
for (auto It : MapOfValueMappings)
delete It.second;
} }
bool RegisterBankInfo::verify(const TargetRegisterInfo &TRI) const { bool RegisterBankInfo::verify(const TargetRegisterInfo &TRI) const {
@ -283,8 +285,7 @@ RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const {
} }
RegBank = CurRegBank; RegBank = CurRegBank;
RegSize = getSizeInBits(Reg, MRI, TRI); RegSize = getSizeInBits(Reg, MRI, TRI);
Mapping.setOperandMapping( Mapping.setOperandMapping(OpIdx, getValueMapping(0, RegSize, *CurRegBank));
OpIdx, ValueMapping{&getPartialMapping(0, RegSize, *CurRegBank), 1});
} }
if (CompleteMapping) if (CompleteMapping)
@ -306,23 +307,33 @@ RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const {
continue; continue;
// If a mapping already exists, do not touch it. // If a mapping already exists, do not touch it.
if (static_cast<const InstructionMapping *>(&Mapping) if (Mapping.isOperandMappingSet(OpIdx))
->getOperandMapping(OpIdx)
.NumBreakDowns)
continue; continue;
Mapping.setOperandMapping( Mapping.setOperandMapping(OpIdx, getValueMapping(0, RegSize, *RegBank));
OpIdx, ValueMapping{&getPartialMapping(0, RegSize, *RegBank), 1});
} }
return Mapping; return Mapping;
} }
/// Hashing function for PartialMapping.
static hash_code hashPartialMapping(unsigned StartIdx, unsigned Length,
const RegisterBank *RegBank) {
return hash_combine(StartIdx, Length, RegBank ? RegBank->getID() : 0);
}
/// Overloaded version of hash_value for a PartialMapping.
hash_code
llvm::hash_value(const RegisterBankInfo::PartialMapping &PartMapping) {
return hashPartialMapping(PartMapping.StartIdx, PartMapping.Length,
PartMapping.RegBank);
}
const RegisterBankInfo::PartialMapping & const RegisterBankInfo::PartialMapping &
RegisterBankInfo::getPartialMapping(unsigned StartIdx, unsigned Length, RegisterBankInfo::getPartialMapping(unsigned StartIdx, unsigned Length,
const RegisterBank &RegBank) const { const RegisterBank &RegBank) const {
++NumPartialMappingsAccessed; ++NumPartialMappingsAccessed;
hash_code Hash = hash_combine(StartIdx, Length, RegBank.getID()); hash_code Hash = hashPartialMapping(StartIdx, Length, &RegBank);
const auto &It = MapOfPartialMappings.find(Hash); const auto &It = MapOfPartialMappings.find(Hash);
if (It != MapOfPartialMappings.end()) if (It != MapOfPartialMappings.end())
return *It->second; return *It->second;
@ -334,6 +345,34 @@ RegisterBankInfo::getPartialMapping(unsigned StartIdx, unsigned Length,
return *PartMapping; return *PartMapping;
} }
const RegisterBankInfo::ValueMapping &
RegisterBankInfo::getValueMapping(unsigned StartIdx, unsigned Length,
const RegisterBank &RegBank) const {
return getValueMapping(&getPartialMapping(StartIdx, Length, RegBank), 1);
}
const RegisterBankInfo::ValueMapping &
RegisterBankInfo::getValueMapping(const PartialMapping *BreakDown,
unsigned NumBreakDowns) const {
hash_code Hash;
if (LLVM_LIKELY(NumBreakDowns == 1))
Hash = hash_value(*BreakDown);
else {
SmallVector<size_t, 8> Hashes;
for (unsigned Idx = 0; Idx != NumBreakDowns; ++Idx)
Hashes.push_back(hash_value(BreakDown[Idx]));
Hash = hash_combine_range(Hashes.begin(), Hashes.end());
}
const auto &It = MapOfValueMappings.find(Hash);
if (It != MapOfValueMappings.end())
return *It->second;
ValueMapping *&ValMapping = MapOfValueMappings[Hash];
ValMapping = new ValueMapping{BreakDown, NumBreakDowns};
return *ValMapping;
}
RegisterBankInfo::InstructionMapping RegisterBankInfo::InstructionMapping
RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
RegisterBankInfo::InstructionMapping Mapping = getInstrMappingImpl(MI); RegisterBankInfo::InstructionMapping Mapping = getInstrMappingImpl(MI);
@ -496,16 +535,18 @@ bool RegisterBankInfo::InstructionMapping::verify(
for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
const MachineOperand &MO = MI.getOperand(Idx); const MachineOperand &MO = MI.getOperand(Idx);
const RegisterBankInfo::ValueMapping &MOMapping = getOperandMapping(Idx);
(void)MOMapping;
if (!MO.isReg()) { if (!MO.isReg()) {
assert(!MOMapping.NumBreakDowns && assert(!isOperandMappingSet(Idx) &&
"We should not care about non-reg mapping"); "We should not care about non-reg mapping");
continue; continue;
} }
unsigned Reg = MO.getReg(); unsigned Reg = MO.getReg();
if (!Reg) if (!Reg)
continue; continue;
assert(isOperandMappingSet(Idx) &&
"We must have a mapping for reg operands");
const RegisterBankInfo::ValueMapping &MOMapping = getOperandMapping(Idx);
(void)MOMapping;
// Register size in bits. // Register size in bits.
// This size must match what the mapping expects. // This size must match what the mapping expects.
assert(MOMapping.verify(getSizeInBits( assert(MOMapping.verify(getSizeInBits(

View File

@ -205,15 +205,15 @@ AArch64RegisterBankInfo::getInstrAlternativeMappings(
InstructionMapping FPRMapping(/*ID*/ 2, /*Cost*/ 1, /*NumOperands*/ 3); InstructionMapping FPRMapping(/*ID*/ 2, /*Cost*/ 1, /*NumOperands*/ 3);
for (unsigned Idx = 0; Idx != 3; ++Idx) { for (unsigned Idx = 0; Idx != 3; ++Idx) {
GPRMapping.setOperandMapping( GPRMapping.setOperandMapping(
Idx, Idx, getValueMapping(
ValueMapping{&AArch64::PartMappings[AArch64::getRegBankBaseIdx(Size) + &AArch64::PartMappings[AArch64::getRegBankBaseIdx(Size) +
AArch64::FirstGPR], AArch64::FirstGPR],
1}); 1));
FPRMapping.setOperandMapping( FPRMapping.setOperandMapping(
Idx, Idx, getValueMapping(
ValueMapping{&AArch64::PartMappings[AArch64::getRegBankBaseIdx(Size) + &AArch64::PartMappings[AArch64::getRegBankBaseIdx(Size) +
AArch64::FirstFPR], AArch64::FirstFPR],
1}); 1));
} }
AltMappings.emplace_back(std::move(GPRMapping)); AltMappings.emplace_back(std::move(GPRMapping));
AltMappings.emplace_back(std::move(FPRMapping)); AltMappings.emplace_back(std::move(FPRMapping));
@ -325,7 +325,7 @@ AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
for (unsigned Idx = 0; Idx < MI.getNumOperands(); ++Idx) for (unsigned Idx = 0; Idx < MI.getNumOperands(); ++Idx)
if (MI.getOperand(Idx).isReg()) if (MI.getOperand(Idx).isReg())
Mapping.setOperandMapping( Mapping.setOperandMapping(
Idx, ValueMapping{&AArch64::PartMappings[OpFinalIdx[Idx]], 1}); Idx, getValueMapping(&AArch64::PartMappings[OpFinalIdx[Idx]], 1));
return Mapping; return Mapping;
} }