mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-16 14:31:59 +00:00
Fix for PR4051. When 2address pass delete an instruction, update kill info when necessary.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70279 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c69d56f115
commit
e9ccb3a7d4
@ -88,6 +88,9 @@ namespace {
|
|||||||
bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist,
|
bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist,
|
||||||
unsigned &LastDef);
|
unsigned &LastDef);
|
||||||
|
|
||||||
|
MachineInstr *FindLastUseInMBB(unsigned Reg, MachineBasicBlock *MBB,
|
||||||
|
unsigned Dist);
|
||||||
|
|
||||||
bool isProfitableToCommute(unsigned regB, unsigned regC,
|
bool isProfitableToCommute(unsigned regB, unsigned regC,
|
||||||
MachineInstr *MI, MachineBasicBlock *MBB,
|
MachineInstr *MI, MachineBasicBlock *MBB,
|
||||||
unsigned Dist);
|
unsigned Dist);
|
||||||
@ -310,6 +313,28 @@ bool TwoAddressInstructionPass::NoUseAfterLastDef(unsigned Reg,
|
|||||||
return !(LastUse > LastDef && LastUse < Dist);
|
return !(LastUse > LastDef && LastUse < Dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MachineInstr *TwoAddressInstructionPass::FindLastUseInMBB(unsigned Reg,
|
||||||
|
MachineBasicBlock *MBB,
|
||||||
|
unsigned Dist) {
|
||||||
|
unsigned LastUseDist = Dist;
|
||||||
|
MachineInstr *LastUse = 0;
|
||||||
|
for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(Reg),
|
||||||
|
E = MRI->reg_end(); I != E; ++I) {
|
||||||
|
MachineOperand &MO = I.getOperand();
|
||||||
|
MachineInstr *MI = MO.getParent();
|
||||||
|
if (MI->getParent() != MBB)
|
||||||
|
continue;
|
||||||
|
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(MI);
|
||||||
|
if (DI == DistanceMap.end())
|
||||||
|
continue;
|
||||||
|
if (MO.isUse() && DI->second < LastUseDist) {
|
||||||
|
LastUse = DI->first;
|
||||||
|
LastUseDist = DI->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LastUse;
|
||||||
|
}
|
||||||
|
|
||||||
/// isCopyToReg - Return true if the specified MI is a copy instruction or
|
/// isCopyToReg - Return true if the specified MI is a copy instruction or
|
||||||
/// a extract_subreg instruction. It also returns the source and destination
|
/// a extract_subreg instruction. It also returns the source and destination
|
||||||
/// registers and whether they are physical registers by reference.
|
/// registers and whether they are physical registers by reference.
|
||||||
@ -684,7 +709,9 @@ void TwoAddressInstructionPass::ProcessCopy(MachineInstr *MI,
|
|||||||
|
|
||||||
/// isSafeToDelete - If the specified instruction does not produce any side
|
/// isSafeToDelete - If the specified instruction does not produce any side
|
||||||
/// effects and all of its defs are dead, then it's safe to delete.
|
/// effects and all of its defs are dead, then it's safe to delete.
|
||||||
static bool isSafeToDelete(MachineInstr *MI, const TargetInstrInfo *TII) {
|
static bool isSafeToDelete(MachineInstr *MI, unsigned Reg,
|
||||||
|
const TargetInstrInfo *TII,
|
||||||
|
SmallVector<unsigned, 4> &Kills) {
|
||||||
const TargetInstrDesc &TID = MI->getDesc();
|
const TargetInstrDesc &TID = MI->getDesc();
|
||||||
if (TID.mayStore() || TID.isCall())
|
if (TID.mayStore() || TID.isCall())
|
||||||
return false;
|
return false;
|
||||||
@ -693,10 +720,12 @@ static bool isSafeToDelete(MachineInstr *MI, const TargetInstrInfo *TII) {
|
|||||||
|
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
MachineOperand &MO = MI->getOperand(i);
|
MachineOperand &MO = MI->getOperand(i);
|
||||||
if (!MO.isReg() || !MO.isDef())
|
if (!MO.isReg())
|
||||||
continue;
|
continue;
|
||||||
if (!MO.isDead())
|
if (MO.isDef() && !MO.isDead())
|
||||||
return false;
|
return false;
|
||||||
|
if (MO.isUse() && MO.getReg() != Reg && MO.isKill())
|
||||||
|
Kills.push_back(MO.getReg());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -787,11 +816,53 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
if (!isKilled(*mi, regB, MRI, TII)) {
|
if (!isKilled(*mi, regB, MRI, TII)) {
|
||||||
// If regA is dead and the instruction can be deleted, just delete
|
// If regA is dead and the instruction can be deleted, just delete
|
||||||
// it so it doesn't clobber regB.
|
// it so it doesn't clobber regB.
|
||||||
if (mi->getOperand(ti).isDead() && isSafeToDelete(mi, TII)) {
|
SmallVector<unsigned, 4> Kills;
|
||||||
mbbi->erase(mi); // Nuke the old inst.
|
if (mi->getOperand(ti).isDead() &&
|
||||||
mi = nmi;
|
isSafeToDelete(mi, regB, TII, Kills)) {
|
||||||
++NumDeletes;
|
SmallVector<std::pair<std::pair<unsigned, bool>
|
||||||
break; // Done with this instruction.
|
,MachineInstr*>, 4> NewKills;
|
||||||
|
bool ReallySafe = true;
|
||||||
|
// If this instruction kills some virtual registers, we need
|
||||||
|
// update the kill information. If it's not possible to do so,
|
||||||
|
// then bail out.
|
||||||
|
while (!Kills.empty()) {
|
||||||
|
unsigned Kill = Kills.back();
|
||||||
|
Kills.pop_back();
|
||||||
|
if (TargetRegisterInfo::isPhysicalRegister(Kill)) {
|
||||||
|
ReallySafe = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MachineInstr *LastKill = FindLastUseInMBB(Kill, &*mbbi, Dist);
|
||||||
|
if (LastKill) {
|
||||||
|
bool isModRef = LastKill->modifiesRegister(Kill);
|
||||||
|
NewKills.push_back(std::make_pair(std::make_pair(Kill,isModRef),
|
||||||
|
LastKill));
|
||||||
|
} else {
|
||||||
|
ReallySafe = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ReallySafe) {
|
||||||
|
if (LV) {
|
||||||
|
while (!NewKills.empty()) {
|
||||||
|
MachineInstr *NewKill = NewKills.back().second;
|
||||||
|
unsigned Kill = NewKills.back().first.first;
|
||||||
|
bool isDead = NewKills.back().first.second;
|
||||||
|
NewKills.pop_back();
|
||||||
|
if (LV->removeVirtualRegisterKilled(Kill, mi)) {
|
||||||
|
if (isDead)
|
||||||
|
LV->addVirtualRegisterDead(Kill, NewKill);
|
||||||
|
else
|
||||||
|
LV->addVirtualRegisterKilled(Kill, NewKill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbbi->erase(mi); // Nuke the old inst.
|
||||||
|
mi = nmi;
|
||||||
|
++NumDeletes;
|
||||||
|
break; // Done with this instruction.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this instruction is commutative, check to see if C dies. If
|
// If this instruction is commutative, check to see if C dies. If
|
||||||
|
23
test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll
Normal file
23
test/CodeGen/X86/2009-04-27-LiveIntervalsAssert2.ll
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9
|
||||||
|
; PR4051
|
||||||
|
|
||||||
|
define void @int163(i32 %p_4, i32 %p_5) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = tail call i32 @foo(i32 1) nounwind ; <i32> [#uses=2]
|
||||||
|
%1 = icmp eq i32 %0, 0 ; <i1> [#uses=1]
|
||||||
|
br i1 %1, label %bb.i, label %bar.exit
|
||||||
|
|
||||||
|
bb.i: ; preds = %entry
|
||||||
|
%2 = lshr i32 1, %0 ; <i32> [#uses=1]
|
||||||
|
%3 = icmp eq i32 %2, 0 ; <i1> [#uses=1]
|
||||||
|
%retval.i = select i1 %3, i32 1, i32 %p_5 ; <i32> [#uses=1]
|
||||||
|
br label %bar.exit
|
||||||
|
|
||||||
|
bar.exit: ; preds = %bb.i, %entry
|
||||||
|
%4 = phi i32 [ %retval.i, %bb.i ], [ %p_5, %entry ] ; <i32> [#uses=1]
|
||||||
|
%5 = icmp eq i32 %4, 0 ; <i1> [#uses=0]
|
||||||
|
%6 = tail call i32 @foo(i32 %p_5) nounwind ; <i32> [#uses=0]
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @foo(i32)
|
Loading…
x
Reference in New Issue
Block a user