diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2011-06-12 15:42:51 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2011-06-12 15:42:51 +0000 | 
| commit | 56fe8f14099930935e3870e3e823c322a85c1c89 (patch) | |
| tree | b3032e51d630e8070e9e08d6641648f195316a80 /lib/CodeGen/RegAllocGreedy.cpp | |
| parent | 6b943ff3a3f8617113ecbf611cf0f8957e4e19d2 (diff) | |
Notes
Diffstat (limited to 'lib/CodeGen/RegAllocGreedy.cpp')
| -rw-r--r-- | lib/CodeGen/RegAllocGreedy.cpp | 259 | 
1 files changed, 152 insertions, 107 deletions
diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp index 7c461d8ea7874..8d0632567bb16 100644 --- a/lib/CodeGen/RegAllocGreedy.cpp +++ b/lib/CodeGen/RegAllocGreedy.cpp @@ -62,7 +62,6 @@ class RAGreedy : public MachineFunctionPass,    // context    MachineFunction *MF; -  BitVector ReservedRegs;    // analyses    SlotIndexes *Indexes; @@ -72,6 +71,7 @@ class RAGreedy : public MachineFunctionPass,    MachineLoopRanges *LoopRanges;    EdgeBundles *Bundles;    SpillPlacement *SpillPlacer; +  LiveDebugVariables *DebugVars;    // state    std::auto_ptr<Spiller> SpillerInstance; @@ -99,6 +99,8 @@ class RAGreedy : public MachineFunctionPass,      RS_Spill     ///< Produced by spilling.    }; +  static const char *const StageName[]; +    IndexedMap<unsigned char, VirtReg2IndexFunctor> LRStage;    LiveRangeStage getStage(const LiveInterval &VirtReg) const { @@ -115,6 +117,15 @@ class RAGreedy : public MachineFunctionPass,      }    } +  // Eviction. Sometimes an assigned live range can be evicted without +  // conditions, but other times it must be split after being evicted to avoid +  // infinite loops. +  enum CanEvict { +    CE_Never,    ///< Can never evict. +    CE_Always,   ///< Can always evict. +    CE_WithSplit ///< Can evict only if range is also split or spilled. +  }; +    // splitting state.    std::auto_ptr<SplitAnalysis> SA;    std::auto_ptr<SplitEditor> SE; @@ -143,10 +154,6 @@ class RAGreedy : public MachineFunctionPass,    /// class.    SmallVector<GlobalSplitCandidate, 32> GlobalCand; -  /// For every instruction in SA->UseSlots, store the previous non-copy -  /// instruction. -  SmallVector<SlotIndex, 8> PrevSlot; -  public:    RAGreedy(); @@ -183,9 +190,7 @@ private:    void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&,                           SmallVectorImpl<LiveInterval*>&);    void calcGapWeights(unsigned, SmallVectorImpl<float>&); -  SlotIndex getPrevMappedIndex(const MachineInstr*); -  void calcPrevSlots(); -  unsigned nextSplitPoint(unsigned); +  CanEvict canEvict(LiveInterval &A, LiveInterval &B);    bool canEvictInterference(LiveInterval&, unsigned, float&);    unsigned tryAssign(LiveInterval&, AllocationOrder&, @@ -203,6 +208,17 @@ private:  char RAGreedy::ID = 0; +#ifndef NDEBUG +const char *const RAGreedy::StageName[] = { +  "RS_New", +  "RS_First", +  "RS_Second", +  "RS_Global", +  "RS_Local", +  "RS_Spill" +}; +#endif +  // Hysteresis to use when comparing floats.  // This helps stabilize decisions based on float comparisons.  const float Hysteresis = 0.98f; @@ -377,6 +393,20 @@ unsigned RAGreedy::tryAssign(LiveInterval &VirtReg,  //                         Interference eviction  //===----------------------------------------------------------------------===// +/// canEvict - determine if A can evict the assigned live range B. The eviction +/// policy defined by this function together with the allocation order defined +/// by enqueue() decides which registers ultimately end up being split and +/// spilled. +/// +/// This function must define a non-circular relation when it returns CE_Always, +/// otherwise infinite eviction loops are possible. When evicting a <= RS_Second +/// range, it is possible to return CE_WithSplit which forces the evicted +/// register to be split or spilled before it can evict anything again. That +/// guarantees progress. +RAGreedy::CanEvict RAGreedy::canEvict(LiveInterval &A, LiveInterval &B) { +  return A.weight > B.weight ? CE_Always : CE_Never; +} +  /// canEvict - Return true if all interferences between VirtReg and PhysReg can  /// be evicted.  /// Return false if any interference is heavier than MaxWeight. @@ -397,6 +427,16 @@ bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg,          return false;        if (Intf->weight >= MaxWeight)          return false; +      switch (canEvict(VirtReg, *Intf)) { +      case CE_Always: +        break; +      case CE_Never: +        return false; +      case CE_WithSplit: +        if (getStage(*Intf) > RS_Second) +          return false; +        break; +      }        Weight = std::max(Weight, Intf->weight);      }    } @@ -415,7 +455,7 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,    NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled);    // Keep track of the lightest single interference seen so far. -  float BestWeight = VirtReg.weight; +  float BestWeight = HUGE_VALF;    unsigned BestPhys = 0;    Order.rewind(); @@ -456,6 +496,11 @@ unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,        unassign(*Intf, VRM->getPhys(Intf->reg));        ++NumEvicted;        NewVRegs.push_back(Intf); +      // Prevent looping by forcing the evicted ranges to be split before they +      // can evict anything else. +      if (getStage(*Intf) < RS_Second && +          canEvict(VirtReg, *Intf) == CE_WithSplit) +        LRStage[Intf->reg] = RS_Second;      }    }    return BestPhys; @@ -499,7 +544,7 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf,          BC.Entry = SpillPlacement::MustSpill, ++Ins;        else if (Intf.first() < BI.FirstUse)          BC.Entry = SpillPlacement::PrefSpill, ++Ins; -      else if (Intf.first() < (BI.LiveThrough ? BI.LastUse : BI.Kill)) +      else if (Intf.first() < BI.LastUse)          ++Ins;      } @@ -509,7 +554,7 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf,          BC.Exit = SpillPlacement::MustSpill, ++Ins;        else if (Intf.last() > BI.LastUse)          BC.Exit = SpillPlacement::PrefSpill, ++Ins; -      else if (Intf.last() > (BI.LiveThrough ? BI.FirstUse : BI.Def)) +      else if (Intf.last() > BI.FirstUse)          ++Ins;      } @@ -758,7 +803,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,        DEBUG(dbgs() << ", no interference");        if (!BI.LiveThrough) {          DEBUG(dbgs() << ", not live-through.\n"); -        SE->useIntv(SE->enterIntvBefore(BI.Def), Stop); +        SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop);          continue;        }        if (!RegIn) { @@ -775,10 +820,10 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,      // Block has interference.      DEBUG(dbgs() << ", interference to " << Intf.last()); -    if (!BI.LiveThrough && Intf.last() <= BI.Def) { +    if (!BI.LiveThrough && Intf.last() <= BI.FirstUse) {        // The interference doesn't reach the outgoing segment. -      DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n'); -      SE->useIntv(BI.Def, Stop); +      DEBUG(dbgs() << " doesn't affect def from " << BI.FirstUse << '\n'); +      SE->useIntv(BI.FirstUse, Stop);        continue;      } @@ -834,7 +879,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,        DEBUG(dbgs() << ", no interference");        if (!BI.LiveThrough) {          DEBUG(dbgs() << ", killed in block.\n"); -        SE->useIntv(Start, SE->leaveIntvAfter(BI.Kill)); +        SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse));          continue;        }        if (!RegOut) { @@ -867,10 +912,10 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,      // Block has interference.      DEBUG(dbgs() << ", interference from " << Intf.first()); -    if (!BI.LiveThrough && Intf.first() >= BI.Kill) { +    if (!BI.LiveThrough && Intf.first() >= BI.LastUse) {        // The interference doesn't reach the outgoing segment. -      DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n'); -      SE->useIntv(Start, BI.Kill); +      DEBUG(dbgs() << " doesn't affect kill at " << BI.LastUse << '\n'); +      SE->useIntv(Start, BI.LastUse);        continue;      } @@ -920,8 +965,10 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,    SmallVector<unsigned, 8> IntvMap;    SE->finish(&IntvMap); +  DebugVars->splitRegister(VirtReg.reg, LREdit.regs()); +    LRStage.resize(MRI->getNumVirtRegs()); -  unsigned OrigBlocks = SA->getNumThroughBlocks() + SA->getUseBlocks().size(); +  unsigned OrigBlocks = SA->getNumLiveBlocks();    // Sort out the new intervals created by splitting. We get four kinds:    // - Remainder intervals should not be split again. @@ -1083,47 +1130,6 @@ void RAGreedy::calcGapWeights(unsigned PhysReg,    }  } -/// getPrevMappedIndex - Return the slot index of the last non-copy instruction -/// before MI that has a slot index. If MI is the first mapped instruction in -/// its block, return the block start index instead. -/// -SlotIndex RAGreedy::getPrevMappedIndex(const MachineInstr *MI) { -  assert(MI && "Missing MachineInstr"); -  const MachineBasicBlock *MBB = MI->getParent(); -  MachineBasicBlock::const_iterator B = MBB->begin(), I = MI; -  while (I != B) -    if (!(--I)->isDebugValue() && !I->isCopy()) -      return Indexes->getInstructionIndex(I); -  return Indexes->getMBBStartIdx(MBB); -} - -/// calcPrevSlots - Fill in the PrevSlot array with the index of the previous -/// real non-copy instruction for each instruction in SA->UseSlots. -/// -void RAGreedy::calcPrevSlots() { -  const SmallVectorImpl<SlotIndex> &Uses = SA->UseSlots; -  PrevSlot.clear(); -  PrevSlot.reserve(Uses.size()); -  for (unsigned i = 0, e = Uses.size(); i != e; ++i) { -    const MachineInstr *MI = Indexes->getInstructionFromIndex(Uses[i]); -    PrevSlot.push_back(getPrevMappedIndex(MI).getDefIndex()); -  } -} - -/// nextSplitPoint - Find the next index into SA->UseSlots > i such that it may -/// be beneficial to split before UseSlots[i]. -/// -/// 0 is always a valid split point -unsigned RAGreedy::nextSplitPoint(unsigned i) { -  const SmallVectorImpl<SlotIndex> &Uses = SA->UseSlots; -  const unsigned Size = Uses.size(); -  assert(i != Size && "No split points after the end"); -  // Allow split before i when Uses[i] is not adjacent to the previous use. -  while (++i != Size && PrevSlot[i].getBaseIndex() <= Uses[i-1].getBaseIndex()) -    ; -  return i; -} -  /// tryLocalSplit - Try to split VirtReg into smaller intervals inside its only  /// basic block.  /// @@ -1151,11 +1157,27 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,      dbgs() << '\n';    }); -  // For every use, find the previous mapped non-copy instruction. -  // We use this to detect valid split points, and to estimate new interval -  // sizes. -  calcPrevSlots(); +  // Since we allow local split results to be split again, there is a risk of +  // creating infinite loops. It is tempting to require that the new live +  // ranges have less instructions than the original. That would guarantee +  // convergence, but it is too strict. A live range with 3 instructions can be +  // split 2+3 (including the COPY), and we want to allow that. +  // +  // Instead we use these rules: +  // +  // 1. Allow any split for ranges with getStage() < RS_Local. (Except for the +  //    noop split, of course). +  // 2. Require progress be made for ranges with getStage() >= RS_Local. All +  //    the new ranges must have fewer instructions than before the split. +  // 3. New ranges with the same number of instructions are marked RS_Local, +  //    smaller ranges are marked RS_New. +  // +  // These rules allow a 3 -> 2+3 split once, which we need. They also prevent +  // excessive splitting and infinite loops. +  // +  bool ProgressRequired = getStage(VirtReg) >= RS_Local; +  // Best split candidate.    unsigned BestBefore = NumGaps;    unsigned BestAfter = 0;    float BestDiff = 0; @@ -1173,13 +1195,11 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,      // The new spill weight must be larger than any gap interference.      // We will split before Uses[SplitBefore] and after Uses[SplitAfter]. -    unsigned SplitBefore = 0, SplitAfter = nextSplitPoint(1) - 1; +    unsigned SplitBefore = 0, SplitAfter = 1;      // MaxGap should always be max(GapWeight[SplitBefore..SplitAfter-1]).      // It is the spill weight that needs to be evicted.      float MaxGap = GapWeight[0]; -    for (unsigned i = 1; i != SplitAfter; ++i) -      MaxGap = std::max(MaxGap, GapWeight[i]);      for (;;) {        // Live before/after split? @@ -1197,32 +1217,22 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,        }        // Should the interval be extended or shrunk?        bool Shrink = true; -      if (MaxGap < HUGE_VALF) { -        // Estimate the new spill weight. -        // -        // Each instruction reads and writes the register, except the first -        // instr doesn't read when !FirstLive, and the last instr doesn't write -        // when !LastLive. -        // -        // We will be inserting copies before and after, so the total number of -        // reads and writes is 2 * EstUses. -        // -        const unsigned EstUses = 2*(SplitAfter - SplitBefore) + -                                 2*(LiveBefore + LiveAfter); -        // Try to guess the size of the new interval. This should be trivial, -        // but the slot index of an inserted copy can be a lot smaller than the -        // instruction it is inserted before if there are many dead indexes -        // between them. -        // -        // We measure the distance from the instruction before SplitBefore to -        // get a conservative estimate. -        // -        // The final distance can still be different if inserting copies -        // triggers a slot index renumbering. +      // How many gaps would the new range have? +      unsigned NewGaps = LiveBefore + SplitAfter - SplitBefore + LiveAfter; + +      // Legally, without causing looping? +      bool Legal = !ProgressRequired || NewGaps < NumGaps; + +      if (Legal && MaxGap < HUGE_VALF) { +        // Estimate the new spill weight. Each instruction reads or writes the +        // register. Conservatively assume there are no read-modify-write +        // instructions.          // -        const float EstWeight = normalizeSpillWeight(blockFreq * EstUses, -                              PrevSlot[SplitBefore].distance(Uses[SplitAfter])); +        // Try to guess the size of the new interval. +        const float EstWeight = normalizeSpillWeight(blockFreq * (NewGaps + 1), +                                 Uses[SplitBefore].distance(Uses[SplitAfter]) + +                                 (LiveBefore + LiveAfter)*SlotIndex::InstrDist);          // Would this split be possible to allocate?          // Never allocate all gaps, we wouldn't be making progress.          DEBUG(dbgs() << " w=" << EstWeight); @@ -1240,8 +1250,7 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,        // Try to shrink.        if (Shrink) { -        SplitBefore = nextSplitPoint(SplitBefore); -        if (SplitBefore < SplitAfter) { +        if (++SplitBefore < SplitAfter) {            DEBUG(dbgs() << " shrink\n");            // Recompute the max when necessary.            if (GapWeight[SplitBefore - 1] >= MaxGap) { @@ -1261,10 +1270,7 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,        }        DEBUG(dbgs() << " extend\n"); -      for (unsigned e = nextSplitPoint(SplitAfter + 1) - 1; -           SplitAfter != e; ++SplitAfter) -        MaxGap = std::max(MaxGap, GapWeight[SplitAfter]); -          continue; +      MaxGap = std::max(MaxGap, GapWeight[SplitAfter++]);      }    } @@ -1283,8 +1289,27 @@ unsigned RAGreedy::tryLocalSplit(LiveInterval &VirtReg, AllocationOrder &Order,    SlotIndex SegStart = SE->enterIntvBefore(Uses[BestBefore]);    SlotIndex SegStop  = SE->leaveIntvAfter(Uses[BestAfter]);    SE->useIntv(SegStart, SegStop); -  SE->finish(); -  setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local); +  SmallVector<unsigned, 8> IntvMap; +  SE->finish(&IntvMap); +  DebugVars->splitRegister(VirtReg.reg, LREdit.regs()); + +  // If the new range has the same number of instructions as before, mark it as +  // RS_Local so the next split will be forced to make progress. Otherwise, +  // leave the new intervals as RS_New so they can compete. +  bool LiveBefore = BestBefore != 0 || BI.LiveIn; +  bool LiveAfter = BestAfter != NumGaps || BI.LiveOut; +  unsigned NewGaps = LiveBefore + BestAfter - BestBefore + LiveAfter; +  if (NewGaps >= NumGaps) { +    DEBUG(dbgs() << "Tagging non-progress ranges: "); +    assert(!ProgressRequired && "Didn't make progress when it was required."); +    LRStage.resize(MRI->getNumVirtRegs()); +    for (unsigned i = 0, e = IntvMap.size(); i != e; ++i) +      if (IntvMap[i] == 1) { +        LRStage[LREdit.get(i)->reg] = RS_Local; +        DEBUG(dbgs() << PrintReg(LREdit.get(i)->reg)); +      } +    DEBUG(dbgs() << '\n'); +  }    ++NumLocalSplits;    return 0; @@ -1315,6 +1340,17 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order,    SA->analyze(&VirtReg); +  // FIXME: SplitAnalysis may repair broken live ranges coming from the +  // coalescer. That may cause the range to become allocatable which means that +  // tryRegionSplit won't be making progress. This check should be replaced with +  // an assertion when the coalescer is fixed. +  if (SA->didRepairRange()) { +    // VirtReg has changed, so all cached queries are invalid. +    invalidateVirtRegs(); +    if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs)) +      return PhysReg; +  } +    // First try to split around a region spanning multiple blocks.    unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs);    if (PhysReg || !NewVRegs.empty()) @@ -1343,19 +1379,25 @@ unsigned RAGreedy::trySplit(LiveInterval &VirtReg, AllocationOrder &Order,  unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,                                   SmallVectorImpl<LiveInterval*> &NewVRegs) {    // First try assigning a free register. -  AllocationOrder Order(VirtReg.reg, *VRM, ReservedRegs); +  AllocationOrder Order(VirtReg.reg, *VRM, RegClassInfo);    if (unsigned PhysReg = tryAssign(VirtReg, Order, NewVRegs))      return PhysReg; -  if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs)) -    return PhysReg; +  LiveRangeStage Stage = getStage(VirtReg); +  DEBUG(dbgs() << StageName[Stage] << '\n'); + +  // Try to evict a less worthy live range, but only for ranges from the primary +  // queue. The RS_Second ranges already failed to do this, and they should not +  // get a second chance until they have been split. +  if (Stage != RS_Second) +    if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs)) +      return PhysReg;    assert(NewVRegs.empty() && "Cannot append to existing NewVRegs");    // The first time we see a live range, don't try to split or spill.    // Wait until the second time, when all smaller ranges have been allocated.    // This gives a better picture of the interference to split around. -  LiveRangeStage Stage = getStage(VirtReg);    if (Stage == RS_First) {      LRStage[VirtReg.reg] = RS_Second;      DEBUG(dbgs() << "wait for second round\n"); @@ -1363,7 +1405,10 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,      return 0;    } -  assert(Stage < RS_Spill && "Cannot allocate after spilling"); +  // If we couldn't allocate a register from spilling, there is probably some +  // invalid inline assembly. The base class wil report it. +  if (Stage >= RS_Spill) +    return ~0u;    // Try splitting VirtReg or interferences.    unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs); @@ -1396,12 +1441,12 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {    RegAllocBase::init(getAnalysis<VirtRegMap>(), getAnalysis<LiveIntervals>());    Indexes = &getAnalysis<SlotIndexes>();    DomTree = &getAnalysis<MachineDominatorTree>(); -  ReservedRegs = TRI->getReservedRegs(*MF);    SpillerInstance.reset(createInlineSpiller(*this, *MF, *VRM));    Loops = &getAnalysis<MachineLoopInfo>();    LoopRanges = &getAnalysis<MachineLoopRanges>();    Bundles = &getAnalysis<EdgeBundles>();    SpillPlacer = &getAnalysis<SpillPlacement>(); +  DebugVars = &getAnalysis<LiveDebugVariables>();    SA.reset(new SplitAnalysis(*VRM, *LIS, *Loops));    SE.reset(new SplitEditor(*SA, *LIS, *VRM, *DomTree)); @@ -1420,7 +1465,7 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {    }    // Write out new DBG_VALUE instructions. -  getAnalysis<LiveDebugVariables>().emitDebugValues(VRM); +  DebugVars->emitDebugValues(VRM);    // The pass output is in VirtRegMap. Release all the transient data.    releaseMemory();  | 
