//===- CriticalAntiDepBreaker.cpp - Anti-dep breaker ----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the CriticalAntiDepBreaker class, which
// implements register anti-dependence breaking along a blocks
// critical path during post-RA scheduler.
//
//===----------------------------------------------------------------------===//

#include "CriticalAntiDepBreaker.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <utility>

using namespace llvm;

#define DEBUG_TYPE "post-RA-sched"

CriticalAntiDepBreaker::CriticalAntiDepBreaker(MachineFunction &MFi,
                                               const RegisterClassInfo &RCI)
    : MF(MFi), MRI(MF.getRegInfo()), TII(MF.getSubtarget().getInstrInfo()),
      TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RCI),
      Classes(TRI->getNumRegs(), nullptr), KillIndices(TRI->getNumRegs(), 0),
      DefIndices(TRI->getNumRegs(), 0), KeepRegs(TRI->getNumRegs(), false) {}

CriticalAntiDepBreaker::~CriticalAntiDepBreaker() = default;

void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
  const unsigned BBSize = BB->size();
  for (unsigned i = 1, e = TRI->getNumRegs(); i != e; ++i) {
    // Clear out the register class data.
    Classes[i] = nullptr;

    // Initialize the indices to indicate that no registers are live.
    KillIndices[i] = ~0u;
    DefIndices[i] = BBSize;
  }

  // Clear "do not change" set.
  KeepRegs.reset();

  bool IsReturnBlock = BB->isReturnBlock();

  // Examine the live-in regs of all successors.
  for (const MachineBasicBlock *Succ : BB->successors())
    for (const auto &LI : Succ->liveins()) {
      for (MCRegAliasIterator AI(LI.PhysReg, TRI, true); AI.isValid(); ++AI) {
        MCRegister Reg = *AI;
        Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);
        KillIndices[Reg.id()] = BBSize;
        DefIndices[Reg.id()] = ~0u;
      }
    }

  // Mark live-out callee-saved registers. In a return block this is
  // all callee-saved registers. In non-return this is any
  // callee-saved register that is not saved in the prolog.
  const MachineFrameInfo &MFI = MF.getFrameInfo();
  BitVector Pristine = MFI.getPristineRegs(MF);
  for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I;
       ++I) {
    unsigned Reg = *I;
    if (!IsReturnBlock && !Pristine.test(Reg))
      continue;
    for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI) {
      MCRegister Reg = *AI;
      Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);
      KillIndices[Reg.id()] = BBSize;
      DefIndices[Reg.id()] = ~0u;
    }
  }
}

void CriticalAntiDepBreaker::FinishBlock() {
  RegRefs.clear();
  KeepRegs.reset();
}

void CriticalAntiDepBreaker::Observe(MachineInstr &MI, unsigned Count,
                                     unsigned InsertPosIndex) {
  // Kill instructions can define registers but are really nops, and there might
  // be a real definition earlier that needs to be paired with uses dominated by
  // this kill.

  // FIXME: It may be possible to remove the isKill() restriction once PR18663
  // has been properly fixed. There can be value in processing kills as seen in
  // the AggressiveAntiDepBreaker class.
  if (MI.isDebugInstr() || MI.isKill())
    return;
  assert(Count < InsertPosIndex && "Instruction index out of expected range!");

  for (unsigned Reg = 1; Reg != TRI->getNumRegs(); ++Reg) {
    if (KillIndices[Reg] != ~0u) {
      // If Reg is currently live, then mark that it can't be renamed as
      // we don't know the extent of its live-range anymore (now that it
      // has been scheduled).
      Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);
      KillIndices[Reg] = Count;
    } else if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) {
      // Any register which was defined within the previous scheduling region
      // may have been rescheduled and its lifetime may overlap with registers
      // in ways not reflected in our current liveness state. For each such
      // register, adjust the liveness state to be conservatively correct.
      Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1);

      // Move the def index to the end of the previous region, to reflect
      // that the def could theoretically have been scheduled at the end.
      DefIndices[Reg] = InsertPosIndex;
    }
  }

  PrescanInstruction(MI);
  ScanInstruction(MI, Count);
}

/// CriticalPathStep - Return the next SUnit after SU on the bottom-up
/// critical path.
static const SDep *CriticalPathStep(const SUnit *SU) {
  const SDep *Next = nullptr;
  unsigned NextDepth = 0;
  // Find the predecessor edge with the greatest depth.
  for (const SDep &P : SU->Preds) {
    const SUnit *PredSU = P.getSUnit();
    unsigned PredLatency = P.getLatency();
    unsigned PredTotalLatency = PredSU->getDepth() + PredLatency;
    // In the case of a latency tie, prefer an anti-dependency edge over
    // other types of edges.
    if (NextDepth < PredTotalLatency ||
        (NextDepth == PredTotalLatency && P.getKind() == SDep::Anti)) {
      NextDepth = PredTotalLatency;
      Next = &P;
    }
  }
  return Next;
}

void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr &MI) {
  // It's not safe to change register allocation for source operands of
  // instructions that have special allocation requirements. Also assume all
  // registers used in a call must not be changed (ABI).
  // FIXME: The issue with predicated instruction is more complex. We are being
  // conservative here because the kill markers cannot be trusted after
  // if-conversion:
  // %r6 = LDR %sp, %reg0, 92, 14, %reg0; mem:LD4[FixedStack14]
  // ...
  // STR %r0, killed %r6, %reg0, 0, 0, %cpsr; mem:ST4[%395]
  // %r6 = LDR %sp, %reg0, 100, 0, %cpsr; mem:LD4[FixedStack12]
  // STR %r0, killed %r6, %reg0, 0, 14, %reg0; mem:ST4[%396](align=8)
  //
  // The first R6 kill is not really a kill since it's killed by a predicated
  // instruction which may not be executed. The second R6 def may or may not
  // re-define R6 so it's not safe to change it since the last R6 use cannot be
  // changed.
  bool Special =
      MI.isCall() || MI.hasExtraSrcRegAllocReq() || TII->isPredicated(MI);

  // Scan the register operands for this instruction and update
  // Classes and RegRefs.
  for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
    MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg()) continue;
    Register Reg = MO.getReg();
    if (!Reg)
      continue;
    const TargetRegisterClass *NewRC = nullptr;

    if (i < MI.getDesc().getNumOperands())
      NewRC = TII->getRegClass(MI.getDesc(), i, TRI);

    // For now, only allow the register to be changed if its register
    // class is consistent across all uses.
    if (!Classes[Reg.id()] && NewRC)
      Classes[Reg.id()] = NewRC;
    else if (!NewRC || Classes[Reg.id()] != NewRC)
      Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);

    // Now check for aliases.
    for (MCRegAliasIterator AI(Reg, TRI, false); AI.isValid(); ++AI) {
      // If an alias of the reg is used during the live range, give up.
      // Note that this allows us to skip checking if AntiDepReg
      // overlaps with any of the aliases, among other things.
      unsigned AliasReg = (*AI).id();
      if (Classes[AliasReg]) {
        Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1);
        Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);
      }
    }

    // If we're still willing to consider this register, note the reference.
    if (Classes[Reg.id()] != reinterpret_cast<TargetRegisterClass *>(-1))
      RegRefs.emplace(Reg, &MO);

    if (MO.isUse() && Special) {
      if (!KeepRegs.test(Reg.id())) {
        for (MCPhysReg SubReg : TRI->subregs_inclusive(Reg))
          KeepRegs.set(SubReg);
      }
    }
  }

  for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
    const MachineOperand &MO = MI.getOperand(I);
    if (!MO.isReg()) continue;
    Register Reg = MO.getReg();
    if (!Reg.isValid())
      continue;
    // If this reg is tied and live (Classes[Reg] is set to -1), we can't change
    // it or any of its sub or super regs. We need to use KeepRegs to mark the
    // reg because not all uses of the same reg within an instruction are
    // necessarily tagged as tied.
    // Example: an x86 "xor %eax, %eax" will have one source operand tied to the
    // def register but not the second (see PR20020 for details).
    // FIXME: can this check be relaxed to account for undef uses
    // of a register? In the above 'xor' example, the uses of %eax are undef, so
    // earlier instructions could still replace %eax even though the 'xor'
    // itself can't be changed.
    if (MI.isRegTiedToUseOperand(I) &&
        Classes[Reg.id()] == reinterpret_cast<TargetRegisterClass *>(-1)) {
      for (MCPhysReg SubReg : TRI->subregs_inclusive(Reg)) {
        KeepRegs.set(SubReg);
      }
      for (MCPhysReg SuperReg : TRI->superregs(Reg)) {
        KeepRegs.set(SuperReg);
      }
    }
  }
}

void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) {
  // Update liveness.
  // Proceeding upwards, registers that are defed but not used in this
  // instruction are now dead.
  assert(!MI.isKill() && "Attempting to scan a kill instruction");

  if (!TII->isPredicated(MI)) {
    // Predicated defs are modeled as read + write, i.e. similar to two
    // address updates.
    for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
      MachineOperand &MO = MI.getOperand(i);

      if (MO.isRegMask()) {
        auto ClobbersPhysRegAndSubRegs = [&](unsigned PhysReg) {
          return all_of(TRI->subregs_inclusive(PhysReg),
                        [&](MCPhysReg SR) { return MO.clobbersPhysReg(SR); });
        };

        for (unsigned i = 1, e = TRI->getNumRegs(); i != e; ++i) {
          if (ClobbersPhysRegAndSubRegs(i)) {
            DefIndices[i] = Count;
            KillIndices[i] = ~0u;
            KeepRegs.reset(i);
            Classes[i] = nullptr;
            RegRefs.erase(i);
          }
        }
      }

      if (!MO.isReg()) continue;
      Register Reg = MO.getReg();
      if (!Reg)
        continue;
      if (!MO.isDef()) continue;

      // Ignore two-addr defs.
      if (MI.isRegTiedToUseOperand(i))
        continue;

      // If we've already marked this reg as unchangeable, don't remove
      // it or any of its subregs from KeepRegs.
      bool Keep = KeepRegs.test(Reg.id());

      // For the reg itself and all subregs: update the def to current;
      // reset the kill state, any restrictions, and references.
      for (MCPhysReg SubregReg : TRI->subregs_inclusive(Reg)) {
        DefIndices[SubregReg] = Count;
        KillIndices[SubregReg] = ~0u;
        Classes[SubregReg] = nullptr;
        RegRefs.erase(SubregReg);
        if (!Keep)
          KeepRegs.reset(SubregReg);
      }
      // Conservatively mark super-registers as unusable.
      for (MCPhysReg SR : TRI->superregs(Reg))
        Classes[SR] = reinterpret_cast<TargetRegisterClass *>(-1);
    }
  }
  for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
    MachineOperand &MO = MI.getOperand(i);
    if (!MO.isReg()) continue;
    Register Reg = MO.getReg();
    if (!Reg)
      continue;
    if (!MO.isUse()) continue;

    const TargetRegisterClass *NewRC = nullptr;
    if (i < MI.getDesc().getNumOperands())
      NewRC = TII->getRegClass(MI.getDesc(), i, TRI);

    // For now, only allow the register to be changed if its register
    // class is consistent across all uses.
    if (!Classes[Reg.id()] && NewRC)
      Classes[Reg.id()] = NewRC;
    else if (!NewRC || Classes[Reg.id()] != NewRC)
      Classes[Reg.id()] = reinterpret_cast<TargetRegisterClass *>(-1);

    RegRefs.emplace(Reg, &MO);

    // It wasn't previously live but now it is, this is a kill.
    // Repeat for all aliases.
    for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) {
      MCRegister AliasReg = *AI;
      if (KillIndices[AliasReg.id()] == ~0u) {
        KillIndices[AliasReg.id()] = Count;
        DefIndices[AliasReg.id()] = ~0u;
      }
    }
  }
}

// Check all machine operands that reference the antidependent register and must
// be replaced by NewReg. Return true if any of their parent instructions may
// clobber the new register.
//
// Note: AntiDepReg may be referenced by a two-address instruction such that
// it's use operand is tied to a def operand. We guard against the case in which
// the two-address instruction also defines NewReg, as may happen with
// pre/postincrement loads. In this case, both the use and def operands are in
// RegRefs because the def is inserted by PrescanInstruction and not erased
// during ScanInstruction. So checking for an instruction with definitions of
// both NewReg and AntiDepReg covers it.
bool CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin,
                                                     RegRefIter RegRefEnd,
                                                     MCRegister NewReg) {
  for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) {
    MachineOperand *RefOper = I->second;

    // Don't allow the instruction defining AntiDepReg to earlyclobber its
    // operands, in case they may be assigned to NewReg. In this case antidep
    // breaking must fail, but it's too rare to bother optimizing.
    if (RefOper->isDef() && RefOper->isEarlyClobber())
      return true;

    // Handle cases in which this instruction defines NewReg.
    MachineInstr *MI = RefOper->getParent();
    for (const MachineOperand &CheckOper : MI->operands()) {
      if (CheckOper.isRegMask() && CheckOper.clobbersPhysReg(NewReg))
        return true;

      if (!CheckOper.isReg() || !CheckOper.isDef() ||
          CheckOper.getReg() != NewReg)
        continue;

      // Don't allow the instruction to define NewReg and AntiDepReg.
      // When AntiDepReg is renamed it will be an illegal op.
      if (RefOper->isDef())
        return true;

      // Don't allow an instruction using AntiDepReg to be earlyclobbered by
      // NewReg.
      if (CheckOper.isEarlyClobber())
        return true;

      // Don't allow inline asm to define NewReg at all. Who knows what it's
      // doing with it.
      if (MI->isInlineAsm())
        return true;
    }
  }
  return false;
}

MCRegister CriticalAntiDepBreaker::findSuitableFreeRegister(
    RegRefIter RegRefBegin, RegRefIter RegRefEnd, MCRegister AntiDepReg,
    MCRegister LastNewReg, const TargetRegisterClass *RC,
    const SmallVectorImpl<Register> &Forbid) {
  ArrayRef<MCPhysReg> Order = RegClassInfo.getOrder(RC);
  for (MCRegister NewReg : Order) {
    // Don't replace a register with itself.
    if (NewReg == AntiDepReg) continue;
    // Don't replace a register with one that was recently used to repair
    // an anti-dependence with this AntiDepReg, because that would
    // re-introduce that anti-dependence.
    if (NewReg == LastNewReg) continue;
    // If any instructions that define AntiDepReg also define the NewReg, it's
    // not suitable.  For example, Instruction with multiple definitions can
    // result in this condition.
    if (isNewRegClobberedByRefs(RegRefBegin, RegRefEnd, NewReg)) continue;
    // If NewReg is dead and NewReg's most recent def is not before
    // AntiDepReg's kill, it's safe to replace AntiDepReg with NewReg.
    assert(((KillIndices[AntiDepReg.id()] == ~0u) !=
            (DefIndices[AntiDepReg.id()] == ~0u)) &&
           "Kill and Def maps aren't consistent for AntiDepReg!");
    assert(((KillIndices[NewReg.id()] == ~0u) !=
            (DefIndices[NewReg.id()] == ~0u)) &&
           "Kill and Def maps aren't consistent for NewReg!");
    if (KillIndices[NewReg.id()] != ~0u ||
        Classes[NewReg.id()] == reinterpret_cast<TargetRegisterClass *>(-1) ||
        KillIndices[AntiDepReg.id()] > DefIndices[NewReg.id()])
      continue;
    // If NewReg overlaps any of the forbidden registers, we can't use it.
    bool Forbidden = false;
    for (Register R : Forbid)
      if (TRI->regsOverlap(NewReg, R)) {
        Forbidden = true;
        break;
      }
    if (Forbidden) continue;
    return NewReg;
  }

  // No registers are free and available!
  return MCRegister();
}

unsigned CriticalAntiDepBreaker::
BreakAntiDependencies(const std::vector<SUnit> &SUnits,
                      MachineBasicBlock::iterator Begin,
                      MachineBasicBlock::iterator End,
                      unsigned InsertPosIndex,
                      DbgValueVector &DbgValues) {
  // The code below assumes that there is at least one instruction,
  // so just duck out immediately if the block is empty.
  if (SUnits.empty()) return 0;

  // Keep a map of the MachineInstr*'s back to the SUnit representing them.
  // This is used for updating debug information.
  //
  // FIXME: Replace this with the existing map in ScheduleDAGInstrs::MISUnitMap
  DenseMap<MachineInstr *, const SUnit *> MISUnitMap;

  // Find the node at the bottom of the critical path.
  const SUnit *Max = nullptr;
  for (const SUnit &SU : SUnits) {
    MISUnitMap[SU.getInstr()] = &SU;
    if (!Max || SU.getDepth() + SU.Latency > Max->getDepth() + Max->Latency)
      Max = &SU;
  }
  assert(Max && "Failed to find bottom of the critical path");

#ifndef NDEBUG
  {
    LLVM_DEBUG(dbgs() << "Critical path has total latency "
                      << (Max->getDepth() + Max->Latency) << "\n");
    LLVM_DEBUG(dbgs() << "Available regs:");
    for (unsigned Reg = 1; Reg < TRI->getNumRegs(); ++Reg) {
      if (KillIndices[Reg] == ~0u)
        LLVM_DEBUG(dbgs() << " " << printReg(Reg, TRI));
    }
    LLVM_DEBUG(dbgs() << '\n');
  }
#endif

  // Track progress along the critical path through the SUnit graph as we walk
  // the instructions.
  const SUnit *CriticalPathSU = Max;
  MachineInstr *CriticalPathMI = CriticalPathSU->getInstr();

  // Consider this pattern:
  //   A = ...
  //   ... = A
  //   A = ...
  //   ... = A
  //   A = ...
  //   ... = A
  //   A = ...
  //   ... = A
  // There are three anti-dependencies here, and without special care,
  // we'd break all of them using the same register:
  //   A = ...
  //   ... = A
  //   B = ...
  //   ... = B
  //   B = ...
  //   ... = B
  //   B = ...
  //   ... = B
  // because at each anti-dependence, B is the first register that
  // isn't A which is free.  This re-introduces anti-dependencies
  // at all but one of the original anti-dependencies that we were
  // trying to break.  To avoid this, keep track of the most recent
  // register that each register was replaced with, avoid
  // using it to repair an anti-dependence on the same register.
  // This lets us produce this:
  //   A = ...
  //   ... = A
  //   B = ...
  //   ... = B
  //   C = ...
  //   ... = C
  //   B = ...
  //   ... = B
  // This still has an anti-dependence on B, but at least it isn't on the
  // original critical path.
  //
  // TODO: If we tracked more than one register here, we could potentially
  // fix that remaining critical edge too. This is a little more involved,
  // because unlike the most recent register, less recent registers should
  // still be considered, though only if no other registers are available.
  std::vector<MCRegister> LastNewReg(TRI->getNumRegs(), MCRegister());

  // Attempt to break anti-dependence edges on the critical path. Walk the
  // instructions from the bottom up, tracking information about liveness
  // as we go to help determine which registers are available.
  unsigned Broken = 0;
  unsigned Count = InsertPosIndex - 1;
  for (MachineBasicBlock::iterator I = End, E = Begin; I != E; --Count) {
    MachineInstr &MI = *--I;
    // Kill instructions can define registers but are really nops, and there
    // might be a real definition earlier that needs to be paired with uses
    // dominated by this kill.

    // FIXME: It may be possible to remove the isKill() restriction once PR18663
    // has been properly fixed. There can be value in processing kills as seen
    // in the AggressiveAntiDepBreaker class.
    if (MI.isDebugInstr() || MI.isKill())
      continue;

    // Check if this instruction has a dependence on the critical path that
    // is an anti-dependence that we may be able to break. If it is, set
    // AntiDepReg to the non-zero register associated with the anti-dependence.
    //
    // We limit our attention to the critical path as a heuristic to avoid
    // breaking anti-dependence edges that aren't going to significantly
    // impact the overall schedule. There are a limited number of registers
    // and we want to save them for the important edges.
    //
    // TODO: Instructions with multiple defs could have multiple
    // anti-dependencies. The current code here only knows how to break one
    // edge per instruction. Note that we'd have to be able to break all of
    // the anti-dependencies in an instruction in order to be effective.
    MCRegister AntiDepReg;
    if (&MI == CriticalPathMI) {
      if (const SDep *Edge = CriticalPathStep(CriticalPathSU)) {
        const SUnit *NextSU = Edge->getSUnit();

        // Only consider anti-dependence edges.
        if (Edge->getKind() == SDep::Anti) {
          AntiDepReg = Edge->getReg().asMCReg();
          assert(AntiDepReg && "Anti-dependence on reg0?");
          if (!MRI.isAllocatable(AntiDepReg))
            // Don't break anti-dependencies on non-allocatable registers.
            AntiDepReg = MCRegister();
          else if (KeepRegs.test(AntiDepReg.id()))
            // Don't break anti-dependencies if a use down below requires
            // this exact register.
            AntiDepReg = MCRegister();
          else {
            // If the SUnit has other dependencies on the SUnit that it
            // anti-depends on, don't bother breaking the anti-dependency
            // since those edges would prevent such units from being
            // scheduled past each other regardless.
            //
            // Also, if there are dependencies on other SUnits with the
            // same register as the anti-dependency, don't attempt to
            // break it.
            for (const SDep &P : CriticalPathSU->Preds)
              if (P.getSUnit() == NextSU
                      ? (P.getKind() != SDep::Anti || P.getReg() != AntiDepReg)
                      : (P.getKind() == SDep::Data &&
                         P.getReg() == AntiDepReg)) {
                AntiDepReg = MCRegister();
                break;
              }
          }
        }
        CriticalPathSU = NextSU;
        CriticalPathMI = CriticalPathSU->getInstr();
      } else {
        // We've reached the end of the critical path.
        CriticalPathSU = nullptr;
        CriticalPathMI = nullptr;
      }
    }

    PrescanInstruction(MI);

    SmallVector<Register, 2> ForbidRegs;

    // If MI's defs have a special allocation requirement, don't allow
    // any def registers to be changed. Also assume all registers
    // defined in a call must not be changed (ABI).
    if (MI.isCall() || MI.hasExtraDefRegAllocReq() || TII->isPredicated(MI))
      // If this instruction's defs have special allocation requirement, don't
      // break this anti-dependency.
      AntiDepReg = MCRegister();
    else if (AntiDepReg) {
      // If this instruction has a use of AntiDepReg, breaking it
      // is invalid.  If the instruction defines other registers,
      // save a list of them so that we don't pick a new register
      // that overlaps any of them.
      for (const MachineOperand &MO : MI.operands()) {
        if (!MO.isReg()) continue;
        Register Reg = MO.getReg();
        if (!Reg)
          continue;
        if (MO.isUse() && TRI->regsOverlap(AntiDepReg, Reg)) {
          AntiDepReg = MCRegister();
          break;
        }
        if (MO.isDef() && Reg != AntiDepReg)
          ForbidRegs.push_back(Reg);
      }
    }

    // Determine AntiDepReg's register class, if it is live and is
    // consistently used within a single class.
    const TargetRegisterClass *RC =
        AntiDepReg ? Classes[AntiDepReg.id()] : nullptr;
    assert((!AntiDepReg || RC != nullptr) &&
           "Register should be live if it's causing an anti-dependence!");
    if (RC == reinterpret_cast<TargetRegisterClass *>(-1))
      AntiDepReg = MCRegister();

    // Look for a suitable register to use to break the anti-dependence.
    //
    // TODO: Instead of picking the first free register, consider which might
    // be the best.
    if (AntiDepReg) {
      std::pair<std::multimap<MCRegister, MachineOperand *>::iterator,
                std::multimap<MCRegister, MachineOperand *>::iterator>
          Range = RegRefs.equal_range(AntiDepReg);
      if (MCRegister NewReg = findSuitableFreeRegister(
              Range.first, Range.second, AntiDepReg,
              LastNewReg[AntiDepReg.id()], RC, ForbidRegs)) {
        LLVM_DEBUG(dbgs() << "Breaking anti-dependence edge on "
                          << printReg(AntiDepReg, TRI) << " with "
                          << RegRefs.count(AntiDepReg) << " references"
                          << " using " << printReg(NewReg, TRI) << "!\n");

        // Update the references to the old register to refer to the new
        // register.
        for (std::multimap<MCRegister, MachineOperand *>::iterator
                 Q = Range.first,
                 QE = Range.second;
             Q != QE; ++Q) {
          Q->second->setReg(NewReg);
          // If the SU for the instruction being updated has debug information
          // related to the anti-dependency register, make sure to update that
          // as well.
          const SUnit *SU = MISUnitMap[Q->second->getParent()];
          if (!SU) continue;
          UpdateDbgValues(DbgValues, Q->second->getParent(),
                          AntiDepReg, NewReg);
        }

        // We just went back in time and modified history; the
        // liveness information for the anti-dependence reg is now
        // inconsistent. Set the state as if it were dead.
        Classes[NewReg.id()] = Classes[AntiDepReg.id()];
        DefIndices[NewReg.id()] = DefIndices[AntiDepReg.id()];
        KillIndices[NewReg.id()] = KillIndices[AntiDepReg.id()];
        assert(((KillIndices[NewReg.id()] == ~0u) !=
                (DefIndices[NewReg.id()] == ~0u)) &&
               "Kill and Def maps aren't consistent for NewReg!");

        Classes[AntiDepReg.id()] = nullptr;
        DefIndices[AntiDepReg.id()] = KillIndices[AntiDepReg.id()];
        KillIndices[AntiDepReg.id()] = ~0u;
        assert(((KillIndices[AntiDepReg.id()] == ~0u) !=
                (DefIndices[AntiDepReg.id()] == ~0u)) &&
               "Kill and Def maps aren't consistent for AntiDepReg!");

        RegRefs.erase(AntiDepReg);
        LastNewReg[AntiDepReg.id()] = NewReg;
        ++Broken;
      }
    }

    ScanInstruction(MI, Count);
  }

  return Broken;
}

AntiDepBreaker *
llvm::createCriticalAntiDepBreaker(MachineFunction &MFi,
                                   const RegisterClassInfo &RCI) {
  return new CriticalAntiDepBreaker(MFi, RCI);
}
