bool LMoveGroup::add(LAllocation from, LAllocation to, LDefinition::Type type) { #ifdef DEBUG MOZ_ASSERT(from != to); for (size_t i = 0; i < moves_.length(); i++) MOZ_ASSERT(to != moves_[i].to()); // Check that SIMD moves are aligned according to ABI requirements. if (LDefinition(type).isSimdType()) { MOZ_ASSERT(from.isMemory() || from.isFloatReg()); if (from.isMemory()) { if (from.isArgument()) MOZ_ASSERT(from.toArgument()->index() % SimdMemoryAlignment == 0); else MOZ_ASSERT(from.toStackSlot()->slot() % SimdMemoryAlignment == 0); } MOZ_ASSERT(to.isMemory() || to.isFloatReg()); if (to.isMemory()) { if (to.isArgument()) MOZ_ASSERT(to.toArgument()->index() % SimdMemoryAlignment == 0); else MOZ_ASSERT(to.toStackSlot()->slot() % SimdMemoryAlignment == 0); } } #endif return moves_.append(LMove(from, to, type)); }
bool LAllocation::aliases(const LAllocation& other) const { if (isFloatReg() && other.isFloatReg()) return toFloatReg()->reg().aliases(other.toFloatReg()->reg()); return *this == other; }
bool GreedyAllocator::allocateDefinition(LInstruction *ins, LDefinition *def) { VirtualRegister *vr = getVirtualRegister(def); LAllocation output; switch (def->policy()) { case LDefinition::PASSTHROUGH: // This is purely passthru, so ignore it. return true; case LDefinition::DEFAULT: case LDefinition::MUST_REUSE_INPUT: { AnyRegister reg; // Either take the register requested, or allocate a new one. if (def->policy() == LDefinition::MUST_REUSE_INPUT && ins->getOperand(def->getReusedInput())->toUse()->isFixedRegister()) { LAllocation *a = ins->getOperand(def->getReusedInput()); VirtualRegister *vuse = getVirtualRegister(a->toUse()); reg = GetFixedRegister(vuse->def, a->toUse()); } else if (vr->hasRegister()) { reg = vr->reg(); } else { if (!allocate(vr->type(), DISALLOW, ®)) return false; } if (def->policy() == LDefinition::MUST_REUSE_INPUT) { LUse *use = ins->getOperand(def->getReusedInput())->toUse(); VirtualRegister *vuse = getVirtualRegister(use); // If the use already has the given register, we need to evict. if (vuse->hasRegister() && vuse->reg() == reg) { if (!evict(reg)) return false; } // Make sure our input is using a fixed register. if (reg.isFloat()) *use = LUse(reg.fpu(), use->virtualRegister()); else *use = LUse(reg.gpr(), use->virtualRegister()); } output = LAllocation(reg); break; } case LDefinition::PRESET: { // Eviction and disallowing occurred during the definition // pre-scan pass. output = *def->output(); break; } } if (output.isRegister()) { JS_ASSERT_IF(output.isFloatReg(), disallowed.has(output.toFloatReg()->reg())); JS_ASSERT_IF(output.isGeneralReg(), disallowed.has(output.toGeneralReg()->reg())); } // Finally, set the output. def->setOutput(output); return true; }