From a4c98a3e342f37f31edf6fa8591902841e9dcabf Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Wed, 23 Sep 2009 16:35:25 +0000 Subject: [PATCH] Fix bug in kill flag updating for post-register-allocation scheduling. When the kill flag of a superreg needs to be cleared because there are one or more subregs live, we instead add implicit-defs of those subregs and leave the kill flag on the superreg. This allows us to end the live-range of the superreg without ending the live-ranges of the subregs. llvm-svn: 82629 --- llvm/lib/CodeGen/PostRASchedulerList.cpp | 53 +++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/llvm/lib/CodeGen/PostRASchedulerList.cpp b/llvm/lib/CodeGen/PostRASchedulerList.cpp index f6c84d89114f..0f2d3095ac0e 100644 --- a/llvm/lib/CodeGen/PostRASchedulerList.cpp +++ b/llvm/lib/CodeGen/PostRASchedulerList.cpp @@ -178,6 +178,11 @@ namespace { unsigned LastNewReg, const TargetRegisterClass *); void StartBlockForKills(MachineBasicBlock *BB); + + // ToggleKillFlag - Toggle a register operand kill flag. Other + // adjustments may be made to the instruction if necessary. Return + // true if the operand has been deleted, false if not. + bool ToggleKillFlag(MachineInstr *MI, MachineOperand &MO); }; } @@ -822,6 +827,40 @@ void SchedulePostRATDList::StartBlockForKills(MachineBasicBlock *BB) { } } +bool SchedulePostRATDList::ToggleKillFlag(MachineInstr *MI, + MachineOperand &MO) { + // Setting kill flag... + if (!MO.isKill()) { + MO.setIsKill(true); + return false; + } + + // If MO itself is live, clear the kill flag... + if (KillIndices[MO.getReg()] != ~0u) { + MO.setIsKill(false); + return false; + } + + // If any subreg of MO is live, then create an imp-def for that + // subreg and keep MO marked as killed. + bool AllDead = true; + const unsigned SuperReg = MO.getReg(); + for (const unsigned *Subreg = TRI->getSubRegisters(SuperReg); + *Subreg; ++Subreg) { + if (KillIndices[*Subreg] != ~0u) { + MI->addOperand(MachineOperand::CreateReg(*Subreg, + true /*IsDef*/, + true /*IsImp*/, + false /*IsKill*/, + false /*IsDead*/)); + AllDead = false; + } + } + + MO.setIsKill(AllDead); + return false; +} + /// FixupKills - Fix the register kill flags, they may have been made /// incorrect by instruction reordering. /// @@ -860,9 +899,9 @@ void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) { } } - // Examine all used registers and set kill flag. When a register - // is used multiple times we only set the kill flag on the first - // use. + // Examine all used registers and set/clear kill flag. When a + // register is used multiple times we only set the kill flag on + // the first use. killedRegs.clear(); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); @@ -889,8 +928,12 @@ void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) { } if (MO.isKill() != kill) { - MO.setIsKill(kill); - DEBUG(errs() << "Fixed " << MO << " in "); + bool removed = ToggleKillFlag(MI, MO); + if (removed) { + DEBUG(errs() << "Fixed in "); + } else { + DEBUG(errs() << "Fixed " << MO << " in "); + } DEBUG(MI->dump()); }