mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 02:29:18 +00:00
ScheduleDAGInstrs should toggle kill flags on bundled instrs.
ScheduleDAGInstrs wasn't setting or clearing the kill flags on instructions inside bundles. This led to code such as this %R3<def> = t2ANDrr %R0 BUNDLE %ITSTATE<imp-def,dead>, %R0<imp-use,kill> t2IT 1, 24, %ITSTATE<imp-def> R6<def,tied6> = t2ORRrr %R0<kill>, ... being transformed to BUNDLE %ITSTATE<imp-def,dead>, %R0<imp-use> t2IT 1, 24, %ITSTATE<imp-def> R6<def,tied6> = t2ORRrr %R0<kill>, ... %R3<def> = t2ANDrr %R0<kill> where the kill flag was removed from the BUNDLE instruction, but not the t2ORRrr inside it. The verifier then thought that R0 was undefined when read by the AND. This change make the toggleKillFlags method also check for bundles and toggle flags on bundled instructions. Setting the kill flag is special cased as we only want to set the kill flag on the last instruction in the bundle. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236428 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
01007da245
commit
ba99a57342
@ -1088,22 +1088,59 @@ void ScheduleDAGInstrs::startBlockForKills(MachineBasicBlock *BB) {
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief If we change a kill flag on the bundle instruction implicit register
|
||||
/// operands, then we also need to propagate that to any instructions inside
|
||||
/// the bundle which had the same kill state.
|
||||
static void toggleBundleKillFlag(MachineInstr *MI, unsigned Reg,
|
||||
bool NewKillState) {
|
||||
if (MI->getOpcode() != TargetOpcode::BUNDLE)
|
||||
return;
|
||||
|
||||
// Walk backwards from the last instruction in the bundle to the first.
|
||||
// Once we set a kill flag on an instruction, we bail out, as otherwise we
|
||||
// might set it on too many operands. We will clear as many flags as we
|
||||
// can though.
|
||||
MachineBasicBlock::instr_iterator Begin = MI;
|
||||
MachineBasicBlock::instr_iterator End = getBundleEnd(MI);
|
||||
while (Begin != End) {
|
||||
for (MIOperands MO(--End); MO.isValid(); ++MO) {
|
||||
if (!MO->isReg() || MO->isDef() || Reg != MO->getReg())
|
||||
continue;
|
||||
|
||||
// If the register has the internal flag then it could be killing an
|
||||
// internal def of the register. In this case, just skip. We only want
|
||||
// to toggle the flag on operands visible outside the bundle.
|
||||
if (MO->isInternalRead())
|
||||
continue;
|
||||
|
||||
if (MO->isKill() == NewKillState)
|
||||
continue;
|
||||
MO->setIsKill(NewKillState);
|
||||
if (NewKillState)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ScheduleDAGInstrs::toggleKillFlag(MachineInstr *MI, MachineOperand &MO) {
|
||||
// Setting kill flag...
|
||||
if (!MO.isKill()) {
|
||||
MO.setIsKill(true);
|
||||
toggleBundleKillFlag(MI, MO.getReg(), true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If MO itself is live, clear the kill flag...
|
||||
if (LiveRegs.test(MO.getReg())) {
|
||||
MO.setIsKill(false);
|
||||
toggleBundleKillFlag(MI, MO.getReg(), false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If any subreg of MO is live, then create an imp-def for that
|
||||
// subreg and keep MO marked as killed.
|
||||
MO.setIsKill(false);
|
||||
toggleBundleKillFlag(MI, MO.getReg(), false);
|
||||
bool AllDead = true;
|
||||
const unsigned SuperReg = MO.getReg();
|
||||
MachineInstrBuilder MIB(MF, MI);
|
||||
@ -1114,8 +1151,10 @@ bool ScheduleDAGInstrs::toggleKillFlag(MachineInstr *MI, MachineOperand &MO) {
|
||||
}
|
||||
}
|
||||
|
||||
if(AllDead)
|
||||
if(AllDead) {
|
||||
MO.setIsKill(true);
|
||||
toggleBundleKillFlag(MI, MO.getReg(), true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1188,6 +1227,12 @@ void ScheduleDAGInstrs::fixupKills(MachineBasicBlock *MBB) {
|
||||
// Warning: toggleKillFlag may invalidate MO.
|
||||
toggleKillFlag(MI, MO);
|
||||
DEBUG(MI->dump());
|
||||
DEBUG(if (MI->getOpcode() == TargetOpcode::BUNDLE) {
|
||||
MachineBasicBlock::instr_iterator Begin = MI;
|
||||
MachineBasicBlock::instr_iterator End = getBundleEnd(MI);
|
||||
while (++Begin != End)
|
||||
DEBUG(Begin->dump());
|
||||
});
|
||||
}
|
||||
|
||||
killedRegs.set(Reg);
|
||||
|
Loading…
Reference in New Issue
Block a user