[GlobalISel] NFCI, Getting GlobalISel ~5% faster

by replacing DenseMap with IndexedMap for LLTs within MRI, as
benchmarked by cross-compiling sqlite3 amalgamation for AArch64
on x86 machine.

Reviewed By: qcolombet

Differential Revision: https://reviews.llvm.org/D46809

llvm-svn: 333125
This commit is contained in:
Roman Tereshin 2018-05-23 21:12:02 +00:00
parent 3e7d8dfae3
commit 13229aff54
4 changed files with 29 additions and 38 deletions

View File

@ -136,9 +136,9 @@ private:
/// started.
BitVector ReservedRegs;
using VRegToTypeMap = DenseMap<unsigned, LLT>;
/// Map generic virtual registers to their actual size.
mutable std::unique_ptr<VRegToTypeMap> VRegToType;
using VRegToTypeMap = IndexedMap<LLT, VirtReg2IndexFunctor>;
/// Map generic virtual registers to their low-level type.
VRegToTypeMap VRegToType;
/// Keep track of the physical registers that are live in to the function.
/// Live in values are typically arguments in registers. LiveIn values are
@ -717,17 +717,13 @@ public:
unsigned createVirtualRegister(const TargetRegisterClass *RegClass,
StringRef Name = "");
/// Accessor for VRegToType. This accessor should only be used
/// by global-isel related work.
VRegToTypeMap &getVRegToType() const {
if (!VRegToType)
VRegToType.reset(new VRegToTypeMap);
return *VRegToType.get();
}
/// Get the low-level type of \p VReg or LLT{} if VReg is not a generic
/// Get the low-level type of \p Reg or LLT{} if Reg is not a generic
/// (target independent) virtual register.
LLT getType(unsigned VReg) const;
LLT getType(unsigned Reg) const {
if (TargetRegisterInfo::isVirtualRegister(Reg) && VRegToType.inBounds(Reg))
return VRegToType[Reg];
return LLT{};
}
/// Set the low-level type of \p VReg to \p Ty.
void setType(unsigned VReg, LLT Ty);

View File

@ -77,7 +77,7 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
// FIXME: There are many other MF/MFI fields we need to initialize.
const MachineRegisterInfo &MRI = MF.getRegInfo();
MachineRegisterInfo &MRI = MF.getRegInfo();
#ifndef NDEBUG
// Check that our input is fully legal: we require the function to have the
// Legalized property, so it should be.
@ -167,7 +167,6 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
unsigned DstReg = MI.getOperand(0).getReg();
if (TargetRegisterInfo::isVirtualRegister(SrcReg) &&
TargetRegisterInfo::isVirtualRegister(DstReg)) {
MachineRegisterInfo &MRI = MF.getRegInfo();
auto SrcRC = MRI.getRegClass(SrcReg);
auto DstRC = MRI.getRegClass(DstReg);
if (SrcRC == DstRC) {
@ -181,27 +180,29 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
// Now that selection is complete, there are no more generic vregs. Verify
// that the size of the now-constrained vreg is unchanged and that it has a
// register class.
for (auto &VRegToType : MRI.getVRegToType()) {
unsigned VReg = VRegToType.first;
auto *RC = MRI.getRegClassOrNull(VReg);
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
unsigned VReg = TargetRegisterInfo::index2VirtReg(I);
MachineInstr *MI = nullptr;
if (!MRI.def_empty(VReg))
MI = &*MRI.def_instr_begin(VReg);
else if (!MRI.use_empty(VReg))
MI = &*MRI.use_instr_begin(VReg);
if (!MI)
continue;
if (MI && !RC) {
const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg);
if (!RC) {
reportGISelFailure(MF, TPC, MORE, "gisel-select",
"VReg has no regclass after selection", *MI);
return false;
} else if (!RC)
continue;
}
if (VRegToType.second.isValid() &&
VRegToType.second.getSizeInBits() > TRI.getRegSizeInBits(*RC)) {
reportGISelFailure(MF, TPC, MORE, "gisel-select",
"VReg has explicit size different from class size",
*MI);
const LLT Ty = MRI.getType(VReg);
if (Ty.isValid() && Ty.getSizeInBits() > TRI.getRegSizeInBits(*RC)) {
reportGISelFailure(
MF, TPC, MORE, "gisel-select",
"VReg's low-level type and register class have different sizes", *MI);
return false;
}
}
@ -234,7 +235,7 @@ bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) {
// If we successfully selected the function nothing is going to use the vreg
// types after us (otherwise MIRPrinter would need them). Make sure the types
// disappear.
MRI.getVRegToType().clear();
MRI.clearVirtRegTypes();
// FIXME: Should we accurately track changes?
return true;

View File

@ -177,17 +177,13 @@ MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass,
return Reg;
}
LLT MachineRegisterInfo::getType(unsigned VReg) const {
VRegToTypeMap::const_iterator TypeIt = getVRegToType().find(VReg);
return TypeIt != getVRegToType().end() ? TypeIt->second : LLT{};
}
void MachineRegisterInfo::setType(unsigned VReg, LLT Ty) {
// Check that VReg doesn't have a class.
assert((getRegClassOrRegBank(VReg).isNull() ||
!getRegClassOrRegBank(VReg).is<const TargetRegisterClass *>()) &&
"Can't set the size of a non-generic virtual register");
getVRegToType()[VReg] = Ty;
VRegToType.grow(VReg);
VRegToType[VReg] = Ty;
}
unsigned
@ -196,15 +192,13 @@ MachineRegisterInfo::createGenericVirtualRegister(LLT Ty, StringRef Name) {
unsigned Reg = createIncompleteVirtualRegister(Name);
// FIXME: Should we use a dummy register class?
VRegInfo[Reg].first = static_cast<RegisterBank *>(nullptr);
getVRegToType()[Reg] = Ty;
setType(Reg, Ty);
if (TheDelegate)
TheDelegate->MRI_NoteNewVirtualRegister(Reg);
return Reg;
}
void MachineRegisterInfo::clearVirtRegTypes() {
getVRegToType().clear();
}
void MachineRegisterInfo::clearVirtRegTypes() { VRegToType.clear(); }
/// clearVirtRegs - Remove all virtual registers (after physreg assignment).
void MachineRegisterInfo::clearVirtRegs() {

View File

@ -49,7 +49,7 @@ namespace {
// or not, nothing is going to use the vreg types after us. Make sure they
// disappear.
auto ClearVRegTypesOnReturn =
make_scope_exit([&MF]() { MF.getRegInfo().getVRegToType().clear(); });
make_scope_exit([&MF]() { MF.getRegInfo().clearVirtRegTypes(); });
if (MF.getProperties().hasProperty(
MachineFunctionProperties::Property::FailedISel)) {