[llvm-commits] [llvm] r121388 - in /llvm/trunk/lib/CodeGen: LiveIntervalUnion.cpp LiveIntervalUnion.h RegAllocBase.h RegAllocBasic.cpp RegAllocGreedy.cpp
Evan Cheng
evan.cheng at apple.com
Thu Dec 9 22:49:06 PST 2010
On Dec 9, 2010, at 10:15 AM, Andrew Trick wrote:
> Author: atrick
> Date: Thu Dec 9 12:15:21 2010
> New Revision: 121388
>
> URL: http://llvm.org/viewvc/llvm-project?rev=121388&view=rev
> Log:
> Added register reassignment prototype to RAGreedy. It's a simple
> heuristic to reshuffle register assignments when we can't find an
> available reg.
Do you mean to use this to vacate a physical register that's preferred by another virtual register with stricter allocation requirement?
e.g. vacate r1 in order to form r0 / r1 pair.
Evan
>
> Modified:
> llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp
> llvm/trunk/lib/CodeGen/LiveIntervalUnion.h
> llvm/trunk/lib/CodeGen/RegAllocBase.h
> llvm/trunk/lib/CodeGen/RegAllocBasic.cpp
> llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp
>
> Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp?rev=121388&r1=121387&r2=121388&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp (original)
> +++ llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp Thu Dec 9 12:15:21 2010
> @@ -247,10 +247,13 @@
> if (!IR.LiveUnionI.value()->isSpillable())
> SeenUnspillableVReg = true;
>
> - InterferingVRegs.push_back(IR.LiveUnionI.value());
> if (InterferingVRegs.size() == MaxInterferingRegs)
> + // Leave SeenAllInterferences set to false to indicate that at least one
> + // interference exists beyond those we collected.
> return MaxInterferingRegs;
>
> + InterferingVRegs.push_back(IR.LiveUnionI.value());
> +
> // Cache the most recent interfering vreg to bypass isSeenInterference.
> RecentInterferingVReg = IR.LiveUnionI.value();
> ++IR.LiveUnionI;
>
> Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalUnion.h?rev=121388&r1=121387&r2=121388&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/LiveIntervalUnion.h (original)
> +++ llvm/trunk/lib/CodeGen/LiveIntervalUnion.h Thu Dec 9 12:15:21 2010
> @@ -159,10 +159,7 @@
> }
>
> void init(LiveInterval *VReg, LiveIntervalUnion *LIU) {
> - if (VirtReg == VReg) {
> - // We currently allow query objects to be reused acrossed live virtual
> - // registers, but always for the same live interval union.
> - assert(LiveUnion == LIU && "inconsistent initialization");
> + if (VirtReg == VReg && LiveUnion == LIU) {
> // Retain cached results, e.g. firstInterference.
> return;
> }
>
> Modified: llvm/trunk/lib/CodeGen/RegAllocBase.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBase.h?rev=121388&r1=121387&r2=121388&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/RegAllocBase.h (original)
> +++ llvm/trunk/lib/CodeGen/RegAllocBase.h Thu Dec 9 12:15:21 2010
> @@ -58,8 +58,8 @@
> /// be extended to add interesting heuristics.
> ///
> /// Register allocators must override the selectOrSplit() method to implement
> -/// live range splitting. LessSpillWeightPriority is provided as a standard
> -/// comparator, but we may add an interface to override it if necessary.
> +/// live range splitting. They may also override getPriority() which otherwise
> +/// defaults to the spill weight computed by CalculateSpillWeights.
> class RegAllocBase {
> LiveIntervalUnion::Allocator UnionAllocator;
> protected:
>
> Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBasic.cpp?rev=121388&r1=121387&r2=121388&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp (original)
> +++ llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Thu Dec 9 12:15:21 2010
> @@ -435,15 +435,13 @@
> LiveInterval *interferingVirtReg =
> Queries[interfReg].firstInterference().liveUnionPos().value();
>
> - // The current VirtReg must either spillable, or one of its interferences
> + // The current VirtReg must either be spillable, or one of its interferences
> // must have less spill weight.
> if (interferingVirtReg->weight < VirtReg.weight ) {
> PhysRegSpillCands.push_back(PhysReg);
> }
> }
> // Try to spill another interfering reg with less spill weight.
> - //
> - // FIXME: RAGreedy will sort this list by spill weight.
> for (SmallVectorImpl<unsigned>::iterator PhysRegI = PhysRegSpillCands.begin(),
> PhysRegE = PhysRegSpillCands.end(); PhysRegI != PhysRegE; ++PhysRegI) {
>
>
> Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=121388&r1=121387&r2=121388&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original)
> +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Thu Dec 9 12:15:21 2010
> @@ -79,6 +79,10 @@
> virtual bool runOnMachineFunction(MachineFunction &mf);
>
> static char ID;
> +
> +private:
> + bool reassignVReg(LiveInterval &InterferingVReg, unsigned OldPhysReg);
> + bool reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg);
> };
> } // end anonymous namespace
>
> @@ -142,10 +146,84 @@
> return Priority;
> }
>
> +// Attempt to reassign this virtual register to a different physical register.
> +//
> +// FIXME: we are not yet caching these "second-level" interferences discovered
> +// in the sub-queries. These interferences can change with each call to
> +// selectOrSplit. However, we could implement a "may-interfere" cache that
> +// could be conservatively dirtied when we reassign or split.
> +//
> +// FIXME: This may result in a lot of alias queries. We could summarize alias
> +// live intervals in their parent register's live union, but it's messy.
> +bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg,
> + unsigned OldPhysReg) {
> + assert(OldPhysReg == VRM->getPhys(InterferingVReg.reg) &&
> + "inconsistent phys reg assigment");
> +
> + const TargetRegisterClass *TRC = MRI->getRegClass(InterferingVReg.reg);
> + for (TargetRegisterClass::iterator I = TRC->allocation_order_begin(*MF),
> + E = TRC->allocation_order_end(*MF);
> + I != E; ++I) {
> + unsigned PhysReg = *I;
> + if (PhysReg == OldPhysReg)
> + continue;
> +
> + // Instantiate a "subquery", not to be confused with the Queries array.
> + LiveIntervalUnion::Query subQ(&InterferingVReg,
> + &PhysReg2LiveUnion[PhysReg]);
> + if (subQ.checkInterference())
> + continue;
> +
> + for (const unsigned *AliasI = TRI->getAliasSet(PhysReg);
> + *AliasI; ++AliasI) {
> + subQ.init(&InterferingVReg, &PhysReg2LiveUnion[*AliasI]);
> + if (subQ.checkInterference())
> + continue;
> + }
> + DEBUG(dbgs() << "reassigning: " << InterferingVReg << " from " <<
> + TRI->getName(OldPhysReg) << " to " << TRI->getName(PhysReg) << '\n');
> +
> + // Reassign the interfering virtual reg to this physical reg.
> + PhysReg2LiveUnion[OldPhysReg].extract(InterferingVReg);
> + VRM->clearVirt(InterferingVReg.reg);
> + VRM->assignVirt2Phys(InterferingVReg.reg, PhysReg);
> + PhysReg2LiveUnion[PhysReg].unify(InterferingVReg);
> +
> + return true;
> + }
> + return false;
> +}
> +
> +// Collect all virtual regs currently assigned to PhysReg that interfere with
> +// VirtReg.
> +//
> +// Currently, for simplicity, we only attempt to reassign a single interference
> +// within the same register class.
> +bool RAGreedy::reassignInterferences(LiveInterval &VirtReg, unsigned PhysReg) {
> + LiveIntervalUnion::Query &Q = query(VirtReg, PhysReg);
> +
> + // Limit the interference search to one interference.
> + Q.collectInterferingVRegs(1);
> + assert(Q.interferingVRegs().size() == 1 &&
> + "expected at least one interference");
> +
> + // Do not attempt reassignment unless we find only a single interference.
> + if (!Q.seenAllInterferences())
> + return false;
> +
> + // Don't allow any interferences on aliases.
> + for (const unsigned *AliasI = TRI->getAliasSet(PhysReg); *AliasI; ++AliasI) {
> + if (query(VirtReg, *AliasI).checkInterference())
> + return false;
> + }
> +
> + return reassignVReg(*Q.interferingVRegs()[0], PhysReg);
> +}
> +
> unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
> SmallVectorImpl<LiveInterval*> &SplitVRegs) {
> // Populate a list of physical register spill candidates.
> - SmallVector<unsigned, 8> PhysRegSpillCands;
> + SmallVector<unsigned, 8> PhysRegSpillCands, ReassignCands;
>
> // Check for an available register in this class.
> const TargetRegisterClass *TRC = MRI->getRegClass(VirtReg.reg);
> @@ -168,24 +246,44 @@
>
> // Check interference and as a side effect, intialize queries for this
> // VirtReg and its aliases.
> - unsigned interfReg = checkPhysRegInterference(VirtReg, PhysReg);
> - if (interfReg == 0) {
> + unsigned InterfReg = checkPhysRegInterference(VirtReg, PhysReg);
> + if (InterfReg == 0) {
> // Found an available register.
> return PhysReg;
> }
> assert(!VirtReg.empty() && "Empty VirtReg has interference");
> - LiveInterval *interferingVirtReg =
> - Queries[interfReg].firstInterference().liveUnionPos().value();
> + LiveInterval *InterferingVirtReg =
> + Queries[InterfReg].firstInterference().liveUnionPos().value();
>
> - // The current VirtReg must either spillable, or one of its interferences
> + // The current VirtReg must either be spillable, or one of its interferences
> // must have less spill weight.
> - if (interferingVirtReg->weight < VirtReg.weight ) {
> - PhysRegSpillCands.push_back(PhysReg);
> + if (InterferingVirtReg->weight < VirtReg.weight ) {
> + // For simplicity, only consider reassigning registers in the same class.
> + if (InterfReg == PhysReg)
> + ReassignCands.push_back(PhysReg);
> + else
> + PhysRegSpillCands.push_back(PhysReg);
> }
> }
> +
> + // Try to reassign interfering physical register. Priority among
> + // PhysRegSpillCands does not matter yet, because the reassigned virtual
> + // registers will still be assigned to physical registers.
> + for (SmallVectorImpl<unsigned>::iterator PhysRegI = ReassignCands.begin(),
> + PhysRegE = ReassignCands.end(); PhysRegI != PhysRegE; ++PhysRegI) {
> + if (reassignInterferences(VirtReg, *PhysRegI))
> + // Reassignment successfull. The caller may allocate now to this PhysReg.
> + return *PhysRegI;
> + }
> +
> + PhysRegSpillCands.insert(PhysRegSpillCands.end(), ReassignCands.begin(),
> + ReassignCands.end());
> +
> // Try to spill another interfering reg with less spill weight.
> //
> - // FIXME: RAGreedy will sort this list by spill weight.
> + // FIXME: do this in two steps: (1) check for unspillable interferences while
> + // accumulating spill weight; (2) spill the interferences with lowest
> + // aggregate spill weight.
> for (SmallVectorImpl<unsigned>::iterator PhysRegI = PhysRegSpillCands.begin(),
> PhysRegE = PhysRegSpillCands.end(); PhysRegI != PhysRegE; ++PhysRegI) {
>
> @@ -196,6 +294,7 @@
> // Tell the caller to allocate to this newly freed physical register.
> return *PhysRegI;
> }
> +
> // No other spill candidates were found, so spill the current VirtReg.
> DEBUG(dbgs() << "spilling: " << VirtReg << '\n');
> SmallVector<LiveInterval*, 1> pendingSpills;
>
>
> _______________________________________________
> 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