[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;
/// Mapping of all the operands.
/// Note: Use a SmallVector to avoid heap allocation in most cases.
SmallVector<ValueMapping, 8> OperandsMapping;
SmallVector<const ValueMapping *, 8> OperandsMapping;
/// Number of operands.
unsigned NumOperands;
ValueMapping &getOperandMapping(unsigned i) {
const ValueMapping *&getOperandMapping(unsigned i) {
assert(i < getNumOperands() && "Out of bound operand");
return OperandsMapping[i];
}
@ -142,7 +142,7 @@ public:
: ID(ID), Cost(Cost), NumOperands(NumOperands) {
assert(getID() != InvalidMappingID &&
"Use the default constructor for invalid mapping");
OperandsMapping.resize(getNumOperands());
OperandsMapping.resize(getNumOperands(), nullptr);
}
/// Default constructor.
@ -159,13 +159,24 @@ public:
unsigned getNumOperands() const { return NumOperands; }
/// 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 {
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.
void setOperandMapping(unsigned i, const ValueMapping &ValMapping) {
getOperandMapping(i) = ValMapping;
getOperandMapping(i) = &ValMapping;
}
/// Check whether this object is valid.
@ -300,6 +311,10 @@ protected:
/// This shouldn't be needed when everything gets TableGen'ed.
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
/// RegisterBank instances.
///
@ -373,6 +388,19 @@ protected:
const PartialMapping &getPartialMapping(unsigned StartIdx, unsigned Length,
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
/// the encoding constraints, if any.
///
@ -578,6 +606,10 @@ operator<<(raw_ostream &OS, const RegisterBankInfo::OperandsMapper &OpdMapper) {
OpdMapper.print(OS, /*ForDebug*/ false);
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.
#endif

View File

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

View File

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