From: Evan Cheng Date: Wed, 16 Apr 2008 09:46:40 +0000 (+0000) Subject: Rewrite LiveVariable liveness computation. The new implementation is much simplified... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=0d4bdde3270a8ed182a685a580031d6d5d743164;hp=9b6d7b9fb36b5cf87d291881dfcea399796f7826;p=oota-llvm.git Rewrite LiveVariable liveness computation. The new implementation is much simplified. It eliminated the nasty recursive routines and removed the partial def / use bookkeeping. There is also potential for performance improvement by replacing the conservative handling of partial physical register definitions. The code is currently disabled until live interval analysis is taught of the name scheme. This patch also fixed a couple of nasty corner cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49784 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 49fc90f00e5..efa5f3c869f 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -134,25 +134,15 @@ private: // Intermediate data structures const TargetRegisterInfo *TRI; - // PhysRegInfo - Keep track of which instruction was the last def/use of a + // PhysRegInfo - Keep track of which instruction was the last def of a // physical register. This is a purely local property, because all physical // register references are presumed dead across basic blocks. - MachineInstr **PhysRegInfo; + MachineInstr **PhysRegDef; - // PhysRegUsed - Keep track of whether the physical register has been used - // after its last definition. This is local property. - bool *PhysRegUsed; - - // PhysRegPartUse - Keep track of which instruction was the last partial use - // of a physical register (e.g. on X86 a def of EAX followed by a use of AX). - // This is a purely local property. - MachineInstr **PhysRegPartUse; - - // PhysRegPartDef - Keep track of a list of instructions which "partially" - // defined the physical register (e.g. on X86 AX partially defines EAX). - // These are turned into use/mod/write if there is a use of the register - // later in the same block. This is local property. - SmallVector *PhysRegPartDef; + // PhysRegInfo - Keep track of which instruction was the last use of a + // physical register. This is a purely local property, because all physical + // register references are presumed dead across basic blocks. + MachineInstr **PhysRegUse; SmallVector *PHIVarInfo; @@ -160,22 +150,21 @@ private: // Intermediate data structures // current basic block. DenseMap DistanceMap; - void addRegisterKills(unsigned Reg, MachineInstr *MI, - SmallSet &SubKills); - /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the /// uses. Pay special attention to the sub-register uses which may come below /// the last use of the whole register. - bool HandlePhysRegKill(unsigned Reg, const MachineInstr *MI, - SmallSet &SubKills); - bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); + bool HandlePhysRegKill(unsigned Reg); + void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); void HandlePhysRegDef(unsigned Reg, MachineInstr *MI); + /// FindLastPartialDef - Return the last partial def of the specified register. + /// Also returns the sub-register that's defined. + MachineInstr *FindLastPartialDef(unsigned Reg, unsigned &PartDefReg); + /// hasRegisterUseBelow - Return true if the specified register is used after /// the current instruction and before it's next definition. - bool hasRegisterUseBelow(unsigned Reg, - MachineBasicBlock::iterator I, + bool hasRegisterUseBelow(unsigned Reg, MachineBasicBlock::iterator I, MachineBasicBlock *MBB); /// analyzePHINodes - Gather information about the PHI nodes in here. In diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index 101d1e866d6..4a4ef37b004 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -154,147 +154,88 @@ void LiveVariables::HandleVirtRegUse(unsigned reg, MachineBasicBlock *MBB, MarkVirtRegAliveInBlock(VRInfo, MRI->getVRegDef(reg)->getParent(), *PI); } +/// FindLastPartialDef - Return the last partial def of the specified register. +/// Also returns the sub-register that's defined. +MachineInstr *LiveVariables::FindLastPartialDef(unsigned Reg, + unsigned &PartDefReg) { + unsigned LastDefReg = 0; + unsigned LastDefDist = 0; + MachineInstr *LastDef = NULL; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *Def = PhysRegDef[SubReg]; + if (!Def) + continue; + unsigned Dist = DistanceMap[Def]; + if (Dist > LastDefDist) { + LastDefReg = SubReg; + LastDef = Def; + LastDefDist = Dist; + } + } + PartDefReg = LastDefReg; + return LastDef; +} + /// HandlePhysRegUse - Turn previous partial def's into read/mod/writes. Add /// implicit defs to a machine instruction if there was an earlier def of its /// super-register. void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) { - // Turn previous partial def's into read/mod/write. - for (unsigned i = 0, e = PhysRegPartDef[Reg].size(); i != e; ++i) { - MachineInstr *Def = PhysRegPartDef[Reg][i]; - - // First one is just a def. This means the use is reading some undef bits. - if (i != 0) - Def->addOperand(MachineOperand::CreateReg(Reg, - false /*IsDef*/, - true /*IsImp*/, - true /*IsKill*/)); - - Def->addOperand(MachineOperand::CreateReg(Reg, - true /*IsDef*/, - true /*IsImp*/)); + // If there was a previous use or a "full" def all is well. + if (!PhysRegDef[Reg] && !PhysRegUse[Reg]) { + // Otherwise, the last sub-register def implicitly defines this register. + // e.g. + // AH = + // AL = ... , + // = AH + // ... + // = EAX + // All of the sub-registers must have been defined before the use of Reg! + unsigned PartDefReg = 0; + MachineInstr *LastPartialDef = FindLastPartialDef(Reg, PartDefReg); + // If LastPartialDef is NULL, it must be using a livein register. + if (LastPartialDef) { + LastPartialDef->addOperand(MachineOperand::CreateReg(Reg, true/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[Reg] = LastPartialDef; + std::set Processed; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (Processed.count(SubReg)) + continue; + if (SubReg == PartDefReg || TRI->isSubRegister(PartDefReg, SubReg)) + continue; + // This part of Reg was defined before the last partial def. It's killed + // here. + LastPartialDef->addOperand(MachineOperand::CreateReg(SubReg, + false/*IsDef*/, + true/*IsImp*/)); + PhysRegDef[SubReg] = LastPartialDef; + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Processed.insert(*SS); + } + } } - PhysRegPartDef[Reg].clear(); - // There was an earlier def of a super-register. Add implicit def to that MI. // // A: EAX = ... // B: ... = AX // - // Add implicit def to A. - if (PhysRegInfo[Reg] && PhysRegInfo[Reg] != PhysRegPartUse[Reg] && - !PhysRegUsed[Reg]) { - MachineInstr *Def = PhysRegInfo[Reg]; - - if (!Def->modifiesRegister(Reg)) + // Add implicit def to A if there isn't a use of AX (or EAX) before B. + if (!PhysRegUse[Reg]) { + MachineInstr *Def = PhysRegDef[Reg]; + if (Def && !Def->modifiesRegister(Reg)) Def->addOperand(MachineOperand::CreateReg(Reg, true /*IsDef*/, true /*IsImp*/)); } - - // There is a now a proper use, forget about the last partial use. - PhysRegPartUse[Reg] = NULL; - PhysRegInfo[Reg] = MI; - PhysRegUsed[Reg] = true; - - // Now reset the use information for the sub-registers. + + // Remember this use. + PhysRegUse[Reg] = MI; for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); - unsigned SubReg = *SubRegs; ++SubRegs) { - PhysRegPartUse[SubReg] = NULL; - PhysRegInfo[SubReg] = MI; - PhysRegUsed[SubReg] = true; - } - - for (const unsigned *SuperRegs = TRI->getSuperRegisters(Reg); - unsigned SuperReg = *SuperRegs; ++SuperRegs) { - // Remember the partial use of this super-register if it was previously - // defined. - bool HasPrevDef = PhysRegInfo[SuperReg] != NULL; - - if (!HasPrevDef) - // No need to go up more levels. A def of a register also sets its sub- - // registers. So if PhysRegInfo[SuperReg] is NULL, it means SuperReg's - // super-registers are not previously defined. - for (const unsigned *SSRegs = TRI->getSuperRegisters(SuperReg); - unsigned SSReg = *SSRegs; ++SSRegs) - if (PhysRegInfo[SSReg] != NULL) { - HasPrevDef = true; - break; - } - - if (HasPrevDef) { - PhysRegInfo[SuperReg] = MI; - PhysRegPartUse[SuperReg] = MI; - } - } -} - -/// addRegisterKills - For all of a register's sub-registers that are killed in -/// at this machine instruction, mark them as "killed". (If the machine operand -/// isn't found, add it first.) -void LiveVariables::addRegisterKills(unsigned Reg, MachineInstr *MI, - SmallSet &SubKills) { - if (SubKills.count(Reg) == 0) { - MI->addRegisterKilled(Reg, TRI, true); - return; - } - - for (const unsigned *SubRegs = TRI->getImmediateSubRegisters(Reg); unsigned SubReg = *SubRegs; ++SubRegs) - addRegisterKills(SubReg, MI, SubKills); -} - -/// HandlePhysRegKill - The recursive version of HandlePhysRegKill. Returns true -/// if: -/// -/// - The register has no sub-registers and the machine instruction is the -/// last def/use of the register, or -/// - The register has sub-registers and none of them are killed elsewhere. -/// -/// SubKills is filled with the set of sub-registers that are killed elsewhere. -bool LiveVariables::HandlePhysRegKill(unsigned Reg, const MachineInstr *RefMI, - SmallSet &SubKills) { - const unsigned *SubRegs = TRI->getImmediateSubRegisters(Reg); - - for (; unsigned SubReg = *SubRegs; ++SubRegs) { - const MachineInstr *LastRef = PhysRegInfo[SubReg]; - - if (LastRef != RefMI || - !HandlePhysRegKill(SubReg, RefMI, SubKills)) - SubKills.insert(SubReg); - } - - if (*SubRegs == 0) { - // No sub-registers, just check if reg is killed by RefMI. - if (PhysRegInfo[Reg] == RefMI && PhysRegInfo[Reg]->readsRegister(Reg)) { - return true; - } - } else if (SubKills.empty()) { - // None of the sub-registers are killed elsewhere. - return true; - } - - return false; -} - -/// HandlePhysRegKill - Returns true if the whole register is killed in the -/// machine instruction. If only some of its sub-registers are killed in this -/// machine instruction, then mark those as killed and return false. -bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *RefMI) { - SmallSet SubKills; - - if (HandlePhysRegKill(Reg, RefMI, SubKills)) { - // This machine instruction kills this register. - RefMI->addRegisterKilled(Reg, TRI, true); - return true; - } - - // Some sub-registers are killed by another machine instruction. - for (const unsigned *SubRegs = TRI->getImmediateSubRegisters(Reg); - unsigned SubReg = *SubRegs; ++SubRegs) - addRegisterKills(SubReg, RefMI, SubKills); - - return false; + PhysRegUse[SubReg] = MI; } /// hasRegisterUseBelow - Return true if the specified register is used after @@ -348,8 +289,8 @@ bool LiveVariables::hasRegisterUseBelow(unsigned Reg, DistanceMap.insert(std::make_pair(I, CurDist)); } - unsigned EarliestUse = CurDist; - for (unsigned i = 0, e = Uses.size(); i != e; ++i) { + unsigned EarliestUse = DistanceMap[Uses[0]]; + for (unsigned i = 1, e = Uses.size(); i != e; ++i) { unsigned Dist = DistanceMap[Uses[i]]; if (Dist < EarliestUse) EarliestUse = Dist; @@ -363,46 +304,124 @@ bool LiveVariables::hasRegisterUseBelow(unsigned Reg, return true; } +bool LiveVariables::HandlePhysRegKill(unsigned Reg) { + if (!PhysRegUse[Reg] && !PhysRegDef[Reg]) + return false; + + MachineInstr *LastRefOrPartRef = PhysRegUse[Reg] + ? PhysRegUse[Reg] : PhysRegDef[Reg]; + unsigned LastRefOrPartRefDist = DistanceMap[LastRefOrPartRef]; + // The whole register is used. + // AL = + // AH = + // + // = AX + // = AL, AX + // AX = + // + // Or whole register is defined, but not used at all. + // AX = + // ... + // AX = + // + // Or whole register is defined, but only partly used. + // AX = AL + // = AL + // AX = + std::set PartUses; + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (MachineInstr *Use = PhysRegUse[SubReg]) { + PartUses.insert(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + PartUses.insert(*SS); + unsigned Dist = DistanceMap[Use]; + if (Dist > LastRefOrPartRefDist) { + LastRefOrPartRefDist = Dist; + LastRefOrPartRef = Use; + } + } + } + if (LastRefOrPartRef == PhysRegDef[Reg]) + // Not used at all. + LastRefOrPartRef->addRegisterDead(Reg, TRI, true); + + /* Partial uses. Mark register def dead and add implicit def of + sub-registers which are used. + FIXME: LiveIntervalAnalysis can't handle this yet! + EAX = op AL + That is, EAX def is dead but AL def extends pass it. + Enable this after live interval analysis is fixed to improve codegen! + else if (!PhysRegUse[Reg]) { + PhysRegDef[Reg]->addRegisterDead(Reg, TRI, true); + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (PartUses.count(SubReg)) { + PhysRegDef[Reg]->addOperand(MachineOperand::CreateReg(SubReg, + true, true)); + LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + PartUses.erase(*SS); + } + } + } */ + else + LastRefOrPartRef->addRegisterKilled(Reg, TRI, true); + return true; +} + void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { - // Does this kill a previous version of this register? - if (MachineInstr *LastRef = PhysRegInfo[Reg]) { - if (PhysRegUsed[Reg]) { - if (!HandlePhysRegKill(Reg, LastRef)) { - if (PhysRegPartUse[Reg]) - PhysRegPartUse[Reg]->addRegisterKilled(Reg, TRI, true); + // What parts of the register are previously defined? + std::set Live; + if (PhysRegDef[Reg] || PhysRegUse[Reg]) { + Live.insert(Reg); + for (const unsigned *SS = TRI->getSubRegisters(Reg); *SS; ++SS) + Live.insert(*SS); + } else { + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + // If a register isn't itself defined, but all parts that make up of it + // are defined, then consider it also defined. + // e.g. + // AL = + // AH = + // = AX + if (PhysRegDef[SubReg] || PhysRegUse[SubReg]) { + Live.insert(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Live.insert(*SS); } - } else if (PhysRegPartUse[Reg]) { - // Add implicit use / kill to last partial use. - PhysRegPartUse[Reg]->addRegisterKilled(Reg, TRI, true); - } else if (LastRef != MI) { - // Defined, but not used. However, watch out for cases where a super-reg - // is also defined on the same MI. - LastRef->addRegisterDead(Reg, TRI); } } - for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); - unsigned SubReg = *SubRegs; ++SubRegs) { - if (MachineInstr *LastRef = PhysRegInfo[SubReg]) { - if (PhysRegUsed[SubReg]) { - if (!HandlePhysRegKill(SubReg, LastRef)) { - if (PhysRegPartUse[SubReg]) - PhysRegPartUse[SubReg]->addRegisterKilled(SubReg, TRI, true); - } - } else if (PhysRegPartUse[SubReg]) { - // Add implicit use / kill to last use of a sub-register. - PhysRegPartUse[SubReg]->addRegisterKilled(SubReg, TRI, true); - } else if (LastRef != MI) { - // This must be a def of the subreg on the same MI. - LastRef->addRegisterDead(SubReg, TRI); + // Start from the largest piece, find the last time any part of the register + // is referenced. + if (!HandlePhysRegKill(Reg)) { + // Only some of the sub-registers are used. + for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + if (!Live.count(SubReg)) + // Skip if this sub-register isn't defined. + continue; + if (HandlePhysRegKill(SubReg)) { + Live.erase(SubReg); + for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) + Live.erase(*SS); } } + assert(Live.empty() && "Not all defined registers are killed / dead?"); } if (MI) { + // Does this extend the live range of a super-register? + std::set Processed; for (const unsigned *SuperRegs = TRI->getSuperRegisters(Reg); unsigned SuperReg = *SuperRegs; ++SuperRegs) { - if (PhysRegInfo[SuperReg] && PhysRegInfo[SuperReg] != MI) { + if (Processed.count(SuperReg)) + continue; + MachineInstr *LastRef = PhysRegUse[SuperReg] + ? PhysRegUse[SuperReg] : PhysRegDef[SuperReg]; + if (LastRef && LastRef != MI) { // The larger register is previously defined. Now a smaller part is // being re-defined. Treat it as read/mod/write if there are uses // below. @@ -410,35 +429,41 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { // AX = EAX, EAX // ... /// = EAX - if (MI && hasRegisterUseBelow(SuperReg, MI, MI->getParent())) { + if (hasRegisterUseBelow(SuperReg, MI, MI->getParent())) { MI->addOperand(MachineOperand::CreateReg(SuperReg, false/*IsDef*/, - true/*IsImp*/,true/*IsKill*/)); + true/*IsImp*/,true/*IsKill*/)); MI->addOperand(MachineOperand::CreateReg(SuperReg, true/*IsDef*/, true/*IsImp*/)); - PhysRegInfo[SuperReg] = MI; + PhysRegDef[SuperReg] = MI; + PhysRegUse[SuperReg] = NULL; + Processed.insert(SuperReg); + for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) { + PhysRegDef[*SS] = MI; + PhysRegUse[*SS] = NULL; + Processed.insert(*SS); + } } else { - PhysRegInfo[SuperReg]->addRegisterKilled(SuperReg, TRI, true); - PhysRegInfo[SuperReg] = NULL; + // Otherwise, the super register is killed. + if (HandlePhysRegKill(SuperReg)) { + PhysRegDef[SuperReg] = NULL; + PhysRegUse[SuperReg] = NULL; + for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) { + PhysRegDef[*SS] = NULL; + PhysRegUse[*SS] = NULL; + Processed.insert(*SS); + } + } } - PhysRegUsed[SuperReg] = false; - PhysRegPartUse[SuperReg] = NULL; - } else { - // Remember this partial def. - PhysRegPartDef[SuperReg].push_back(MI); } } - PhysRegInfo[Reg] = MI; - PhysRegUsed[Reg] = false; - PhysRegPartDef[Reg].clear(); - PhysRegPartUse[Reg] = NULL; - + // Remember this def. + PhysRegDef[Reg] = MI; + PhysRegUse[Reg] = NULL; for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); unsigned SubReg = *SubRegs; ++SubRegs) { - PhysRegInfo[SubReg] = MI; - PhysRegUsed[SubReg] = false; - PhysRegPartDef[SubReg].clear(); - PhysRegPartUse[SubReg] = NULL; + PhysRegDef[SubReg] = MI; + PhysRegUse[SubReg] = NULL; } } } @@ -451,14 +476,11 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { ReservedRegisters = TRI->getReservedRegs(mf); unsigned NumRegs = TRI->getNumRegs(); - PhysRegInfo = new MachineInstr*[NumRegs]; - PhysRegUsed = new bool[NumRegs]; - PhysRegPartUse = new MachineInstr*[NumRegs]; - PhysRegPartDef = new SmallVector[NumRegs]; + PhysRegDef = new MachineInstr*[NumRegs]; + PhysRegUse = new MachineInstr*[NumRegs]; PHIVarInfo = new SmallVector[MF->getNumBlockIDs()]; - std::fill(PhysRegInfo, PhysRegInfo + NumRegs, (MachineInstr*)0); - std::fill(PhysRegUsed, PhysRegUsed + NumRegs, false); - std::fill(PhysRegPartUse, PhysRegPartUse + NumRegs, (MachineInstr*)0); + std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); + std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); /// Get some space for a respectable number of registers. VirtRegInfo.resize(64); @@ -501,38 +523,43 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { if (MI->getOpcode() == TargetInstrInfo::PHI) NumOperandsToProcess = 1; - // Process all uses. + SmallVector UseRegs; + SmallVector DefRegs; for (unsigned i = 0; i != NumOperandsToProcess; ++i) { const MachineOperand &MO = MI->getOperand(i); - - if (MO.isRegister() && MO.isUse() && MO.getReg()) { + if (MO.isRegister() && MO.getReg()) { unsigned MOReg = MO.getReg(); - - if (TargetRegisterInfo::isVirtualRegister(MOReg)) - HandleVirtRegUse(MOReg, MBB, MI); - else if (TargetRegisterInfo::isPhysicalRegister(MOReg) && - !ReservedRegisters[MOReg]) - HandlePhysRegUse(MOReg, MI); + if (!MOReg) + continue; + if (MO.isUse()) + UseRegs.push_back(MOReg); + if (MO.isDef()) + DefRegs.push_back(MOReg); } } - // Process all defs. - for (unsigned i = 0; i != NumOperandsToProcess; ++i) { - const MachineOperand &MO = MI->getOperand(i); - - if (MO.isRegister() && MO.isDef() && MO.getReg()) { - unsigned MOReg = MO.getReg(); - - if (TargetRegisterInfo::isVirtualRegister(MOReg)) { - VarInfo &VRInfo = getVarInfo(MOReg); + // Process all uses. + for (unsigned i = 0, e = UseRegs.size(); i != e; ++i) { + unsigned MOReg = UseRegs[i]; + if (TargetRegisterInfo::isVirtualRegister(MOReg)) + HandleVirtRegUse(MOReg, MBB, MI); + else if (TargetRegisterInfo::isPhysicalRegister(MOReg) && + !ReservedRegisters[MOReg]) + HandlePhysRegUse(MOReg, MI); + } - if (VRInfo.AliveBlocks.none()) - // If vr is not alive in any block, then defaults to dead. - VRInfo.Kills.push_back(MI); - } else if (TargetRegisterInfo::isPhysicalRegister(MOReg) && - !ReservedRegisters[MOReg]) { - HandlePhysRegDef(MOReg, MI); - } + // Process all defs. + for (unsigned i = 0, e = DefRegs.size(); i != e; ++i) { + unsigned MOReg = DefRegs[i]; + if (TargetRegisterInfo::isVirtualRegister(MOReg)) { + VarInfo &VRInfo = getVarInfo(MOReg); + + if (VRInfo.AliveBlocks.none()) + // If vr is not alive in any block, then defaults to dead. + VRInfo.Kills.push_back(MI); + } else if (TargetRegisterInfo::isPhysicalRegister(MOReg) && + !ReservedRegisters[MOReg]) { + HandlePhysRegDef(MOReg, MI); } } } @@ -569,19 +596,14 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { } } - // Loop over PhysRegInfo, killing any registers that are available at the - // end of the basic block. This also resets the PhysRegInfo map. + // Loop over PhysRegDef / PhysRegUse, killing any registers that are + // available at the end of the basic block. for (unsigned i = 0; i != NumRegs; ++i) - if (PhysRegInfo[i]) + if (PhysRegDef[i] || PhysRegUse[i]) HandlePhysRegDef(i, 0); - // Clear some states between BB's. These are purely local information. - for (unsigned i = 0; i != NumRegs; ++i) - PhysRegPartDef[i].clear(); - - std::fill(PhysRegInfo, PhysRegInfo + NumRegs, (MachineInstr*)0); - std::fill(PhysRegUsed, PhysRegUsed + NumRegs, false); - std::fill(PhysRegPartUse, PhysRegPartUse + NumRegs, (MachineInstr*)0); + std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); + std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); } // Convert and transfer the dead / killed information we have gathered into @@ -608,10 +630,8 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { assert(Visited.count(&*i) != 0 && "unreachable basic block found"); #endif - delete[] PhysRegInfo; - delete[] PhysRegUsed; - delete[] PhysRegPartUse; - delete[] PhysRegPartDef; + delete[] PhysRegDef; + delete[] PhysRegUse; delete[] PHIVarInfo; return false; diff --git a/test/CodeGen/X86/2008-04-15-LiveVariableBug.ll b/test/CodeGen/X86/2008-04-15-LiveVariableBug.ll new file mode 100644 index 00000000000..4f41906c162 --- /dev/null +++ b/test/CodeGen/X86/2008-04-15-LiveVariableBug.ll @@ -0,0 +1,48 @@ +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin + + %struct.CGPoint = type { double, double } + %struct.NSArray = type { %struct.NSObject } + %struct.NSAssertionHandler = type { %struct.NSObject, i8* } + %struct.NSDockTile = type { %struct.NSObject, %struct.NSObject*, i8*, %struct.NSView*, %struct.NSView*, %struct.NSView*, %struct.NSArray*, %struct._SPFlags, %struct.CGPoint, [5 x %struct.NSObject*] } + %struct.NSDocument = type { %struct.NSObject, %struct.NSWindow*, %struct.NSObject*, %struct.NSURL*, %struct.NSArray*, %struct.NSPrintInfo*, i64, %struct.NSView*, %struct.NSObject*, %struct.NSObject*, %struct.NSUndoManager*, %struct._BCFlags2, %struct.NSArray* } + %struct.AA = type { %struct.NSObject, %struct.NSDocument*, %struct.NSURL*, %struct.NSArray*, %struct.NSArray* } + %struct.NSError = type { %struct.NSObject, i8*, i64, %struct.NSArray*, %struct.NSArray* } + %struct.NSImage = type { %struct.NSObject, %struct.NSArray*, %struct.CGPoint, %struct._BCFlags2, %struct.NSObject*, %struct._NSImageAuxiliary* } + %struct.NSMutableArray = type { %struct.NSArray } + %struct.NSObject = type { %struct.NSObject* } + %struct.NSPrintInfo = type { %struct.NSObject, %struct.NSMutableArray*, %struct.NSObject* } + %struct.NSRect = type { %struct.CGPoint, %struct.CGPoint } + %struct.NSRegion = type opaque + %struct.NSResponder = type { %struct.NSObject, %struct.NSObject* } + %struct.NSToolbar = type { %struct.NSObject, %struct.NSArray*, %struct.NSMutableArray*, %struct.NSMutableArray*, %struct.NSArray*, %struct.NSObject*, %struct.NSArray*, i8*, %struct.NSObject*, %struct.NSWindow*, %struct.NSObject*, %struct.NSObject*, i64, %struct._BCFlags2, i64, %struct.NSObject* } + %struct.NSURL = type { %struct.NSObject, %struct.NSArray*, %struct.NSURL*, i8*, i8* } + %struct.NSUndoManager = type { %struct.NSObject, %struct.NSObject*, %struct.NSObject*, %struct.NSArray*, i64, %struct._SPFlags, %struct.NSObject*, i8*, i8*, i8* } + %struct.NSView = type { %struct.NSResponder, %struct.NSRect, %struct.NSRect, %struct.NSObject*, %struct.NSObject*, %struct.NSWindow*, %struct.NSObject*, %struct.NSObject*, %struct.NSObject*, %struct.NSObject*, %struct._NSViewAuxiliary*, %struct._BCFlags, %struct._SPFlags } + %struct.NSWindow = type { %struct.NSResponder, %struct.NSRect, %struct.NSObject*, %struct.NSObject*, %struct.NSResponder*, %struct.NSView*, %struct.NSView*, %struct.NSObject*, %struct.NSObject*, i32, i64, i32, %struct.NSArray*, %struct.NSObject*, i8, i8, i8, i8, i8*, i8*, %struct.NSImage*, i32, %struct.NSMutableArray*, %struct.NSURL*, %struct.CGPoint*, %struct.NSArray*, %struct.NSArray*, %struct.__wFlags, %struct.NSObject*, %struct.NSView*, %struct.NSWindowAuxiliary* } + %struct.NSWindowAuxiliary = type { %struct.NSObject, %struct.NSArray*, %struct.NSDockTile*, %struct._NSWindowAnimator*, %struct.NSRect, i32, %struct.NSAssertionHandler*, %struct.NSUndoManager*, %struct.NSWindowController*, %struct.NSAssertionHandler*, %struct.NSObject*, i32, %struct.__CFRunLoopObserver*, %struct.__CFRunLoopObserver*, %struct.NSArray*, %struct.NSArray*, %struct.NSView*, %struct.NSRegion*, %struct.NSWindow*, %struct.NSWindow*, %struct.NSArray*, %struct.NSMutableArray*, %struct.NSArray*, %struct.NSWindow*, %struct.CGPoint, %struct.NSObject*, i8*, i8*, i32, %struct.NSObject*, %struct.NSArray*, double, %struct.CGPoint, %struct.NSArray*, %struct.NSMutableArray*, %struct.NSMutableArray*, %struct.NSWindow*, %struct.NSView*, %struct.NSArray*, %struct.__auxWFlags, i32, i8*, double, %struct.NSObject*, %struct.NSObject*, %struct.__CFArray*, %struct.NSRegion*, %struct.NSArray*, %struct.NSRect, %struct.NSToolbar*, %struct.NSRect, %struct.NSMutableArray* } + %struct.NSWindowController = type { %struct.NSResponder, %struct.NSWindow*, %struct.NSArray*, %struct.NSDocument*, %struct.NSArray*, %struct.NSObject*, %struct._SPFlags, %struct.NSArray*, %struct.NSObject* } + %struct._BCFlags = type <{ i8, i8, i8, i8 }> + %struct._BCFlags2 = type <{ i8, [3 x i8] }> + %struct._NSImageAuxiliary = type opaque + %struct._NSViewAuxiliary = type opaque + %struct._NSWindowAnimator = type opaque + %struct._SPFlags = type <{ i32 }> + %struct.__CFArray = type opaque + %struct.__CFRunLoopObserver = type opaque + %struct.__auxWFlags = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i32, i16 } + %struct.__wFlags = type <{ i8, i8, i8, i8, i8, i8, i8, i8 }> + %struct._message_ref_t = type { %struct.NSObject* (%struct.NSObject*, %struct._message_ref_t*, ...)*, %struct.objc_selector* } + %struct.objc_selector = type opaque +@"\01L_OBJC_MESSAGE_REF_228" = internal global %struct._message_ref_t zeroinitializer ; <%struct._message_ref_t*> [#uses=1] +@llvm.used1 = appending global [1 x i8*] [ i8* bitcast (void (%struct.AA*, %struct._message_ref_t*, %struct.NSError*, i64, %struct.NSObject*, %struct.objc_selector*, i8*)* @"-[AA BB:optionIndex:delegate:CC:contextInfo:]" to i8*) ], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0] + +define void @"-[AA BB:optionIndex:delegate:CC:contextInfo:]"(%struct.AA* %self, %struct._message_ref_t* %_cmd, %struct.NSError* %inError, i64 %inOptionIndex, %struct.NSObject* %inDelegate, %struct.objc_selector* %inDidRecoverSelector, i8* %inContextInfo) { +entry: + %tmp105 = load %struct.NSArray** null, align 8 ; <%struct.NSArray*> [#uses=1] + %tmp107 = load %struct.NSObject** null, align 8 ; <%struct.NSObject*> [#uses=1] + call void null( %struct.NSObject* %tmp107, %struct._message_ref_t* @"\01L_OBJC_MESSAGE_REF_228", %struct.NSArray* %tmp105, i8 signext 0 ) + %tmp111 = call %struct.NSObject* (%struct.NSObject*, %struct.objc_selector*, ...)* @objc_msgSend( %struct.NSObject* null, %struct.objc_selector* null, i32 0, i8* null ) ; <%struct.NSObject*> [#uses=0] + ret void +} + +declare %struct.NSObject* @objc_msgSend(%struct.NSObject*, %struct.objc_selector*, ...)