Remove special handling of implicit_def. Fix a couple more bugs in liveintervalanalysis and coalescer handling of implicit_def.

Note, isUndef marker must be placed even on implicit_def def operand or else the scavenger will not ignore it. This is necessary because -O0 path does not use liveintervalanalysis, it treats implicit_def just like any other def.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74601 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-07-01 08:19:36 +00:00
parent d6bb283de9
commit 459a7c6b6a
5 changed files with 175 additions and 64 deletions

View File

@ -69,10 +69,6 @@ class RegScavenger {
/// available, unset means the register is currently being used.
BitVector RegsAvailable;
/// ImplicitDefed - If bit is set that means the register is defined by an
/// implicit_def instructions. That means it can be clobbered at will.
BitVector ImplicitDefed;
/// CurrDist - Distance from MBB entry to the current instruction MBBI.
///
unsigned CurrDist;
@ -117,25 +113,18 @@ public:
bool isUsed(unsigned Reg) const { return !RegsAvailable[Reg]; }
bool isUnused(unsigned Reg) const { return RegsAvailable[Reg]; }
bool isImplicitlyDefined(unsigned Reg) const { return ImplicitDefed[Reg]; }
/// getRegsUsed - return all registers currently in use in used.
void getRegsUsed(BitVector &used, bool includeReserved);
/// setUsed / setUnused - Mark the state of one or a number of registers.
///
void setUsed(unsigned Reg, bool ImpDef = false);
void setUsed(BitVector &Regs, bool ImpDef = false) {
void setUsed(unsigned Reg);
void setUsed(BitVector &Regs) {
RegsAvailable &= ~Regs;
if (ImpDef)
ImplicitDefed |= Regs;
else
ImplicitDefed &= ~Regs;
}
void setUnused(unsigned Reg, const MachineInstr *MI);
void setUnused(BitVector &Regs) {
RegsAvailable |= Regs;
ImplicitDefed &= ~Regs;
}
/// FindUnusedReg - Find a unused register of the specified register class

View File

@ -124,7 +124,9 @@ void LiveIntervals::processImplicitDefs() {
ImpDefMIs.push_back(MI);
continue;
}
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
bool ChangedToImpDef = false;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MachineOperand& MO = MI->getOperand(i);
if (!MO.isReg() || !MO.isUse())
continue;
@ -133,16 +135,35 @@ void LiveIntervals::processImplicitDefs() {
continue;
if (!ImpDefRegs.count(Reg))
continue;
// Use is a copy, just turn it into an implicit_def.
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
Reg == SrcReg) {
bool isKill = MO.isKill();
MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j)
MI->RemoveOperand(j);
if (isKill)
ImpDefRegs.erase(Reg);
ChangedToImpDef = true;
break;
}
MO.setIsUndef();
if (MO.isKill() || MI->isRegTiedToDefOperand(i))
ImpDefRegs.erase(Reg);
}
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
MachineOperand& MO = MI->getOperand(i);
if (!MO.isReg() || !MO.isDef())
continue;
ImpDefRegs.erase(MO.getReg());
if (ChangedToImpDef) {
// Backtrack to process this new implicit_def.
--I;
} else {
for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
MachineOperand& MO = MI->getOperand(i);
if (!MO.isReg() || !MO.isDef())
continue;
ImpDefRegs.erase(MO.getReg());
}
}
}
@ -155,33 +176,39 @@ void LiveIntervals::processImplicitDefs() {
continue;
if (!ImpDefRegs.count(Reg))
continue;
bool HasLocalUse = false;
for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(Reg),
RE = mri_->reg_end(); RI != RE; ) {
MachineOperand &RMO = RI.getOperand();
MachineInstr *RMI = &*RI;
++RI;
if (RMO.isDef()) {
// Don't expect another def of the same register.
assert(RMI == MI &&
"Register with multiple defs including an implicit_def?");
continue;
// If there are multiple defs of the same register and at least one
// is not an implicit_def, do not insert implicit_def's before the
// uses.
bool Skip = false;
for (MachineRegisterInfo::def_iterator DI = mri_->def_begin(Reg),
DE = mri_->def_end(); DI != DE; ++DI) {
if (DI->getOpcode() != TargetInstrInfo::IMPLICIT_DEF) {
Skip = true;
break;
}
}
if (Skip)
continue;
for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg),
UE = mri_->use_end(); UI != UE; ) {
MachineOperand &RMO = UI.getOperand();
MachineInstr *RMI = &*UI;
++UI;
MachineBasicBlock *RMBB = RMI->getParent();
if (RMBB == MBB) {
HasLocalUse = true;
if (RMBB == MBB)
continue;
}
const TargetRegisterClass* RC = mri_->getRegClass(Reg);
unsigned NewVReg = mri_->createVirtualRegister(RC);
BuildMI(*RMBB, RMI, RMI->getDebugLoc(),
tii_->get(TargetInstrInfo::IMPLICIT_DEF), NewVReg);
MachineInstrBuilder MIB =
BuildMI(*RMBB, RMI, RMI->getDebugLoc(),
tii_->get(TargetInstrInfo::IMPLICIT_DEF), NewVReg);
(*MIB).getOperand(0).setIsUndef();
RMO.setReg(NewVReg);
RMO.setIsUndef();
RMO.setIsKill();
}
if (!HasLocalUse)
MI->eraseFromParent();
}
ImpDefRegs.clear();
ImpDefMIs.clear();

View File

@ -57,28 +57,22 @@ static bool RedefinesSuperRegPart(const MachineInstr *MI,
}
/// setUsed - Set the register and its sub-registers as being used.
void RegScavenger::setUsed(unsigned Reg, bool ImpDef) {
void RegScavenger::setUsed(unsigned Reg) {
RegsAvailable.reset(Reg);
ImplicitDefed[Reg] = ImpDef;
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs) {
unsigned SubReg = *SubRegs; ++SubRegs)
RegsAvailable.reset(SubReg);
ImplicitDefed[SubReg] = ImpDef;
}
}
/// setUnused - Set the register and its sub-registers as being unused.
void RegScavenger::setUnused(unsigned Reg, const MachineInstr *MI) {
RegsAvailable.set(Reg);
ImplicitDefed.reset(Reg);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs)
if (!RedefinesSuperRegPart(MI, Reg, TRI)) {
if (!RedefinesSuperRegPart(MI, Reg, TRI))
RegsAvailable.set(SubReg);
ImplicitDefed.reset(SubReg);
}
}
void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
@ -94,7 +88,6 @@ void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
if (!MBB) {
NumPhysRegs = TRI->getNumRegs();
RegsAvailable.resize(NumPhysRegs);
ImplicitDefed.resize(NumPhysRegs);
// Create reserved registers bitvector.
ReservedRegs = TRI->getReservedRegs(MF);
@ -113,7 +106,6 @@ void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
ScavengeRestore = NULL;
CurrDist = 0;
DistanceMap.clear();
ImplicitDefed.reset();
// All registers started out unused.
RegsAvailable.set();
@ -195,7 +187,10 @@ void RegScavenger::forward() {
ScavengeRestore = NULL;
}
bool IsImpDef = MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF;
#if 0
if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
return;
#endif
// Separate register operands into 3 classes: uses, defs, earlyclobbers.
SmallVector<std::pair<const MachineOperand*,unsigned>, 4> UseMOs;
@ -221,14 +216,7 @@ void RegScavenger::forward() {
assert(isUsed(Reg) && "Using an undefined register!");
// Kill of implicit_def defined registers are ignored. e.g.
// entry: 0x2029ab8, LLVM BB @0x1b06080, ID#0:
// Live Ins: %R0
// %R0<def> = IMPLICIT_DEF
// %R0<def> = IMPLICIT_DEF
// STR %R0<kill>, %R0, %reg0, 0, 14, %reg0, Mem:ST(4,4) [0x1b06510 + 0]
// %R1<def> = LDR %R0, %reg0, 24, 14, %reg0, Mem:LD(4,4) [0x1b065bc + 0]
if (MO.isKill() && !isReserved(Reg) && !isImplicitlyDefined(Reg)) {
if (MO.isKill() && !isReserved(Reg)) {
KillRegs.set(Reg);
// Mark sub-registers as used.
@ -278,10 +266,9 @@ void RegScavenger::forward() {
// Implicit def is allowed to "re-define" any register. Similarly,
// implicitly defined registers can be clobbered.
assert((isReserved(Reg) || isUnused(Reg) ||
IsImpDef || isImplicitlyDefined(Reg) ||
isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
"Re-defining a live register!");
setUsed(Reg, IsImpDef);
setUsed(Reg);
}
}

View File

@ -2669,19 +2669,28 @@ SimpleRegisterCoalescing::TurnCopyIntoImpDef(MachineBasicBlock::iterator &I,
CopyMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
for (int i = CopyMI->getNumOperands() - 1, e = 0; i > e; --i)
CopyMI->RemoveOperand(i);
CopyMI->getOperand(0).setIsUndef();
bool NoUse = mri_->use_empty(SrcReg);
if (NoUse) {
for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg),
E = mri_->reg_end(); I != E; ) {
assert(I.getOperand().isDef());
MachineInstr *DefMI = &*I;
++I;
for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(SrcReg),
RE = mri_->reg_end(); RI != RE; ) {
assert(RI.getOperand().isDef());
MachineInstr *DefMI = &*RI;
++RI;
// The implicit_def source has no other uses, delete it.
assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF);
li_->RemoveMachineInstrFromMaps(DefMI);
DefMI->eraseFromParent();
}
}
// Mark uses of implicit_def isUndef.
for (MachineRegisterInfo::use_iterator RI = mri_->use_begin(DstReg),
RE = mri_->use_end(); RI != RE; ++RI) {
assert((*RI).getParent() == MBB);
RI.getOperand().setIsUndef();
}
++I;
return true;
}

View File

@ -0,0 +1,99 @@
; RUN: llvm-as < %s | llc -march=arm -mtriple=armv6-apple-darwin9
@XX = external global i32* ; <i32**> [#uses=1]
define arm_apcscc void @SIM(i8* %A, i8* %B, i32 %M, i32 %N, i32 %K, [256 x i32]* %V, i32 %Q, i32 %R, i32 %nseq) nounwind {
entry:
br i1 undef, label %bb5, label %bb
bb: ; preds = %bb, %entry
br label %bb
bb5: ; preds = %entry
br i1 undef, label %bb6, label %bb8
bb6: ; preds = %bb6, %bb5
br i1 undef, label %bb8, label %bb6
bb8: ; preds = %bb6, %bb5
br label %bb15
bb9: ; preds = %bb15
br i1 undef, label %bb10, label %bb11
bb10: ; preds = %bb9
unreachable
bb11: ; preds = %bb9
br i1 undef, label %bb15, label %bb12
bb12: ; preds = %bb11
%0 = load i32** @XX, align 4 ; <i32*> [#uses=0]
br label %bb228.i
bb74.i: ; preds = %bb228.i
br i1 undef, label %bb138.i, label %bb145.i
bb138.i: ; preds = %bb74.i
br label %bb145.i
bb145.i: ; preds = %bb228.i, %bb138.i, %bb74.i
br i1 undef, label %bb146.i, label %bb151.i
bb146.i: ; preds = %bb145.i
br i1 undef, label %bb228.i, label %bb151.i
bb151.i: ; preds = %bb146.i, %bb145.i
br i1 undef, label %bb153.i, label %bb228.i
bb153.i: ; preds = %bb151.i
br i1 undef, label %bb220.i, label %bb.nph.i98
bb.nph.i98: ; preds = %bb153.i
br label %bb158.i
bb158.i: ; preds = %bb218.i, %bb.nph.i98
%1 = sub i32 undef, undef ; <i32> [#uses=4]
%2 = sub i32 undef, undef ; <i32> [#uses=1]
br i1 undef, label %bb168.i, label %bb160.i
bb160.i: ; preds = %bb158.i
br i1 undef, label %bb161.i, label %bb168.i
bb161.i: ; preds = %bb160.i
br i1 undef, label %bb168.i, label %bb163.i
bb163.i: ; preds = %bb161.i
br i1 undef, label %bb167.i, label %bb168.i
bb167.i: ; preds = %bb163.i
br label %bb168.i
bb168.i: ; preds = %bb167.i, %bb163.i, %bb161.i, %bb160.i, %bb158.i
%f.5.i = phi i32 [ %1, %bb167.i ], [ %2, %bb158.i ], [ %1, %bb160.i ], [ %1, %bb161.i ], [ %1, %bb163.i ] ; <i32> [#uses=1]
%c.14.i = select i1 undef, i32 %f.5.i, i32 undef ; <i32> [#uses=1]
store i32 %c.14.i, i32* undef, align 4
store i32 undef, i32* null, align 4
br i1 undef, label %bb211.i, label %bb218.i
bb211.i: ; preds = %bb168.i
br label %bb218.i
bb218.i: ; preds = %bb211.i, %bb168.i
br i1 undef, label %bb220.i, label %bb158.i
bb220.i: ; preds = %bb218.i, %bb153.i
br i1 undef, label %bb221.i, label %bb228.i
bb221.i: ; preds = %bb220.i
br label %bb228.i
bb228.i: ; preds = %bb221.i, %bb220.i, %bb151.i, %bb146.i, %bb12
br i1 undef, label %bb74.i, label %bb145.i
bb15: ; preds = %bb11, %bb8
br i1 undef, label %return, label %bb9
return: ; preds = %bb15
ret void
}