Fix live variables issues:

1. If part of a register is re-defined, an implicit kill and an implicit def are added to denote read / mod / write. However, this should only be necessary if the register is actually read later. This is a performance issue.
2. If a sub-register is being defined, and it doesn't have a previous use, do not add a implicit kill to the last use of a super-register:
   = EAX, AX<imp-use,kill>
...
AX =
In this case, EAX is live but AX is killed, this is wrong and will cause the coalescer to do bad things.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48521 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2008-03-19 00:52:20 +00:00
parent c7fe32e840
commit 94202018c5
4 changed files with 63 additions and 6 deletions

View File

@ -165,6 +165,12 @@ private: // Intermediate data structures
void HandlePhysRegUse(unsigned Reg, MachineInstr *MI);
void HandlePhysRegDef(unsigned Reg, MachineInstr *MI);
/// 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,
MachineBasicBlock *MBB);
/// analyzePHINodes - Gather information about the PHI nodes in here. In
/// particular, we want to map the variable information of a virtual
/// register which is used in a PHI node. We map that to the BB the vreg

View File

@ -267,8 +267,9 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, const MachineInstr *RefMI,
if (*SubRegs == 0) {
// No sub-registers, just check if reg is killed by RefMI.
if (PhysRegInfo[Reg] == 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;
@ -297,6 +298,34 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *RefMI) {
return false;
}
/// hasRegisterUseBelow - Return true if the specified register is used after
/// the current instruction and before it's next definition.
bool LiveVariables::hasRegisterUseBelow(unsigned Reg,
MachineBasicBlock::iterator I,
MachineBasicBlock *MBB) {
if (I == MBB->end())
return false;
++I;
// FIXME: This is slow. We probably need a smarter solution. Possibilities:
// 1. Scan all instructions once and build def / use information of physical
// registers. We also need a fast way to compare relative ordering of
// instructions.
// 2. Cache information so this function only has to scan instructions that
// read / def physical instructions.
for (MachineBasicBlock::iterator E = MBB->end(); I != E; ++I) {
MachineInstr *MI = I;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
if (!MO.isRegister() || MO.getReg() != Reg)
continue;
if (MO.isDef())
return false;
return true;
}
}
return false;
}
void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) {
// Does this kill a previous version of this register?
if (MachineInstr *LastRef = PhysRegInfo[Reg]) {
@ -338,14 +367,22 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI) {
unsigned SuperReg = *SuperRegs; ++SuperRegs) {
if (PhysRegInfo[SuperReg] && PhysRegInfo[SuperReg] != MI) {
// The larger register is previously defined. Now a smaller part is
// being re-defined. Treat it as read/mod/write.
// being re-defined. Treat it as read/mod/write if there are uses
// below.
// EAX =
// AX = EAX<imp-use,kill>, EAX<imp-def>
MI->addOperand(MachineOperand::CreateReg(SuperReg, false/*IsDef*/,
// ...
/// = EAX
if (MI && hasRegisterUseBelow(SuperReg, MI, MI->getParent())) {
MI->addOperand(MachineOperand::CreateReg(SuperReg, false/*IsDef*/,
true/*IsImp*/,true/*IsKill*/));
MI->addOperand(MachineOperand::CreateReg(SuperReg, true/*IsDef*/,
true/*IsImp*/));
PhysRegInfo[SuperReg] = MI;
MI->addOperand(MachineOperand::CreateReg(SuperReg, true/*IsDef*/,
true/*IsImp*/));
PhysRegInfo[SuperReg] = MI;
} else {
PhysRegInfo[SuperReg]->addRegisterKilled(SuperReg, TRI, true);
PhysRegInfo[SuperReg] = NULL;
}
PhysRegUsed[SuperReg] = false;
PhysRegPartUse[SuperReg] = NULL;
} else {

View File

@ -0,0 +1,6 @@
; RUN: llvm-as < %s | llc -march=ppc64 -enable-ppc64-regscavenger
define i16 @test(i8* %d1, i16* %d2) {
%tmp237 = call i16 asm "lhbrx $0, $2, $1", "=r,r,bO,m"( i8* %d1, i32 0, i16* %d2 )
ret i16 %tmp237
}

View File

@ -0,0 +1,8 @@
; RUN: llvm-as < %s | llc -march=x86-64 | grep mov | count 1
define i32 @f() nounwind {
tail call void @t( i32 1 ) nounwind
ret i32 0
}
declare void @t(i32)