Exemple #1
0
/// Allocates a physical register for VirtReg.
void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, unsigned Hint) {
  const unsigned VirtReg = LR.VirtReg;

  assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
         "Can only allocate virtual registers");

  const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
  LLVM_DEBUG(dbgs() << "Search register for " << printReg(VirtReg)
                    << " in class " << TRI->getRegClassName(&RC)
                    << " with hint " << printReg(Hint, TRI) << '\n');

  // Take hint when possible.
  if (TargetRegisterInfo::isPhysicalRegister(Hint) &&
      MRI->isAllocatable(Hint) && RC.contains(Hint)) {
    // Ignore the hint if we would have to spill a dirty register.
    unsigned Cost = calcSpillCost(Hint);
    if (Cost < spillDirty) {
      if (Cost)
        definePhysReg(MI, Hint, regFree);
      assignVirtToPhysReg(LR, Hint);
      return;
    }
  }

  MCPhysReg BestReg = 0;
  unsigned BestCost = spillImpossible;
  ArrayRef<MCPhysReg> AllocationOrder = RegClassInfo.getOrder(&RC);
  for (MCPhysReg PhysReg : AllocationOrder) {
    LLVM_DEBUG(dbgs() << "\tRegister: " << printReg(PhysReg, TRI) << ' ');
    unsigned Cost = calcSpillCost(PhysReg);
    LLVM_DEBUG(dbgs() << "Cost: " << Cost << " BestCost: " << BestCost << '\n');
    // Immediate take a register with cost 0.
    if (Cost == 0) {
      assignVirtToPhysReg(LR, PhysReg);
      return;
    }
    if (Cost < BestCost) {
      BestReg = PhysReg;
      BestCost = Cost;
    }
  }

  if (!BestReg) {
    // Nothing we can do: Report an error and keep going with an invalid
    // allocation.
    if (MI.isInlineAsm())
      MI.emitError("inline assembly requires more registers than available");
    else
      MI.emitError("ran out of registers during register allocation");
    definePhysReg(MI, *AllocationOrder.begin(), regFree);
    assignVirtToPhysReg(LR, *AllocationOrder.begin());
    return;
  }

  definePhysReg(MI, BestReg, regFree);
  assignVirtToPhysReg(LR, BestReg);
}
Exemple #2
0
void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
{
  if (MI.getParent()->getParent()->getInfo<ARMFunctionInfo>()
    ->isThumbFunction())
  {
    MI.emitError("An attempt to perform XRay instrumentation for a"
      " Thumb function (not supported). Detected when emitting a sled.");
    return;
  }
  static const int8_t NoopsInSledCount = 6;
  // We want to emit the following pattern:
  //
  // .Lxray_sled_N:
  //   ALIGN
  //   B #20
  //   ; 6 NOP instructions (24 bytes)
  // .tmpN
  //
  // We need the 24 bytes (6 instructions) because at runtime, we'd be patching
  // over the full 28 bytes (7 instructions) with the following pattern:
  //
  //   PUSH{ r0, lr }
  //   MOVW r0, #<lower 16 bits of function ID>
  //   MOVT r0, #<higher 16 bits of function ID>
  //   MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>
  //   MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>
  //   BLX ip
  //   POP{ r0, lr }
  //
  OutStreamer->EmitCodeAlignment(4);
  auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
  OutStreamer->EmitLabel(CurSled);
  auto Target = OutContext.createTempSymbol();

  // Emit "B #20" instruction, which jumps over the next 24 bytes (because
  // register pc is 8 bytes ahead of the jump instruction by the moment CPU
  // is executing it).
  // By analogy to ARMAsmPrinter::emitPseudoExpansionLowering() |case ARM::B|.
  // It is not clear why |addReg(0)| is needed (the last operand).
  EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)
    .addImm(ARMCC::AL).addReg(0));

  MCInst Noop;
  Subtarget->getInstrInfo()->getNoopForElfTarget(Noop);
  for (int8_t I = 0; I < NoopsInSledCount; I++)
  {
    OutStreamer->EmitInstruction(Noop, getSubtargetInfo());
  }

  OutStreamer->EmitLabel(Target);
  recordSled(CurSled, MI, Kind);
}
Exemple #3
0
// Top-level driver to manage the queue of unassigned VirtRegs and call the
// selectOrSplit implementation.
void RegAllocBase::allocatePhysRegs() {
    seedLiveRegs();

    // Continue assigning vregs one at a time to available physical registers.
    while (LiveInterval *VirtReg = dequeue()) {
        assert(!VRM->hasPhys(VirtReg->reg) && "Register already assigned");

        // Unused registers can appear when the spiller coalesces snippets.
        if (MRI->reg_nodbg_empty(VirtReg->reg)) {
            DEBUG(dbgs() << "Dropping unused " << *VirtReg << '\n');
            LIS->removeInterval(VirtReg->reg);
            continue;
        }

        // Invalidate all interference queries, live ranges could have changed.
        invalidateVirtRegs();

        // selectOrSplit requests the allocator to return an available physical
        // register if possible and populate a list of new live intervals that
        // result from splitting.
        DEBUG(dbgs() << "\nselectOrSplit "
              << MRI->getRegClass(VirtReg->reg)->getName()
              << ':' << *VirtReg << '\n');
        typedef SmallVector<LiveInterval*, 4> VirtRegVec;
        VirtRegVec SplitVRegs;
        unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs);

        if (AvailablePhysReg == ~0u) {
            // selectOrSplit failed to find a register!
            const char *Msg = "ran out of registers during register allocation";
            // Probably caused by an inline asm.
            MachineInstr *MI;
            for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(VirtReg->reg);
                    (MI = I.skipInstruction());)
                if (MI->isInlineAsm())
                    break;
            if (MI)
                MI->emitError(Msg);
            else
                report_fatal_error(Msg);
            // Keep going after reporting the error.
            VRM->assignVirt2Phys(VirtReg->reg,
                                 RegClassInfo.getOrder(MRI->getRegClass(VirtReg->reg)).front());
            continue;
        }

        if (AvailablePhysReg)
            assign(*VirtReg, AvailablePhysReg);

        for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end();
                I != E; ++I) {
            LiveInterval *SplitVirtReg = *I;
            assert(!VRM->hasPhys(SplitVirtReg->reg) && "Register already assigned");
            if (MRI->reg_nodbg_empty(SplitVirtReg->reg)) {
                DEBUG(dbgs() << "not queueing unused  " << *SplitVirtReg << '\n');
                LIS->removeInterval(SplitVirtReg->reg);
                continue;
            }
            DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n");
            assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) &&
                   "expect split value in virtual register");
            enqueue(SplitVirtReg);
            ++NumNewQueued;
        }
    }
}