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];
}
: 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.
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.
/// 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.
///
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.
///
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
RegisterBankInfo::~RegisterBankInfo() {
for (auto It : MapOfPartialMappings)
delete It.second;
+ for (auto It : MapOfValueMappings)
+ delete It.second;
}
bool RegisterBankInfo::verify(const TargetRegisterInfo &TRI) 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)
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;
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);
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(
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));
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;
}