Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/LiveIntervals.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ class LiveIntervals {
/// have any segments or value numbers.
LLVM_ABI void constructMainRangeFromSubranges(LiveInterval &LI);

/// \returns true if all registers used by \p OrigMI at \p OrigIdx are also
/// available with the same value at \p UseIdx.
bool allUsesAvailableAt(const MachineInstr &MI, SlotIndex UseIdx) const;

private:
/// Compute live intervals for all virtual registers.
void computeVirtRegs();
Expand Down
5 changes: 0 additions & 5 deletions llvm/include/llvm/CodeGen/LiveRangeEdit.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,6 @@ class LiveRangeEdit : private MachineRegisterInfo::Delegate {
explicit Remat(const VNInfo *ParentVNI) : ParentVNI(ParentVNI) {}
};

/// allUsesAvailableAt - Return true if all registers used by OrigMI at
/// OrigIdx are also available with the same value at UseIdx.
bool allUsesAvailableAt(const MachineInstr *OrigMI, SlotIndex OrigIdx,
SlotIndex UseIdx) const;

/// canRematerializeAt - Determine if ParentVNI can be rematerialized at
/// UseIdx. It is assumed that parent_.getVNINfoAt(UseIdx) == ParentVNI.
bool canRematerializeAt(Remat &RM, VNInfo *OrigVNI, SlotIndex UseIdx);
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/CodeGen/CalcSpillWeights.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ bool VirtRegAuxInfo::isRematerializable(const LiveInterval &LI,

if (!TII.isTriviallyReMaterializable(*MI))
return false;

// If MI has register uses, it will only be rematerializable if its uses are
// also live at the indices it will be rematerialized at.
const MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
for (MachineInstr &Use : MRI.use_nodbg_instructions(Reg)) {
SlotIndex UseIdx = LIS.getInstructionIndex(Use);
if (LI.getVNInfoAt(UseIdx) != VNI)
continue;
if (!LIS.allUsesAvailableAt(*MI, UseIdx))
return false;
}
}
return true;
}
Expand Down
52 changes: 52 additions & 0 deletions llvm/lib/CodeGen/LiveIntervals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
Expand Down Expand Up @@ -1820,3 +1821,54 @@ void LiveIntervals::constructMainRangeFromSubranges(LiveInterval &LI) {
LICalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator());
LICalc->constructMainRangeFromSubranges(LI);
}

bool LiveIntervals::allUsesAvailableAt(const MachineInstr &MI,
SlotIndex UseIdx) const {
SlotIndex OrigIdx = getInstructionIndex(MI).getRegSlot(true);
UseIdx = std::max(UseIdx, UseIdx.getRegSlot(true));
for (const MachineOperand &MO : MI.operands()) {
if (!MO.isReg() || !MO.getReg() || !MO.readsReg())
continue;

// We can't remat physreg uses, unless it is a constant or target wants
// to ignore this use.
if (MO.getReg().isPhysical()) {
if (MRI->isConstantPhysReg(MO.getReg()) || TII->isIgnorableUse(MO))
continue;
return false;
}

const LiveInterval &li = getInterval(MO.getReg());
const VNInfo *OVNI = li.getVNInfoAt(OrigIdx);
if (!OVNI)
continue;

// Don't allow rematerialization immediately after the original def.
// It would be incorrect if OrigMI redefines the register.
// See PR14098.
if (SlotIndex::isSameInstr(OrigIdx, UseIdx))
return false;

if (OVNI != li.getVNInfoAt(UseIdx))
return false;

// Check that subrange is live at UseIdx.
if (li.hasSubRanges()) {
const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
unsigned SubReg = MO.getSubReg();
LaneBitmask LM = SubReg ? TRI->getSubRegIndexLaneMask(SubReg)
: MRI->getMaxLaneMaskForVReg(MO.getReg());
for (const LiveInterval::SubRange &SR : li.subranges()) {
if ((SR.LaneMask & LM).none())
continue;
if (!SR.liveAt(UseIdx))
return false;
// Early exit if all used lanes are checked. No need to continue.
LM &= ~SR.LaneMask;
if (LM.none())
break;
}
}
}
return true;
}
61 changes: 2 additions & 59 deletions llvm/lib/CodeGen/LiveRangeEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,60 +101,6 @@ bool LiveRangeEdit::anyRematerializable() {
return !Remattable.empty();
}

/// allUsesAvailableAt - Return true if all registers used by OrigMI at
/// OrigIdx are also available with the same value at UseIdx.
bool LiveRangeEdit::allUsesAvailableAt(const MachineInstr *OrigMI,
SlotIndex OrigIdx,
SlotIndex UseIdx) const {
OrigIdx = OrigIdx.getRegSlot(true);
UseIdx = std::max(UseIdx, UseIdx.getRegSlot(true));
for (const MachineOperand &MO : OrigMI->operands()) {
if (!MO.isReg() || !MO.getReg() || !MO.readsReg())
continue;

// We can't remat physreg uses, unless it is a constant or target wants
// to ignore this use.
if (MO.getReg().isPhysical()) {
if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))
continue;
return false;
}

LiveInterval &li = LIS.getInterval(MO.getReg());
const VNInfo *OVNI = li.getVNInfoAt(OrigIdx);
if (!OVNI)
continue;

// Don't allow rematerialization immediately after the original def.
// It would be incorrect if OrigMI redefines the register.
// See PR14098.
if (SlotIndex::isSameInstr(OrigIdx, UseIdx))
return false;

if (OVNI != li.getVNInfoAt(UseIdx))
return false;

// Check that subrange is live at UseIdx.
if (li.hasSubRanges()) {
const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
unsigned SubReg = MO.getSubReg();
LaneBitmask LM = SubReg ? TRI->getSubRegIndexLaneMask(SubReg)
: MRI.getMaxLaneMaskForVReg(MO.getReg());
for (LiveInterval::SubRange &SR : li.subranges()) {
if ((SR.LaneMask & LM).none())
continue;
if (!SR.liveAt(UseIdx))
return false;
// Early exit if all used lanes are checked. No need to continue.
LM &= ~SR.LaneMask;
if (LM.none())
break;
}
}
}
return true;
}

bool LiveRangeEdit::canRematerializeAt(Remat &RM, VNInfo *OrigVNI,
SlotIndex UseIdx) {
assert(ScannedRemattable && "Call anyRematerializable first");
Expand All @@ -164,12 +110,10 @@ bool LiveRangeEdit::canRematerializeAt(Remat &RM, VNInfo *OrigVNI,
return false;

// No defining instruction provided.
SlotIndex DefIdx;
assert(RM.OrigMI && "No defining instruction for remattable value");
DefIdx = LIS.getInstructionIndex(*RM.OrigMI);

// Verify that all used registers are available with the same values.
if (!allUsesAvailableAt(RM.OrigMI, DefIdx, UseIdx))
if (!LIS.allUsesAvailableAt(*RM.OrigMI, UseIdx))
return false;

return true;
Expand Down Expand Up @@ -230,8 +174,7 @@ bool LiveRangeEdit::foldAsLoad(LiveInterval *LI,

// Since we're moving the DefMI load, make sure we're not extending any live
// ranges.
if (!allUsesAvailableAt(DefMI, LIS.getInstructionIndex(*DefMI),
LIS.getInstructionIndex(*UseMI)))
if (!LIS.allUsesAvailableAt(*DefMI, LIS.getInstructionIndex(*UseMI)))
return false;

// We also need to make sure it is safe to move the load.
Expand Down
Loading
Loading