diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2009-12-10 17:48:32 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2009-12-10 17:48:32 +0000 |
commit | cf97036675340bc889cfe04295cda63afe9496e2 (patch) | |
tree | 9f44d599aa051eb2bab3ba3780a4e261346be54b /lib | |
parent | f05e45eb373a47054cd569e9bf727f71109be382 (diff) | |
download | external_llvm-cf97036675340bc889cfe04295cda63afe9496e2.zip external_llvm-cf97036675340bc889cfe04295cda63afe9496e2.tar.gz external_llvm-cf97036675340bc889cfe04295cda63afe9496e2.tar.bz2 |
Also attempt trivial coalescing for live intervals that end in a copy.
The coalescer is supposed to clean these up, but when setting up parameters
for a function call, there may be copies to physregs. If the defining
instruction has been LICM'ed far away, the coalescer won't touch it.
The register allocation hint does not always work - when the register
allocator is backtracking, it clears the hints.
This patch is more conservative than r90502, and does not break
483.xalancbmk/i686. It still breaks the PowerPC bootstrap, so it is disabled
by default, and can be enabled with the -trivial-coalesce-ends option.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91049 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 87 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocLinearScan.cpp | 98 |
2 files changed, 111 insertions, 74 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index c16ddc5..4d73b50 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -149,42 +149,69 @@ void LiveIntervals::dumpInstrs() const { printInstrs(errs()); } -/// conflictsWithPhysRegDef - Returns true if the specified register -/// is defined during the duration of the specified interval. -bool LiveIntervals::conflictsWithPhysRegDef(const LiveInterval &li, - VirtRegMap &vrm, unsigned reg) { - for (LiveInterval::Ranges::const_iterator - I = li.ranges.begin(), E = li.ranges.end(); I != E; ++I) { - for (SlotIndex index = I->start.getBaseIndex(), - end = I->end.getPrevSlot().getBaseIndex().getNextIndex(); - index != end; - index = index.getNextIndex()) { - MachineInstr *MI = getInstructionFromIndex(index); - if (!MI) - continue; // skip deleted instructions +bool LiveIntervals::conflictsWithPhysReg(const LiveInterval &li, + VirtRegMap &vrm, unsigned reg) { + // We don't handle fancy stuff crossing basic block boundaries + if (li.ranges.size() != 1) + return true; + const LiveRange &range = li.ranges.front(); + SlotIndex idx = range.start.getBaseIndex(); + SlotIndex end = range.end.getPrevSlot().getBaseIndex().getNextIndex(); + + // Skip deleted instructions + MachineInstr *firstMI = getInstructionFromIndex(idx); + while (!firstMI && idx != end) { + idx = idx.getNextIndex(); + firstMI = getInstructionFromIndex(idx); + } + if (!firstMI) + return false; - unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; - if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg)) - if (SrcReg == li.reg || DstReg == li.reg) - continue; - for (unsigned i = 0; i != MI->getNumOperands(); ++i) { - MachineOperand& mop = MI->getOperand(i); - if (!mop.isReg()) - continue; - unsigned PhysReg = mop.getReg(); - if (PhysReg == 0 || PhysReg == li.reg) + // Find last instruction in range + SlotIndex lastIdx = end.getPrevIndex(); + MachineInstr *lastMI = getInstructionFromIndex(lastIdx); + while (!lastMI && lastIdx != idx) { + lastIdx = lastIdx.getPrevIndex(); + lastMI = getInstructionFromIndex(lastIdx); + } + if (!lastMI) + return false; + + // Range cannot cross basic block boundaries or terminators + MachineBasicBlock *MBB = firstMI->getParent(); + if (MBB != lastMI->getParent() || lastMI->getDesc().isTerminator()) + return true; + + MachineBasicBlock::const_iterator E = lastMI; + ++E; + for (MachineBasicBlock::const_iterator I = firstMI; I != E; ++I) { + const MachineInstr &MI = *I; + + // Allow copies to and from li.reg + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (tii_->isMoveInstr(MI, SrcReg, DstReg, SrcSubReg, DstSubReg)) + if (SrcReg == li.reg || DstReg == li.reg) + continue; + + // Check for operands using reg + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand& mop = MI.getOperand(i); + if (!mop.isReg()) + continue; + unsigned PhysReg = mop.getReg(); + if (PhysReg == 0 || PhysReg == li.reg) + continue; + if (TargetRegisterInfo::isVirtualRegister(PhysReg)) { + if (!vrm.hasPhys(PhysReg)) continue; - if (TargetRegisterInfo::isVirtualRegister(PhysReg)) { - if (!vrm.hasPhys(PhysReg)) - continue; - PhysReg = vrm.getPhys(PhysReg); - } - if (PhysReg && tri_->regsOverlap(PhysReg, reg)) - return true; + PhysReg = vrm.getPhys(PhysReg); } + if (PhysReg && tri_->regsOverlap(PhysReg, reg)) + return true; } } + // No conflicts found. return false; } diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index c1f5875..2a43811 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -59,6 +59,11 @@ PreSplitIntervals("pre-alloc-split", cl::desc("Pre-register allocation live interval splitting"), cl::init(false), cl::Hidden); +static cl::opt<bool> +TrivCoalesceEnds("trivial-coalesce-ends", + cl::desc("Attempt trivial coalescing of interval ends"), + cl::init(false), cl::Hidden); + static RegisterRegAlloc linearscanRegAlloc("linearscan", "linear scan register allocator", createLinearScanRegisterAllocator); @@ -390,66 +395,71 @@ void RALinScan::ComputeRelatedRegClasses() { RelatedRegClasses.unionSets(I->second, OneClassForEachPhysReg[*AS]); } -/// attemptTrivialCoalescing - If a simple interval is defined by a copy, -/// try allocate the definition the same register as the source register -/// if the register is not defined during live time of the interval. This -/// eliminate a copy. This is used to coalesce copies which were not -/// coalesced away before allocation either due to dest and src being in -/// different register classes or because the coalescer was overly -/// conservative. +/// attemptTrivialCoalescing - If a simple interval is defined by a copy, try +/// allocate the definition the same register as the source register if the +/// register is not defined during live time of the interval. If the interval is +/// killed by a copy, try to use the destination register. This eliminates a +/// copy. This is used to coalesce copies which were not coalesced away before +/// allocation either due to dest and src being in different register classes or +/// because the coalescer was overly conservative. unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) { unsigned Preference = vrm_->getRegAllocPref(cur.reg); if ((Preference && Preference == Reg) || !cur.containsOneValue()) return Reg; - VNInfo *vni = cur.begin()->valno; - if ((vni->def == SlotIndex()) || - vni->isUnused() || !vni->isDefAccurate()) + // We cannot handle complicated live ranges. Simple linear stuff only. + if (cur.ranges.size() != 1) return Reg; - MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def); - unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg; - if (!CopyMI || - !tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg)) + + const LiveRange &range = cur.ranges.front(); + + VNInfo *vni = range.valno; + if (vni->isUnused()) return Reg; - PhysReg = SrcReg; - if (TargetRegisterInfo::isVirtualRegister(SrcReg)) { - if (!vrm_->isAssignedReg(SrcReg)) + + unsigned CandReg; + { + MachineInstr *CopyMI; + unsigned SrcReg, DstReg, SrcSubReg, DstSubReg; + if (vni->def != SlotIndex() && vni->isDefAccurate() && + (CopyMI = li_->getInstructionFromIndex(vni->def)) && + tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg)) + // Defined by a copy, try to extend SrcReg forward + CandReg = SrcReg; + else if (TrivCoalesceEnds && + (CopyMI = + li_->getInstructionFromIndex(range.end.getBaseIndex())) && + tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg) && + cur.reg == SrcReg) + // Only used by a copy, try to extend DstReg backwards + CandReg = DstReg; + else return Reg; - PhysReg = vrm_->getPhys(SrcReg); } - if (Reg == PhysReg) + + if (TargetRegisterInfo::isVirtualRegister(CandReg)) { + if (!vrm_->isAssignedReg(CandReg)) + return Reg; + CandReg = vrm_->getPhys(CandReg); + } + if (Reg == CandReg) return Reg; const TargetRegisterClass *RC = mri_->getRegClass(cur.reg); - if (!RC->contains(PhysReg)) + if (!RC->contains(CandReg)) return Reg; - // Try to coalesce. - if (!li_->conflictsWithPhysRegDef(cur, *vrm_, PhysReg)) { - DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(PhysReg) - << '\n'); - vrm_->clearVirt(cur.reg); - vrm_->assignVirt2Phys(cur.reg, PhysReg); - - // Remove unnecessary kills since a copy does not clobber the register. - if (li_->hasInterval(SrcReg)) { - LiveInterval &SrcLI = li_->getInterval(SrcReg); - for (MachineRegisterInfo::use_iterator I = mri_->use_begin(cur.reg), - E = mri_->use_end(); I != E; ++I) { - MachineOperand &O = I.getOperand(); - if (!O.isKill()) - continue; - MachineInstr *MI = &*I; - if (SrcLI.liveAt(li_->getInstructionIndex(MI).getDefIndex())) - O.setIsKill(false); - } - } + if (li_->conflictsWithPhysReg(cur, *vrm_, CandReg)) + return Reg; - ++NumCoalesce; - return PhysReg; - } + // Try to coalesce. + DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg) + << '\n'); + vrm_->clearVirt(cur.reg); + vrm_->assignVirt2Phys(cur.reg, CandReg); - return Reg; + ++NumCoalesce; + return CandReg; } bool RALinScan::runOnMachineFunction(MachineFunction &fn) { |