[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