void IRInstruction::convertToMov() { assert(!isControlFlow()); m_op = Mov; m_typeParam = Type::None; assert(m_numSrcs == 1); assert(m_numDsts == 1); }
void IRInstruction::convertToMov() { assert(!isControlFlow()); m_op = Mov; m_typeParam = Type::None; m_extra = nullptr; assert(m_numSrcs == 1); // Instructions in the simplifier don't have dests yet assert((m_numDsts == 1) != isTransient()); }
void IRInstruction::convertToMov() { assert(!isControlFlow()); m_op = Mov; m_typeParam.clear(); m_extra = nullptr; if (m_numDsts == 1) m_dst->setInstruction(this); // recompute type assert(m_numSrcs == 1); // Instructions in the simplifier don't have dests yet assert((m_numDsts == 1) != isTransient()); }
void IRInstruction::convertToJmp() { assert(isControlFlow()); assert(IMPLIES(block(), block()->back() == this)); m_op = Jmp_; m_typeParam = Type::None; m_numSrcs = 0; m_numDsts = 0; m_srcs = nullptr; m_dst = nullptr; // Instructions in the simplifier don't have blocks yet. if (block()) block()->setNext(nullptr); }
void IRInstruction::convertToJmp() { assert(isControlFlow()); assert(IMPLIES(block(), &block()->back() == this)); m_op = Jmp; m_typeParam.clear(); m_numSrcs = 0; m_numDsts = 0; m_srcs = nullptr; m_dst = nullptr; m_extra = nullptr; // Instructions in the simplifier don't have blocks yet. setNext(nullptr); }
void cloneToBlock(const BlockList& rpoBlocks, IRUnit& unit, Block::iterator const first, Block::iterator const last, Block* const target) { StateVector<SSATmp,SSATmp*> rewriteMap(unit, nullptr); auto rewriteSources = [&] (IRInstruction* inst) { for (int i = 0; i < inst->numSrcs(); ++i) { if (auto newTmp = rewriteMap[inst->src(i)]) { FTRACE(5, " rewrite: {} -> {}\n", inst->src(i)->toString(), newTmp->toString()); inst->setSrc(i, newTmp); } } }; auto targetIt = target->skipHeader(); for (auto it = first; it != last; ++it) { assert(!it->isControlFlow()); FTRACE(5, "cloneToBlock({}): {}\n", target->id(), it->toString()); auto const newInst = unit.cloneInstruction(&*it); if (auto const numDests = newInst->numDsts()) { for (int i = 0; i < numDests; ++i) { FTRACE(5, " add rewrite: {} -> {}\n", it->dst(i)->toString(), newInst->dst(i)->toString()); rewriteMap[it->dst(i)] = newInst->dst(i); } } target->insert(targetIt, newInst); targetIt = ++target->iteratorTo(newInst); } postorderWalk( unit, [&](Block* block) { FTRACE(5, "cloneToBlock: rewriting block {}\n", block->id()); for (auto& inst : *block) { FTRACE(5, " rewriting {}\n", inst.toString()); rewriteSources(&inst); } }, target ); }
void cloneToBlock(const BlockList& rpoBlocks, IRFactory* const irFactory, Block::iterator const first, Block::iterator const last, Block* const target) { assert(isRPOSorted(rpoBlocks)); StateVector<SSATmp,SSATmp*> rewriteMap(irFactory, nullptr); auto rewriteSources = [&] (IRInstruction* inst) { for (int i = 0; i < inst->numSrcs(); ++i) { if (auto newTmp = rewriteMap[inst->src(i)]) { FTRACE(5, " rewrite: {} -> {}\n", inst->src(i)->toString(), newTmp->toString()); inst->setSrc(i, newTmp); } } }; auto targetIt = target->skipHeader(); for (auto it = first; it != last; ++it) { assert(!it->isControlFlow()); FTRACE(5, "cloneToBlock({}): {}\n", target->id(), it->toString()); auto const newInst = irFactory->cloneInstruction(&*it); if (auto const numDests = newInst->numDsts()) { for (int i = 0; i < numDests; ++i) { FTRACE(5, " add rewrite: {} -> {}\n", it->dst(i)->toString(), newInst->dst(i)->toString()); rewriteMap[it->dst(i)] = newInst->dst(i); } } target->insert(targetIt, newInst); targetIt = ++target->iteratorTo(newInst); } auto it = rpoIteratorTo(rpoBlocks, target); for (; it != rpoBlocks.end(); ++it) { FTRACE(5, "cloneToBlock: rewriting block {}\n", (*it)->id()); for (auto& inst : **it) { FTRACE(5, " rewriting {}\n", inst.toString()); rewriteSources(&inst); } } }
bool IRInstruction::isEssential() const { Opcode opc = op(); if (opc == DecRefNZ) { // If the source of a DecRefNZ is not an IncRef, mark it as essential // because we won't remove its source as well as itself. // If the ref count optimization is turned off, mark all DecRefNZ as // essential. if (!RuntimeOption::EvalHHIREnableRefCountOpt || src(0)->inst()->op() != IncRef) { return true; } } return isControlFlow() || opcodeHasFlags(opc, Essential) || mayReenterHelper(); }
bool IRInstruction::mayModifyRefs() const { Opcode opc = op(); // DecRefNZ does not have side effects other than decrementing the ref // count. Therefore, its MayModifyRefs should be false. if (opc == DecRef) { auto type = src(0)->type(); if (isControlFlow()) { // If the decref has a target label, then it exits if the destructor // has to be called, so it does not have any side effects on the main // trace. return false; } if (!type.canRunDtor()) { return false; } } return opcodeHasFlags(opc, MayModifyRefs) || mayReenterHelper(); }
void moveToBlock(Block::iterator const first, Block::iterator const last, Block* const target) { if (first == last) return; auto const srcBlock = first->block(); auto targetIt = target->skipHeader(); for (auto it = first; it != last;) { auto const inst = &*it; assert(!inst->isControlFlow()); FTRACE(5, "moveToBlock({}): {}\n", target->id(), inst->toString()); it = srcBlock->erase(it); target->insert(targetIt, inst); targetIt = ++target->iteratorTo(inst); } }
bool IRInstruction::isEssential() const { return isControlFlow() || opcodeHasFlags(op(), Essential); }