diff options
Diffstat (limited to 'llvm/lib/CodeGen/VirtRegMap.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/VirtRegMap.cpp | 68 |
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)); + } + } } } |
