Skip to content

Commit 473ce09

Browse files
committed
Precompute subreg info with TableGen
1 parent 3b40757 commit 473ce09

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

llvm/include/llvm/CodeGen/TargetRegisterInfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,15 @@ class TargetRegisterInfo : public MCRegisterInfo {
745745
return reverseComposeSubRegIndexLaneMaskImpl(IdxA, LaneMask);
746746
}
747747

748+
/// Returns the number of allocatable sub registers for R, which is the
749+
/// number of register units that are not artificial and part of an
750+
/// allocatable register class. For a register like D0_D1, which consists of
751+
/// D0 and D1, this function would return '2'. For an architecture where
752+
/// D0=S0_S1 and D1=S2_S3, this would return '4' for S0, S1, S2, S3.
753+
unsigned getNumAllocatableSubRegs(MCPhysReg R) const {
754+
return getNumAllocatableSubRegsImpl(R);
755+
}
756+
748757
/// Debugging helper: dump register in human readable form to dbgs() stream.
749758
static void dumpReg(Register Reg, unsigned SubRegIndex = 0,
750759
const TargetRegisterInfo *TRI = nullptr);
@@ -774,6 +783,10 @@ class TargetRegisterInfo : public MCRegisterInfo {
774783
llvm_unreachable("Target has no sub-registers");
775784
}
776785

786+
virtual unsigned getNumAllocatableSubRegsImpl(MCPhysReg) const {
787+
llvm_unreachable("Target has no sub-registers");
788+
}
789+
777790
/// Return the register cost table index. This implementation is sufficient
778791
/// for most architectures and can be overriden by targets in case there are
779792
/// multiple cost values associated with each register.

llvm/lib/CodeGen/LiveIntervals.cpp

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -710,30 +710,6 @@ void LiveIntervals::pruneValue(LiveRange &LR, SlotIndex Kill,
710710
// Register allocator hooks.
711711
//
712712

713-
/// Returns true if the physreg has multiple regunits that can be accessed
714-
/// as independent registers.
715-
///
716-
/// Returns 'true' for e.g.:
717-
/// gpr64_0_gpr64_1
718-
// => two independently accessible registers gpr64_0 and gpr64_1.
719-
///
720-
/// Returns 'false' for e.g.:
721-
/// gpr64_0: => accessible register, reads/writes 64bits
722-
/// gpr32_0: => accessible sub-regsiter of gpr64_0, reads/writes 32bits
723-
// gpr32_0_hi => top 32bits of gpr64_0, not independently accessible.
724-
static bool hasMultipleAddressableRegUnits(const TargetRegisterInfo *TRI,
725-
MCPhysReg PhysReg) {
726-
unsigned NumAddressableRegUnits = 0;
727-
for (MCRegUnit U : TRI->regunits(PhysReg)) {
728-
for (MCRegUnitRootIterator RI(U, TRI); RI.isValid(); ++RI)
729-
if (!TRI->isArtificial(*RI) && TRI->isInAllocatableClass(*RI))
730-
NumAddressableRegUnits++;
731-
if (NumAddressableRegUnits > 1)
732-
return true;
733-
}
734-
return false;
735-
}
736-
737713
void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
738714
// Keep track of regunit ranges.
739715
SmallVector<std::pair<const LiveRange*, LiveRange::const_iterator>, 8> RU;
@@ -760,18 +736,6 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
760736
continue;
761737
RU.push_back(std::make_pair(&RURange, RURange.find(LI.begin()->end)));
762738
}
763-
764-
// If parts of a physical register for a given liverange, as assigned by the
765-
// register allocator, can be used to store other values not represented by
766-
// this liverange, then `LiveIntervals::addKillFlags` normally avoids adding
767-
// a kill flag on the use of this register when the value's liverange ends.
768-
//
769-
// However, if all the other regunits are artificial, then we can still
770-
// safely add the kill flag, since those parts of the register can never be
771-
// accessed independently.
772-
bool AssumeOtherUnitsCanBeUsed =
773-
hasMultipleAddressableRegUnits(TRI, PhysReg);
774-
775739
// Every instruction that kills Reg corresponds to a segment range end
776740
// point.
777741
for (LiveInterval::const_iterator RI = LI.begin(), RE = LI.end(); RI != RE;
@@ -806,6 +770,9 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
806770
if (MRI->subRegLivenessEnabled()) {
807771
// When reading a partial undefined value we must not add a kill flag.
808772
// The regalloc might have used the undef lane for something else.
773+
// If the register consists of a single allocatable subreg, then
774+
// we can assume the other (undef) lanes cannot be used.
775+
//
809776
// Example:
810777
// %1 = ... ; R32: %1
811778
// %2:high16 = ... ; R64: %2
@@ -816,7 +783,7 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
816783
// are actually never written by %2. After assignment the <kill>
817784
// flag at the read instruction is invalid.
818785
LaneBitmask DefinedLanesMask;
819-
if (LI.hasSubRanges() && AssumeOtherUnitsCanBeUsed) {
786+
if (LI.hasSubRanges() && TRI->getNumAllocatableSubRegs(PhysReg) > 1) {
820787
// Compute a mask of lanes that are defined.
821788
DefinedLanesMask = LaneBitmask::getNone();
822789
for (const LiveInterval::SubRange &SR : LI.subranges())

llvm/utils/TableGen/RegisterInfoEmitter.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class RegisterInfoEmitter {
9393
void EmitRegUnitPressure(raw_ostream &OS, StringRef ClassName);
9494
void emitComposeSubRegIndices(raw_ostream &OS, StringRef ClassName);
9595
void emitComposeSubRegIndexLaneMask(raw_ostream &OS, StringRef ClassName);
96+
void emitNumAllocatableSubRegs(raw_ostream &OS, StringRef ClassName,
97+
llvm::BitVector &InAllocClass);
9698
};
9799

98100
} // end anonymous namespace
@@ -677,6 +679,31 @@ static bool combine(const CodeGenSubRegIndex *Idx,
677679
return true;
678680
}
679681

682+
void RegisterInfoEmitter::emitNumAllocatableSubRegs(
683+
raw_ostream &OS, StringRef ClassName, llvm::BitVector &InAllocClass) {
684+
OS << "unsigned " << ClassName
685+
<< "::getNumAllocatableSubRegsImpl(MCPhysReg R) const {\n";
686+
OS << " static unsigned numAllocatableSubRegsMap[] = { \n";
687+
OS << " 0, // NoRegister\n";
688+
const auto &Regs = RegBank.getRegisters();
689+
for (auto [I, R] : llvm::enumerate(Regs)) {
690+
unsigned NumAllocatableSubRegs = 0;
691+
for (unsigned U : R.getRegUnits()) {
692+
for (const CodeGenRegister *UR : RegBank.getRegUnit(U).getRoots())
693+
if (!UR->Artificial && InAllocClass[UR->EnumValue])
694+
NumAllocatableSubRegs++;
695+
}
696+
OS << " " << NumAllocatableSubRegs;
697+
if (I < Regs.size() - 1)
698+
OS << ",";
699+
OS << " // " << R.getName() << "\n";
700+
}
701+
OS << " };\n";
702+
OS << " assert(R <= " << Regs.size() << " && \"Unexpected physreg\");\n";
703+
OS << " return numAllocatableSubRegsMap[R];\n";
704+
OS << "};\n";
705+
}
706+
680707
void RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
681708
StringRef ClassName) {
682709
const auto &SubRegIndices = RegBank.getSubRegIndices();
@@ -1122,7 +1149,9 @@ void RegisterInfoEmitter::runTargetHeader(raw_ostream &OS) {
11221149
<< " const TargetRegisterClass *getSubClassWithSubReg"
11231150
<< "(const TargetRegisterClass *, unsigned) const override;\n"
11241151
<< " const TargetRegisterClass *getSubRegisterClass"
1125-
<< "(const TargetRegisterClass *, unsigned) const override;\n";
1152+
<< "(const TargetRegisterClass *, unsigned) const override;\n"
1153+
<< " unsigned getNumAllocatableSubRegsImpl(MCPhysReg) const "
1154+
"override;\n";
11261155
}
11271156
OS << " const RegClassWeight &getRegClassWeight("
11281157
<< "const TargetRegisterClass *RC) const override;\n"
@@ -1483,6 +1512,7 @@ void RegisterInfoEmitter::runTargetDesc(raw_ostream &OS) {
14831512
if (!SubRegIndices.empty()) {
14841513
emitComposeSubRegIndices(OS, ClassName);
14851514
emitComposeSubRegIndexLaneMask(OS, ClassName);
1515+
emitNumAllocatableSubRegs(OS, ClassName, InAllocClass);
14861516
}
14871517

14881518
if (!SubRegIndices.empty()) {

0 commit comments

Comments
 (0)