mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
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:
parent
1d75d3a8ae
commit
ad934b821c
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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]
|
||||
|
91
test/CodeGen/X86/2009-09-23-LiveVariablesBug.ll
Normal file
91
test/CodeGen/X86/2009-09-23-LiveVariablesBug.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user