//===- LiveIntervalUnion.cpp - Live interval union data structure ---------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// LiveIntervalUnion represents a coalesced set of live intervals. This may be
// used during coalescing to represent a congruence class, or during register
// allocation to model liveness of a physical register.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/LiveIntervalUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdlib>

using namespace llvm;

#define DEBUG_TYPE "regalloc"

// Merge a LiveInterval's segments. Guarantee no overlaps.
void LiveIntervalUnion::unify(const LiveInterval &VirtReg,
                              const LiveRange &Range) {
  if (Range.empty())
    return;
  ++Tag;

  // Insert each of the virtual register's live segments into the map.
  LiveRange::const_iterator RegPos = Range.begin();
  LiveRange::const_iterator RegEnd = Range.end();
  SegmentIter SegPos = Segments.find(RegPos->start);

  while (SegPos.valid()) {
    SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
    if (++RegPos == RegEnd)
      return;
    SegPos.advanceTo(RegPos->start);
  }

  // We have reached the end of Segments, so it is no longer necessary to search
  // for the insertion position.
  // It is faster to insert the end first.
  --RegEnd;
  SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg);
  for (; RegPos != RegEnd; ++RegPos, ++SegPos)
    SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
}

// Remove a live virtual register's segments from this union.
void LiveIntervalUnion::extract(const LiveInterval &VirtReg,
                                const LiveRange &Range) {
  if (Range.empty())
    return;
  ++Tag;

  // Remove each of the virtual register's live segments from the map.
  LiveRange::const_iterator RegPos = Range.begin();
  LiveRange::const_iterator RegEnd = Range.end();
  SegmentIter SegPos = Segments.find(RegPos->start);

  while (true) {
    assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
    SegPos.erase();
    if (!SegPos.valid())
      return;

    // Skip all segments that may have been coalesced.
    RegPos = Range.advanceTo(RegPos, SegPos.start());
    if (RegPos == RegEnd)
      return;

    SegPos.advanceTo(RegPos->start);
  }
}

void LiveIntervalUnion::clearAllSegmentsReferencing(
    const LiveInterval &VirtRegLI) {
  ++Tag;

  // Remove all segments referencing VirtReg.
  for (SegmentIter SegPos = Segments.begin(); SegPos.valid();) {
    if (SegPos.value()->reg() == VirtRegLI.reg())
      SegPos.erase();
    else
      ++SegPos;
  }
}

void
LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
  if (empty()) {
    OS << " empty\n";
    return;
  }
  for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
    OS << " [" << SI.start() << ' ' << SI.stop()
       << "):" << printReg(SI.value()->reg(), TRI);
  }
  OS << '\n';
}

#ifndef NDEBUG
// Verify the live intervals in this union and add them to the visited set.
void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
  for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
    VisitedVRegs.set(SI.value()->reg().id());
}
#endif //!NDEBUG

const LiveInterval *LiveIntervalUnion::getOneVReg() const {
  if (empty())
    return nullptr;
  for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
    // return the first valid live interval
    return SI.value();
  }
  return nullptr;
}

// Scan the vector of interfering virtual registers in this union. Assume it's
// quite small.
bool LiveIntervalUnion::Query::isSeenInterference(
    const LiveInterval *VirtReg) const {
  return is_contained(InterferingVRegs, VirtReg);
}

// Collect virtual registers in this union that interfere with this
// query's live virtual register.
//
// The query state is one of:
//
// 1. CheckedFirstInterference == false: Iterators are uninitialized.
// 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
// 3. Iterators left at the last seen intersection.
//
unsigned
LiveIntervalUnion::Query::collectInterferingVRegs(unsigned MaxInterferingRegs) {
  // Fast path return if we already have the desired information.
  if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
    return InterferingVRegs.size();

  // Set up iterators on the first call.
  if (!CheckedFirstInterference) {
    CheckedFirstInterference = true;

    // Quickly skip interference check for empty sets.
    if (LR->empty() || LiveUnion->empty()) {
      SeenAllInterferences = true;
      return 0;
    }

    // In most cases, the union will start before LR.
    LRI = LR->begin();
    LiveUnionI.setMap(LiveUnion->getMap());
    LiveUnionI.find(LRI->start);
  }

  LiveRange::const_iterator LREnd = LR->end();
  const LiveInterval *RecentReg = nullptr;
  while (LiveUnionI.valid()) {
    assert(LRI != LREnd && "Reached end of LR");

    // Check for overlapping interference.
    while (LRI->start < LiveUnionI.stop() && LRI->end > LiveUnionI.start()) {
      // This is an overlap, record the interfering register.
      const LiveInterval *VReg = LiveUnionI.value();
      if (VReg != RecentReg && !isSeenInterference(VReg)) {
        RecentReg = VReg;
        InterferingVRegs.push_back(VReg);
        if (InterferingVRegs.size() >= MaxInterferingRegs)
          return InterferingVRegs.size();
      }
      // This LiveUnion segment is no longer interesting.
      if (!(++LiveUnionI).valid()) {
        SeenAllInterferences = true;
        return InterferingVRegs.size();
      }
    }

    // The iterators are now not overlapping, LiveUnionI has been advanced
    // beyond LRI.
    assert(LRI->end <= LiveUnionI.start() && "Expected non-overlap");

    // Advance the iterator that ends first.
    LRI = LR->advanceTo(LRI, LiveUnionI.start());
    if (LRI == LREnd)
      break;

    // Detect overlap, handle above.
    if (LRI->start < LiveUnionI.stop())
      continue;

    // Still not overlapping. Catch up LiveUnionI.
    LiveUnionI.advanceTo(LRI->start);
  }
  SeenAllInterferences = true;
  return InterferingVRegs.size();
}

void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,
                                    unsigned NSize) {
  // Reuse existing allocation.
  if (NSize == Size)
    return;
  clear();
  Size = NSize;
  LIUs = static_cast<LiveIntervalUnion*>(
      safe_malloc(sizeof(LiveIntervalUnion)*NSize));
  for (unsigned i = 0; i != Size; ++i)
    new(LIUs + i) LiveIntervalUnion(Alloc);
}

void LiveIntervalUnion::Array::clear() {
  if (!LIUs)
    return;
  for (unsigned i = 0; i != Size; ++i)
    LIUs[i].~LiveIntervalUnion();
  free(LIUs);
  Size =  0;
  LIUs = nullptr;
}
