summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/VirtRegMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/VirtRegMap.cpp')
-rw-r--r--llvm/lib/CodeGen/VirtRegMap.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/VirtRegMap.cpp b/llvm/lib/CodeGen/VirtRegMap.cpp
index 46253b1743d9..26a12512c87b 100644
--- a/llvm/lib/CodeGen/VirtRegMap.cpp
+++ b/llvm/lib/CodeGen/VirtRegMap.cpp
@@ -21,6 +21,7 @@
#include "llvm/CodeGen/LiveDebugVariables.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/LiveRegMatrix.h"
#include "llvm/CodeGen/LiveStacks.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -203,6 +204,7 @@ class VirtRegRewriter : public MachineFunctionPass {
MachineRegisterInfo *MRI = nullptr;
SlotIndexes *Indexes = nullptr;
LiveIntervals *LIS = nullptr;
+ LiveRegMatrix *LRM = nullptr;
VirtRegMap *VRM = nullptr;
LiveDebugVariables *DebugVars = nullptr;
DenseSet<Register> RewriteRegs;
@@ -215,6 +217,9 @@ class VirtRegRewriter : public MachineFunctionPass {
void handleIdentityCopy(MachineInstr &MI);
void expandCopyBundle(MachineInstr &MI) const;
bool subRegLiveThrough(const MachineInstr &MI, MCRegister SuperPhysReg) const;
+ LaneBitmask liveOutUndefPhiLanesForUndefSubregDef(
+ const LiveInterval &LI, const MachineBasicBlock &MBB, unsigned SubReg,
+ MCPhysReg PhysReg, const MachineInstr &MI) const;
public:
static char ID;
@@ -247,6 +252,7 @@ INITIALIZE_PASS_BEGIN(VirtRegRewriter, "virtregrewriter",
INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LiveDebugVariables)
+INITIALIZE_PASS_DEPENDENCY(LiveRegMatrixWrapperLegacy)
INITIALIZE_PASS_DEPENDENCY(LiveStacks)
INITIALIZE_PASS_DEPENDENCY(VirtRegMapWrapperLegacy)
INITIALIZE_PASS_END(VirtRegRewriter, "virtregrewriter",
@@ -262,6 +268,7 @@ void VirtRegRewriter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
AU.addRequired<VirtRegMapWrapperLegacy>();
+ AU.addRequired<LiveRegMatrixWrapperLegacy>();
if (!ClearVirtRegs)
AU.addPreserved<LiveDebugVariables>();
@@ -276,6 +283,7 @@ bool VirtRegRewriter::runOnMachineFunction(MachineFunction &fn) {
MRI = &MF->getRegInfo();
Indexes = &getAnalysis<SlotIndexesWrapperPass>().getSI();
LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS();
+ LRM = &getAnalysis<LiveRegMatrixWrapperLegacy>().getLRM();
VRM = &getAnalysis<VirtRegMapWrapperLegacy>().getVRM();
DebugVars = &getAnalysis<LiveDebugVariables>();
LLVM_DEBUG(dbgs() << "********** REWRITE VIRTUAL REGISTERS **********\n"
@@ -548,6 +556,40 @@ bool VirtRegRewriter::subRegLiveThrough(const MachineInstr &MI,
return false;
}
+/// Compute a lanemask for undef lanes which need to be preserved out of the
+/// defining block for a register assignment for a subregister def. \p PhysReg
+/// is assigned to \p LI, which is the main range.
+LaneBitmask VirtRegRewriter::liveOutUndefPhiLanesForUndefSubregDef(
+ const LiveInterval &LI, const MachineBasicBlock &MBB, unsigned SubReg,
+ MCPhysReg PhysReg, const MachineInstr &MI) const {
+ LaneBitmask UndefMask = ~TRI->getSubRegIndexLaneMask(SubReg);
+ LaneBitmask LiveOutUndefLanes;
+
+ for (const LiveInterval::SubRange &SR : LI.subranges()) {
+ // Figure out which lanes are undef live into a successor.
+ LaneBitmask NeedImpDefLanes = UndefMask & SR.LaneMask;
+ if (NeedImpDefLanes.any() && !LIS->isLiveOutOfMBB(SR, &MBB)) {
+ for (const MachineBasicBlock *Succ : MBB.successors()) {
+ if (LIS->isLiveInToMBB(SR, Succ))
+ LiveOutUndefLanes |= NeedImpDefLanes;
+ }
+ }
+ }
+
+ SlotIndex MIIndex = LIS->getInstructionIndex(MI);
+ SlotIndex BeforeMIUses = MIIndex.getBaseIndex();
+ LaneBitmask InterferingLanes =
+ LRM->checkInterferenceLanes(BeforeMIUses, MIIndex.getRegSlot(), PhysReg);
+ LiveOutUndefLanes &= ~InterferingLanes;
+
+ LLVM_DEBUG(if (LiveOutUndefLanes.any()) {
+ dbgs() << "Need live out undef defs for " << printReg(PhysReg)
+ << LiveOutUndefLanes << " from " << printMBBReference(MBB) << '\n';
+ });
+
+ return LiveOutUndefLanes;
+}
+
void VirtRegRewriter::rewrite() {
bool NoSubRegLiveness = !MRI->subRegLivenessEnabled();
SmallVector<Register, 8> SuperDeads;
@@ -602,6 +644,32 @@ void VirtRegRewriter::rewrite() {
MO.setIsUndef(true);
} else if (!MO.isDead()) {
assert(MO.isDef());
+ if (MO.isUndef()) {
+ const LiveInterval &LI = LIS->getInterval(VirtReg);
+
+ LaneBitmask LiveOutUndefLanes =
+ liveOutUndefPhiLanesForUndefSubregDef(LI, *MBBI, SubReg,
+ PhysReg, MI);
+ if (LiveOutUndefLanes.any()) {
+ SmallVector<unsigned, 16> CoveringIndexes;
+
+ // TODO: Just use one super register def if none of the lanes
+ // are needed?
+ if (!TRI->getCoveringSubRegIndexes(
+ *MRI, MRI->getRegClass(VirtReg), LiveOutUndefLanes,
+ CoveringIndexes))
+ llvm_unreachable(
+ "cannot represent required subregister defs");
+
+ // Try to represent the minimum needed live out def as a
+ // sequence of subregister defs.
+ //
+ // FIXME: It would be better if we could directly represent
+ // liveness with a lanemask instead of spamming operands.
+ for (unsigned SubIdx : CoveringIndexes)
+ SuperDefs.push_back(TRI->getSubReg(PhysReg, SubIdx));
+ }
+ }
}
}