[llvm-commits] [llvm] r61458 - /llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp
Evan Cheng
evan.cheng at apple.com
Thu Jan 1 18:08:24 PST 2009
Ok. Does it make sense to move the code out preallocsplitting?
Thanks,
Evan
On Jan 1, 2009, at 10:57 AM, Owen Anderson wrote:
> 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
>
> _______________________________________________
> 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