diff options
Diffstat (limited to 'llvm/lib/CodeGen/SlotIndexes.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SlotIndexes.cpp | 271 | 
1 files changed, 271 insertions, 0 deletions
| diff --git a/llvm/lib/CodeGen/SlotIndexes.cpp b/llvm/lib/CodeGen/SlotIndexes.cpp new file mode 100644 index 0000000000000..9fff873324d0d --- /dev/null +++ b/llvm/lib/CodeGen/SlotIndexes.cpp @@ -0,0 +1,271 @@ +//===-- SlotIndexes.cpp - Slot Indexes Pass  ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "slotindexes" + +char SlotIndexes::ID = 0; +INITIALIZE_PASS(SlotIndexes, DEBUG_TYPE, +                "Slot index numbering", false, false) + +STATISTIC(NumLocalRenum,  "Number of local renumberings"); + +void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const { +  au.setPreservesAll(); +  MachineFunctionPass::getAnalysisUsage(au); +} + +void SlotIndexes::releaseMemory() { +  mi2iMap.clear(); +  MBBRanges.clear(); +  idx2MBBMap.clear(); +  indexList.clear(); +  ileAllocator.Reset(); +} + +bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) { + +  // Compute numbering as follows: +  // Grab an iterator to the start of the index list. +  // Iterate over all MBBs, and within each MBB all MIs, keeping the MI +  // iterator in lock-step (though skipping it over indexes which have +  // null pointers in the instruction field). +  // At each iteration assert that the instruction pointed to in the index +  // is the same one pointed to by the MI iterator. This + +  // FIXME: This can be simplified. The mi2iMap_, Idx2MBBMap, etc. should +  // only need to be set up once after the first numbering is computed. + +  mf = &fn; + +  // Check that the list contains only the sentinal. +  assert(indexList.empty() && "Index list non-empty at initial numbering?"); +  assert(idx2MBBMap.empty() && +         "Index -> MBB mapping non-empty at initial numbering?"); +  assert(MBBRanges.empty() && +         "MBB -> Index mapping non-empty at initial numbering?"); +  assert(mi2iMap.empty() && +         "MachineInstr -> Index mapping non-empty at initial numbering?"); + +  unsigned index = 0; +  MBBRanges.resize(mf->getNumBlockIDs()); +  idx2MBBMap.reserve(mf->size()); + +  indexList.push_back(createEntry(nullptr, index)); + +  // Iterate over the function. +  for (MachineBasicBlock &MBB : *mf) { +    // Insert an index for the MBB start. +    SlotIndex blockStartIndex(&indexList.back(), SlotIndex::Slot_Block); + +    for (MachineInstr &MI : MBB) { +      if (MI.isDebugInstr()) +        continue; + +      // Insert a store index for the instr. +      indexList.push_back(createEntry(&MI, index += SlotIndex::InstrDist)); + +      // Save this base index in the maps. +      mi2iMap.insert(std::make_pair( +          &MI, SlotIndex(&indexList.back(), SlotIndex::Slot_Block))); +    } + +    // We insert one blank instructions between basic blocks. +    indexList.push_back(createEntry(nullptr, index += SlotIndex::InstrDist)); + +    MBBRanges[MBB.getNumber()].first = blockStartIndex; +    MBBRanges[MBB.getNumber()].second = SlotIndex(&indexList.back(), +                                                   SlotIndex::Slot_Block); +    idx2MBBMap.push_back(IdxMBBPair(blockStartIndex, &MBB)); +  } + +  // Sort the Idx2MBBMap +  llvm::sort(idx2MBBMap, less_first()); + +  LLVM_DEBUG(mf->print(dbgs(), this)); + +  // And we're done! +  return false; +} + +void SlotIndexes::removeMachineInstrFromMaps(MachineInstr &MI) { +  assert(!MI.isBundledWithPred() && +         "Use removeSingleMachineInstrFromMaps() instread"); +  Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI); +  if (mi2iItr == mi2iMap.end()) +    return; + +  SlotIndex MIIndex = mi2iItr->second; +  IndexListEntry &MIEntry = *MIIndex.listEntry(); +  assert(MIEntry.getInstr() == &MI && "Instruction indexes broken."); +  mi2iMap.erase(mi2iItr); +  // FIXME: Eventually we want to actually delete these indexes. +  MIEntry.setInstr(nullptr); +} + +void SlotIndexes::removeSingleMachineInstrFromMaps(MachineInstr &MI) { +  Mi2IndexMap::iterator mi2iItr = mi2iMap.find(&MI); +  if (mi2iItr == mi2iMap.end()) +    return; + +  SlotIndex MIIndex = mi2iItr->second; +  IndexListEntry &MIEntry = *MIIndex.listEntry(); +  assert(MIEntry.getInstr() == &MI && "Instruction indexes broken."); +  mi2iMap.erase(mi2iItr); + +  // When removing the first instruction of a bundle update mapping to next +  // instruction. +  if (MI.isBundledWithSucc()) { +    // Only the first instruction of a bundle should have an index assigned. +    assert(!MI.isBundledWithPred() && "Should have first bundle isntruction"); + +    MachineBasicBlock::instr_iterator Next = std::next(MI.getIterator()); +    MachineInstr &NextMI = *Next; +    MIEntry.setInstr(&NextMI); +    mi2iMap.insert(std::make_pair(&NextMI, MIIndex)); +    return; +  } else { +    // FIXME: Eventually we want to actually delete these indexes. +    MIEntry.setInstr(nullptr); +  } +} + +// Renumber indexes locally after curItr was inserted, but failed to get a new +// index. +void SlotIndexes::renumberIndexes(IndexList::iterator curItr) { +  // Number indexes with half the default spacing so we can catch up quickly. +  const unsigned Space = SlotIndex::InstrDist/2; +  static_assert((Space & 3) == 0, "InstrDist must be a multiple of 2*NUM"); + +  IndexList::iterator startItr = std::prev(curItr); +  unsigned index = startItr->getIndex(); +  do { +    curItr->setIndex(index += Space); +    ++curItr; +    // If the next index is bigger, we have caught up. +  } while (curItr != indexList.end() && curItr->getIndex() <= index); + +  LLVM_DEBUG(dbgs() << "\n*** Renumbered SlotIndexes " << startItr->getIndex() +                    << '-' << index << " ***\n"); +  ++NumLocalRenum; +} + +// Repair indexes after adding and removing instructions. +void SlotIndexes::repairIndexesInRange(MachineBasicBlock *MBB, +                                       MachineBasicBlock::iterator Begin, +                                       MachineBasicBlock::iterator End) { +  // FIXME: Is this really necessary? The only caller repairIntervalsForRange() +  // does the same thing. +  // Find anchor points, which are at the beginning/end of blocks or at +  // instructions that already have indexes. +  while (Begin != MBB->begin() && !hasIndex(*Begin)) +    --Begin; +  while (End != MBB->end() && !hasIndex(*End)) +    ++End; + +  bool includeStart = (Begin == MBB->begin()); +  SlotIndex startIdx; +  if (includeStart) +    startIdx = getMBBStartIdx(MBB); +  else +    startIdx = getInstructionIndex(*Begin); + +  SlotIndex endIdx; +  if (End == MBB->end()) +    endIdx = getMBBEndIdx(MBB); +  else +    endIdx = getInstructionIndex(*End); + +  // FIXME: Conceptually, this code is implementing an iterator on MBB that +  // optionally includes an additional position prior to MBB->begin(), indicated +  // by the includeStart flag. This is done so that we can iterate MIs in a MBB +  // in parallel with SlotIndexes, but there should be a better way to do this. +  IndexList::iterator ListB = startIdx.listEntry()->getIterator(); +  IndexList::iterator ListI = endIdx.listEntry()->getIterator(); +  MachineBasicBlock::iterator MBBI = End; +  bool pastStart = false; +  while (ListI != ListB || MBBI != Begin || (includeStart && !pastStart)) { +    assert(ListI->getIndex() >= startIdx.getIndex() && +           (includeStart || !pastStart) && +           "Decremented past the beginning of region to repair."); + +    MachineInstr *SlotMI = ListI->getInstr(); +    MachineInstr *MI = (MBBI != MBB->end() && !pastStart) ? &*MBBI : nullptr; +    bool MBBIAtBegin = MBBI == Begin && (!includeStart || pastStart); + +    if (SlotMI == MI && !MBBIAtBegin) { +      --ListI; +      if (MBBI != Begin) +        --MBBI; +      else +        pastStart = true; +    } else if (MI && mi2iMap.find(MI) == mi2iMap.end()) { +      if (MBBI != Begin) +        --MBBI; +      else +        pastStart = true; +    } else { +      --ListI; +      if (SlotMI) +        removeMachineInstrFromMaps(*SlotMI); +    } +  } + +  // In theory this could be combined with the previous loop, but it is tricky +  // to update the IndexList while we are iterating it. +  for (MachineBasicBlock::iterator I = End; I != Begin;) { +    --I; +    MachineInstr &MI = *I; +    if (!MI.isDebugInstr() && mi2iMap.find(&MI) == mi2iMap.end()) +      insertMachineInstrInMaps(MI); +  } +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void SlotIndexes::dump() const { +  for (IndexList::const_iterator itr = indexList.begin(); +       itr != indexList.end(); ++itr) { +    dbgs() << itr->getIndex() << " "; + +    if (itr->getInstr()) { +      dbgs() << *itr->getInstr(); +    } else { +      dbgs() << "\n"; +    } +  } + +  for (unsigned i = 0, e = MBBRanges.size(); i != e; ++i) +    dbgs() << "%bb." << i << "\t[" << MBBRanges[i].first << ';' +           << MBBRanges[i].second << ")\n"; +} +#endif + +// Print a SlotIndex to a raw_ostream. +void SlotIndex::print(raw_ostream &os) const { +  if (isValid()) +    os << listEntry()->getIndex() << "Berd"[getSlot()]; +  else +    os << "invalid"; +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +// Dump a SlotIndex to stderr. +LLVM_DUMP_METHOD void SlotIndex::dump() const { +  print(dbgs()); +  dbgs() << "\n"; +} +#endif + | 
