diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index c1a4f4e8813..ec01556a7e7 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -31,6 +31,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include @@ -163,6 +164,15 @@ private: // Intermediate data structures bool addRegisterDead(unsigned IncomingReg, MachineInstr *MI, bool AddIfNotFound = false); + 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, MachineInstr *MI, + SmallSet &SubKills); + bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); void HandlePhysRegDef(unsigned Reg, MachineInstr *MI); diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index 32d3d387edd..65129eb14cc 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -286,38 +286,85 @@ void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) { PhysRegPartUse[SuperReg] = MI; } +bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *RefMI, + SmallSet &SubKills) { + for (const unsigned *SubRegs = RegInfo->getImmediateSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + MachineInstr *LastRef = PhysRegInfo[SubReg]; + if (LastRef != RefMI) + SubKills.insert(SubReg); + else if (!HandlePhysRegKill(SubReg, RefMI, SubKills)) + SubKills.insert(SubReg); + } + + if (*RegInfo->getImmediateSubRegisters(Reg) == 0) { + // No sub-registers, just check if reg is killed by RefMI. + if (PhysRegInfo[Reg] == RefMI) + return true; + } else if (SubKills.empty()) + // None of the sub-registers are killed elsewhere... + return true; + return false; +} + +void LiveVariables::addRegisterKills(unsigned Reg, MachineInstr *MI, + SmallSet &SubKills) { + if (SubKills.count(Reg) == 0) + addRegisterKilled(Reg, MI, true); + else { + for (const unsigned *SubRegs = RegInfo->getImmediateSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + addRegisterKills(SubReg, MI, SubKills); + } +} + +bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *RefMI) { + SmallSet SubKills; + if (HandlePhysRegKill(Reg, RefMI, SubKills)) { + addRegisterKilled(Reg, RefMI); + return true; + } else { + // Some sub-registers are killed by another MI. + for (const unsigned *SubRegs = RegInfo->getImmediateSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) + addRegisterKills(SubReg, RefMI, SubKills); + return false; + } +} + void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { // Does this kill a previous version of this register? if (MachineInstr *LastRef = PhysRegInfo[Reg]) { - if (PhysRegUsed[Reg]) - addRegisterKilled(Reg, LastRef); - else if (PhysRegPartUse[Reg]) + if (PhysRegUsed[Reg]) { + if (!HandlePhysRegKill(Reg, LastRef)) { + if (PhysRegPartUse[Reg]) + addRegisterKilled(Reg, PhysRegPartUse[Reg], true); + } + } else if (PhysRegPartUse[Reg]) // Add implicit use / kill to last use of a sub-register. addRegisterKilled(Reg, PhysRegPartUse[Reg], true); else addRegisterDead(Reg, LastRef); } - PhysRegInfo[Reg] = MI; - PhysRegUsed[Reg] = false; - PhysRegPartUse[Reg] = NULL; for (const unsigned *SubRegs = RegInfo->getSubRegisters(Reg); unsigned SubReg = *SubRegs; ++SubRegs) { if (MachineInstr *LastRef = PhysRegInfo[SubReg]) { - if (PhysRegUsed[SubReg]) - addRegisterKilled(SubReg, LastRef); - else if (PhysRegPartUse[SubReg]) + if (PhysRegUsed[SubReg]) { + if (!HandlePhysRegKill(SubReg, LastRef)) { + if (PhysRegPartUse[SubReg]) + addRegisterKilled(SubReg, PhysRegPartUse[SubReg], true); + } + //addRegisterKilled(SubReg, LastRef); + } else if (PhysRegPartUse[SubReg]) // Add implicit use / kill to last use of a sub-register. addRegisterKilled(SubReg, PhysRegPartUse[SubReg], true); else addRegisterDead(SubReg, LastRef); } - PhysRegInfo[SubReg] = MI; - PhysRegUsed[SubReg] = false; - PhysRegPartUse[SubReg] = NULL; } - if (MI) + if (MI) { for (const unsigned *SuperRegs = RegInfo->getSuperRegisters(Reg); unsigned SuperReg = *SuperRegs; ++SuperRegs) { if (PhysRegInfo[SuperReg]) { @@ -334,6 +381,17 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) { // Remember this partial def. PhysRegPartDef[SuperReg].push_back(MI); } + } + + PhysRegInfo[Reg] = MI; + PhysRegUsed[Reg] = false; + PhysRegPartUse[Reg] = NULL; + for (const unsigned *SubRegs = RegInfo->getSubRegisters(Reg); + unsigned SubReg = *SubRegs; ++SubRegs) { + PhysRegInfo[SubReg] = MI; + PhysRegUsed[SubReg] = false; + PhysRegPartUse[SubReg] = NULL; + } } } @@ -465,6 +523,8 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { // 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); }