bool Loop::hoistInstructions(InstructionQueue &toHoist) { // Iterate in post-order (uses before definitions) for (int32_t i = toHoist.length() - 1; i >= 0; i--) { MInstruction *ins = toHoist[i]; // Don't hoist MConstantElements, MConstant and MBox // if it doesn't enable us to hoist one of its uses. // We want those instructions as close as possible to their use. if (ins->isConstantElements() || ins->isConstant() || ins->isBox()) { bool loopInvariantUse = false; for (MUseDefIterator use(ins); use; use++) { if (use.def()->isLoopInvariant()) { loopInvariantUse = true; break; } } if (!loopInvariantUse) ins->setNotLoopInvariant(); } } // Move all instructions to the preLoop_ block just before the control instruction. for (size_t i = 0; i < toHoist.length(); i++) { MInstruction *ins = toHoist[i]; // Loads may have an implicit dependency on either stores (effectful instructions) or // control instructions so we should never move these. JS_ASSERT(!ins->isControlInstruction()); JS_ASSERT(!ins->isEffectful()); JS_ASSERT(ins->isMovable()); if (!ins->isLoopInvariant()) continue; if (checkHotness(ins->block())) { ins->block()->moveBefore(preLoop_->lastIns(), ins); ins->setNotLoopInvariant(); } } return true; }