diff options
-rw-r--r-- | include/llvm/CodeGen/LiveIntervalAnalysis.h | 144 | ||||
-rw-r--r-- | include/llvm/CodeGen/Passes.h | 5 | ||||
-rw-r--r-- | include/llvm/CodeGen/SimpleRegisterCoalescing.h | 160 | ||||
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 1058 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocLinearScan.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/SimpleRegisterCoalescing.cpp | 1138 |
6 files changed, 1337 insertions, 1169 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 10f60f4f05..4783df40bd 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -44,7 +44,7 @@ namespace llvm { /// MBB2IdxMap - The index of the first instruction in the specified basic /// block. std::vector<unsigned> MBB2IdxMap; - + typedef std::map<MachineInstr*, unsigned> Mi2IndexMap; Mi2IndexMap mi2iMap_; @@ -54,31 +54,12 @@ namespace llvm { typedef std::map<unsigned, LiveInterval> Reg2IntervalMap; Reg2IntervalMap r2iMap_; - typedef IndexedMap<unsigned> Reg2RegMap; - Reg2RegMap r2rMap_; - BitVector allocatableRegs_; - DenseMap<const TargetRegisterClass*, BitVector> allocatableRCRegs_; - - /// JoinedLIs - Keep track which register intervals have been coalesced - /// with other intervals. - BitVector JoinedLIs; public: static char ID; // Pass identification, replacement for typeid LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {} - struct CopyRec { - MachineInstr *MI; - unsigned SrcReg, DstReg; - }; - CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) { - CopyRec R; - R.MI = MI; - R.SrcReg = SrcReg; - R.DstReg = DstReg; - return R; - } struct InstrSlots { enum { LOAD = 0, @@ -158,29 +139,31 @@ namespace llvm { "index does not correspond to an instruction"); return i2miMap_[index]; } - - std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i, - VirtRegMap& vrm, - int slot); + + // Interval creation + + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); + 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<LiveRange> &LRs); - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - virtual void releaseMemory(); + std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i, + VirtRegMap& vrm, + int slot); - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); + // Interval removal - /// print - Implement the dump method. - virtual void print(std::ostream &O, const Module* = 0) const; - void print(std::ostream *O, const Module* M = 0) const { - if (O) print(*O, M); + void removeInterval(unsigned Reg) { + r2iMap_.erase(Reg); } - private: /// isRemoved - returns true if the specified machine instr has been /// removed. bool isRemoved(MachineInstr* instr) const { @@ -198,40 +181,22 @@ namespace llvm { mi2iMap_.erase(mi2i); } } - + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: /// computeIntervals - Compute live intervals. void computeIntervals(); - - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// CopyCoallesceInMBB - Coallsece copies in the specified MBB, putting - /// copies that cannot yet be coallesced into the "TryAgain" list. - void CopyCoallesceInMBB(MachineBasicBlock *MBB, - std::vector<CopyRec> *TryAgain, bool PhysOnly = false); - - /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, - /// which are the src/dst of the copy instruction CopyMI. This returns true - /// if the copy was successfully coallesced away, or if it is never possible - /// to coallesce these this copy, due to register constraints. It returns - /// false if it is not currently possible to coallesce this interval, but - /// it may be possible if other things get coallesced. - bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg, - bool PhysOnly = false); - - /// JoinIntervals - Attempt to join these two intervals. On failure, this - /// returns false. Otherwise, if one of the intervals being joined is a - /// physreg, this method always canonicalizes DestInt to be it. The output - /// "SrcInt" will not have been modified, so we can use this information - /// below to update aliases. - bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); - - /// SimpleJoin - Attempt to join the specified interval into this one. The - /// caller of this method must guarantee that the RHS only contains a single - /// value number and that the RHS is not defined by a copy from this - /// interval. This returns false if the intervals are not joinable, or it - /// joins them and returns true. - bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); /// handleRegisterDef - update intervals for a register def /// (calls handlePhysicalRegisterDef and @@ -260,57 +225,8 @@ namespace llvm { unsigned MIIdx, LiveInterval &interval, bool isAlias = false); - /// Return true if the two specified registers belong to different - /// register classes. The registers may be either phys or virt regs. - bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; - - - bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, - MachineInstr *CopyMI); - - /// lastRegisterUse - Returns the last use of the specific register between - /// cycles Start and End. It also returns the use operand by reference. It - /// returns NULL if there are no uses. - MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, - MachineOperand *&MOU); - - /// findDefOperand - Returns the MachineOperand that is a def of the specific - /// register. It returns NULL if the def is not found. - MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); - - /// unsetRegisterKill - Unset IsKill property of all uses of the specific - /// register of the specific instruction. - void unsetRegisterKill(MachineInstr *MI, unsigned Reg); - - /// unsetRegisterKills - Unset IsKill property of all uses of specific register - /// between cycles Start and End. - void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg); - - /// hasRegisterDef - True if the instruction defines the specific register. - /// - bool hasRegisterDef(MachineInstr *MI, unsigned Reg); - static LiveInterval createInterval(unsigned Reg); - void removeInterval(unsigned Reg) { - r2iMap_.erase(Reg); - } - - LiveInterval &getOrCreateInterval(unsigned reg) { - Reg2IntervalMap::iterator I = r2iMap_.find(reg); - if (I == r2iMap_.end()) - I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); - return I->second; - } - - /// rep - returns the representative of this register - unsigned rep(unsigned Reg) { - unsigned Rep = r2rMap_[Reg]; - if (Rep) - return r2rMap_[Reg] = rep(Rep); - return Reg; - } - void printRegName(unsigned reg) const; }; diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index e7a97cf6bd..88d51aaefd 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -44,6 +44,11 @@ namespace llvm { /// extern const PassInfo *PHIEliminationID; + /// SimpleRegisterCoalescing pass. Aggressively coalesces every register + /// copy it can. + /// + extern const PassInfo *SimpleRegisterCoalescingID; + /// TwoAddressInstruction pass - This pass reduces two-address instructions to /// use two operands. This destroys SSA information but it is desired by /// register allocators. diff --git a/include/llvm/CodeGen/SimpleRegisterCoalescing.h b/include/llvm/CodeGen/SimpleRegisterCoalescing.h new file mode 100644 index 0000000000..0e3d169992 --- /dev/null +++ b/include/llvm/CodeGen/SimpleRegisterCoalescing.h @@ -0,0 +1,160 @@ +//===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple register copy coalescing phase. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H +#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/IndexedMap.h" + +namespace llvm { + + class LiveVariables; + class MRegisterInfo; + class TargetInstrInfo; + class VirtRegMap; + + class SimpleRegisterCoalescing : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveVariables *lv_; + + typedef IndexedMap<unsigned> Reg2RegMap; + Reg2RegMap r2rMap_; + + BitVector allocatableRegs_; + DenseMap<const TargetRegisterClass*, BitVector> allocatableRCRegs_; + + /// JoinedLIs - Keep track which register intervals have been coalesced + /// with other intervals. + BitVector JoinedLIs; + + public: + static char ID; // Pass identifcation, replacement for typeid + SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {}; + + struct CopyRec { + MachineInstr *MI; + unsigned SrcReg, DstReg; + }; + CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) { + CopyRec R; + R.MI = MI; + R.SrcReg = SrcReg; + R.DstReg = DstReg; + return R; + } + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + }; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoallesceInMBB - Coallsece copies in the specified MBB, putting + /// copies that cannot yet be coallesced into the "TryAgain" list. + void CopyCoallesceInMBB(MachineBasicBlock *MBB, + std::vector<CopyRec> *TryAgain, bool PhysOnly = false); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coallesced away, or if it is never possible + /// to coallesce these this copy, due to register constraints. It returns + /// false if it is not currently possible to coallesce this interval, but + /// it may be possible if other things get coallesced. + bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg, + bool PhysOnly = false); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. Otherwise, if one of the intervals being joined is a + /// physreg, this method always canonicalizes DestInt to be it. The output + /// "SrcInt" will not have been modified, so we can use this information + /// below to update aliases. + bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); + + /// SimpleJoin - Attempt to join the specified interval into this one. The + /// caller of this method must guarantee that the RHS only contains a single + /// value number and that the RHS is not defined by a copy from this + /// interval. This returns false if the intervals are not joinable, or it + /// joins them and returns true. + bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); + + /// Return true if the two specified registers belong to different + /// register classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + + bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, + MachineInstr *CopyMI); + + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End. It also returns the use operand by reference. It + /// returns NULL if there are no uses. + MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, + MachineOperand *&MOU); + + /// findDefOperand - Returns the MachineOperand that is a def of the specific + /// register. It returns NULL if the def is not found. + MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); + + /// unsetRegisterKill - Unset IsKill property of all uses of the specific + /// register of the specific instruction. + void unsetRegisterKill(MachineInstr *MI, unsigned Reg); + + /// unsetRegisterKills - Unset IsKill property of all uses of specific register + /// between cycles Start and End. + void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg); + + /// hasRegisterDef - True if the instruction defines the specific register. + /// + bool hasRegisterDef(MachineInstr *MI, unsigned Reg); + + /// rep - returns the representative of this register + unsigned rep(unsigned Reg) { + unsigned Rep = r2rMap_[Reg]; + if (Rep) + return r2rMap_[Reg] = rep(Rep); + return Reg; + } + + void printRegName(unsigned reg) const; + }; + +} // End llvm namespace + +#endif diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 00c212d4b8..eadd47b009 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -39,22 +39,15 @@ using namespace llvm; STATISTIC(numIntervals, "Number of original intervals"); STATISTIC(numIntervalsAfter, "Number of intervals after coalescing"); -STATISTIC(numJoins , "Number of interval joins performed"); -STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); STATISTIC(numFolded , "Number of loads/stores folded into instructions"); -STATISTIC(numAborts , "Number of times interval joining aborted"); char LiveIntervals::ID = 0; namespace { RegisterPass<LiveIntervals> X("liveintervals", "Live Interval Analysis"); - - static cl::opt<bool> - EnableJoining("join-liveintervals", - cl::desc("Coallesce copies (default=true)"), - cl::init(true)); } void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved<LiveVariables>(); AU.addRequired<LiveVariables>(); AU.addPreservedID(PHIEliminationID); AU.addRequiredID(PHIEliminationID); @@ -67,20 +60,8 @@ void LiveIntervals::releaseMemory() { mi2iMap_.clear(); i2miMap_.clear(); r2iMap_.clear(); - r2rMap_.clear(); - JoinedLIs.clear(); -} - - -static bool isZeroLengthInterval(LiveInterval *li) { - for (LiveInterval::Ranges::const_iterator - i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) - if (i->end - i->start > LiveIntervals::InstrSlots::NUM) - return false; - return true; } - /// runOnMachineFunction - Register allocate the whole function /// bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { @@ -89,11 +70,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { mri_ = tm_->getRegisterInfo(); tii_ = tm_->getInstrInfo(); lv_ = &getAnalysis<LiveVariables>(); - r2rMap_.grow(mf_->getSSARegMap()->getLastVirtReg()); allocatableRegs_ = mri_->getAllocatableSet(fn); - for (MRegisterInfo::regclass_iterator I = mri_->regclass_begin(), - E = mri_->regclass_end(); I != E; ++I) - allocatableRCRegs_.insert(std::make_pair(*I,mri_->getAllocatableSet(fn, *I))); // Number MachineInstrs and MachineBasicBlocks. // Initialize MBB indexes to a sentinal. @@ -124,99 +101,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { DOUT << "\n"; } - // Join (coallesce) intervals if requested. - if (EnableJoining) { - joinIntervals(); - DOUT << "********** INTERVALS POST JOINING **********\n"; - for (iterator I = begin(), E = end(); I != E; ++I) { - I->second.print(DOUT, mri_); - DOUT << "\n"; - } - } - numIntervalsAfter += getNumIntervals(); - - // perform a final pass over the instructions and compute spill - // weights, coalesce virtual registers and remove identity moves. - const LoopInfo &loopInfo = getAnalysis<LoopInfo>(); - - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); - mbbi != mbbe; ++mbbi) { - MachineBasicBlock* mbb = mbbi; - unsigned loopDepth = loopInfo.getLoopDepth(mbb->getBasicBlock()); - - for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); - mii != mie; ) { - // if the move will be an identity move delete it - unsigned srcReg, dstReg, RegRep; - if (tii_->isMoveInstr(*mii, srcReg, dstReg) && - (RegRep = rep(srcReg)) == rep(dstReg)) { - // remove from def list - LiveInterval &RegInt = getOrCreateInterval(RegRep); - MachineOperand *MO = mii->findRegisterDefOperand(dstReg); - // If def of this move instruction is dead, remove its live range from - // the dstination register's live interval. - if (MO->isDead()) { - unsigned MoveIdx = getDefIndex(getInstructionIndex(mii)); - LiveInterval::iterator MLR = RegInt.FindLiveRangeContaining(MoveIdx); - RegInt.removeRange(MLR->start, MoveIdx+1); - if (RegInt.empty()) - removeInterval(RegRep); - } - RemoveMachineInstrFromMaps(mii); - mii = mbbi->erase(mii); - ++numPeep; - } else { - SmallSet<unsigned, 4> UniqueUses; - for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) { - const MachineOperand &mop = mii->getOperand(i); - if (mop.isRegister() && mop.getReg() && - MRegisterInfo::isVirtualRegister(mop.getReg())) { - // replace register with representative register - unsigned reg = rep(mop.getReg()); - mii->getOperand(i).setReg(reg); - - // Multiple uses of reg by the same instruction. It should not - // contribute to spill weight again. - if (UniqueUses.count(reg) != 0) - continue; - LiveInterval &RegInt = getInterval(reg); - float w = (mop.isUse()+mop.isDef()) * powf(10.0F, (float)loopDepth); - // If the definition instruction is re-materializable, its spill - // weight is half of what it would have been normally unless it's - // a load from fixed stack slot. - int Dummy; - if (RegInt.remat && !tii_->isLoadFromStackSlot(RegInt.remat, Dummy)) - w /= 2; - RegInt.weight += w; - UniqueUses.insert(reg); - } - } - ++mii; - } - } - } - - for (iterator I = begin(), E = end(); I != E; ++I) { - LiveInterval &LI = I->second; - if (MRegisterInfo::isVirtualRegister(LI.reg)) { - // If the live interval length is essentially zero, i.e. in every live - // range the use follows def immediately, it doesn't make sense to spill - // it and hope it will be easier to allocate for this li. - if (isZeroLengthInterval(&LI)) - LI.weight = HUGE_VALF; - - // Slightly prefer live interval that has been assigned a preferred reg. - if (LI.preference) - LI.weight *= 1.01F; - - // Divide the weight of the interval by its size. This encourages - // spilling of intervals that are large and have few uses, and - // discourages spilling of small intervals with many uses. - LI.weight /= LI.getSize(); - } - } - DEBUG(dump()); return true; } @@ -240,6 +125,7 @@ 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& @@ -268,7 +154,7 @@ LiveIntervals::CreateNewLiveInterval(const LiveInterval *LI, for (unsigned J = 0, e = MI->getNumOperands(); J != e; ++J) { MachineOperand &MOp = MI->getOperand(J); - if (MOp.isRegister() && rep(MOp.getReg()) == LI->reg) + if (MOp.isRegister() && MOp.getReg() == LI->reg) MOp.setReg(NewVReg); } } @@ -794,944 +680,6 @@ void LiveIntervals::computeIntervals() { } } -/// AdjustCopiesBackFrom - We found a non-trivially-coallescable copy with IntA -/// being the source and IntB being the dest, thus this defines a value number -/// in IntB. If the source value number (in IntA) is defined by a copy from B, -/// see if we can merge these two pieces of B into a single value number, -/// eliminating a copy. For example: -/// -/// A3 = B0 -/// ... -/// B1 = A3 <- this copy -/// -/// In this case, B0 can be extended to where the B1 copy lives, allowing the B1 -/// value number to be replaced with B0 (which simplifies the B liveinterval). -/// -/// This returns true if an interval was modified. -/// -bool LiveIntervals::AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, - MachineInstr *CopyMI) { - unsigned CopyIdx = getDefIndex(getInstructionIndex(CopyMI)); - - // BValNo is a value number in B that is defined by a copy from A. 'B3' in - // the example above. - LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx); - unsigned BValNo = BLR->ValId; - - // Get the location that B is defined at. Two options: either this value has - // an unknown definition point or it is defined at CopyIdx. If unknown, we - // can't process it. - unsigned BValNoDefIdx = IntB.getInstForValNum(BValNo); - if (BValNoDefIdx == ~0U) return false; - assert(BValNoDefIdx == CopyIdx && - "Copy doesn't define the value?"); - - // AValNo is the value number in A that defines the copy, A0 in the example. - LiveInterval::iterator AValLR = IntA.FindLiveRangeContaining(CopyIdx-1); - unsigned AValNo = AValLR->ValId; - - // If AValNo is defined as a copy from IntB, we can potentially process this. - - // Get the instruction that defines this value number. - unsigned SrcReg = IntA.getSrcRegForValNum(AValNo); - if (!SrcReg) return false; // Not defined by a copy. - - // If the value number is not defined by a copy instruction, ignore it. - - // If the source register comes from an interval other than IntB, we can't - // handle this. - if (rep(SrcReg) != IntB.reg) return false; - - // Get the LiveRange in IntB that this value number starts with. - unsigned AValNoInstIdx = IntA.getInstForValNum(AValNo); - LiveInterval::iterator ValLR = IntB.FindLiveRangeContaining(AValNoInstIdx-1); - - // Make sure that the end of the live range is inside the same block as - // CopyMI. - MachineInstr *ValLREndInst = getInstructionFromIndex(ValLR->end-1); - if (!ValLREndInst || - ValLREndInst->getParent() != CopyMI->getParent()) return false; - - // Okay, we now know that ValLR ends in the same block that the CopyMI - // live-range starts. If there are no intervening live ranges between them in - // IntB, we can merge them. - if (ValLR+1 != BLR) return false; - - DOUT << "\nExtending: "; IntB.print(DOUT, mri_); - - // We are about to delete CopyMI, so need to remove it as the 'instruction - // that defines this value #'. - IntB.setValueNumberInfo(BValNo, std::make_pair(~0U, 0)); - - // Okay, we can merge them. We need to insert a new liverange: - // [ValLR.end, BLR.begin) of either value number, then we merge the - // two value numbers. - unsigned FillerStart = ValLR->end, FillerEnd = BLR->start; - IntB.addRange(LiveRange(FillerStart, FillerEnd, BValNo)); - - // If the IntB live range is assigned to a physical register, and if that - // physreg has aliases, - if (MRegisterInfo::isPhysicalRegister(IntB.reg)) { - // Update the liveintervals of sub-registers. - for (const unsigned *AS = mri_->getSubRegisters(IntB.reg); *AS; ++AS) { - LiveInterval &AliasLI = getInterval(*AS); - AliasLI.addRange(LiveRange(FillerStart, FillerEnd, - AliasLI.getNextValue(~0U, 0))); - } - } - - // Okay, merge "B1" into the same value number as "B0". - if (BValNo != ValLR->ValId) - IntB.MergeValueNumberInto(BValNo, ValLR->ValId); - DOUT << " result = "; IntB.print(DOUT, mri_); - DOUT << "\n"; - - // If the source instruction was killing the source register before the - // merge, unset the isKill marker given the live range has been extended. - int UIdx = ValLREndInst->findRegisterUseOperandIdx(IntB.reg, true); - if (UIdx != -1) - ValLREndInst->getOperand(UIdx).unsetIsKill(); - - // Finally, delete the copy instruction. - RemoveMachineInstrFromMaps(CopyMI); - CopyMI->eraseFromParent(); - ++numPeep; - return true; -} - - -/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, -/// which are the src/dst of the copy instruction CopyMI. This returns true -/// if the copy was successfully coallesced away, or if it is never possible -/// to coallesce this copy, due to register constraints. It returns -/// false if it is not currently possible to coallesce this interval, but -/// it may be possible if other things get coallesced. -bool LiveIntervals::JoinCopy(MachineInstr *CopyMI, - unsigned SrcReg, unsigned DstReg, bool PhysOnly) { - DOUT << getInstructionIndex(CopyMI) << '\t' << *CopyMI; - - // Get representative registers. - unsigned repSrcReg = rep(SrcReg); - unsigned repDstReg = rep(DstReg); - - // If they are already joined we continue. - if (repSrcReg == repDstReg) { - DOUT << "\tCopy already coallesced.\n"; - return true; // Not coallescable. - } - - bool SrcIsPhys = MRegisterInfo::isPhysicalRegister(repSrcReg); - bool DstIsPhys = MRegisterInfo::isPhysicalRegister(repDstReg); - if (PhysOnly && !SrcIsPhys && !DstIsPhys) - // Only joining physical registers with virtual registers in this round. - return true; - - // If they are both physical registers, we cannot join them. - if (SrcIsPhys && DstIsPhys) { - DOUT << "\tCan not coallesce physregs.\n"; - return true; // Not coallescable. - } - - // We only join virtual registers with allocatable physical registers. - if (SrcIsPhys && !allocatableRegs_[repSrcReg]) { - DOUT << "\tSrc reg is unallocatable physreg.\n"; - return true; // Not coallescable. - } - if (DstIsPhys && !allocatableRegs_[repDstReg]) { - DOUT << "\tDst reg is unallocatable physreg.\n"; - return true; // Not coallescable. - } - - // If they are not of the same register class, we cannot join them. - if (differingRegisterClasses(repSrcReg, repDstReg)) { - DOUT << "\tSrc/Dest are different register classes.\n"; - return true; // Not coallescable. - } - - LiveInterval &SrcInt = getInterval(repSrcReg); - LiveInterval &DstInt = getInterval(repDstReg); - assert(SrcInt.reg == repSrcReg && DstInt.reg == repDstReg && - "Register mapping is horribly broken!"); - - DOUT << "\t\tInspecting "; SrcInt.print(DOUT, mri_); - DOUT << " and "; DstInt.print(DOUT, mri_); - DOUT << ": "; - - // Check if it is necessary to propagate "isDead" property before intervals - // are joined. - MachineOperand *mopd = CopyMI->findRegisterDefOperand(DstReg); - bool isDead = mopd->isDead(); - bool isShorten = false; - unsigned SrcStart = 0, RemoveStart = 0; - unsigned SrcEnd = 0, RemoveEnd = 0; - if (isDead) { - unsigned CopyIdx = getInstructionIndex(CopyMI); - LiveInterval::iterator SrcLR = - SrcInt.FindLiveRangeContaining(getUseIndex(CopyIdx)); - RemoveStart = SrcStart = SrcLR->start; - RemoveEnd = SrcEnd = SrcLR->end; - // The instruction which defines the src is only truly dead if there are - // no intermediate uses and there isn't a use beyond the copy. - // FIXME: find the last use, mark is kill and shorten the live range. - if (SrcEnd > getDefIndex(CopyIdx)) { - isDead = false; - } else { - MachineOperand *MOU; - MachineInstr *LastUse= lastRegisterUse(SrcStart, CopyIdx, repSrcReg, MOU); - if (LastUse) { - // Shorten the liveinterval to the end of last use. - MOU->setIsKill(); - isDead = false; - isShorten = true; - RemoveStart = getDefIndex(getInstructionIndex(LastUse)); - RemoveEnd = SrcEnd; - } else { - MachineInstr *SrcMI = getInstructionFromIndex(SrcStart); - if (SrcMI) { - MachineOperand *mops = findDefOperand(SrcMI, repSrcReg); - if (mops) - // A dead def should have a single cycle interval. - ++RemoveStart; - } - } - } - } - - // We need to be careful about coalescing a source physical register with a - // 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)) { - 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, - // do not join them, instead mark the physical register as its allocation - // preference. - unsigned Length = JoinVInt.getSize() / InstrSlots::NUM; - LiveVariables::VarInfo &vi = lv_->getVarInfo(JoinVReg); - if (Length > Threshold && - (((float)vi.NumUses / Length) < (1.0 / Threshold))) { - JoinVInt.preference = JoinPReg; - ++numAborts; - DOUT << "\tMay tie down a physical register, abort!\n"; - return false; - } - } - - // Okay, attempt to join these two intervals. On failure, this returns false. - // Otherwise, if one of the intervals being joined is a physreg, this method - // always canonicalizes DstInt to be it. The output "SrcInt" will not have - // been modified, so we can use this information below to update aliases. - if (JoinIntervals(DstInt, SrcInt)) { - if (isDead) { - // Result of the copy is dead. Propagate this property. - if (SrcStart == 0) { - assert(MRegisterInfo::isPhysicalRegister(repSrcReg) && - "Live-in must be a physical register!"); - // Live-in to the function but dead. Remove it from entry live-in set. - // JoinIntervals may end up swapping the two intervals. - mf_->begin()->removeLiveIn(repSrcReg); - } else { - MachineInstr *SrcMI = getInstructionFromIndex(SrcStart); - if (SrcMI) { - MachineOperand *mops = findDefOperand(SrcMI, repSrcReg); - if (mops) - mops->setIsDead(); - } - } - } - - if (isShorten || isDead) { - // Shorten the live interval. - LiveInterval &LiveInInt = (repSrcReg == DstInt.reg) ? DstInt : SrcInt; - LiveInInt.removeRange(RemoveStart, RemoveEnd); - } - } else { - // Coallescing failed. - - // If we can eliminate the copy without merging the live ranges, do so now. - if (AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI)) - return true; - - // Otherwise, we are unable to join the intervals. - DOUT << "Interference!\n"; - return false; - } - - bool Swapped = repSrcReg == DstInt.reg; - if (Swapped) - std::swap(repSrcReg, repDstReg); - assert(MRegisterInfo::isVirtualRegister(repSrcReg) && - "LiveInterval::join didn't work right!"); - - // If we're about to merge live ranges into a physical register live range, - // we have to update any aliased register's live ranges to indicate that they - // have clobbered values for this range. - if (MRegisterInfo::isPhysicalRegister(repDstReg)) { - // Unset unnecessary kills. - if (!DstInt.containsOneValue()) { - for (LiveInterval::Ranges::const_iterator I = SrcInt.begin(), - E = SrcInt.end(); I != E; ++I) - unsetRegisterKills(I->start, I->end, repDstReg); - } - - // Update the liveintervals of sub-registers. - for (const unsigned *AS = mri_->getSubRegisters(repDstReg); *AS; ++AS) - getInterval(*AS).MergeInClobberRanges(SrcInt); - } else { - // Merge use info if the destination is a virtual register. - LiveVariables::VarInfo& dVI = lv_->getVarInfo(repDstReg); - LiveVariables::VarInfo& sVI = lv_->getVarInfo(repSrcReg); - dVI.NumUses += sVI.NumUses; - } - - DOUT << "\n\t\tJoined. Result = "; DstInt.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 the intervals were swapped by Join, swap them back so that the register - // mapping (in the r2i map) is correct. - if (Swapped) SrcInt.swap(DstInt); - removeInterval(repSrcReg); - r2rMap_[repSrcReg] = repDstReg; - - // Finally, delete the copy instruction. - RemoveMachineInstrFromMaps(CopyMI); - CopyMI->eraseFromParent(); - ++numPeep; - ++numJoins; - return true; -} - -/// ComputeUltimateVN - Assuming we are going to join two live intervals, -/// compute what the resultant value numbers for each value in the input two -/// ranges will be. This is complicated by copies between the two which can -/// and will commonly cause multiple value numbers to be merged into one. -/// -/// VN is the value number that we're trying to resolve. InstDefiningValue -/// keeps track of the new InstDefiningValue assignment for the result -/// LiveInterval. ThisFromOther/OtherFromThis are sets that keep track of -/// whether a value in this or other is a copy from the opposite set. -/// Th |