tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SimpleAllocator.cpp (46040B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      3 * This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "jit/SimpleAllocator.h"
      8 
      9 #include "mozilla/Maybe.h"
     10 
     11 #include <algorithm>
     12 
     13 #include "jit/BitSet.h"
     14 #include "jit/CompileInfo.h"
     15 #include "js/Printf.h"
     16 
     17 using namespace js;
     18 using namespace js::jit;
     19 
     20 using mozilla::DebugOnly;
     21 using mozilla::Maybe;
     22 
     23 // [SMDOC] Simple Register Allocator
     24 //
     25 // This is an alternative register allocator for Ion that's simpler than the
     26 // backtracking allocator. It attempts to perform register allocation quickly
     27 // while still producing fairly decent code within basic blocks.
     28 //
     29 // The Backtracking allocator is usually the slowest part of the Ion compiler
     30 // backend, whereas this Simple allocator is often faster than codegen and/or
     31 // GVN.
     32 //
     33 // This allocator lets us experiment with different compilation strategies and
     34 // it provides a useful baseline for measuring and optimizing the performance of
     35 // the backtracking allocator.
     36 //
     37 // This allocator also helps document our LIR => Register Allocator interface
     38 // and will make it easier to experiment with alternative register allocators in
     39 // the future.
     40 //
     41 // Phases
     42 // ======
     43 // This allocator has 3 phases with the following main goals:
     44 //
     45 // (1) init: initializes a VirtualRegister instance for each virtual register.
     46 //
     47 // (2) analyzeLiveness: iterates over all LIR instructions in reverse order to
     48 //     collect the following information:
     49 //
     50 //     * For each virtual register we record where it's last used (its
     51 //       lastUseInsId_). Register allocation uses this information to free
     52 //       dead registers and stack slots in freeDeadVregsAfterInstruction.
     53 //
     54 //     * For each basic block it records the set of live GC things (liveGCIn_)
     55 //       at the start of the block. This is used by the register allocation pass
     56 //       to populate safepoints (used for GC tracing).
     57 //
     58 //     * For virtual registers with fixed register uses, it assigns a register
     59 //       hint to help avoid moves (fixedUseHint_).
     60 //
     61 //     This function is based on BacktrackingAllocator::buildLivenessInfo.
     62 //
     63 // (3) allocateRegisters: this iterates over all LIR instructions (from first to
     64 //     last) to allocate registers and to populate safepoints.
     65 //
     66 // Register allocation
     67 // ===================
     68 // Producing the fastest possible code is not a goal for this allocator, so it
     69 // makes the following trade-offs:
     70 //
     71 // * It tries to keep values in registers within a basic block, but values that
     72 //   are used across blocks are spilled in the block where they're defined.
     73 //   We try to spill these values as early as possible (instead of all at the
     74 //   end of the block) to help avoid CPU store buffer stalls.
     75 //
     76 // * Blocks with a single predecessor can reuse the register state at the end of
     77 //   that predecessor block. Values in these registers must have a stack
     78 //   location too so reusing this state is optional. This is based on a small
     79 //   array with state for just four recent blocks in it, but in practice this is
     80 //   good enough to eliminate a lot of memory loads.
     81 //
     82 // * Phis are always assigned a stack slot and phi operands are stored to this
     83 //   location at the end of the predecessor blocks (in allocateForBlockEnd).
     84 //
     85 // * Stack slots are freed when virtual registers die and can then be reused.
     86 //
     87 // In practice this results in fairly decent code within basic blocks. This
     88 // allocator generates relatively poor code for tight loops or for code with
     89 // many short blocks.
     90 
     91 static AnyRegister MaybeGetRegisterFromSet(AllocatableRegisterSet regs,
     92                                           LDefinition::Type type) {
     93  // Get an available register from `regs`, or return an invalid register if no
     94  // register is available.
     95  switch (type) {
     96    case LDefinition::Type::FLOAT32:
     97      if (regs.hasAny<RegTypeName::Float32>()) {
     98        return AnyRegister(regs.getAnyFloat<RegTypeName::Float32>());
     99      }
    100      break;
    101    case LDefinition::Type::DOUBLE:
    102      if (regs.hasAny<RegTypeName::Float64>()) {
    103        return AnyRegister(regs.getAnyFloat<RegTypeName::Float64>());
    104      }
    105      break;
    106    case LDefinition::Type::SIMD128:
    107      if (regs.hasAny<RegTypeName::Vector128>()) {
    108        return AnyRegister(regs.getAnyFloat<RegTypeName::Vector128>());
    109      }
    110      break;
    111    default:
    112      MOZ_ASSERT(!LDefinition::isFloatReg(type));
    113      if (regs.hasAny<RegTypeName::GPR>()) {
    114        return AnyRegister(regs.getAnyGeneral());
    115      }
    116      break;
    117  }
    118  return AnyRegister();
    119 }
    120 
    121 bool SimpleAllocator::init() {
    122  size_t numBlocks = graph.numBlocks();
    123  if (!liveGCIn_.growBy(numBlocks)) {
    124    return false;
    125  }
    126 
    127  size_t numVregs = graph.numVirtualRegisters();
    128  if (!vregs_.initCapacity(numVregs)) {
    129    return false;
    130  }
    131  for (size_t i = 0; i < numVregs; i++) {
    132    vregs_.infallibleEmplaceBack();
    133  }
    134 
    135  // Initialize virtual registers.
    136  for (size_t blockIndex = 0; blockIndex < numBlocks; blockIndex++) {
    137    if (mir->shouldCancel("init (block loop)")) {
    138      return false;
    139    }
    140 
    141    LBlock* block = graph.getBlock(blockIndex);
    142 
    143    for (uint32_t i = 0, numPhis = block->numPhis(); i < numPhis; i++) {
    144      LPhi* phi = block->getPhi(i);
    145      LDefinition* def = phi->getDef(0);
    146      vregs_[def->virtualRegister()].init(phi, def, /* isTemp = */ false);
    147    }
    148 
    149    for (LInstructionIterator iter = block->begin(); iter != block->end();
    150         iter++) {
    151      LInstruction* ins = *iter;
    152      for (LInstruction::OutputIter output(ins); !output.done(); output++) {
    153        LDefinition* def = *output;
    154        vregs_[def->virtualRegister()].init(ins, def, /* isTemp = */ false);
    155      }
    156      for (LInstruction::TempIter temp(ins); !temp.done(); temp++) {
    157        LDefinition* def = *temp;
    158        vregs_[def->virtualRegister()].init(ins, def, /* isTemp = */ true);
    159      }
    160    }
    161  }
    162 
    163  return true;
    164 }
    165 
    166 bool SimpleAllocator::analyzeLiveness() {
    167  JitSpew(JitSpew_RegAlloc, "Beginning liveness analysis");
    168 
    169  // Stack of active loops.
    170  struct LoopState {
    171    // The first instruction of the loop header.
    172    uint32_t firstId;
    173    // The last instruction of the backedge.
    174    uint32_t lastId;
    175    explicit LoopState(LBlock* header, uint32_t lastId)
    176        : firstId(header->firstId()), lastId(lastId) {}
    177  };
    178  Vector<LoopState, 4, BackgroundSystemAllocPolicy> loopStack;
    179 
    180 #ifdef DEBUG
    181  // In debug builds, assert that each instruction has a smaller ID than the
    182  // previous instructions we saw (since we're iterating over instructions in
    183  // reverse order). Our simple liveness analysis relies on this for the vreg's
    184  // lastUseInsId_.
    185  uint32_t lastInsId = UINT32_MAX;
    186 #endif
    187 
    188  for (size_t i = graph.numBlocks(); i > 0; i--) {
    189    if (mir->shouldCancel("analyzeLiveness (block loop)")) {
    190      return false;
    191    }
    192 
    193    LBlock* block = graph.getBlock(i - 1);
    194    MBasicBlock* mblock = block->mir();
    195    VirtualRegBitSet& liveGC = liveGCIn_[mblock->id()];
    196 
    197    if (mblock->isLoopBackedge()) {
    198      if (!loopStack.emplaceBack(mblock->loopHeaderOfBackedge()->lir(),
    199                                 block->lastId())) {
    200        return false;
    201      }
    202    }
    203 
    204    // Propagate liveGCIn from our successors to us. Skip backedges, as we fix
    205    // them up at the loop header.
    206    for (size_t i = 0; i < mblock->lastIns()->numSuccessors(); i++) {
    207      MBasicBlock* successor = mblock->lastIns()->getSuccessor(i);
    208      if (mblock->id() < successor->id()) {
    209        if (!liveGC.insertAll(liveGCIn_[successor->id()])) {
    210          return false;
    211        }
    212      }
    213    }
    214 
    215    uint32_t blockFirstId = block->firstId();
    216 
    217    auto handleUseOfVreg = [&](uint32_t insId, uint32_t vregId) {
    218      uint32_t defId = vregs_[vregId].insId();
    219      const LoopState* outerLoop = nullptr;
    220      if (defId < blockFirstId) {
    221        // This vreg is defined before the current block. We need to add it to
    222        // the block's liveGC set if it's a GC type.
    223        if (vregs_[vregId].isGCType() && !liveGC.insert(vregId)) {
    224          return false;
    225        }
    226        // If we're inside a loop, search for the outermost loop that has this
    227        // vreg live across the entire loop. We need to extend the vreg's range
    228        // to cover this loop.
    229        for (size_t i = loopStack.length(); i > 0; i--) {
    230          const LoopState& loop = loopStack[i - 1];
    231          if (defId >= loop.firstId) {
    232            break;
    233          }
    234          outerLoop = &loop;
    235        }
    236      }
    237      vregs_[vregId].updateLastUseId(outerLoop ? outerLoop->lastId : insId);
    238      return true;
    239    };
    240 
    241    // If this block has a successor with phis, the phi operands will be used at
    242    // the end of the current block.
    243    if (MBasicBlock* successor = mblock->successorWithPhis()) {
    244      LBlock* phiSuccessor = successor->lir();
    245      uint32_t blockLastInsId = block->lastId();
    246      for (size_t j = 0; j < phiSuccessor->numPhis(); j++) {
    247        LPhi* phi = phiSuccessor->getPhi(j);
    248        LAllocation* use = phi->getOperand(mblock->positionInPhiSuccessor());
    249        if (!handleUseOfVreg(blockLastInsId, use->toUse()->virtualRegister())) {
    250          return false;
    251        }
    252      }
    253    }
    254 
    255    // Handle instruction uses and outputs.
    256    for (LInstructionReverseIterator ins = block->rbegin();
    257         ins != block->rend(); ins++) {
    258      if (mir->shouldCancel("analyzeLiveness (instruction loop)")) {
    259        return false;
    260      }
    261 
    262 #ifdef DEBUG
    263      MOZ_ASSERT(ins->id() < lastInsId);
    264      lastInsId = ins->id();
    265 #endif
    266 
    267      for (LInstruction::OutputIter output(*ins); !output.done(); output++) {
    268        uint32_t vregId = output->virtualRegister();
    269        if (vregs_[vregId].isGCType()) {
    270          liveGC.remove(vregId);
    271        }
    272      }
    273      for (LInstruction::InputIter inputAlloc(**ins); inputAlloc.more();
    274           inputAlloc.next()) {
    275        if (!inputAlloc->isUse()) {
    276          continue;
    277        }
    278        LUse* use = inputAlloc->toUse();
    279        uint32_t vregId = use->virtualRegister();
    280        if (!handleUseOfVreg(ins->id(), vregId)) {
    281          return false;
    282        }
    283        if (use->policy() == LUse::FIXED) {
    284          // Assign a register hint to the vreg. We'll prefer allocating this
    285          // register later to avoid unnecessary moves.
    286          VirtualRegister& vreg = vregs_[vregId];
    287          AnyRegister fixedReg = GetFixedRegister(vreg.def(), use);
    288          if (vreg.fixedUseHint().isNothing()) {
    289            vreg.setFixedUseHint(fixedReg);
    290          } else if (*vreg.fixedUseHint() != fixedReg) {
    291            // Conflicting fixed register uses. Clear the hint.
    292            vreg.setFixedUseHint(AnyRegister());
    293          }
    294        }
    295      }
    296    }
    297 
    298    // Handle phi definitions.
    299    for (size_t i = 0; i < block->numPhis(); i++) {
    300      LPhi* phi = block->getPhi(i);
    301      LDefinition* def = phi->getDef(0);
    302      uint32_t vregId = def->virtualRegister();
    303      if (vregs_[vregId].isGCType()) {
    304        liveGC.remove(vregId);
    305      }
    306      // Loop header phis must not be freed before the end of the backedge
    307      // because the backedge might store to the phi's stack slot.
    308      if (mblock->isLoopHeader()) {
    309        vregs_[vregId].updateLastUseId(loopStack.back().lastId);
    310      }
    311    }
    312 
    313    if (mblock->isLoopHeader()) {
    314      MBasicBlock* backedge = mblock->backedge();
    315      MOZ_ASSERT(loopStack.back().firstId == block->firstId());
    316      loopStack.popBack();
    317 
    318      // Propagate the loop header's liveGCIn set to all blocks within the loop.
    319      if (mblock != backedge && !liveGC.empty()) {
    320        // Start at the block after |mblock|.
    321        MOZ_ASSERT(graph.getBlock(i - 1) == mblock->lir());
    322        size_t j = i;
    323        while (true) {
    324          MBasicBlock* loopBlock = graph.getBlock(j)->mir();
    325          if (!liveGCIn_[loopBlock->id()].insertAll(liveGC)) {
    326            return false;
    327          }
    328          if (loopBlock == backedge) {
    329            break;
    330          }
    331          j++;
    332        }
    333      }
    334    }
    335 
    336    MOZ_ASSERT_IF(!mblock->numPredecessors(), liveGC.empty());
    337  }
    338 
    339  MOZ_ASSERT(loopStack.empty());
    340 
    341  // Initialize vregLastUses_ vector and sort it by instructionId in descending
    342  // order. This will be used in freeDeadVregsAfterInstruction.
    343  uint32_t numVregs = vregs_.length();
    344  if (!vregLastUses_.reserve(numVregs)) {
    345    return false;
    346  }
    347  for (uint32_t vregId = 1; vregId < numVregs; vregId++) {
    348    vregLastUses_.infallibleEmplaceBack(vregs_[vregId].lastUseInsId(), vregId);
    349  }
    350  auto compareEntries = [](VregLastUse a, VregLastUse b) {
    351    return a.instructionId > b.instructionId;
    352  };
    353  std::sort(vregLastUses_.begin(), vregLastUses_.end(), compareEntries);
    354  return true;
    355 }
    356 
    357 void SimpleAllocator::removeAllocatedRegisterAtIndex(size_t index) {
    358  // Release the register for this entry.
    359  AllocatedRegister allocated = allocatedRegs_[index];
    360  uint32_t vregId = allocated.vregId();
    361  availableRegs_.add(allocated.reg());
    362 
    363  // Use the swap-and-pop idiom to remove the entry so that we don't change the
    364  // register index of other entries.
    365  size_t lastIndex = allocatedRegs_.length() - 1;
    366  if (index != lastIndex) {
    367    uint32_t lastVregId = allocatedRegs_.back().vregId();
    368    allocatedRegs_[index] = allocatedRegs_.back();
    369    if (vregs_[lastVregId].registerIndex() == lastIndex) {
    370      vregs_[lastVregId].setRegisterIndex(index);
    371    }
    372  }
    373  allocatedRegs_.popBack();
    374  vregs_[vregId].clearRegisterIndex();
    375 
    376  // In the uncommon case where the vreg might have another allocated register,
    377  // assign the other register to this vreg if needed.
    378  if (MOZ_UNLIKELY(hasMultipleRegsForVreg_)) {
    379    for (size_t j = 0; j < allocatedRegs_.length(); j++) {
    380      if (allocatedRegs_[j].vregId() == vregId) {
    381        vregs_[vregId].setRegisterIndex(j);
    382        break;
    383      }
    384    }
    385  }
    386 }
    387 
    388 LAllocation SimpleAllocator::ensureStackLocation(uint32_t vregId) {
    389  // Allocate a stack slot for this virtual register if needed.
    390  VirtualRegister& vreg = vregs_[vregId];
    391  if (vreg.hasStackLocation()) {
    392    return vreg.stackLocation();
    393  }
    394  LStackSlot::Width width = LStackSlot::width(vreg.def()->type());
    395  LStackSlot::SlotAndWidth slot(stackSlotAllocator_.allocateSlot(width), width);
    396  vreg.setAllocatedStackSlot(slot);
    397  return LStackSlot(slot);
    398 }
    399 
    400 LAllocation SimpleAllocator::registerOrStackLocation(LInstruction* ins,
    401                                                     uint32_t vregId,
    402                                                     bool trackRegUse) {
    403  const VirtualRegister& vreg = vregs_[vregId];
    404  if (vreg.hasRegister()) {
    405    AllocatedRegister& allocated = allocatedRegs_[vreg.registerIndex()];
    406    if (trackRegUse) {
    407      allocated.setLastUsedAtInsId(ins->id());
    408    }
    409    return LAllocation(allocated.reg());
    410  }
    411  return vreg.stackLocation();
    412 }
    413 
    414 bool SimpleAllocator::spillRegister(LInstruction* ins,
    415                                    AllocatedRegister allocated) {
    416  VirtualRegister& vreg = vregs_[allocated.vregId()];
    417  MOZ_ASSERT(vreg.insId() < ins->id());
    418  if (vreg.hasStackLocation()) {
    419    return true;
    420  }
    421  // Allocate a new stack slot and insert a register => stack move.
    422  LMoveGroup* input = getInputMoveGroup(ins);
    423  LAllocation dest = ensureStackLocation(allocated.vregId());
    424  return input->addAfter(LAllocation(allocated.reg()), dest,
    425                         vreg.def()->type());
    426 }
    427 
    428 bool SimpleAllocator::allocateForBlockEnd(LBlock* block, LInstruction* ins) {
    429 #ifdef DEBUG
    430  // All vregs that are live after this block must have a stack location at this
    431  // point.
    432  for (const AllocatedRegister& allocated : allocatedRegs_) {
    433    MOZ_ASSERT_IF(vregs_[allocated.vregId()].lastUseInsId() > ins->id(),
    434                  vregs_[allocated.vregId()].hasStackLocation());
    435  }
    436 #endif
    437 
    438  MBasicBlock* successor = block->mir()->successorWithPhis();
    439  if (!successor) {
    440    return true;
    441  }
    442 
    443  // The current block has a successor with phis. For each successor phi, insert
    444  // a move at the end of the current block to store the phi's operand into the
    445  // phi's stack slot.
    446 
    447  uint32_t position = block->mir()->positionInPhiSuccessor();
    448  LBlock* lirSuccessor = successor->lir();
    449  LMoveGroup* group = nullptr;
    450 
    451  for (size_t i = 0, numPhis = lirSuccessor->numPhis(); i < numPhis; i++) {
    452    LPhi* phi = lirSuccessor->getPhi(i);
    453 
    454    uint32_t sourceVreg = phi->getOperand(position)->toUse()->virtualRegister();
    455    uint32_t destVreg = phi->getDef(0)->virtualRegister();
    456    if (sourceVreg == destVreg) {
    457      continue;
    458    }
    459 
    460    if (!group) {
    461      // The moves we insert here need to happen simultaneously with each other,
    462      // yet after any existing moves before the instruction.
    463      LMoveGroup* input = getInputMoveGroup(ins);
    464      if (input->numMoves() == 0) {
    465        group = input;
    466      } else {
    467        group = LMoveGroup::New(alloc());
    468        block->insertAfter(input, group);
    469      }
    470    }
    471 
    472    LAllocation source =
    473        registerOrStackLocation(ins, sourceVreg, /* trackRegUse = */ true);
    474    LAllocation dest = ensureStackLocation(destVreg);
    475    if (!group->add(source, dest, phi->getDef(0)->type())) {
    476      return false;
    477    }
    478  }
    479 
    480  return true;
    481 }
    482 
    483 void SimpleAllocator::scanDefinition(LInstruction* ins, LDefinition* def,
    484                                     bool isTemp) {
    485  // Record fixed registers to make sure we don't assign these registers to
    486  // uses.
    487  if (def->policy() == LDefinition::FIXED && def->output()->isAnyRegister()) {
    488    AnyRegister reg = def->output()->toAnyRegister();
    489    if (isTemp) {
    490      fixedTempRegs_.add(reg);
    491    }
    492    // Note: addUnchecked because some instructions use the same fixed register
    493    // for a Temp and an Output (eg LCallNative). See bug 1962671.
    494    fixedOutputAndTempRegs_.addUnchecked(reg);
    495    return;
    496  }
    497  if (def->policy() == LDefinition::MUST_REUSE_INPUT) {
    498    ins->changePolicyOfReusedInputToAny(def);
    499  }
    500 }
    501 
    502 bool SimpleAllocator::allocateForNonFixedDefOrUse(LInstruction* ins,
    503                                                  uint32_t vregId,
    504                                                  AllocationKind kind,
    505                                                  AnyRegister* reg) {
    506  // This function is responsible for finding a new register for a (non-fixed)
    507  // register def or use. If no register is available, it will evict something.
    508 
    509  // This should only be called if the vreg doesn't have a register yet, unless
    510  // the caller set hasMultipleRegsForVreg_ to true.
    511  const VirtualRegister& vreg = vregs_[vregId];
    512  MOZ_ASSERT_IF(!hasMultipleRegsForVreg_, !vreg.hasRegister());
    513 
    514  // Determine the set of available registers. We can pick any register in
    515  // availableRegs_ except for fixed output/temp registers that we need to
    516  // allocate later. Note that UseAtStart inputs may use the same register as
    517  // outputs (but not temps).
    518  bool isUseAtStart = (kind == AllocationKind::UseAtStart);
    519  RegisterSet fixedDefs =
    520      isUseAtStart ? fixedTempRegs_.set() : fixedOutputAndTempRegs_.set();
    521  AllocatableRegisterSet available(
    522      RegisterSet::Subtract(availableRegs_.set(), fixedDefs));
    523 
    524  // If the virtual register has a register hint, pick that register if it's
    525  // available.
    526  if (vreg.fixedUseHint().isSome() && vreg.fixedUseHint()->isValid()) {
    527    AnyRegister regHint = *vreg.fixedUseHint();
    528    if (available.has(regHint)) {
    529      *reg = regHint;
    530      return addAllocatedReg(ins, vregId, isUseAtStart, *reg);
    531    }
    532  }
    533 
    534  // Try to get an arbitrary register from the set.
    535  *reg = MaybeGetRegisterFromSet(available, vreg.def()->type());
    536  if (reg->isValid()) {
    537    return addAllocatedReg(ins, vregId, isUseAtStart, *reg);
    538  }
    539 
    540  // No register is available. We need to evict something.
    541 
    542  // Determine which registers we must not evict. These are the registers in
    543  // fixedDefs (same as above) + registers we've already allocated for this
    544  // instruction. Note again that outputs can be assigned the same register as
    545  // UseAtStart inputs and we rely on this to not run out of registers on 32-bit
    546  // x86.
    547  AllocatableRegisterSet notEvictable;
    548  if (kind == AllocationKind::Output) {
    549    notEvictable.set() =
    550        RegisterSet::Union(fixedDefs, currentInsRegsNotAtStart_.set());
    551  } else {
    552    notEvictable.set() = RegisterSet::Union(fixedDefs, currentInsRegs_.set());
    553  }
    554 
    555  // Search for the best register to evict.
    556  LDefinition* def = vreg.def();
    557  const AllocatedRegister* bestToEvict = nullptr;
    558  for (size_t i = 0, len = allocatedRegs_.length(); i < len; i++) {
    559    AllocatedRegister& allocated = allocatedRegs_[i];
    560    if (!def->isCompatibleReg(allocated.reg()) ||
    561        notEvictable.has(allocated.reg())) {
    562      continue;
    563    }
    564    // Heuristics: prefer evicting registers where the vreg is also in another
    565    // register (uncommon), registers that already have a stack location, or
    566    // registers that haven't been used recently.
    567    if (!bestToEvict || vregs_[allocated.vregId()].registerIndex() != i ||
    568        (vregs_[allocated.vregId()].hasStackLocation() &&
    569         !vregs_[bestToEvict->vregId()].hasStackLocation()) ||
    570        allocated.lastUsedAtInsId() < bestToEvict->lastUsedAtInsId()) {
    571      bestToEvict = &allocated;
    572    }
    573  }
    574 
    575  if (bestToEvict) {
    576    *reg = bestToEvict->reg();
    577  } else {
    578    // We didn't find a compatible register to evict. This can happen for
    579    // aliased registers, for example if we allocated all Float32 registers and
    580    // now need a Double register. Pick an arbitrary register that's evictable
    581    // and evict all of its aliases.
    582    AllocatableRegisterSet evictable;
    583    evictable.set() =
    584        RegisterSet::Subtract(allRegisters_.set(), notEvictable.set());
    585    *reg = MaybeGetRegisterFromSet(evictable, def->type());
    586    MOZ_ASSERT(reg->numAliased() > 1);
    587  }
    588  if (!evictRegister(ins, *reg)) {
    589    return false;
    590  }
    591  return addAllocatedReg(ins, vregId, isUseAtStart, *reg);
    592 }
    593 
    594 bool SimpleAllocator::allocateForFixedUse(LInstruction* ins, const LUse* use,
    595                                          AnyRegister* reg) {
    596  uint32_t vregId = use->virtualRegister();
    597  VirtualRegister& vreg = vregs_[vregId];
    598  *reg = GetFixedRegister(vreg.def(), use);
    599 
    600  // Determine the vreg's current location.
    601  LAllocation alloc;
    602  if (vreg.hasRegister()) {
    603    // Check if the vreg is already using the fixed register.
    604    AllocatedRegister& allocated = allocatedRegs_[vreg.registerIndex()];
    605    if (allocated.reg() == *reg) {
    606      markUseOfAllocatedReg(ins, allocated, use->usedAtStart());
    607      return true;
    608    }
    609 
    610    // Try to avoid having multiple registers for the same vreg by replacing the
    611    // current register with the new one. If this is not possible (this is
    612    // uncommon) we set hasMultipleRegsForVreg_ and fix this up at the end of
    613    // allocateForInstruction.
    614    alloc = LAllocation(allocated.reg());
    615    if (currentInsRegs_.has(allocated.reg())) {
    616      hasMultipleRegsForVreg_ = true;
    617    } else {
    618      removeAllocatedRegisterAtIndex(vreg.registerIndex());
    619    }
    620  } else {
    621    alloc = vreg.stackLocation();
    622  }
    623 
    624  // If the fixed register is not available we have to evict it.
    625  if (!availableRegs_.has(*reg) && !evictRegister(ins, *reg)) {
    626    return false;
    627  }
    628 
    629  // Mark register as allocated and load the value in it.
    630  if (!addAllocatedReg(ins, vregId, use->usedAtStart(), *reg)) {
    631    return false;
    632  }
    633  LMoveGroup* input = getInputMoveGroup(ins);
    634  return input->addAfter(alloc, LAllocation(*reg), vreg.def()->type());
    635 }
    636 
    637 bool SimpleAllocator::allocateForRegisterUse(LInstruction* ins, const LUse* use,
    638                                             AnyRegister* reg) {
    639  uint32_t vregId = use->virtualRegister();
    640  VirtualRegister& vreg = vregs_[vregId];
    641  bool useAtStart = use->usedAtStart();
    642 
    643  // Determine the vreg's current location.
    644  LAllocation alloc;
    645  if (vreg.hasRegister()) {
    646    // The vreg already has a register. We can use it if we won't need this
    647    // register later for a fixed output or temp.
    648    AllocatedRegister& allocated = allocatedRegs_[vreg.registerIndex()];
    649    bool isReserved = useAtStart ? fixedTempRegs_.has(allocated.reg())
    650                                 : fixedOutputAndTempRegs_.has(allocated.reg());
    651    if (!isReserved) {
    652      markUseOfAllocatedReg(ins, allocated, useAtStart);
    653      *reg = allocated.reg();
    654      return true;
    655    }
    656 
    657    // Try to avoid having multiple registers for the same vreg by replacing the
    658    // current register with the new one. If this is not possible (this is
    659    // uncommon) we set hasMultipleRegsForVreg_ and fix this up at the end of
    660    // allocateForInstruction.
    661    alloc = LAllocation(allocated.reg());
    662    if (currentInsRegs_.has(allocated.reg())) {
    663      hasMultipleRegsForVreg_ = true;
    664    } else {
    665      removeAllocatedRegisterAtIndex(vreg.registerIndex());
    666    }
    667  } else {
    668    alloc = vreg.stackLocation();
    669  }
    670 
    671  // This vreg is not in a register or it's in a reserved register. Allocate a
    672  // new register.
    673  AllocationKind kind =
    674      useAtStart ? AllocationKind::UseAtStart : AllocationKind::UseOrTemp;
    675  if (!allocateForNonFixedDefOrUse(ins, vregId, kind, reg)) {
    676    return false;
    677  }
    678  LMoveGroup* input = getInputMoveGroup(ins);
    679  return input->addAfter(alloc, LAllocation(*reg), vreg.def()->type());
    680 }
    681 
    682 bool SimpleAllocator::evictRegister(LInstruction* ins, AnyRegister reg) {
    683  // The caller wants to use `reg` but it's not available. Spill this register
    684  // (and its aliases) to make it available.
    685 
    686  MOZ_ASSERT(reg.isValid());
    687  MOZ_ASSERT(!availableRegs_.has(reg));
    688 
    689  for (size_t i = 0; i < allocatedRegs_.length();) {
    690    AllocatedRegister allocated = allocatedRegs_[i];
    691    if (!allocated.reg().aliases(reg)) {
    692      i++;
    693      continue;
    694    }
    695 
    696    // Registers are added to the safepoint in `populateSafepoint`, but if we're
    697    // evicting a register that's being used at-start we lose information about
    698    // this so we have to add it to the safepoint now.
    699    if (ins->safepoint() && !ins->isCall() &&
    700        currentInsRegs_.has(allocated.reg())) {
    701      MOZ_ASSERT(!currentInsRegsNotAtStart_.has(allocated.reg()));
    702      if (!addLiveRegisterToSafepoint(ins->safepoint(), allocated)) {
    703        return false;
    704      }
    705    }
    706 
    707    // Spill this register unless we know this vreg also lives in a different
    708    // register (this is uncommon).
    709    uint32_t vregId = allocated.vregId();
    710    if (vregs_[vregId].registerIndex() == i) {
    711      if (!spillRegister(ins, allocated)) {
    712        return false;
    713      }
    714    } else {
    715      MOZ_ASSERT(hasMultipleRegsForVreg_);
    716    }
    717    removeAllocatedRegisterAtIndex(i);
    718 
    719    if (availableRegs_.has(reg)) {
    720      return true;
    721    }
    722  }
    723 
    724  MOZ_CRASH("failed to evict register");
    725 }
    726 
    727 bool SimpleAllocator::allocateForDefinition(uint32_t blockLastId,
    728                                            LInstruction* ins, LDefinition* def,
    729                                            bool isTemp) {
    730  uint32_t vregId = def->virtualRegister();
    731 
    732  // Allocate a register for this definition. Return early for definitions that
    733  // don't need a register.
    734  AnyRegister reg;
    735  switch (def->policy()) {
    736    case LDefinition::FIXED: {
    737      if (!def->output()->isAnyRegister()) {
    738        MOZ_ASSERT(!isTemp);
    739        vregs_[vregId].setHasStackLocation();
    740        return true;
    741      }
    742 
    743      // We need a fixed register. Evict it if it's not available.
    744      reg = def->output()->toAnyRegister();
    745      if (!availableRegs_.has(reg)) {
    746        // For call instructions we allow Temps and Outputs to use the same
    747        // fixed register. That should probably be changed at some point, but
    748        // for now we can handle this edge case by removing the temp's register.
    749        // See bug 1962671.
    750        if (!isTemp && fixedTempRegs_.has(reg)) {
    751          MOZ_ASSERT(ins->isCall());
    752          for (size_t i = 0; i < allocatedRegs_.length(); i++) {
    753            if (allocatedRegs_[i].reg() == reg) {
    754              removeAllocatedRegisterAtIndex(i);
    755              break;
    756            }
    757          }
    758          MOZ_ASSERT(availableRegs_.has(reg));
    759        } else {
    760          if (!evictRegister(ins, reg)) {
    761            return false;
    762          }
    763        }
    764      }
    765      if (!addAllocatedReg(ins, vregId, /* usedAtStart = */ false, reg)) {
    766        return false;
    767      }
    768      break;
    769    }
    770    case LDefinition::REGISTER: {
    771      AllocationKind kind =
    772          isTemp ? AllocationKind::UseOrTemp : AllocationKind::Output;
    773      if (!allocateForNonFixedDefOrUse(ins, vregId, kind, &reg)) {
    774        return false;
    775      }
    776      break;
    777    }
    778    case LDefinition::MUST_REUSE_INPUT: {
    779      // Allocate a new register and add an entry to reusedInputs_ to move the
    780      // input into this register when we're done allocating registers.
    781      AllocationKind kind =
    782          isTemp ? AllocationKind::UseOrTemp : AllocationKind::Output;
    783      if (!allocateForNonFixedDefOrUse(ins, vregId, kind, &reg)) {
    784        return false;
    785      }
    786      LAllocation* useAlloc = ins->getOperand(def->getReusedInput());
    787      uint32_t useVregId = useAlloc->toUse()->virtualRegister();
    788      LDefinition::Type type = vregs_[useVregId].def()->type();
    789      if (!reusedInputs_.emplaceBack(useAlloc, reg, type)) {
    790        return false;
    791      }
    792      break;
    793    }
    794    case LDefinition::STACK: {
    795      // This is a Wasm stack area or stack result. This is used when calling
    796      // functions with multiple return values.
    797      MOZ_ASSERT(!isTemp);
    798      if (def->type() == LDefinition::STACKRESULTS) {
    799        LStackArea alloc(ins->toInstruction());
    800        stackSlotAllocator_.allocateStackArea(&alloc);
    801        def->setOutput(alloc);
    802      } else {
    803        // Because the definitions are visited in order, the area has been
    804        // allocated before we reach this result, so we know the operand is an
    805        // LStackArea.
    806        const LUse* use = ins->getOperand(0)->toUse();
    807        VirtualRegister& area = vregs_[use->virtualRegister()];
    808        const LStackArea* areaAlloc = area.def()->output()->toStackArea();
    809        def->setOutput(areaAlloc->resultAlloc(ins, def));
    810      }
    811      vregs_[vregId].setHasStackLocation();
    812      return true;
    813    }
    814  }
    815 
    816  def->setOutput(LAllocation(reg));
    817 
    818  // If this is an output register for a vreg that's used in a different block,
    819  // we have to spill it to the stack at some point and we want to do that as
    820  // early as possible. We can't do it here though because we're not allowed to
    821  // insert moves right before LOsiPoint instructions. Add the outputs to a
    822  // vector that we check at the start of allocateForInstruction.
    823  if (!isTemp && vregs_[vregId].lastUseInsId() > blockLastId) {
    824    if (!eagerSpillOutputs_.append(def)) {
    825      return false;
    826    }
    827  }
    828 
    829  return true;
    830 }
    831 
    832 bool SimpleAllocator::allocateForInstruction(VirtualRegBitSet& liveGC,
    833                                             uint32_t blockLastId,
    834                                             LInstruction* ins) {
    835  if (!alloc().ensureBallast()) {
    836    return false;
    837  }
    838 
    839  assertValidRegisterStateBeforeInstruction();
    840  MOZ_ASSERT(reusedInputs_.empty());
    841 
    842  // If we have to spill output registers of a previous instruction, do that now
    843  // if the instruction is not an LOsiPoint instruction. See the comment at the
    844  // end of allocateForDefinition.
    845  if (!eagerSpillOutputs_.empty() && !ins->isOsiPoint()) {
    846    LMoveGroup* moves = getInputMoveGroup(ins);
    847    for (LDefinition* def : eagerSpillOutputs_) {
    848      MOZ_ASSERT(!vregs_[def->virtualRegister()].hasStackLocation());
    849      LAllocation dest = ensureStackLocation(def->virtualRegister());
    850      if (!moves->add(*def->output(), dest, def->type())) {
    851        return false;
    852      }
    853    }
    854    eagerSpillOutputs_.clear();
    855  }
    856 
    857  // Clear per-instruction register sets.
    858  currentInsRegs_ = AllocatableRegisterSet();
    859  currentInsRegsNotAtStart_ = AllocatableRegisterSet();
    860  fixedTempRegs_ = AllocatableRegisterSet();
    861  fixedOutputAndTempRegs_ = AllocatableRegisterSet();
    862 
    863  // Allocate all fixed inputs first.
    864  for (LInstruction::NonSnapshotInputIter alloc(*ins); alloc.more();
    865       alloc.next()) {
    866    if (!alloc->isUse() || alloc->toUse()->policy() != LUse::FIXED) {
    867      continue;
    868    }
    869    AnyRegister reg;
    870    if (!allocateForFixedUse(ins, alloc->toUse(), &reg)) {
    871      return false;
    872    }
    873    alloc.replace(LAllocation(reg));
    874  }
    875 
    876  // Scan all definitions. If any of these require fixed registers, it will
    877  // affect which registers are available for the inputs.
    878  for (LInstruction::TempIter temp(ins); !temp.done(); temp++) {
    879    scanDefinition(ins, *temp, /* isTemp = */ true);
    880  }
    881  for (LInstruction::OutputIter output(ins); !output.done(); output++) {
    882    scanDefinition(ins, *output, /* isTemp = */ false);
    883  }
    884 
    885  // Allocate inputs which are required to be in non-fixed registers.
    886  for (LInstruction::NonSnapshotInputIter alloc(*ins); alloc.more();
    887       alloc.next()) {
    888    if (!alloc->isUse() || alloc->toUse()->policy() != LUse::REGISTER) {
    889      continue;
    890    }
    891    AnyRegister reg;
    892    if (!allocateForRegisterUse(ins, alloc->toUse(), &reg)) {
    893      return false;
    894    }
    895    alloc.replace(LAllocation(reg));
    896  }
    897 
    898  // Allocate all definitions.
    899  for (LInstruction::TempIter temp(ins); !temp.done(); temp++) {
    900    if (!allocateForDefinition(blockLastId, ins, *temp, /* isTemp = */ true)) {
    901      return false;
    902    }
    903  }
    904  for (LInstruction::OutputIter output(ins); !output.done(); output++) {
    905    LDefinition* def = *output;
    906    if (!allocateForDefinition(blockLastId, ins, def, /* isTemp = */ false)) {
    907      return false;
    908    }
    909    if (vregs_[def->virtualRegister()].isGCType()) {
    910      if (!liveGC.insert(def->virtualRegister())) {
    911        return false;
    912      }
    913    }
    914  }
    915 
    916  // If this instruction is a call, we need to evict all registers except for
    917  // preserved registers or the instruction's definitions. We have to do this
    918  // before the next step because call instructions are allowed to clobber
    919  // their input registers so we shouldn't use the same register for snapshot
    920  // inputs.
    921  if (ins->isCall()) {
    922    for (size_t i = 0; i < allocatedRegs_.length();) {
    923      AllocatedRegister allocated = allocatedRegs_[i];
    924      if (ins->isCallPreserved(allocated.reg()) ||
    925          vregs_[allocated.vregId()].insId() == ins->id()) {
    926        i++;
    927        continue;
    928      }
    929      if (!spillRegister(ins, allocated)) {
    930        return false;
    931      }
    932      removeAllocatedRegisterAtIndex(i);
    933    }
    934  }
    935 
    936  // Allocate for remaining inputs which do not need to be in registers.
    937  for (LInstruction::InputIter alloc(*ins); alloc.more(); alloc.next()) {
    938    if (!alloc->isUse()) {
    939      continue;
    940    }
    941    LUse* use = alloc->toUse();
    942    MOZ_ASSERT(use->policy() != LUse::REGISTER && use->policy() != LUse::FIXED);
    943    uint32_t vreg = use->virtualRegister();
    944    // KEEPALIVE uses are very common in JS code for snapshots and these uses
    945    // don't prefer a register. Don't update the register's last-use (used for
    946    // eviction heuristics) for them.
    947    bool trackRegUse = (use->policy() != LUse::KEEPALIVE);
    948    LAllocation allocated = registerOrStackLocation(ins, vreg, trackRegUse);
    949    alloc.replace(allocated);
    950  }
    951 
    952  // If this instruction had MUST_REUSE_INPUT definitions, we've now assigned a
    953  // register or stack slot for the input and we allocated a register for the
    954  // output. We can now insert a move and then rewrite the input LAllocation to
    955  // match the LDefinition (code generation relies on this).
    956  while (!reusedInputs_.empty()) {
    957    auto entry = reusedInputs_.popCopy();
    958    LMoveGroup* input = getInputMoveGroup(ins);
    959    if (!input->addAfter(*entry.source, LAllocation(entry.dest), entry.type)) {
    960      return false;
    961    }
    962    *entry.source = LAllocation(entry.dest);
    963  }
    964 
    965  // Add registers and stack locations to the instruction's safepoint if needed.
    966  if (LSafepoint* safepoint = ins->safepoint()) {
    967    if (!populateSafepoint(liveGC, ins, safepoint)) {
    968      return false;
    969    }
    970  }
    971 
    972  // In the uncommon case where a vreg might have multiple allocated registers,
    973  // discard the registers not linked from the vreg. This simplifies other parts
    974  // of the allocator.
    975  if (hasMultipleRegsForVreg_) {
    976    for (size_t i = 0; i < allocatedRegs_.length();) {
    977      VirtualRegister& vreg = vregs_[allocatedRegs_[i].vregId()];
    978      if (vreg.registerIndex() != i) {
    979        removeAllocatedRegisterAtIndex(i);
    980        continue;
    981      }
    982      i++;
    983    }
    984    hasMultipleRegsForVreg_ = false;
    985  }
    986 
    987  return true;
    988 }
    989 
    990 bool SimpleAllocator::addLiveRegisterToSafepoint(LSafepoint* safepoint,
    991                                                 AllocatedRegister allocated) {
    992  safepoint->addLiveRegister(allocated.reg());
    993  const VirtualRegister& vreg = vregs_[allocated.vregId()];
    994  if (vreg.isGCType()) {
    995    if (!safepoint->addGCAllocation(allocated.vregId(), vreg.def(),
    996                                    LAllocation(allocated.reg()))) {
    997      return false;
    998    }
    999  }
   1000  return true;
   1001 }
   1002 
   1003 bool SimpleAllocator::populateSafepoint(VirtualRegBitSet& liveGC,
   1004                                        LInstruction* ins,
   1005                                        LSafepoint* safepoint) {
   1006  // Add allocated registers to the safepoint. Safepoints for call instructions
   1007  // never include any registers.
   1008  if (!ins->isCall()) {
   1009    for (AllocatedRegister allocated : allocatedRegs_) {
   1010      // Outputs (but not temps) of the current instruction are ignored, except
   1011      // for the clobberedRegs set that's used for debug assertions.
   1012      const VirtualRegister& vreg = vregs_[allocated.vregId()];
   1013      if (vreg.insId() == ins->id()) {
   1014 #ifdef CHECK_OSIPOINT_REGISTERS
   1015        safepoint->addClobberedRegister(allocated.reg());
   1016 #endif
   1017        if (!vreg.isTemp()) {
   1018          continue;
   1019        }
   1020      }
   1021      if (!addLiveRegisterToSafepoint(safepoint, allocated)) {
   1022        return false;
   1023      }
   1024    }
   1025  }
   1026 
   1027  // Also add stack locations that store GC things.
   1028  for (VirtualRegBitSet::Iterator liveRegId(liveGC); liveRegId; ++liveRegId) {
   1029    uint32_t vregId = *liveRegId;
   1030    const VirtualRegister& vreg = vregs_[vregId];
   1031    MOZ_ASSERT(vreg.isGCType());
   1032    if (!vreg.hasStackLocation() || vreg.insId() == ins->id()) {
   1033      continue;
   1034    }
   1035    if (!safepoint->addGCAllocation(vregId, vreg.def(), vreg.stackLocation())) {
   1036      return false;
   1037    }
   1038  }
   1039 
   1040  return true;
   1041 }
   1042 
   1043 void SimpleAllocator::freeDeadVregsAfterInstruction(VirtualRegBitSet& liveGC,
   1044                                                    LNode* ins) {
   1045  // Mark virtual registers that won't be used after `ins` as dead. This also
   1046  // frees their stack slots and registers.
   1047  while (!vregLastUses_.empty() &&
   1048         vregLastUses_.back().instructionId <= ins->id()) {
   1049    VregLastUse entry = vregLastUses_.popCopy();
   1050    VirtualRegister& vreg = vregs_[entry.vregId];
   1051    if (vreg.hasRegister()) {
   1052      removeAllocatedRegisterAtIndex(vreg.registerIndex());
   1053    }
   1054    if (vreg.hasAllocatedStackSlot()) {
   1055      LStackSlot::SlotAndWidth stackSlot = vreg.stackSlot();
   1056      stackSlotAllocator_.freeSlot(stackSlot.width(), stackSlot.slot());
   1057    }
   1058    if (vreg.isGCType()) {
   1059      liveGC.remove(entry.vregId);
   1060    }
   1061    vreg.markDead();
   1062  }
   1063 }
   1064 
   1065 bool SimpleAllocator::tryReuseRegistersFromPredecessor(MBasicBlock* block) {
   1066  // Try to reuse the register state from our predecessor block if we have a
   1067  // single predecessor. Note that this is completely optional because all live
   1068  // vregs must have a stack location at this point.
   1069 
   1070  if (block->numPredecessors() != 1) {
   1071    return true;
   1072  }
   1073 
   1074  auto findBlockState = [this](uint32_t predId) -> const BlockState* {
   1075    for (const BlockState& state : blockStates_) {
   1076      if (state.blockIndex == predId) {
   1077        return &state;
   1078      }
   1079    }
   1080    return nullptr;
   1081  };
   1082  const BlockState* state = findBlockState(block->getPredecessor(0)->id());
   1083  if (!state) {
   1084    return true;
   1085  }
   1086 
   1087  MOZ_ASSERT(allocatedRegs_.empty());
   1088  availableRegs_ = state->availableRegs;
   1089  for (AllocatedRegister allocated : state->allocatedRegs) {
   1090    // Ignore registers for vregs that were marked dead between the
   1091    // predecessor block and the current block.
   1092    if (vregs_[allocated.vregId()].isDead()) {
   1093      availableRegs_.add(allocated.reg());
   1094    } else {
   1095      VirtualRegister& vreg = vregs_[allocated.vregId()];
   1096      MOZ_ASSERT(!vreg.hasRegister());
   1097      vreg.setRegisterIndex(allocatedRegs_.length());
   1098      if (!allocatedRegs_.append(allocated)) {
   1099        return false;
   1100      }
   1101    }
   1102  }
   1103  return true;
   1104 }
   1105 
   1106 void SimpleAllocator::saveAndClearAllocatedRegisters(MBasicBlock* block) {
   1107  if (allocatedRegs_.empty()) {
   1108    return;
   1109  }
   1110 
   1111  for (AllocatedRegister allocated : allocatedRegs_) {
   1112    vregs_[allocated.vregId()].clearRegisterIndex();
   1113  }
   1114 
   1115  // Ensure at least one successor has a single predecessor block that could use
   1116  // our register state later in tryReuseRegistersFromPredecessor.
   1117  bool shouldSave = false;
   1118  for (size_t i = 0; i < block->numSuccessors(); i++) {
   1119    if (block->getSuccessor(i)->numPredecessors() == 1 &&
   1120        block->getSuccessor(i)->id() > block->id()) {
   1121      shouldSave = true;
   1122      break;
   1123    }
   1124  }
   1125  if (shouldSave) {
   1126    // Save current register state in the circular buffer. We use std::swap for
   1127    // the vectors to try to reuse malloc buffers.
   1128    BlockState& state = blockStates_[nextBlockStateIndex_];
   1129    std::swap(allocatedRegs_, state.allocatedRegs);
   1130    state.availableRegs = availableRegs_;
   1131    state.blockIndex = block->id();
   1132    nextBlockStateIndex_ = (nextBlockStateIndex_ + 1) % BlockStateLength;
   1133  }
   1134  allocatedRegs_.clear();
   1135  availableRegs_ = allRegisters_;
   1136 }
   1137 
   1138 bool SimpleAllocator::allocateRegisters() {
   1139  // Initialize register state.
   1140  MOZ_ASSERT(allocatedRegs_.empty());
   1141  availableRegs_ = allRegisters_;
   1142 
   1143  size_t numBlocks = graph.numBlocks();
   1144 
   1145  // It's very common for JS code to have a basic block that jumps to the next
   1146  // block and the next block doesn't have any other predecessors. We treat
   1147  // such blocks as a single block.
   1148  bool fuseWithNextBlock = false;
   1149 
   1150  for (size_t blockIndex = 0; blockIndex < numBlocks; blockIndex++) {
   1151    if (mir->shouldCancel("allocateRegisters (block loop)")) {
   1152      return false;
   1153    }
   1154 
   1155    LBlock* block = graph.getBlock(blockIndex);
   1156    MBasicBlock* mblock = block->mir();
   1157    MOZ_ASSERT(mblock->id() == blockIndex);
   1158 
   1159    VirtualRegBitSet& liveGC = liveGCIn_[blockIndex];
   1160 
   1161    // Try to reuse the register state from our predecessor. If we fused this
   1162    // block with the previous block we're already using its register state.
   1163    if (!fuseWithNextBlock) {
   1164      MOZ_ASSERT(allocatedRegs_.empty());
   1165      if (!tryReuseRegistersFromPredecessor(mblock)) {
   1166        return false;
   1167      }
   1168    }
   1169 
   1170    // Note: sometimes two blocks appear fusable but the successor block still
   1171    // has an (unnecessary) phi. Don't fuse in this edge case.
   1172    fuseWithNextBlock = mblock->numSuccessors() == 1 &&
   1173                        mblock->getSuccessor(0)->id() == blockIndex + 1 &&
   1174                        mblock->getSuccessor(0)->numPredecessors() == 1 &&
   1175                        graph.getBlock(blockIndex + 1)->numPhis() == 0;
   1176 
   1177    uint32_t blockLastId = fuseWithNextBlock
   1178                               ? graph.getBlock(blockIndex + 1)->lastId()
   1179                               : block->lastId();
   1180 
   1181    // Allocate stack slots for phis.
   1182    for (uint32_t i = 0, numPhis = block->numPhis(); i < numPhis; i++) {
   1183      LPhi* phi = block->getPhi(i);
   1184      LDefinition* def = phi->getDef(0);
   1185      uint32_t vregId = def->virtualRegister();
   1186      bool isGCType = vregs_[vregId].isGCType();
   1187      def->setOutput(ensureStackLocation(vregId));
   1188      if (isGCType && !liveGC.insert(vregId)) {
   1189        return false;
   1190      }
   1191      if (i == numPhis - 1) {
   1192        freeDeadVregsAfterInstruction(liveGC, phi);
   1193      }
   1194    }
   1195 
   1196    // Allocate registers for each instruction.
   1197    for (LInstructionIterator iter = block->begin(); iter != block->end();
   1198         iter++) {
   1199      if (mir->shouldCancel("allocateRegisters (instruction loop)")) {
   1200        return false;
   1201      }
   1202 
   1203      LInstruction* ins = *iter;
   1204      if (!allocateForInstruction(liveGC, blockLastId, ins)) {
   1205        return false;
   1206      }
   1207      if (ins == *block->rbegin() && !fuseWithNextBlock) {
   1208        if (!allocateForBlockEnd(block, ins)) {
   1209          return false;
   1210        }
   1211      }
   1212      freeDeadVregsAfterInstruction(liveGC, ins);
   1213    }
   1214 
   1215    if (!fuseWithNextBlock) {
   1216      saveAndClearAllocatedRegisters(mblock);
   1217    }
   1218  }
   1219 
   1220  // All vregs must now be dead.
   1221  MOZ_ASSERT(vregLastUses_.empty());
   1222 #ifdef DEBUG
   1223  for (size_t i = 1; i < vregs_.length(); i++) {
   1224    MOZ_ASSERT(vregs_[i].isDead());
   1225  }
   1226 #endif
   1227 
   1228  graph.setLocalSlotsSize(stackSlotAllocator_.stackHeight());
   1229  return true;
   1230 }
   1231 
   1232 void SimpleAllocator::assertValidRegisterStateBeforeInstruction() const {
   1233 #ifdef DEBUG
   1234  MOZ_ASSERT(!hasMultipleRegsForVreg_);
   1235 
   1236  // Assert allocatedRegs_ does not contain duplicate registers and matches the
   1237  // availableRegs_ set.
   1238  AllocatableRegisterSet available = allRegisters_;
   1239  for (size_t i = 0; i < allocatedRegs_.length(); i++) {
   1240    AllocatedRegister allocated = allocatedRegs_[i];
   1241    available.take(allocated.reg());
   1242    const VirtualRegister& vreg = vregs_[allocated.vregId()];
   1243    MOZ_ASSERT(vreg.registerIndex() == i);
   1244    MOZ_ASSERT(!vreg.isTemp());
   1245  }
   1246  MOZ_ASSERT(availableRegs_.set() == available.set());
   1247 
   1248  // Assert vregs have a valid register index. Limit this to the first 20 vregs
   1249  // to not slow down debug builds too much.
   1250  size_t numVregsToCheck = std::min<size_t>(20, vregs_.length());
   1251  for (size_t i = 1; i < numVregsToCheck; i++) {
   1252    if (!vregs_[i].isDead() && vregs_[i].hasRegister()) {
   1253      size_t index = vregs_[i].registerIndex();
   1254      MOZ_ASSERT(allocatedRegs_[index].vregId() == i);
   1255    }
   1256  }
   1257 #endif
   1258 }
   1259 
   1260 bool SimpleAllocator::go() {
   1261  JitSpewCont(JitSpew_RegAlloc, "\n");
   1262  JitSpew(JitSpew_RegAlloc, "Beginning register allocation");
   1263 
   1264  JitSpewCont(JitSpew_RegAlloc, "\n");
   1265  if (JitSpewEnabled(JitSpew_RegAlloc)) {
   1266    dumpInstructions("(Pre-allocation LIR)");
   1267  }
   1268 
   1269  if (!init()) {
   1270    return false;
   1271  }
   1272  if (!analyzeLiveness()) {
   1273    return false;
   1274  }
   1275  if (!allocateRegisters()) {
   1276    return false;
   1277  }
   1278  return true;
   1279 }