diff options
author | Evan Cheng <evan.cheng@apple.com> | 2009-07-01 01:59:31 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2009-07-01 01:59:31 +0000 |
commit | 6521982510e67c23441d94dd4c4a7167527356cb (patch) | |
tree | cff0b3ae5b241d3ad9f268cdf515d8cff4f3aada /lib/CodeGen | |
parent | b10d22209eac7e43d917ef2194e7a159b9b1c689 (diff) | |
download | external_llvm-6521982510e67c23441d94dd4c4a7167527356cb.zip external_llvm-6521982510e67c23441d94dd4c4a7167527356cb.tar.gz external_llvm-6521982510e67c23441d94dd4c4a7167527356cb.tar.bz2 |
Handle IMPLICIT_DEF with isUndef operand marker, part 2. This patch moves the code to annotate machineoperands to LiveIntervalAnalysis. It also add markers for implicit_def that define physical registers. The rest, is just a lot of details.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74580 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/LiveIntervalAnalysis.cpp | 93 | ||||
-rw-r--r-- | lib/CodeGen/RegAllocLinearScan.cpp | 31 | ||||
-rw-r--r-- | lib/CodeGen/RegisterScavenging.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/VirtRegRewriter.cpp | 8 |
4 files changed, 104 insertions, 36 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index b017f91..9339c95 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" @@ -33,6 +34,8 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include <algorithm> @@ -98,6 +101,93 @@ void LiveIntervals::releaseMemory() { } } +/// processImplicitDefs - Process IMPLICIT_DEF instructions and make sure +/// there is one implicit_def for each use. Add isUndef marker to +/// implicit_def defs and their uses. +void LiveIntervals::processImplicitDefs() { + SmallSet<unsigned, 8> ImpDefRegs; + SmallVector<MachineInstr*, 8> ImpDefMIs; + MachineBasicBlock *Entry = mf_->begin(); + SmallPtrSet<MachineBasicBlock*,16> Visited; + for (df_ext_iterator<MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*,16> > + DFI = df_ext_begin(Entry, Visited), E = df_ext_end(Entry, Visited); + DFI != E; ++DFI) { + MachineBasicBlock *MBB = *DFI; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ) { + MachineInstr *MI = &*I; + ++I; + if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) { + unsigned Reg = MI->getOperand(0).getReg(); + MI->getOperand(0).setIsUndef(); + ImpDefRegs.insert(Reg); + ImpDefMIs.push_back(MI); + continue; + } + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (!ImpDefRegs.count(Reg)) + continue; + MO.setIsUndef(); + if (MO.isKill() || MI->isRegTiedToDefOperand(i)) + ImpDefRegs.erase(Reg); + } + + for (unsigned i = 0; i != MI->getNumOperands(); ++i) { + MachineOperand& MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + ImpDefRegs.erase(MO.getReg()); + } + } + + // Any outstanding liveout implicit_def's? + for (unsigned i = 0, e = ImpDefMIs.size(); i != e; ++i) { + MachineInstr *MI = ImpDefMIs[i]; + unsigned Reg = MI->getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(Reg)) + // Physical registers are not liveout (yet). + continue; + if (!ImpDefRegs.count(Reg)) + continue; + bool HasLocalUse = false; + for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(Reg), + RE = mri_->reg_end(); RI != RE; ) { + MachineOperand &RMO = RI.getOperand(); + MachineInstr *RMI = &*RI; + ++RI; + if (RMO.isDef()) { + // Don't expect another def of the same register. + assert(RMI == MI && + "Register with multiple defs including an implicit_def?"); + continue; + } + MachineBasicBlock *RMBB = RMI->getParent(); + if (RMBB == MBB) { + HasLocalUse = true; + continue; + } + const TargetRegisterClass* RC = mri_->getRegClass(Reg); + unsigned NewVReg = mri_->createVirtualRegister(RC); + BuildMI(*RMBB, RMI, RMI->getDebugLoc(), + tii_->get(TargetInstrInfo::IMPLICIT_DEF), NewVReg); + RMO.setReg(NewVReg); + RMO.setIsUndef(); + RMO.setIsKill(); + } + if (!HasLocalUse) + MI->eraseFromParent(); + } + ImpDefRegs.clear(); + ImpDefMIs.clear(); + } +} + void LiveIntervals::computeNumbering() { Index2MiMap OldI2MI = i2miMap_; std::vector<IdxMBBPair> OldI2MBB = Idx2MBBMap; @@ -299,6 +389,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { lv_ = &getAnalysis<LiveVariables>(); allocatableRegs_ = tri_->getAllocatableSet(fn); + processImplicitDefs(); computeNumbering(); computeIntervals(); @@ -1785,8 +1876,6 @@ LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, if (MO.isReg() && MO.getReg() == li.reg) { MO.setReg(NewVReg); MO.setIsUndef(); - if (MO.isKill()) - MO.setIsKill(false); } } } diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 2caa2f9..904b4cb 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -545,26 +545,6 @@ void RALinScan::linearScan() if (!isPhys && vrm_->getPreSplitReg(cur.reg)) continue; - // A register defined by an implicit_def can be liveout the def BB and livein - // to a use BB. Add it to the livein set of the use BB's. - if (!isPhys && cur.empty()) { - if (MachineInstr *DefMI = mri_->getVRegDef(cur.reg)) { - assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF); - MachineBasicBlock *DefMBB = DefMI->getParent(); - SmallPtrSet<MachineBasicBlock*, 4> Seen; - Seen.insert(DefMBB); - for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(cur.reg), - re = mri_->reg_end(); ri != re; ++ri) { - MachineInstr *UseMI = &*ri; - MachineBasicBlock *UseMBB = UseMI->getParent(); - if (Seen.insert(UseMBB)) { - assert(TargetRegisterInfo::isPhysicalRegister(Reg) && - "Adding a virtual register to livein set?"); - UseMBB->addLiveIn(Reg); - } - } - } - } for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end(); I != E; ++I) { const LiveRange &LR = *I; @@ -905,17 +885,6 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) DOUT << tri_->getName(physReg) << '\n'; // Note the register is not really in use. vrm_->assignVirt2Phys(cur->reg, physReg); - // Since the register allocator is allowed to assign this virtual register - // physical register that overlaps other live intervals. Mark these - // operands as "Undef" which means later passes, e.g. register scavenger - // can ignore them. - for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(cur->reg), - RE = mri_->reg_end(); RI != RE; ++RI) { - MachineOperand &MO = RI.getOperand(); - MO.setIsUndef(); - if (MO.isKill()) - MO.setIsKill(false); - } return; } diff --git a/lib/CodeGen/RegisterScavenging.cpp b/lib/CodeGen/RegisterScavenging.cpp index 382741e..58f4284 100644 --- a/lib/CodeGen/RegisterScavenging.cpp +++ b/lib/CodeGen/RegisterScavenging.cpp @@ -254,6 +254,8 @@ void RegScavenger::forward() { unsigned Idx = (i < NumECs) ? EarlyClobberMOs[i].second : DefMOs[i-NumECs].second; unsigned Reg = MO.getReg(); + if (MO.isUndef()) + continue; // If it's dead upon def, then it is now free. if (MO.isDead()) { @@ -262,7 +264,9 @@ void RegScavenger::forward() { } // Skip two-address destination operand. - if (MI->isRegTiedToUseOperand(Idx)) { + unsigned UseIdx; + if (MI->isRegTiedToUseOperand(Idx, &UseIdx) && + !MI->getOperand(UseIdx).isUndef()) { assert(isUsed(Reg) && "Using an undefined register!"); continue; } @@ -316,6 +320,8 @@ void RegScavenger::backward() { ? *DefMOs[i].first : *EarlyClobberMOs[i-NumDefs].first; unsigned Idx = (i < NumECs) ? DefMOs[i].second : EarlyClobberMOs[i-NumDefs].second; + if (MO.isUndef()) + continue; // Skip two-address destination operand. if (MI->isRegTiedToUseOperand(Idx)) diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index bbf1e24..be0b016 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -2029,8 +2029,12 @@ private: if (!TargetRegisterInfo::isVirtualRegister(VirtReg)) { // Check to see if this is a noop copy. If so, eliminate the // instruction before considering the dest reg to be changed. + // Also check if it's copying from an "undef", if so, we can't + // eliminate this or else the undef marker is lost and it will + // confuses the scavenger. This is extremely rare. unsigned Src, Dst, SrcSR, DstSR; - if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst) { + if (TII->isMoveInstr(MI, Src, Dst, SrcSR, DstSR) && Src == Dst && + !MI.findRegisterUseOperand(Src)->isUndef()) { ++NumDCE; DOUT << "Removing now-noop copy: " << MI; SmallVector<unsigned, 2> KillRegs; @@ -2049,7 +2053,7 @@ private: Spills.disallowClobberPhysReg(VirtReg); goto ProcessNextInst; } - + // If it's not a no-op copy, it clobbers the value in the destreg. Spills.ClobberPhysReg(VirtReg); ReusedOperands.markClobbered(VirtReg); |