From 32dfbeada7292167bb488f36a71a5a6a519ddaff Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Fri, 12 Oct 2007 08:50:34 +0000 Subject: [PATCH] EXTRACT_SUBREG coalescing support. The coalescer now treats EXTRACT_SUBREG like (almost) a register copy. However, it always coalesced to the register of the RHS (the super-register). All uses of the result of a EXTRACT_SUBREG are sub- register uses which adds subtle complications to load folding, spiller rewrite, etc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42899 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/LiveInterval.h | 18 +- include/llvm/CodeGen/LiveIntervalAnalysis.h | 9 +- include/llvm/CodeGen/MachineInstr.h | 4 + include/llvm/CodeGen/SSARegMap.h | 19 ++ .../llvm/CodeGen/SimpleRegisterCoalescing.h | 4 + lib/CodeGen/LiveInterval.cpp | 37 +++ lib/CodeGen/LiveIntervalAnalysis.cpp | 300 ++++++++---------- lib/CodeGen/MachineInstr.cpp | 18 ++ lib/CodeGen/SelectionDAG/ScheduleDAG.cpp | 3 - .../SelectionDAG/ScheduleDAGRRList.cpp | 13 + lib/CodeGen/SimpleRegisterCoalescing.cpp | 123 ++++++- lib/CodeGen/VirtRegMap.cpp | 108 ++++--- 12 files changed, 415 insertions(+), 241 deletions(-) diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 50ac1585903..34e53a9a678 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -155,7 +155,7 @@ namespace llvm { /// copyValNumInfo - Copy the value number info for one value number to /// another. - void copyValNumInfo(VNInfo *DstValNo, VNInfo *SrcValNo) { + void copyValNumInfo(VNInfo *DstValNo, const VNInfo *SrcValNo) { DstValNo->def = SrcValNo->def; DstValNo->reg = SrcValNo->reg; DstValNo->kills = SrcValNo->kills; @@ -241,11 +241,23 @@ namespace llvm { void MergeInClobberRanges(const LiveInterval &Clobbers, BumpPtrAllocator &VNInfoAllocator); - /// MergeRangesInAsValue - Merge all of the intervals in RHS into this live - /// interval as the specified value number. The LiveRanges in RHS are + /// MergeRangesInAsValue - Merge all of the live ranges in RHS into this + /// live interval as the specified value number. The LiveRanges in RHS are /// allowed to overlap with LiveRanges in the current interval, but only if /// the overlapping LiveRanges have the specified value number. void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo); + + /// MergeValueInAsValue - Merge all of the live ranges of a specific val# + /// in RHS into this live interval as the specified value number. + /// The LiveRanges in RHS are allowed to overlap with LiveRanges in the + /// current interval, but only if the overlapping LiveRanges have the + /// specified value number. + void MergeValueInAsValue(const LiveInterval &RHS, + VNInfo *RHSValNo, VNInfo *LHSValNo); + + /// Copy - Copy the specified live interval. This copies all the fields + /// except for the register of the interval. + void Copy(const LiveInterval &RHS, BumpPtrAllocator &VNInfoAllocator); bool empty() const { return ranges.empty(); } diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 671de02eeeb..bf0a8295d5f 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -167,11 +167,6 @@ namespace llvm { return I->second; } - /// CreateNewLiveInterval - Create a new live interval with the given live - /// ranges. The new live interval will have an infinite spill weight. - LiveInterval &CreateNewLiveInterval(const LiveInterval *LI, - const std::vector &LRs); - std::vector addIntervalsForSpills(const LiveInterval& i, VirtRegMap& vrm, unsigned reg); @@ -254,8 +249,8 @@ namespace llvm { /// MI. If it is successul, MI is updated with the newly created MI and /// returns true. bool tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm, - unsigned index, unsigned i, bool isSS, - MachineInstr *DefMI, int slot, unsigned reg); + MachineInstr *DefMI, unsigned index, unsigned i, + bool isSS, int slot, unsigned reg); static LiveInterval createInterval(unsigned Reg); diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 3dbda8dc787..beba6923ee7 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -418,6 +418,10 @@ public: /// none is found. int findFirstPredOperandIdx() const; + /// isRegReDefinedByTwoAddr - Returns true if the Reg re-definition is due + /// to two addr elimination. + bool isRegReDefinedByTwoAddr(unsigned Reg) const; + /// copyKillDeadInfo - Copies kill / dead operand properties from MI. /// void copyKillDeadInfo(const MachineInstr *MI); diff --git a/include/llvm/CodeGen/SSARegMap.h b/include/llvm/CodeGen/SSARegMap.h index 97d8d6988c4..a92222a5c36 100644 --- a/include/llvm/CodeGen/SSARegMap.h +++ b/include/llvm/CodeGen/SSARegMap.h @@ -26,6 +26,7 @@ class TargetRegisterClass; class SSARegMap { IndexedMap RegClassMap; + IndexedMap, VirtReg2IndexFunctor> RegSubIdxMap; unsigned NextRegNum; public: @@ -42,12 +43,30 @@ class SSARegMap { assert(RegClass && "Cannot create register without RegClass!"); RegClassMap.grow(NextRegNum); RegClassMap[NextRegNum] = RegClass; + RegSubIdxMap.grow(NextRegNum); + RegSubIdxMap[NextRegNum] = std::make_pair(0,0); return NextRegNum++; } unsigned getLastVirtReg() const { return NextRegNum - 1; } + + void setIsSubRegister(unsigned Reg, unsigned SuperReg, unsigned SubIdx) { + RegSubIdxMap[Reg] = std::make_pair(SuperReg, SubIdx); + } + + bool isSubRegister(unsigned Reg) const { + return RegSubIdxMap[Reg].first != 0; + } + + unsigned getSuperRegister(unsigned Reg) const { + return RegSubIdxMap[Reg].first; + } + + unsigned getSubRegisterIndex(unsigned Reg) const { + return RegSubIdxMap[Reg].second; + } }; } // End llvm namespace diff --git a/include/llvm/CodeGen/SimpleRegisterCoalescing.h b/include/llvm/CodeGen/SimpleRegisterCoalescing.h index 4e760815b9c..00095dd1761 100644 --- a/include/llvm/CodeGen/SimpleRegisterCoalescing.h +++ b/include/llvm/CodeGen/SimpleRegisterCoalescing.h @@ -47,6 +47,10 @@ namespace llvm { /// with other intervals. BitVector JoinedLIs; + /// SubRegIdxes - Keep track of sub-register and sub-indexes. + /// + std::vector > SubRegIdxes; + public: static char ID; // Pass identifcation, replacement for typeid SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {} diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp index f205d0c5e28..b2f7d7fe13d 100644 --- a/lib/CodeGen/LiveInterval.cpp +++ b/lib/CodeGen/LiveInterval.cpp @@ -383,6 +383,26 @@ void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS, } +/// MergeValueInAsValue - Merge all of the live ranges of a specific val# +/// in RHS into this live interval as the specified value number. +/// The LiveRanges in RHS are allowed to overlap with LiveRanges in the +/// current interval, but only if the overlapping LiveRanges have the +/// specified value number. +void LiveInterval::MergeValueInAsValue(const LiveInterval &RHS, + VNInfo *RHSValNo, VNInfo *LHSValNo) { + // TODO: Make this more efficient. + iterator InsertPos = begin(); + for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { + if (I->valno != RHSValNo) + continue; + // Map the valno in the other live range to the current live range. + LiveRange Tmp = *I; + Tmp.valno = LHSValNo; + InsertPos = addRangeFrom(Tmp, InsertPos); + } +} + + /// MergeInClobberRanges - For any live ranges that are not defined in the /// current interval, but are defined in the Clobbers interval, mark them /// used with an unknown definition value. @@ -485,6 +505,23 @@ void LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) { } } +void LiveInterval::Copy(const LiveInterval &RHS, + BumpPtrAllocator &VNInfoAllocator) { + ranges.clear(); + valnos.clear(); + preference = RHS.preference; + weight = RHS.weight; + for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) { + const VNInfo *VNI = RHS.getValNumInfo(i); + VNInfo *NewVNI = getNextValue(~0U, 0, VNInfoAllocator); + copyValNumInfo(NewVNI, VNI); + } + for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) { + const LiveRange &LR = RHS.ranges[i]; + addRange(LiveRange(LR.start, LR.end, getValNumInfo(LR.valno->id))); + } +} + unsigned LiveInterval::getSize() const { unsigned Sum = 0; for (const_iterator I = begin(), E = end(); I != E; ++I) diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 5ada75ca016..5ed24a3be23 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -136,75 +136,6 @@ void LiveIntervals::print(std::ostream &O, const Module* ) const { } } -// Not called? -/// CreateNewLiveInterval - Create a new live interval with the given live -/// ranges. The new live interval will have an infinite spill weight. -LiveInterval& -LiveIntervals::CreateNewLiveInterval(const LiveInterval *LI, - const std::vector &LRs) { - const TargetRegisterClass *RC = mf_->getSSARegMap()->getRegClass(LI->reg); - - // Create a new virtual register for the spill interval. - unsigned NewVReg = mf_->getSSARegMap()->createVirtualRegister(RC); - - // Replace the old virtual registers in the machine operands with the shiny - // new one. - for (std::vector::const_iterator - I = LRs.begin(), E = LRs.end(); I != E; ++I) { - unsigned Index = getBaseIndex(I->start); - unsigned End = getBaseIndex(I->end - 1) + InstrSlots::NUM; - - for (; Index != End; Index += InstrSlots::NUM) { - // Skip deleted instructions - while (Index != End && !getInstructionFromIndex(Index)) - Index += InstrSlots::NUM; - - if (Index == End) break; - - MachineInstr *MI = getInstructionFromIndex(Index); - - for (unsigned J = 0, e = MI->getNumOperands(); J != e; ++J) { - MachineOperand &MOp = MI->getOperand(J); - if (MOp.isRegister() && MOp.getReg() == LI->reg) - MOp.setReg(NewVReg); - } - } - } - - LiveInterval &NewLI = getOrCreateInterval(NewVReg); - - // The spill weight is now infinity as it cannot be spilled again - NewLI.weight = float(HUGE_VAL); - - for (std::vector::const_iterator - I = LRs.begin(), E = LRs.end(); I != E; ++I) { - DOUT << " Adding live range " << *I << " to new interval\n"; - NewLI.addRange(*I); - } - - DOUT << "Created new live interval " << NewLI << "\n"; - return NewLI; -} - -/// isReDefinedByTwoAddr - Returns true if the Reg re-definition is due to -/// two addr elimination. -static bool isReDefinedByTwoAddr(MachineInstr *MI, unsigned Reg, - const TargetInstrInfo *TII) { - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - MachineOperand &MO1 = MI->getOperand(i); - if (MO1.isRegister() && MO1.isDef() && MO1.getReg() == Reg) { - for (unsigned j = i+1; j < e; ++j) { - MachineOperand &MO2 = MI->getOperand(j); - if (MO2.isRegister() && MO2.isUse() && MO2.getReg() == Reg && - MI->getInstrDescriptor()-> - getOperandConstraint(j, TOI::TIED_TO) == (int)i) - return true; - } - } - } - return false; -} - /// isReMaterializable - Returns true if the definition MI of the specified /// val# of the specified interval is re-materializable. bool LiveIntervals::isReMaterializable(const LiveInterval &li, @@ -232,7 +163,7 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li, continue; // Dead val#. MachineInstr *DefMI = (DefIdx == ~0u) ? NULL : getInstructionFromIndex(DefIdx); - if (DefMI && isReDefinedByTwoAddr(DefMI, li.reg, tii_)) + if (DefMI && DefMI->isRegReDefinedByTwoAddr(li.reg)) return false; } return true; @@ -243,9 +174,9 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li, /// MI. If it is successul, MI is updated with the newly created MI and /// returns true. bool LiveIntervals::tryFoldMemoryOperand(MachineInstr* &MI, VirtRegMap &vrm, + MachineInstr *DefMI, unsigned index, unsigned i, - bool isSS, MachineInstr *DefMI, - int slot, unsigned reg) { + bool isSS, int slot, unsigned reg) { MachineInstr *fmi = isSS ? mri_->foldMemoryOperand(MI, i, slot) : mri_->foldMemoryOperand(MI, i, DefMI); @@ -281,7 +212,8 @@ addIntervalsForSpills(const LiveInterval &li, VirtRegMap &vrm, unsigned reg) { li.print(DOUT, mri_); DOUT << '\n'; - const TargetRegisterClass* rc = mf_->getSSARegMap()->getRegClass(li.reg); + SSARegMap *RegMap = mf_->getSSARegMap(); + const TargetRegisterClass* rc = RegMap->getRegClass(li.reg); unsigned NumValNums = li.getNumValNums(); SmallVector ReMatDefs; @@ -364,113 +296,126 @@ addIntervalsForSpills(const LiveInterval &li, VirtRegMap &vrm, unsigned reg) { RestartInstruction: for (unsigned i = 0; i != MI->getNumOperands(); ++i) { MachineOperand& mop = MI->getOperand(i); - if (mop.isRegister() && mop.getReg() == li.reg) { - if (DefIsReMat) { - // If this is the rematerializable definition MI itself and - // all of its uses are rematerialized, simply delete it. - if (MI == OrigDefMI) { - if (CanDelete) { - RemoveMachineInstrFromMaps(MI); - MI->eraseFromParent(); - break; - } else if (tryFoldMemoryOperand(MI, vrm, index, i, true, - DefMI, slot, li.reg)) { - // Folding the load/store can completely change the instruction - // in unpredictable ways, rescan it from the beginning. - goto RestartInstruction; - } - } else if (isLoad && - tryFoldMemoryOperand(MI, vrm, index, i, isLoadSS, - DefMI, LdSlot, li.reg)) - // Folding the load/store can completely change the - // instruction in unpredictable ways, rescan it from - // the beginning. - goto RestartInstruction; - } else { - if (tryFoldMemoryOperand(MI, vrm, index, i, true, DefMI, - slot, li.reg)) - // Folding the load/store can completely change the instruction in - // unpredictable ways, rescan it from the beginning. - goto RestartInstruction; + if (!mop.isRegister()) + continue; + unsigned Reg = mop.getReg(); + if (Reg == 0 || MRegisterInfo::isPhysicalRegister(Reg)) + continue; + bool isSubReg = RegMap->isSubRegister(Reg); + unsigned SubIdx = 0; + if (isSubReg) { + SubIdx = RegMap->getSubRegisterIndex(Reg); + Reg = RegMap->getSuperRegister(Reg); + } + if (Reg != li.reg) + continue; + + bool TryFold = !DefIsReMat; + bool FoldSS = true; + int FoldSlot = slot; + if (DefIsReMat) { + // If this is the rematerializable definition MI itself and + // all of its uses are rematerialized, simply delete it. + if (MI == OrigDefMI && CanDelete) { + RemoveMachineInstrFromMaps(MI); + MI->eraseFromParent(); + break; } - // Create a new virtual register for the spill interval. - unsigned NewVReg = mf_->getSSARegMap()->createVirtualRegister(rc); + // If def for this use can't be rematerialized, then try folding. + TryFold = !OrigDefMI || (OrigDefMI && (MI == OrigDefMI || isLoad)); + if (isLoad) { + // Try fold loads (from stack slot, constant pool, etc.) into uses. + FoldSS = isLoadSS; + FoldSlot = LdSlot; + } + } + + // FIXME: fold subreg use + if (!isSubReg && TryFold && + tryFoldMemoryOperand(MI, vrm, DefMI, index, i, FoldSS, FoldSlot, Reg)) + // Folding the load/store can completely change the instruction in + // unpredictable ways, rescan it from the beginning. + goto RestartInstruction; + + // Create a new virtual register for the spill interval. + unsigned NewVReg = RegMap->createVirtualRegister(rc); + if (isSubReg) + RegMap->setIsSubRegister(NewVReg, NewVReg, SubIdx); - // Scan all of the operands of this instruction rewriting operands - // to use NewVReg instead of li.reg as appropriate. We do this for - // two reasons: - // - // 1. If the instr reads the same spilled vreg multiple times, we - // want to reuse the NewVReg. - // 2. If the instr is a two-addr instruction, we are required to - // keep the src/dst regs pinned. - // - // Keep track of whether we replace a use and/or def so that we can - // create the spill interval with the appropriate range. - mop.setReg(NewVReg); + // Scan all of the operands of this instruction rewriting operands + // to use NewVReg instead of li.reg as appropriate. We do this for + // two reasons: + // + // 1. If the instr reads the same spilled vreg multiple times, we + // want to reuse the NewVReg. + // 2. If the instr is a two-addr instruction, we are required to + // keep the src/dst regs pinned. + // + // Keep track of whether we replace a use and/or def so that we can + // create the spill interval with the appropriate range. + mop.setReg(NewVReg); - bool HasUse = mop.isUse(); - bool HasDef = mop.isDef(); - for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) { - if (MI->getOperand(j).isRegister() && - MI->getOperand(j).getReg() == li.reg) { - MI->getOperand(j).setReg(NewVReg); - HasUse |= MI->getOperand(j).isUse(); - HasDef |= MI->getOperand(j).isDef(); - } + bool HasUse = mop.isUse(); + bool HasDef = mop.isDef(); + for (unsigned j = i+1, e = MI->getNumOperands(); j != e; ++j) { + if (MI->getOperand(j).isRegister() && + MI->getOperand(j).getReg() == li.reg) { + MI->getOperand(j).setReg(NewVReg); + HasUse |= MI->getOperand(j).isUse(); + HasDef |= MI->getOperand(j).isDef(); } + } - vrm.grow(); - if (DefIsReMat) { - vrm.setVirtIsReMaterialized(NewVReg, DefMI/*, CanDelete*/); - if (ReMatIds[I->valno->id] == VirtRegMap::MAX_STACK_SLOT) { - // Each valnum may have its own remat id. - ReMatIds[I->valno->id] = vrm.assignVirtReMatId(NewVReg); - } else { - vrm.assignVirtReMatId(NewVReg, ReMatIds[I->valno->id]); - } - if (!CanDelete || (HasUse && HasDef)) { - // If this is a two-addr instruction then its use operands are - // rematerializable but its def is not. It should be assigned a - // stack slot. - vrm.assignVirt2StackSlot(NewVReg, slot); - } + vrm.grow(); + if (DefIsReMat) { + vrm.setVirtIsReMaterialized(NewVReg, DefMI/*, CanDelete*/); + if (ReMatIds[I->valno->id] == VirtRegMap::MAX_STACK_SLOT) { + // Each valnum may have its own remat id. + ReMatIds[I->valno->id] = vrm.assignVirtReMatId(NewVReg); } else { + vrm.assignVirtReMatId(NewVReg, ReMatIds[I->valno->id]); + } + if (!CanDelete || (HasUse && HasDef)) { + // If this is a two-addr instruction then its use operands are + // rematerializable but its def is not. It should be assigned a + // stack slot. vrm.assignVirt2StackSlot(NewVReg, slot); } + } else { + vrm.assignVirt2StackSlot(NewVReg, slot); + } - // create a new register interval for this spill / remat. - LiveInterval &nI = getOrCreateInterval(NewVReg); - assert(nI.empty()); + // create a new register interval for this spill / remat. + LiveInterval &nI = getOrCreateInterval(NewVReg); + assert(nI.empty()); - // the spill weight is now infinity as it - // cannot be spilled again - nI.weight = HUGE_VALF; + // the spill weight is now infinity as it + // cannot be spilled again + nI.weight = HUGE_VALF; - if (HasUse) { - LiveRange LR(getLoadIndex(index), getUseIndex(index)+1, - nI.getNextValue(~0U, 0, VNInfoAllocator)); - DOUT << " +" << LR; - nI.addRange(LR); - } - if (HasDef) { - LiveRange LR(getDefIndex(index), getStoreIndex(index), - nI.getNextValue(~0U, 0, VNInfoAllocator)); - DOUT << " +" << LR; - nI.addRange(LR); - } + if (HasUse) { + LiveRange LR(getLoadIndex(index), getUseIndex(index)+1, + nI.getNextValue(~0U, 0, VNInfoAllocator)); + DOUT << " +" << LR; + nI.addRange(LR); + } + if (HasDef) { + LiveRange LR(getDefIndex(index), getStoreIndex(index), + nI.getNextValue(~0U, 0, VNInfoAllocator)); + DOUT << " +" << LR; + nI.addRange(LR); + } - added.push_back(&nI); + added.push_back(&nI); - // update live variables if it is available - if (lv_) - lv_->addVirtualRegisterKilled(NewVReg, MI); + // update live variables if it is available + if (lv_) + lv_->addVirtualRegisterKilled(NewVReg, MI); - DOUT << "\t\t\t\tadded new interval: "; - nI.print(DOUT, mri_); - DOUT << '\n'; - } + DOUT << "\t\t\t\tadded new interval: "; + nI.print(DOUT, mri_); + DOUT << '\n'; } } } @@ -501,10 +446,14 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, unsigned defIndex = getDefIndex(MIIdx); VNInfo *ValNo; unsigned SrcReg, DstReg; - if (!tii_->isMoveInstr(*mi, SrcReg, DstReg)) - ValNo = interval.getNextValue(defIndex, 0, VNInfoAllocator); - else + if (tii_->isMoveInstr(*mi, SrcReg, DstReg)) ValNo = interval.getNextValue(defIndex, SrcReg, VNInfoAllocator); + else if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG || + mi->getOpcode() == TargetInstrInfo::INSERT_SUBREG) + ValNo = interval.getNextValue(defIndex, mi->getOperand(1).getReg(), + VNInfoAllocator); + else + ValNo = interval.getNextValue(defIndex, 0, VNInfoAllocator); assert(ValNo->id == 0 && "First value in interval is not 0?"); @@ -576,7 +525,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, // must be due to phi elimination or two addr elimination. If this is // the result of two address elimination, then the vreg is one of the // def-and-use register operand. - if (isReDefinedByTwoAddr(mi, interval.reg, tii_)) { + if (mi->isRegReDefinedByTwoAddr(interval.reg)) { // If this is a two-address definition, then we have already processed // the live range. The only problem is that we didn't realize there // are actually two values in the live interval. Because of this we @@ -656,10 +605,13 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, VNInfo *ValNo; unsigned SrcReg, DstReg; - if (!tii_->isMoveInstr(*mi, SrcReg, DstReg)) - ValNo = interval.getNextValue(defIndex, 0, VNInfoAllocator); - else + if (tii_->isMoveInstr(*mi, SrcReg, DstReg)) ValNo = interval.getNextValue(defIndex, SrcReg, VNInfoAllocator); + else if (mi->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) + ValNo = interval.getNextValue(defIndex, mi->getOperand(1).getReg(), + VNInfoAllocator); + else + ValNo = interval.getNextValue(defIndex, 0, VNInfoAllocator); unsigned killIndex = getInstructionIndex(&mbb->back()) + InstrSlots::NUM; LiveRange LR(defIndex, killIndex, ValNo); @@ -741,7 +693,9 @@ void LiveIntervals::handleRegisterDef(MachineBasicBlock *MBB, handleVirtualRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(reg)); else if (allocatableRegs_[reg]) { unsigned SrcReg, DstReg; - if (!tii_->isMoveInstr(*MI, SrcReg, DstReg)) + if (MI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) + SrcReg = MI->getOperand(1).getReg(); + else if (!tii_->isMoveInstr(*MI, SrcReg, DstReg)) SrcReg = 0; handlePhysicalRegisterDef(MBB, MI, MIIdx, getOrCreateInterval(reg), SrcReg); // Def of a register also defines its sub-registers. diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 1634c7880e2..1ac955a743c 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -220,6 +220,24 @@ int MachineInstr::findFirstPredOperandIdx() const { return -1; } +/// isRegReDefinedByTwoAddr - Returns true if the Reg re-definition is due +/// to two addr elimination. +bool MachineInstr::isRegReDefinedByTwoAddr(unsigned Reg) const { + const TargetInstrDescriptor *TID = getInstrDescriptor(); + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO1 = getOperand(i); + if (MO1.isRegister() && MO1.isDef() && MO1.getReg() == Reg) { + for (unsigned j = i+1; j < e; ++j) { + const MachineOperand &MO2 = getOperand(j); + if (MO2.isRegister() && MO2.isUse() && MO2.getReg() == Reg && + TID->getOperandConstraint(j, TOI::TIED_TO) == (int)i) + return true; + } + } + } + return false; +} + /// copyKillDeadInfo - Copies kill / dead operand properties from MI. /// void MachineInstr::copyKillDeadInfo(const MachineInstr *MI) { diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp index b616b7e4825..bb5379c3491 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp @@ -567,9 +567,6 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node, // TODO: If the node is a use of a CopyFromReg from a physical register // fold the extract into the copy now - // TODO: Add tracking info to SSARegMap of which vregs are subregs - // to allow coalescing in the allocator - // Create the extract_subreg machine instruction. MachineInstr *MI = new MachineInstr(BB, TII->get(TargetInstrInfo::EXTRACT_SUBREG)); diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp index c1a85096157..2baf24d7d54 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp @@ -1097,6 +1097,11 @@ namespace { // CopyToReg should be close to its uses to facilitate coalescing and // avoid spilling. return 0; + else if (Opc == TargetInstrInfo::EXTRACT_SUBREG || + Opc == TargetInstrInfo::INSERT_SUBREG) + // EXTRACT_SUBREG / INSERT_SUBREG should be close to its use to + // facilitate coalescing. + return 0; else if (SU->NumSuccs == 0) // If SU does not have a use, i.e. it doesn't produce a value that would // be consumed (e.g. store), then it terminates a chain of computation. @@ -1308,6 +1313,14 @@ void BURegReductionPriorityQueue::AddPseudoTwoAddrDeps() { // Be conservative. Ignore if nodes aren't at the same depth. if (SuccSU->Depth != SU->Depth) continue; + if (!SuccSU->Node || !SuccSU->Node->isTargetOpcode()) + continue; + // Don't constraint extract_subreg / insert_subreg these may be + // coalesced away. We don't them close to their uses. + unsigned SuccOpc = SuccSU->Node->getTargetOpcode(); + if (SuccOpc == TargetInstrInfo::EXTRACT_SUBREG || + SuccOpc == TargetInstrInfo::INSERT_SUBREG) + continue; if ((!canClobber(SuccSU, DUSU) || (hasCopyToRegUse(SU) && !hasCopyToRegUse(SuccSU)) || (!SU->isCommutable && SuccSU->isCommutable)) && diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 59e9e4501a2..9d43750f1c6 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -226,11 +226,55 @@ bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, DOUT << "\tDst reg is unallocatable physreg.\n"; return true; // Not coalescable. } - - // If they are not of the same register class, we cannot join them. - if (differingRegisterClasses(repSrcReg, repDstReg)) { + + bool isExtSubReg = CopyMI->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG; + unsigned RealDstReg = 0; + if (isExtSubReg) { + unsigned SubIdx = CopyMI->getOperand(2).getImm(); + if (SrcIsPhys) + // r1024 = EXTRACT_SUBREG EAX, 0 then r1024 is really going to be + // coalesced with AX. + repSrcReg = mri_->getSubReg(repSrcReg, SubIdx); + else if (DstIsPhys) { + // If this is a extract_subreg where dst is a physical register, e.g. + // cl = EXTRACT_SUBREG reg1024, 1 + // then create and update the actual physical register allocated to RHS. + const TargetRegisterClass *RC = mf_->getSSARegMap()->getRegClass(SrcReg); + for (const unsigned *SRs = mri_->getSuperRegisters(repDstReg); + unsigned SR = *SRs; ++SRs) { + if (repDstReg == mri_->getSubReg(SR, SubIdx) && + RC->contains(SR)) { + RealDstReg = SR; + break; + } + } + assert(RealDstReg && "Invalid extra_subreg instruction!"); + + // For this type of EXTRACT_SUBREG, conservatively + // check if the live interval of the source register interfere with the + // actual super physical register we are trying to coalesce with. + LiveInterval &RHS = li_->getInterval(repSrcReg); + if (li_->hasInterval(RealDstReg) && + RHS.overlaps(li_->getInterval(RealDstReg))) { + DOUT << "Interfere with register "; + DEBUG(li_->getInterval(RealDstReg).print(DOUT, mri_)); + return true; // Not coalescable + } + for (const unsigned* SR = mri_->getSubRegisters(RealDstReg); *SR; ++SR) + if (li_->hasInterval(*SR) && RHS.overlaps(li_->getInterval(*SR))) { + DOUT << "Interfere with sub-register "; + DEBUG(li_->getInterval(*SR).print(DOUT, mri_)); + return true; + } + } + } else if (differingRegisterClasses(repSrcReg, repDstReg)) { + // If they are not of the same register class, we cannot join them. DOUT << "\tSrc/Dest are different register classes.\n"; - return true; // Not coalescable. + // Allow the coalescer to try again in case either side gets coalesced to + // a physical register that's compatible with the other side. e.g. + // r1024 = MOV32to32_ r1025 + // but later r1024 is assigned EAX then r1025 may be coalesced with EAX. + return false; } LiveInterval &SrcInt = li_->getInterval(repSrcReg); @@ -286,14 +330,14 @@ bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, // virtual register. Once the coalescing is done, it cannot be broken and // these are not spillable! If the destination interval uses are far away, // think twice about coalescing them! - if (!mopd->isDead() && (SrcIsPhys || DstIsPhys)) { + if (!mopd->isDead() && (SrcIsPhys || DstIsPhys) && !isExtSubReg) { LiveInterval &JoinVInt = SrcIsPhys ? DstInt : SrcInt; unsigned JoinVReg = SrcIsPhys ? repDstReg : repSrcReg; unsigned JoinPReg = SrcIsPhys ? repSrcReg : repDstReg; const TargetRegisterClass *RC = mf_->getSSARegMap()->getRegClass(JoinVReg); unsigned Threshold = allocatableRCRegs_[RC].count(); - // If the virtual register live interval is long has it has low use desity, + // If the virtual register live interval is long but it has low use desity, // do not join them, instead mark the physical register as its allocation // preference. unsigned Length = JoinVInt.getSize() / InstrSlots::NUM; @@ -340,7 +384,7 @@ bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, // Coalescing failed. // If we can eliminate the copy without merging the live ranges, do so now. - if (AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI)) + if (!isExtSubReg && AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI)) return true; // Otherwise, we are unable to join the intervals. @@ -368,9 +412,24 @@ bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, unsetRegisterKills(I->start, I->end, repDstReg); } + // If this is a extract_subreg where dst is a physical register, e.g. + // cl = EXTRACT_SUBREG reg1024, 1 + // then create and update the actual physical register allocated to RHS. + if (RealDstReg) { + unsigned CopyIdx = li_->getInstructionIndex(CopyMI); + VNInfo *DstValNo = + ResDstInt->getLiveRangeContaining(li_->getUseIndex(CopyIdx))->valno; + LiveInterval &RealDstInt = li_->getOrCreateInterval(RealDstReg); + VNInfo *ValNo = RealDstInt.getNextValue(DstValNo->def, DstValNo->reg, + li_->getVNInfoAllocator()); + RealDstInt.addKills(ValNo, DstValNo->kills); + RealDstInt.MergeValueInAsValue(*ResDstInt, DstValNo, ValNo); + repDstReg = RealDstReg; + } + // Update the liveintervals of sub-registers. for (const unsigned *AS = mri_->getSubRegisters(repDstReg); *AS; ++AS) - li_->getInterval(*AS).MergeInClobberRanges(*ResSrcInt, + li_->getOrCreateInterval(*AS).MergeInClobberRanges(*ResSrcInt, li_->getVNInfoAllocator()); } else { // Merge use info if the destination is a virtual register. @@ -379,14 +438,25 @@ bool SimpleRegisterCoalescing::JoinCopy(MachineInstr *CopyMI, dVI.NumUses += sVI.NumUses; } - DOUT << "\n\t\tJoined. Result = "; ResDstInt->print(DOUT, mri_); - DOUT << "\n"; - // Remember these liveintervals have been joined. JoinedLIs.set(repSrcReg - MRegisterInfo::FirstVirtualRegister); if (MRegisterInfo::isVirtualRegister(repDstReg)) JoinedLIs.set(repDstReg - MRegisterInfo::FirstVirtualRegister); + if (isExtSubReg && !SrcIsPhys && !DstIsPhys) { + if (!Swapped) { + // Make sure we allocate the larger super-register. + ResSrcInt->Copy(*ResDstInt, li_->getVNInfoAllocator()); + std::swap(repSrcReg, repDstReg); + std::swap(ResSrcInt, ResDstInt); + } + SubRegIdxes.push_back(std::make_pair(repSrcReg, + CopyMI->getOperand(2).getImm())); + } + + DOUT << "\n\t\tJoined. Result = "; ResDstInt->print(DOUT, mri_); + DOUT << "\n"; + // repSrcReg is guarateed to be the register whose live interval that is // being merged. li_->removeInterval(repSrcReg); @@ -857,9 +927,13 @@ void SimpleRegisterCoalescing::CopyCoalesceInMBB(MachineBasicBlock *MBB, MII != E;) { MachineInstr *Inst = MII++; - // If this isn't a copy, we can't join intervals. + // If this isn't a copy nor a extract_subreg, we can't join intervals. unsigned SrcReg, DstReg; - if (!tii_->isMoveInstr(*Inst, SrcReg, DstReg)) continue; + if (Inst->getOpcode() == TargetInstrInfo::EXTRACT_SUBREG) { + DstReg = Inst->getOperand(0).getReg(); + SrcReg = Inst->getOperand(1).getReg(); + } else if (!tii_->isMoveInstr(*Inst, SrcReg, DstReg)) + continue; bool Done = JoinCopy(Inst, SrcReg, DstReg, PhysOnly); if (TryAgain && !Done) @@ -950,7 +1024,7 @@ void SimpleRegisterCoalescing::joinIntervals() { /// Return true if the two specified registers belong to different register /// classes. The registers may be either phys or virt regs. bool SimpleRegisterCoalescing::differingRegisterClasses(unsigned RegA, - unsigned RegB) const { + unsigned RegB) const { // Get the register classes for the first reg. if (MRegisterInfo::isPhysicalRegister(RegA)) { @@ -1074,6 +1148,7 @@ void SimpleRegisterCoalescing::printRegName(unsigned reg) const { void SimpleRegisterCoalescing::releaseMemory() { r2rMap_.clear(); JoinedLIs.clear(); + SubRegIdxes.clear(); } static bool isZeroLengthInterval(LiveInterval *li) { @@ -1101,7 +1176,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { E = mri_->regclass_end(); I != E; ++I) allocatableRCRegs_.insert(std::make_pair(*I,mri_->getAllocatableSet(fn, *I))); - r2rMap_.grow(mf_->getSSARegMap()->getLastVirtReg()); + SSARegMap *RegMap = mf_->getSSARegMap(); + r2rMap_.grow(RegMap->getLastVirtReg()); // Join (coalesce) intervals if requested. if (EnableJoining) { @@ -1111,6 +1187,13 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { I->second.print(DOUT, mri_); DOUT << "\n"; } + + // Track coalesced sub-registers. + while (!SubRegIdxes.empty()) { + std::pair RI = SubRegIdxes.back(); + SubRegIdxes.pop_back(); + mf_->getSSARegMap()->setIsSubRegister(RI.first, rep(RI.first), RI.second); + } } // perform a final pass over the instructions and compute spill @@ -1150,8 +1233,14 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) { if (mop.isRegister() && mop.getReg() && MRegisterInfo::isVirtualRegister(mop.getReg())) { // replace register with representative register - unsigned reg = rep(mop.getReg()); - mii->getOperand(i).setReg(reg); + unsigned OrigReg = mop.getReg(); + unsigned reg = rep(OrigReg); + // Don't rewrite if it is a sub-register of a virtual register. + if (!RegMap->isSubRegister(OrigReg)) + mii->getOperand(i).setReg(reg); + else if (MRegisterInfo::isPhysicalRegister(reg)) + mii->getOperand(i).setReg(mri_->getSubReg(reg, + RegMap->getSubRegisterIndex(OrigReg))); // Multiple uses of reg by the same instruction. It should not // contribute to spill weight again. diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index c6ac4b208d0..ebdbb86c2bd 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -242,10 +242,12 @@ namespace { /// blocks that have low register pressure (the vreg may be spilled due to /// register pressure in other blocks). class VISIBILITY_HIDDEN LocalSpiller : public Spiller { + SSARegMap *RegMap; const MRegisterInfo *MRI; const TargetInstrInfo *TII; public: bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM) { + RegMap = MF.getSSARegMap(); MRI = MF.getTarget().getRegisterInfo(); TII = MF.getTarget().getInstrInfo(); DOUT << "\n**** Local spiller rewriting function '" @@ -776,25 +778,33 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { if (!MO.isRegister() || MO.getReg() == 0) continue; // Ignore non-register operands. - if (MRegisterInfo::isPhysicalRegister(MO.getReg())) { + unsigned VirtReg = MO.getReg(); + if (MRegisterInfo::isPhysicalRegister(VirtReg)) { // Ignore physregs for spilling, but remember that it is used by this // function. - MF.setPhysRegUsed(MO.getReg()); - ReusedOperands.markClobbered(MO.getReg()); + MF.setPhysRegUsed(VirtReg); + ReusedOperands.markClobbered(VirtReg); continue; } - assert(MRegisterInfo::isVirtualRegister(MO.getReg()) && + assert(MRegisterInfo::isVirtualRegister(VirtReg) && "Not a virtual or a physical register?"); - unsigned VirtReg = MO.getReg(); + unsigned SubIdx = 0; + bool isSubReg = RegMap->isSubRegister(VirtReg); + if (isSubReg) { + SubIdx = RegMap->getSubRegisterIndex(VirtReg); + VirtReg = RegMap->getSuperRegister(VirtReg); + } + if (VRM.isAssignedReg(VirtReg)) { // This virtual register was assigned a physreg! unsigned Phys = VRM.getPhys(VirtReg); MF.setPhysRegUsed(Phys); if (MO.isDef()) ReusedOperands.markClobbered(Phys); - MI.getOperand(i).setReg(Phys); + unsigned RReg = isSubReg ? MRI->getSubReg(Phys, SubIdx) : Phys; + MI.getOperand(i).setReg(RReg); continue; } @@ -817,6 +827,24 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { if (ReuseSlot != VirtRegMap::NO_STACK_SLOT) PhysReg = Spills.getSpillSlotOrReMatPhysReg(ReuseSlot); } + + // If this is a sub-register use, make sure the reuse register is in the + // right register class. For example, for x86 not all of the 32-bit + // registers have accessible sub-registers. + // Similarly so for EXTRACT_SUBREG. Consider this: + // EDI = op + // MOV32_mr fi#1, EDI + // ... + // = EXTRACT_SUBREG fi#1 + // fi#1 is available in EDI, but it cannot be reused because it's not in + // the right register file. + if (PhysReg && + (isSubReg || MI.getOpcode() == TargetInstrInfo::EXTRACT_SUBREG)) { + const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg); + if (!RC->contains(PhysReg)) + PhysReg = 0; + } + if (PhysReg) { // This spilled operand might be part of a two-address operand. If this // is the case, then changing it will necessarily require changing the @@ -824,6 +852,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // aren't allowed to modify the reused register. If none of these cases // apply, reuse it. bool CanReuse = true; + int ti = TID->getOperandConstraint(i, TOI::TIED_TO); if (ti != -1 && MI.getOperand(ti).isRegister() && @@ -845,7 +874,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { << MRI->getName(PhysReg) << " for vreg" << VirtReg <<" instead of reloading into physreg " << MRI->getName(VRM.getPhys(VirtReg)) << "\n"; - MI.getOperand(i).setReg(PhysReg); + unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); // The only technical detail we have is that we don't know that // PhysReg won't be clobbered by a reloaded stack slot that occurs @@ -883,7 +913,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { } } continue; - } + } // CanReuse // Otherwise we have a situation where we have a two-address instruction // whose mod/ref operand needs to be reloaded. This reload is already @@ -917,13 +947,14 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { DOUT << " from physreg " << MRI->getName(PhysReg) << " for vreg" << VirtReg << " instead of reloading into same physreg.\n"; - MI.getOperand(i).setReg(PhysReg); + unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); ReusedOperands.markClobbered(PhysReg); ++NumReused; continue; } - const TargetRegisterClass* RC = MF.getSSARegMap()->getRegClass(VirtReg); + const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg); MF.setPhysRegUsed(DesignatedReg); ReusedOperands.markClobbered(DesignatedReg); MRI->copyRegToReg(MBB, &MI, DesignatedReg, PhysReg, RC, RC); @@ -935,16 +966,17 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { Spills.ClobberPhysReg(DesignatedReg); Spills.addAvailable(ReuseSlot, &MI, DesignatedReg); - MI.getOperand(i).setReg(DesignatedReg); + unsigned RReg = + isSubReg ? MRI->getSubReg(DesignatedReg, SubIdx) : DesignatedReg; + MI.getOperand(i).setReg(RReg); DOUT << '\t' << *prior(MII); ++NumReused; continue; - } + } // is (PhysReg) // Otherwise, reload it and remember that we have it. PhysReg = VRM.getPhys(VirtReg); assert(PhysReg && "Must map virtreg to physreg!"); - const TargetRegisterClass* RC = MF.getSSARegMap()->getRegClass(VirtReg); // Note that, if we reused a register for a previous operand, the // register we want to reload into might not actually be @@ -960,6 +992,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { MRI->reMaterialize(MBB, &MI, PhysReg, VRM.getReMaterializedMI(VirtReg)); ++NumReMats; } else { + const TargetRegisterClass* RC = RegMap->getRegClass(VirtReg); MRI->loadRegFromStackSlot(MBB, &MI, PhysReg, SSorRMId, RC); ++NumLoads; } @@ -974,7 +1007,8 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // unless it's a two-address operand. if (TID->getOperandConstraint(i, TOI::TIED_TO) == -1) MI.getOperand(i).setIsKill(); - MI.getOperand(i).setReg(PhysReg); + unsigned RReg = isSubReg ? MRI->getSubReg(PhysReg, SubIdx) : PhysReg; + MI.getOperand(i).setReg(RReg); UpdateKills(*prior(MII), RegKills, KillOps); DOUT << '\t' << *prior(MII); } @@ -1002,30 +1036,28 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // straight load from the virt reg slot. if ((MR & VirtRegMap::isRef) && !(MR & VirtRegMap::isMod)) { int FrameIdx; - if (unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx)) { - if (FrameIdx == SS) { - // If this spill slot is available, turn it into a copy (or nothing) - // instead of leaving it as a load! - if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) { - DOUT << "Promoted Load To Copy: " << MI; - if (DestReg != InReg) { - const TargetRegisterClass *RC = - MF.getSSARegMap()->getRegClass(VirtReg); - MRI->copyRegToReg(MBB, &MI, DestReg, InReg, RC, RC); - // Revisit the copy so we make sure to notice the effects of the - // operation on the destreg (either needing to RA it if it's - // virtual or needing to clobber any values if it's physical). - NextMII = &MI; - --NextMII; // backtrack to the copy. - BackTracked = true; - } else - DOUT << "Removing now-noop copy: " << MI; + unsigned DestReg = TII->isLoadFromStackSlot(&MI, FrameIdx); + if (DestReg && FrameIdx == SS) { + // If this spill slot is available, turn it into a copy (or nothing) + // instead of leaving it as a load! + if (unsigned InReg = Spills.getSpillSlotOrReMatPhysReg(SS)) { + DOUT << "Promoted Load To Copy: " << MI; + if (DestReg != InReg) { + const TargetRegisterClass *RC = RegMap->getRegClass(VirtReg); + MRI->copyRegToReg(MBB, &MI, DestReg, InReg, RC, RC); + // Revisit the copy so we make sure to notice the effects of the + // operation on the destreg (either needing to RA it if it's + // virtual or needing to clobber any values if it's physical). + NextMII = &MI; + --NextMII; // backtrack to the copy. + BackTracked = true; + } else + DOUT << "Removing now-noop copy: " << MI; - VRM.RemoveFromFoldedVirtMap(&MI); - MBB.erase(&MI); - Erased = true; - goto ProcessNextInst; - } + VRM.RemoveFromFoldedVirtMap(&MI); + MBB.erase(&MI); + Erased = true; + goto ProcessNextInst; } } } @@ -1121,7 +1153,7 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { // The only vregs left are stack slot definitions. int StackSlot = VRM.getStackSlot(VirtReg); - const TargetRegisterClass *RC = MF.getSSARegMap()->getRegClass(VirtReg); + const TargetRegisterClass *RC = RegMap->getRegClass(VirtReg); // If this def is part of a two-address operand, make sure to execute // the store from the correct physical register. -- 2.34.1