Clean up LiveVariables and change how it deals with partial updates and kills. This also eliminate the horrible check which scan forward to the end of the basic block. It should be faster and more accurate.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82676 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2009-09-24 02:15:22 +00:00
parent 1d75d3a8ae
commit ad934b821c
5 changed files with 170 additions and 209 deletions

View File

@ -150,21 +150,14 @@ private: // Intermediate data structures
void HandlePhysRegUse(unsigned Reg, MachineInstr *MI);
void HandlePhysRegDef(unsigned Reg, MachineInstr *MI,
SmallVector<unsigned, 4> &Defs,
SmallVector<unsigned, 4> &SuperDefs);
SmallVector<unsigned, 4> &Defs);
void UpdatePhysRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs);
void UpdateSuperRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs);
/// FindLastPartialDef - Return the last partial def of the specified register.
/// Also returns the sub-registers that're defined by the instruction.
MachineInstr *FindLastPartialDef(unsigned Reg,
SmallSet<unsigned,4> &PartDefRegs);
/// hasRegisterUseBelow - Return true if the specified register is used after
/// the current instruction and before its 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

@ -265,78 +265,13 @@ void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) {
PhysRegUse[SubReg] = MI;
}
/// 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;
// First find out if there are any uses / defs below.
bool hasDistInfo = true;
unsigned CurDist = DistanceMap[I];
SmallVector<MachineInstr*, 4> Uses;
SmallVector<MachineInstr*, 4> Defs;
for (MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(Reg),
RE = MRI->reg_end(); RI != RE; ++RI) {
MachineOperand &UDO = RI.getOperand();
MachineInstr *UDMI = &*RI;
if (UDMI->getParent() != MBB)
continue;
DenseMap<MachineInstr*, unsigned>::iterator DI = DistanceMap.find(UDMI);
bool isBelow = false;
if (DI == DistanceMap.end()) {
// Must be below if it hasn't been assigned a distance yet.
isBelow = true;
hasDistInfo = false;
} else if (DI->second > CurDist)
isBelow = true;
if (isBelow) {
if (UDO.isUse())
Uses.push_back(UDMI);
if (UDO.isDef())
Defs.push_back(UDMI);
}
}
if (Uses.empty())
// No uses below.
return false;
else if (!Uses.empty() && Defs.empty())
// There are uses below but no defs below.
return true;
// There are both uses and defs below. We need to know which comes first.
if (!hasDistInfo) {
// Complete DistanceMap for this MBB. This information is computed only
// once per MBB.
++I;
++CurDist;
for (MachineBasicBlock::iterator E = MBB->end(); I != E; ++I, ++CurDist)
DistanceMap.insert(std::make_pair(I, CurDist));
}
unsigned EarliestUse = DistanceMap[Uses[0]];
for (unsigned i = 1, e = Uses.size(); i != e; ++i) {
unsigned Dist = DistanceMap[Uses[i]];
if (Dist < EarliestUse)
EarliestUse = Dist;
}
for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
unsigned Dist = DistanceMap[Defs[i]];
if (Dist < EarliestUse)
// The register is defined before its first use below.
return false;
}
return true;
}
bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
if (!PhysRegUse[Reg] && !PhysRegDef[Reg])
MachineInstr *LastDef = PhysRegDef[Reg];
MachineInstr *LastUse = PhysRegUse[Reg];
if (!LastDef && !LastUse)
return false;
MachineInstr *LastRefOrPartRef = PhysRegUse[Reg]
? PhysRegUse[Reg] : PhysRegDef[Reg];
MachineInstr *LastRefOrPartRef = LastUse ? LastUse : LastDef;
unsigned LastRefOrPartRefDist = DistanceMap[LastRefOrPartRef];
// The whole register is used.
// AL =
@ -355,9 +290,22 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
// AX<dead> = AL<imp-def>
// = AL<kill>
// AX =
MachineInstr *LastPartDef = 0;
unsigned LastPartDefDist = 0;
SmallSet<unsigned, 8> PartUses;
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs) {
MachineInstr *Def = PhysRegDef[SubReg];
if (Def && Def != LastDef) {
// There was a def of this sub-register in between. This is a partial
// def, keep track of the last one.
unsigned Dist = DistanceMap[Def];
if (Dist > LastPartDefDist) {
LastPartDefDist = Dist;
LastPartDef = Def;
}
continue;
}
if (MachineInstr *Use = PhysRegUse[SubReg]) {
PartUses.insert(SubReg);
for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS)
@ -370,46 +318,47 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
}
}
if (LastRefOrPartRef == PhysRegDef[Reg] && LastRefOrPartRef != MI)
// If the last reference is the last def, then it's not used at all.
// That is, unless we are currently processing the last reference itself.
LastRefOrPartRef->addRegisterDead(Reg, TRI, true);
// Partial uses. Mark register def dead and add implicit def of
// sub-registers which are used.
// EAX<dead> = op AL<imp-def>
// That is, EAX def is dead but AL def extends pass it.
// Enable this after live interval analysis is fixed to improve codegen!
else if (!PhysRegUse[Reg]) {
if (LastRefOrPartRef == PhysRegDef[Reg] && LastRefOrPartRef != MI) {
if (LastPartDef)
// The last partial def kills the register.
LastPartDef->addOperand(MachineOperand::CreateReg(Reg, false/*IsDef*/,
true/*IsImp*/, true/*IsKill*/));
else
// If the last reference is the last def, then it's not used at all.
// That is, unless we are currently processing the last reference itself.
LastRefOrPartRef->addRegisterDead(Reg, TRI, true);
} else if (!PhysRegUse[Reg]) {
// Partial uses. Mark register def dead and add implicit def of
// sub-registers which are used.
// EAX<dead> = op AL<imp-def>
// That is, EAX def is dead but AL def extends pass it.
PhysRegDef[Reg]->addRegisterDead(Reg, TRI, true);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs) {
if (PartUses.count(SubReg)) {
bool NeedDef = true;
if (PhysRegDef[Reg] == PhysRegDef[SubReg]) {
MachineOperand *MO = PhysRegDef[Reg]->findRegisterDefOperand(SubReg);
if (MO) {
NeedDef = false;
assert(!MO->isDead());
}
if (!PartUses.count(SubReg))
continue;
bool NeedDef = true;
if (PhysRegDef[Reg] == PhysRegDef[SubReg]) {
MachineOperand *MO = PhysRegDef[Reg]->findRegisterDefOperand(SubReg);
if (MO) {
NeedDef = false;
assert(!MO->isDead());
}
if (NeedDef)
PhysRegDef[Reg]->addOperand(MachineOperand::CreateReg(SubReg,
true, true));
LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true);
for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS)
PartUses.erase(*SS);
}
if (NeedDef)
PhysRegDef[Reg]->addOperand(MachineOperand::CreateReg(SubReg,
true/*IsDef*/, true/*IsImp*/));
LastRefOrPartRef->addRegisterKilled(SubReg, TRI, true);
for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS)
PartUses.erase(*SS);
}
}
else
} else
LastRefOrPartRef->addRegisterKilled(Reg, TRI, true);
return true;
}
void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI,
SmallVector<unsigned, 4> &Defs,
SmallVector<unsigned, 4> &SuperDefs) {
SmallVector<unsigned, 4> &Defs) {
// What parts of the register are previously defined?
SmallSet<unsigned, 32> Live;
if (PhysRegDef[Reg] || PhysRegUse[Reg]) {
@ -425,6 +374,8 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI,
// AL =
// AH =
// = AX
if (Live.count(SubReg))
continue;
if (PhysRegDef[SubReg] || PhysRegUse[SubReg]) {
Live.insert(SubReg);
for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS)
@ -435,49 +386,18 @@ void LiveVariables::HandlePhysRegDef(unsigned Reg, MachineInstr *MI,
// Start from the largest piece, find the last time any part of the register
// is referenced.
if (!HandlePhysRegKill(Reg, MI)) {
// Only some of the sub-registers are used.
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs) {
if (!Live.count(SubReg))
// Skip if this sub-register isn't defined.
continue;
if (HandlePhysRegKill(SubReg, MI)) {
Live.erase(SubReg);
for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS)
Live.erase(*SS);
}
}
assert(Live.empty() && "Not all defined registers are killed / dead?");
HandlePhysRegKill(Reg, MI);
// Only some of the sub-registers are used.
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
unsigned SubReg = *SubRegs; ++SubRegs) {
if (!Live.count(SubReg))
// Skip if this sub-register isn't defined.
continue;
HandlePhysRegKill(SubReg, MI);
}
if (MI) {
// Does this extend the live range of a super-register?
SmallSet<unsigned, 8> Processed;
for (const unsigned *SuperRegs = TRI->getSuperRegisters(Reg);
unsigned SuperReg = *SuperRegs; ++SuperRegs) {
if (Processed.count(SuperReg))
continue;
MachineInstr *LastRef = PhysRegUse[SuperReg]
? PhysRegUse[SuperReg] : PhysRegDef[SuperReg];
if (LastRef && LastRef != MI) {
// The larger register is previously defined. Now a smaller part is
// being re-defined. Treat it as read/mod/write if there are uses
// below.
// EAX =
// AX = EAX<imp-use,kill>, EAX<imp-def>
// ...
// = EAX
SuperDefs.push_back(SuperReg);
Processed.insert(SuperReg);
for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS)
Processed.insert(*SS);
}
}
// Remember this def.
Defs.push_back(Reg);
}
if (MI)
Defs.push_back(Reg); // Remember this def.
}
void LiveVariables::UpdatePhysRegDefs(MachineInstr *MI,
@ -510,51 +430,6 @@ namespace {
};
}
void LiveVariables::UpdateSuperRegDefs(MachineInstr *MI,
SmallVector<unsigned, 4> &SuperDefs) {
// This instruction has defined part of some registers. If there are no
// more uses below MI, then the last use / def becomes kill / dead.
if (SuperDefs.empty())
return;
RegSorter RS(TRI);
std::sort(SuperDefs.begin(), SuperDefs.end(), RS);
SmallSet<unsigned, 4> Processed;
for (unsigned j = 0, ee = SuperDefs.size(); j != ee; ++j) {
unsigned SuperReg = SuperDefs[j];
if (!Processed.insert(SuperReg))
continue;
if (hasRegisterUseBelow(SuperReg, MI, MI->getParent())) {
// Previous use / def is not the last use / dead def. It's now
// partially re-defined.
MI->addOperand(MachineOperand::CreateReg(SuperReg, false/*IsDef*/,
true/*IsImp*/,true/*IsKill*/));
MI->addOperand(MachineOperand::CreateReg(SuperReg, true/*IsDef*/,
true/*IsImp*/));
PhysRegDef[SuperReg] = MI;
PhysRegUse[SuperReg] = NULL;
for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) {
Processed.insert(*SS);
PhysRegDef[*SS] = MI;
PhysRegUse[*SS] = NULL;
}
} else {
// Previous use / def is kill / dead. It's not being re-defined.
HandlePhysRegKill(SuperReg, MI);
PhysRegDef[SuperReg] = 0;
PhysRegUse[SuperReg] = NULL;
for (const unsigned *SS = TRI->getSubRegisters(SuperReg); *SS; ++SS) {
Processed.insert(*SS);
if (PhysRegDef[*SS] == MI)
continue; // This instruction may have defined it.
PhysRegDef[*SS] = MI;
PhysRegUse[*SS] = NULL;
}
}
}
SuperDefs.clear();
}
bool LiveVariables::runOnMachineFunction(MachineFunction &mf) {
MF = &mf;
MRI = &mf.getRegInfo();
@ -588,14 +463,11 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) {
// Mark live-in registers as live-in.
SmallVector<unsigned, 4> Defs;
SmallVector<unsigned, 4> SuperDefs;
for (MachineBasicBlock::const_livein_iterator II = MBB->livein_begin(),
EE = MBB->livein_end(); II != EE; ++II) {
assert(TargetRegisterInfo::isPhysicalRegister(*II) &&
"Cannot have a live-in virtual register!");
HandlePhysRegDef(*II, 0, Defs, SuperDefs);
UpdatePhysRegDefs(0, Defs);
SuperDefs.clear();
HandlePhysRegDef(*II, 0, Defs);
}
// Loop over all of the instructions, processing them.
@ -641,12 +513,9 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) {
unsigned MOReg = DefRegs[i];
if (TargetRegisterInfo::isVirtualRegister(MOReg))
HandleVirtRegDef(MOReg, MI);
else if (!ReservedRegisters[MOReg]) {
HandlePhysRegDef(MOReg, MI, Defs, SuperDefs);
}
else if (!ReservedRegisters[MOReg])
HandlePhysRegDef(MOReg, MI, Defs);
}
UpdateSuperRegDefs(MI, SuperDefs);
UpdatePhysRegDefs(MI, Defs);
}
@ -685,11 +554,8 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) {
// Loop over PhysRegDef / PhysRegUse, killing any registers that are
// available at the end of the basic block.
for (unsigned i = 0; i != NumRegs; ++i)
if (PhysRegDef[i] || PhysRegUse[i]) {
HandlePhysRegDef(i, 0, Defs, SuperDefs);
UpdatePhysRegDefs(0, Defs);
SuperDefs.clear();
}
if (PhysRegDef[i] || PhysRegUse[i])
HandlePhysRegDef(i, 0, Defs);
std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0);
std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0);

View File

@ -268,6 +268,16 @@ bool SimpleRegisterCoalescing::HasOtherReachingDefs(LiveInterval &IntA,
return false;
}
static void
TransferImplicitOps(MachineInstr *MI, MachineInstr *NewMI) {
for (unsigned i = MI->getDesc().getNumOperands(), e = MI->getNumOperands();
i != e; ++i) {
MachineOperand &MO = MI->getOperand(i);
if (MO.isReg() && MO.isImplicit())
NewMI->addOperand(MO);
}
}
/// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy with IntA
/// being the source and IntB being the dest, thus this defines a value number
/// in IntB. If the source value number (in IntA) is defined by a commutable
@ -416,7 +426,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
++UI;
if (JoinedCopies.count(UseMI))
continue;
MachineInstrIndex UseIdx = li_->getInstructionIndex(UseMI);
MachineInstrIndex UseIdx= li_->getUseIndex(li_->getInstructionIndex(UseMI));
LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx);
if (ULR == IntA.end() || ULR->valno != AValNo)
continue;
@ -427,7 +437,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
if (Extended)
UseMO.setIsKill(false);
else
BKills.push_back(li_->getNextSlot(li_->getUseIndex(UseIdx)));
BKills.push_back(li_->getNextSlot(UseIdx));
}
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (!tii_->isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx))
@ -724,6 +734,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
}
}
TransferImplicitOps(CopyMI, NewMI);
li_->ReplaceMachineInstrInMaps(CopyMI, NewMI);
CopyMI->eraseFromParent();
ReMatCopies.insert(CopyMI);

View File

@ -1,4 +1,4 @@
; RUN: llc < %s -mtriple=i386-apple-darwin -disable-fp-elim -stats |& grep asm-printer | grep 56
; RUN: llc < %s -mtriple=i386-apple-darwin -disable-fp-elim -stats |& grep asm-printer | grep 59
; PR2568
@g_3 = external global i16 ; <i16*> [#uses=1]

View File

@ -0,0 +1,91 @@
; RUN: llc < %s -mtriple=x86_64-apple-darwin10
; rdar://7247745
%struct._lck_mtx_ = type { %union.anon }
%struct._lck_rw_t_internal_ = type <{ i16, i8, i8, i32, i32, i32 }>
%struct.anon = type { i64, i64, [2 x i8], i8, i8, i32 }
%struct.memory_object = type { i32, i32, %struct.memory_object_pager_ops* }
%struct.memory_object_control = type { i32, i32, %struct.vm_object* }
%struct.memory_object_pager_ops = type { void (%struct.memory_object*)*, void (%struct.memory_object*)*, i32 (%struct.memory_object*, %struct.memory_object_control*, i32)*, i32 (%struct.memory_object*)*, i32 (%struct.memory_object*, i64, i32, i32, i32*)*, i32 (%struct.memory_object*, i64, i32, i64*, i32*, i32, i32, i32)*, i32 (%struct.memory_object*, i64, i32)*, i32 (%struct.memory_object*, i64, i64, i32)*, i32 (%struct.memory_object*, i64, i64, i32)*, i32 (%struct.memory_object*, i32)*, i32 (%struct.memory_object*)*, i8* }
%struct.queue_entry = type { %struct.queue_entry*, %struct.queue_entry* }
%struct.upl = type { %struct._lck_mtx_, i32, i32, %struct.vm_object*, i64, i32, i64, %struct.vm_object*, i32, i8* }
%struct.upl_page_info = type <{ i32, i8, [3 x i8] }>
%struct.vm_object = type { %struct.queue_entry, %struct._lck_rw_t_internal_, i64, %struct.vm_page*, i32, i32, i32, i32, %struct.vm_object*, %struct.vm_object*, i64, %struct.memory_object*, i64, %struct.memory_object_control*, i32, i16, i16, [2 x i8], i8, i8, %struct.queue_entry, %struct.queue_entry, i64, i32, i32, i32, i8*, i64, i8, i8, [2 x i8], %struct.queue_entry }
%struct.vm_page = type { %struct.queue_entry, %struct.queue_entry, %struct.vm_page*, %struct.vm_object*, i64, [2 x i8], i8, i8, i32, i8, i8, i8, i8, i32 }
%union.anon = type { %struct.anon }
declare i64 @OSAddAtomic64(i64, i64*) noredzone noimplicitfloat
define i32 @upl_commit_range(%struct.upl* %upl, i32 %offset, i32 %size, i32 %flags, %struct.upl_page_info* %page_list, i32 %count, i32* nocapture %empty) nounwind noredzone noimplicitfloat {
entry:
br i1 undef, label %if.then, label %if.end
if.end: ; preds = %entry
br i1 undef, label %if.end143, label %if.then136
if.then136: ; preds = %if.end
unreachable
if.end143: ; preds = %if.end
br i1 undef, label %if.else155, label %if.then153
if.then153: ; preds = %if.end143
br label %while.cond
if.else155: ; preds = %if.end143
unreachable
while.cond: ; preds = %if.end1039, %if.then153
br i1 undef, label %if.then1138, label %while.body
while.body: ; preds = %while.cond
br i1 undef, label %if.end260, label %if.then217
if.then217: ; preds = %while.body
br i1 undef, label %if.end260, label %if.then230
if.then230: ; preds = %if.then217
br i1 undef, label %if.then246, label %if.end260
if.then246: ; preds = %if.then230
br label %if.end260
if.end260: ; preds = %if.then246, %if.then230, %if.then217, %while.body
br i1 undef, label %if.end296, label %if.then266
if.then266: ; preds = %if.end260
unreachable
if.end296: ; preds = %if.end260
br i1 undef, label %if.end1039, label %if.end306
if.end306: ; preds = %if.end296
br i1 undef, label %if.end796, label %if.then616
if.then616: ; preds = %if.end306
br i1 undef, label %commit_next_page, label %do.body716
do.body716: ; preds = %if.then616
%call721 = call i64 @OSAddAtomic64(i64 1, i64* undef) nounwind noredzone noimplicitfloat ; <i64> [#uses=0]
call void asm sideeffect "movq\090x0($0),%rdi\0A\09movq\090x8($0),%rsi\0A\09.section __DATA, __data\0A\09.globl __dtrace_probeDOLLAR${:uid}4794___vminfo____pgrec\0A\09__dtrace_probeDOLLAR${:uid}4794___vminfo____pgrec:.quad 1f\0A\09.text\0A\091:nop\0A\09nop\0A\09nop\0A\09", "r,~{memory},~{di},~{si},~{dirflag},~{fpsr},~{flags}"(i64* undef) nounwind
br label %commit_next_page
if.end796: ; preds = %if.end306
unreachable
commit_next_page: ; preds = %do.body716, %if.then616
br i1 undef, label %if.end1039, label %if.then1034
if.then1034: ; preds = %commit_next_page
br label %if.end1039
if.end1039: ; preds = %if.then1034, %commit_next_page, %if.end296
br label %while.cond
if.then1138: ; preds = %while.cond
unreachable
if.then: ; preds = %entry
ret i32 4
}