/* * Look for Jcc instructions in the main trace that * branch to "normal exits". We can optimize these into the * SideExitJcc* instructions that can be patched in place. */ void optimizeSideExitJccs(IRUnit& unit) { auto trace = unit.main(); FTRACE(5, "SideExitJcc:vvvvvvvvvvvvvvvvvvvvv\n"); SCOPE_EXIT { FTRACE(5, "SideExitJcc:^^^^^^^^^^^^^^^^^^^^^\n"); }; forEachInst(trace->blocks(), [&] (IRInstruction* inst) { if (!jccCanBeDirectExit(inst->op())) return; auto const exitBlock = inst->taken(); if (!isNormalExit(exitBlock)) return; auto it = exitBlock->backIter(); auto& reqBindJmp = *(it--); auto& syncABI = *it; assert(syncABI.op() == SyncABIRegs); FTRACE(5, "converting jcc ({}) to side exit\n", inst->id()); auto const newOpcode = jmpToSideExitJmp(inst->op()); SideExitJccData data; data.taken = reqBindJmp.extra<ReqBindJmp>()->offset; auto const block = inst->block(); block->insert(block->iteratorTo(inst), unit.cloneInstruction(&syncABI)); unit.replace( inst, newOpcode, data, std::make_pair(inst->numSrcs(), inst->srcs().begin()) ); }); }
/* * Branch is a conditional branch to a normal exit. Convert it * into a SideExitJcc instruction that can be patched in place. */ void optimizeSideExitJcc(IRUnit& unit, IRInstruction* inst, Block* exitBlock) { assert(isSideExitJcc(inst, exitBlock)); FTRACE(5, "SideExitJcc:vvvvvvvvvvvvvvvvvvvvv\n"); SCOPE_EXIT { FTRACE(5, "SideExitJcc:^^^^^^^^^^^^^^^^^^^^^\n"); }; auto it = exitBlock->backIter(); auto& reqBindJmp = *(it--); auto& syncABI = *it; assert(syncABI.op() == SyncABIRegs); FTRACE(5, "converting jcc ({}) to side exit\n", inst->id()); auto const newOpcode = jmpToSideExitJmp(inst->op()); SideExitJccData data; data.taken = reqBindJmp.extra<ReqBindJmp>()->offset; data.trflags = reqBindJmp.extra<ReqBindJmp>()->trflags; auto const block = inst->block(); block->insert(block->iteratorTo(inst), unit.cloneInstruction(&syncABI)); auto next = inst->next(); unit.replace( inst, newOpcode, data, std::make_pair(inst->numSrcs(), inst->srcs().begin()) ); block->push_back(unit.gen(Jmp, inst->marker(), next)); }