Skip to content

Commit

Permalink
Do not track subregister liveness when it brings no benefits
Browse files Browse the repository at this point in the history
Some subregisters are only to indicate different access sizes, while not
providing any way to actually divide the register up into multiple
disjunct parts. Avoid tracking subregister liveness in these cases as it
is not beneficial.

Differential Revision: http://reviews.llvm.org/D8429

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232695 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
MatzeB committed Mar 19, 2015
1 parent cc690d6 commit 5101c89
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 15 deletions.
13 changes: 12 additions & 1 deletion include/llvm/CodeGen/MachineRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,18 @@ class MachineRegisterInfo {
/// information.
void invalidateLiveness() { TracksLiveness = false; }

bool tracksSubRegLiveness() const { return TracksSubRegLiveness; }
/// Returns true if liveness for register class @p RC should be tracked at
/// the subregister level.
bool shouldTrackSubRegLiveness(const TargetRegisterClass &RC) const {
return subRegLivenessEnabled() && RC.HasDisjunctSubRegs;
}
bool shouldTrackSubRegLiveness(unsigned VReg) const {
assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Must pass a VReg");
return shouldTrackSubRegLiveness(*getRegClass(VReg));
}
bool subRegLivenessEnabled() const {
return TracksSubRegLiveness;
}

void enableSubRegLiveness(bool Enable = true) {
TracksSubRegLiveness = Enable;
Expand Down
6 changes: 4 additions & 2 deletions include/llvm/Target/TargetRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class TargetRegisterClass {
const uint32_t *SubClassMask;
const uint16_t *SuperRegIndices;
const unsigned LaneMask;
/// Whether the class supports two (or more) disjunct subregister indices.
const bool HasDisjunctSubRegs;
const sc_iterator SuperClasses;
ArrayRef<MCPhysReg> (*OrderFunc)(const MachineFunction&);

Expand Down Expand Up @@ -357,13 +359,13 @@ class TargetRegisterInfo : public MCRegisterInfo {
///
/// then:
///
/// getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B) != 0
/// (getSubRegIndexLaneMask(A) & getSubRegIndexLaneMask(B)) != 0
///
/// The converse is not necessarily true. If two lane masks have a common
/// bit, the corresponding sub-registers may not overlap, but it can be
/// assumed that they usually will.
/// SubIdx == 0 is allowed, it has the lane mask ~0u.
unsigned getSubRegIndexLaneMask(unsigned SubIdx) const {
// SubIdx == 0 is allowed, it has the lane mask ~0u.
assert(SubIdx < getNumSubRegIndices() && "This is not a subregister index");
return SubRegIndexLaneMasks[SubIdx];
}
Expand Down
8 changes: 4 additions & 4 deletions lib/CodeGen/LiveIntervalAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ void LiveIntervals::computeVirtRegInterval(LiveInterval &LI) {
assert(LRCalc && "LRCalc not initialized.");
assert(LI.empty() && "Should only compute empty intervals.");
LRCalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator());
LRCalc->calculate(LI);
LRCalc->calculate(LI, MRI->shouldTrackSubRegLiveness(LI.reg));
computeDeadValues(LI, nullptr);
}

Expand Down Expand Up @@ -466,7 +466,7 @@ bool LiveIntervals::computeDeadValues(LiveInterval &LI,

// Is the register live before? Otherwise we may have to add a read-undef
// flag for subregister defs.
if (MRI->tracksSubRegLiveness()) {
if (MRI->shouldTrackSubRegLiveness(LI.reg)) {
if ((I == LI.begin() || std::prev(I)->end < Def) && !VNI->isPHIDef()) {
MachineInstr *MI = getInstructionFromIndex(Def);
MI->addRegisterDefReadUndef(LI.reg);
Expand Down Expand Up @@ -662,7 +662,7 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
RU.push_back(std::make_pair(&RURange, RURange.find(LI.begin()->end)));
}

if (MRI->tracksSubRegLiveness()) {
if (MRI->subRegLivenessEnabled()) {
SRs.clear();
for (const LiveInterval::SubRange &SR : LI.subranges()) {
SRs.push_back(std::make_pair(&SR, SR.find(LI.begin()->end)));
Expand Down Expand Up @@ -700,7 +700,7 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
goto CancelKill;
}

if (MRI->tracksSubRegLiveness()) {
if (MRI->subRegLivenessEnabled()) {
// When reading a partial undefined value we must not add a kill flag.
// The regalloc might have used the undef lane for something else.
// Example:
Expand Down
4 changes: 2 additions & 2 deletions lib/CodeGen/LiveRangeCalc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void createDeadDef(SlotIndexes &Indexes, VNInfo::Allocator &Alloc,
LR.createDeadDef(DefIdx, Alloc);
}

void LiveRangeCalc::calculate(LiveInterval &LI) {
void LiveRangeCalc::calculate(LiveInterval &LI, bool TrackSubRegs) {
assert(MRI && Indexes && "call reset() first");

// Step 1: Create minimal live segments for every definition of Reg.
Expand All @@ -63,7 +63,7 @@ void LiveRangeCalc::calculate(LiveInterval &LI) {
continue;

unsigned SubReg = MO.getSubReg();
if (LI.hasSubRanges() || (SubReg != 0 && MRI->tracksSubRegLiveness())) {
if (LI.hasSubRanges() || (SubReg != 0 && TrackSubRegs)) {
unsigned Mask = SubReg != 0 ? TRI.getSubRegIndexLaneMask(SubReg)
: MRI->getMaxLaneMaskForVReg(Reg);

Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/LiveRangeCalc.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class LiveRangeCalc {
/// Calculates liveness for the register specified in live interval @p LI.
/// Creates subregister live ranges as needed if subreg liveness tracking is
/// enabled.
void calculate(LiveInterval &LI);
void calculate(LiveInterval &LI, bool TrackSubRegs);

//===--------------------------------------------------------------------===//
// Low-level interface.
Expand Down
3 changes: 2 additions & 1 deletion lib/CodeGen/MachineVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,7 +1573,8 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
if (!hasRead) {
// When tracking subregister liveness, the main range must start new
// values on partial register writes, even if there is no read.
if (!MRI->tracksSubRegLiveness() || LaneMask != 0 || !hasSubRegDef) {
if (!MRI->shouldTrackSubRegLiveness(Reg) || LaneMask != 0 ||
!hasSubRegDef) {
report("Instruction ending live segment doesn't read the register",
MI);
errs() << S << " in " << LR << '\n';
Expand Down
4 changes: 2 additions & 2 deletions lib/CodeGen/RegisterCoalescer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ void RegisterCoalescer::updateRegDefsUses(unsigned SrcReg,

// A subreg use of a partially undef (super) register may be a complete
// undef use now and then has to be marked that way.
if (SubIdx != 0 && MO.isUse() && MRI->tracksSubRegLiveness()) {
if (SubIdx != 0 && MO.isUse() && MRI->shouldTrackSubRegLiveness(DstReg)) {
if (!DstInt->hasSubRanges()) {
BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator();
unsigned Mask = MRI->getMaxLaneMaskForVReg(DstInt->reg);
Expand Down Expand Up @@ -2479,7 +2479,7 @@ bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
SmallVector<VNInfo*, 16> NewVNInfo;
LiveInterval &RHS = LIS->getInterval(CP.getSrcReg());
LiveInterval &LHS = LIS->getInterval(CP.getDstReg());
bool TrackSubRegLiveness = MRI->tracksSubRegLiveness();
bool TrackSubRegLiveness = MRI->shouldTrackSubRegLiveness(*CP.getNewRC());
JoinVals RHSVals(RHS, CP.getSrcReg(), CP.getSrcIdx(), 0, NewVNInfo, CP, LIS,
TRI, false, TrackSubRegLiveness);
JoinVals LHSVals(LHS, CP.getDstReg(), CP.getDstIdx(), 0, NewVNInfo, CP, LIS,
Expand Down
2 changes: 1 addition & 1 deletion lib/CodeGen/VirtRegMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ void VirtRegRewriter::addMBBLiveIns() {
}

void VirtRegRewriter::rewrite() {
bool NoSubRegLiveness = !MRI->tracksSubRegLiveness();
bool NoSubRegLiveness = !MRI->subRegLivenessEnabled();
SmallVector<unsigned, 8> SuperDeads;
SmallVector<unsigned, 8> SuperDefs;
SmallVector<unsigned, 8> SuperKills;
Expand Down
11 changes: 11 additions & 0 deletions utils/TableGen/CodeGenRegisters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
EnumValue(Enum),
CostPerUse(R->getValueAsInt("CostPerUse")),
CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
HasDisjunctSubRegs(false),
SubRegsComplete(false),
SuperRegsComplete(false),
TopoSig(~0u)
Expand Down Expand Up @@ -217,6 +218,8 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
return SubRegs;
SubRegsComplete = true;

HasDisjunctSubRegs = ExplicitSubRegs.size() > 1;

// First insert the explicit subregs and make sure they are fully indexed.
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
Expand All @@ -237,6 +240,7 @@ CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
CodeGenRegister *SR = ExplicitSubRegs[i];
const SubRegMap &Map = SR->computeSubRegs(RegBank);
HasDisjunctSubRegs |= SR->HasDisjunctSubRegs;

for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
++SI) {
Expand Down Expand Up @@ -1803,6 +1807,13 @@ void CodeGenRegBank::computeDerivedInfo() {

computeRegUnitLaneMasks();

// Compute register class HasDisjunctSubRegs flag.
for (CodeGenRegisterClass &RC : RegClasses) {
RC.HasDisjunctSubRegs = false;
for (const CodeGenRegister *Reg : RC.getMembers())
RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs;
}

// Get the weight of each set.
for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units);
Expand Down
3 changes: 3 additions & 0 deletions utils/TableGen/CodeGenRegisters.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace llvm {
unsigned EnumValue;
unsigned CostPerUse;
bool CoveredBySubRegs;
bool HasDisjunctSubRegs;

// Map SubRegIndex -> Register.
typedef std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref<llvm::less>>
Expand Down Expand Up @@ -307,6 +308,8 @@ namespace llvm {
std::string AltOrderSelect;
/// Contains the combination of the lane masks of all subregisters.
unsigned LaneMask;
/// True if there are at least 2 subregisters which do not interfere.
bool HasDisjunctSubRegs;

// Return the Record that defined this class, or NULL if the class was
// created by TableGen.
Expand Down
4 changes: 3 additions & 1 deletion utils/TableGen/RegisterInfoEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName()
<< "SubClassMask,\n SuperRegIdxSeqs + "
<< SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n "
<< format("0x%08x,\n ", RC.LaneMask);
<< format("0x%08x,\n ", RC.LaneMask)
<< (RC.HasDisjunctSubRegs?"true":"false")
<< ", /* HasDisjunctSubRegs */\n ";
if (RC.getSuperClasses().empty())
OS << "NullRegClasses,\n ";
else
Expand Down

0 comments on commit 5101c89

Please sign in to comment.