[llvm-commits] [llvm] r61458 - /llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp
Owen Anderson
resistor at mac.com
Thu Jan 1 10:57:46 PST 2009
The goal is to use it to reconstruct the liveinterval in cases where
the splitting creates a new join point.
--Owen
On Jan 1, 2009, at 2:11 AM, Evan Cheng wrote:
> Hi Owen,
>
> When do you envision this code will be used? I guess this is intented
> to replace an old interval with a more precised one? Is it for
> performance benefit?
>
> Evan
>
> On Dec 28, 2008, at 1:48 PM, Owen Anderson <resistor at mac.com> wrote:
>
>> Author: resistor
>> Date: Sun Dec 28 15:48:48 2008
>> New Revision: 61458
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=61458&view=rev
>> Log:
>> Add prototype code for recomputing a live interval's ranges and
>> valnos through recursive phi construction.
>>
>> Modified:
>> llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp
>>
>> Modified: llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp?rev=61458&r1=61457&r2=61458&view=diff
>>
>> ===
>> ===
>> ===
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp Sun Dec 28 15:48:48
>> 2008
>> @@ -171,7 +171,15 @@
>> int& SS,
>> SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
>> void RenumberValno(VNInfo* VN);
>> - };
>> + void ReconstructLiveInterval(LiveInterval* LI);
>> + VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator use,
>> + LiveInterval* LI,
>> + DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*,
>> 2> >& Defs,
>> + DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*,
>> 2> >& Uses,
>> + DenseMap<MachineInstr*,
>> VNInfo*>& NewVNs,
>> + DenseMap<MachineBasicBlock*,
>> VNInfo*>& Visited,
>> + bool toplevel =
>> false);
>> +};
>> } // end anonymous namespace
>>
>> char PreAllocSplitting::ID = 0;
>> @@ -577,6 +585,257 @@
>> return LastMI;
>> }
>>
>> +/// PerformPHIConstruction - From properly set up use and def
>> lists, use a PHI
>> +/// construction algorithm to compute the ranges and valnos for an
>> interval.
>> +VNInfo* PreAllocSplitting::PerformPHIConstruction(
>> +
>> MachineBasicBlock::iterator use,
>> +
>> LiveInterval* LI,
>> + DenseMap<MachineBasicBlock*,
>> SmallPtrSet<MachineInstr*, 2> >& Defs,
>> + DenseMap<MachineBasicBlock*,
>> SmallPtrSet<MachineInstr*, 2> >& Uses,
>> + DenseMap<MachineInstr*,
>> VNInfo*>& NewVNs,
>> + DenseMap<MachineBasicBlock*,
>> VNInfo*>& Visited,
>> + bool
>> toplevel) {
>> + // Return memoized result if it's available.
>> + if (Visited.count(use->getParent()))
>> + return Visited[use->getParent()];
>> +
>> + typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*,
>> 2> > RegMap;
>> +
>> + // Check if our block contains any uses or defs.
>> + bool ContainsDefs = Defs.count(use->getParent());
>> + bool ContainsUses = Uses.count(use->getParent());
>> +
>> + VNInfo* ret = 0;
>> +
>> + // Enumerate the cases of use/def contaning blocks.
>> + if (!ContainsDefs && !ContainsUses) {
>> + Fallback:
>> + // NOTE: Because this is the fallback case from other cases, we
>> do NOT
>> + // assume that we are not at toplevel here.
>> +
>> + // If there are no uses or defs between our starting point and
>> the beginning
>> + // of the block, then recursive perform phi construction on our
>> predecessors
>> + MachineBasicBlock* MBB = use->getParent();
>> + DenseMap<MachineBasicBlock*, VNInfo*> IncomingVNs;
>> + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
>> + PE = MBB->pred_end(); PI != PE; ++PI) {
>> + VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), LI,
>> Defs, Uses,
>> + NewVNs, Visited,
>> false);
>> + IncomingVNs[*PI] = Incoming;
>> + }
>> +
>> + // If only one VNInfo came back from our predecessors, just use
>> that one...
>> + if (IncomingVNs.size() == 1) {
>> + ret = IncomingVNs.begin()->second;
>> + unsigned StartIndex = LIs->getMBBStartIdx(use->getParent());
>> + unsigned EndIndex = 0;
>> + if (toplevel) {
>> + EndIndex = LIs->getInstructionIndex(use);
>> + EndIndex = LiveIntervals::getUseIndex(EndIndex);
>> + } else
>> + EndIndex = LIs->getMBBEndIdx(use->getParent());
>> +
>> + LI->addRange(LiveRange(StartIndex, EndIndex, ret));
>> + } else {
>> + // Otherwise, merge the incoming VNInfos with a phi join.
>> Create a new
>> + // VNInfo to represent the joined value.
>> + for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I =
>> + IncomingVNs.begin(), E = IncomingVNs.end(); I != E; +
>> +I) {
>> + I->second->hasPHIKill = true;
>> + unsigned KillIndex = LIs->getMBBEndIdx(I->first);
>> + LI->addKill(I->second, KillIndex);
>> + }
>> +
>> + unsigned StartIndex = LIs->getMBBStartIdx(use->getParent());
>> + unsigned EndIndex = 0;
>> + if (toplevel) {
>> + EndIndex = LIs->getInstructionIndex(use);
>> + EndIndex = LiveIntervals::getUseIndex(EndIndex);
>> + } else
>> + EndIndex = LIs->getMBBEndIdx(use->getParent());
>> + ret = LI->getNextValue(StartIndex, /*FIXME*/ 0,
>> + LIs->getVNInfoAllocator());
>> + LI->addRange(LiveRange(StartIndex, EndIndex, ret));
>> + }
>> + } else if (ContainsDefs && !ContainsUses) {
>> + SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[use-
>>> getParent()];
>> +
>> + // Search for the def in this block. If we don't find it
>> before the
>> + // instruction we care about, go to the fallback case. Note
>> that that
>> + // should never happen: this cannot be a toplevel block, so use
>> should
>> + // always be an end() iterator.
>> + assert(use == use->getParent()->end() && "No use marked in
>> toplevel block");
>> +
>> + MachineBasicBlock::iterator walker = use;
>> + --walker;
>> + while (walker != use->getParent()->begin())
>> + if (BlockDefs.count(walker)) {
>> + break;
>> + } else
>> + --walker;
>> +
>> + // Once we've found it, extend its VNInfo to our instruction.
>> + unsigned DefIndex = LIs->getInstructionIndex(walker);
>> + DefIndex = LiveIntervals::getDefIndex(DefIndex);
>> + unsigned EndIndex = LIs->getMBBEndIdx(use->getParent());
>> +
>> + ret = NewVNs[walker];
>> + LI->addRange(LiveRange(DefIndex, EndIndex, ret));
>> + } else if (!ContainsDefs && ContainsUses) {
>> + SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[use-
>>> getParent()];
>> +
>> + // Search for the use in this block that precedes the
>> instruction we care
>> + // about, going to the fallback case if we don't find it.
>> +
>> + if (use == use->getParent()->begin())
>> + goto Fallback;
>> +
>> + MachineBasicBlock::iterator walker = use;
>> + --walker;
>> + bool found = false;
>> + while (walker != use->getParent()->begin())
>> + if (BlockUses.count(walker)) {
>> + found = true;
>> + break;
>> + } else
>> + --walker;
>> +
>> + // Must check begin() too.
>> + if (!found)
>> + if (BlockUses.count(walker))
>> + found = true;
>> + else
>> + goto Fallback;
>> +
>> + unsigned UseIndex = LIs->getInstructionIndex(walker);
>> + UseIndex = LiveIntervals::getUseIndex(UseIndex);
>> + unsigned EndIndex = 0;
>> + if (toplevel) {
>> + EndIndex = LIs->getInstructionIndex(walker);
>> + EndIndex = LiveIntervals::getUseIndex(EndIndex);
>> + } else
>> + EndIndex = LIs->getMBBEndIdx(use->getParent());
>> +
>> + // Now, recursively phi construct the VNInfo for the use we
>> found,
>> + // and then extend it to include the instruction we care about
>> + ret = PerformPHIConstruction(walker, LI, Defs, Uses,
>> + NewVNs, Visited, false);
>> +
>> + // FIXME: Need to set kills properly for inter-block stuff.
>> + if (toplevel) {
>> + if (LI->isKill(ret, UseIndex)) LI->removeKill(ret, UseIndex);
>> + LI->addKill(ret, EndIndex);
>> + }
>> +
>> + LI->addRange(LiveRange(UseIndex, EndIndex, ret));
>> + } else if (ContainsDefs && ContainsUses){
>> + SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[use-
>>> getParent()];
>> + SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[use-
>>> getParent()];
>> +
>> + // This case is basically a merging of the two preceding case,
>> with the
>> + // special note that checking for defs must take precedence
>> over checking
>> + // for uses, because of two-address instructions.
>> +
>> + if (use == use->getParent()->begin())
>> + goto Fallback;
>> +
>> + MachineBasicBlock::iterator walker = use;
>> + --walker;
>> + bool foundDef = false;
>> + bool foundUse = false;
>> + while (walker != use->getParent()->begin())
>> + if (BlockDefs.count(walker)) {
>> + foundDef = true;
>> + break;
>> + } else if (BlockUses.count(walker)) {
>> + foundUse = true;
>> + break;
>> + } else
>> + --walker;
>> +
>> + // Must check begin() too.
>> + if (!foundDef && !foundUse)
>> + if (BlockDefs.count(walker))
>> + foundDef = true;
>> + else if (BlockUses.count(walker))
>> + foundUse = true;
>> + else
>> + goto Fallback;
>> +
>> + unsigned StartIndex = LIs->getInstructionIndex(walker);
>> + StartIndex = foundDef ? LiveIntervals::getDefIndex(StartIndex) :
>> + LiveIntervals::getUseIndex(StartIndex);
>> + unsigned EndIndex = 0;
>> + if (toplevel) {
>> + EndIndex = LIs->getInstructionIndex(walker);
>> + EndIndex = LiveIntervals::getUseIndex(EndIndex);
>> + } else
>> + EndIndex = LIs->getMBBEndIdx(use->getParent());
>> +
>> + if (foundDef)
>> + ret = NewVNs[walker];
>> + else
>> + ret = PerformPHIConstruction(walker, LI, Defs, Uses,
>> + NewVNs, Visited, false);
>> +
>> + // FIXME: Need to set kills properly for inter-block stuff.
>> + if (toplevel) {
>> + if (foundUse && LI->isKill(ret, StartIndex))
>> + LI->removeKill(ret, StartIndex);
>> + LI->addKill(ret, EndIndex);
>> + }
>> +
>> + LI->addRange(LiveRange(StartIndex, EndIndex, ret));
>> + }
>> +
>> + // Memoize results so we don't have to recompute them.
>> + if (!toplevel) Visited[use->getParent()] = ret;
>> +
>> + return ret;
>> +}
>> +
>> +/// ReconstructLiveInterval - Recompute a live interval from
>> scratch.
>> +void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) {
>> + BumpPtrAllocator& Alloc = LIs->getVNInfoAllocator();
>> +
>> + // Clear the old ranges and valnos;
>> + LI->clear();
>> +
>> + // Cache the uses and defs of the register
>> + typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*,
>> 2> > RegMap;
>> + RegMap Defs, Uses;
>> +
>> + // Keep track of the new VNs we're creating.
>> + DenseMap<MachineInstr*, VNInfo*> NewVNs;
>> + SmallPtrSet<VNInfo*, 2> PhiVNs;
>> +
>> + // Cache defs, and create a new VNInfo for each def.
>> + for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI-
>>> reg),
>> + DE = MRI->def_end(); DI != DE; ++DI) {
>> + Defs[(*DI).getParent()].insert(&*DI);
>> +
>> + unsigned DefIdx = LIs->getInstructionIndex(&*DI);
>> + DefIdx = LiveIntervals::getDefIndex(DefIdx);
>> +
>> + VNInfo* NewVN = LI->getNextValue(DefIdx, /*FIXME*/ 0, Alloc);
>> + NewVNs[&*DI] = NewVN;
>> + }
>> +
>> + // Cache uses as a separate pass from actually processing them.
>> + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI-
>>> reg),
>> + UE = MRI->use_end(); UI != UE; ++UI)
>> + Uses[(*UI).getParent()].insert(&*UI);
>> +
>> + // Now, actually process every use and use a phi construction
>> algorithm
>> + // to walk from it to its reaching definitions, building VNInfos
>> along
>> + // the way.
>> + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI-
>>> reg),
>> + UE = MRI->use_end(); UI != UE; ++UI) {
>> + DenseMap<MachineBasicBlock*, VNInfo*> Visited;
>> + PerformPHIConstruction(&*UI, LI, Defs, Uses, NewVNs, Visited,
>> true);
>> + }
>> +}
>> +
>> /// ShrinkWrapLiveInterval - Recursively traverse the predecessor
>> /// chain to find the new 'kills' and shrink wrap the live interval
>> to the
>> /// new kill indices.
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list