本文整理汇总了C++中IRInstruction::getOpcode方法的典型用法代码示例。如果您正苦于以下问题:C++ IRInstruction::getOpcode方法的具体用法?C++ IRInstruction::getOpcode怎么用?C++ IRInstruction::getOpcode使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类IRInstruction
的用法示例。
在下文中一共展示了IRInstruction::getOpcode方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: simplifyCall
SSATmp* Simplifier::simplifyCall(IRInstruction* inst) {
auto spillVals = inst->getSrcs().subpiece(3);
IRInstruction* spillStack = m_tb->getSp()->getInstruction();
if (spillStack->getOpcode() != SpillStack) {
return nullptr;
}
SSATmp* sp = spillStack->getSrc(0);
int baseOffset = spillStack->getSrc(1)->getValInt() -
spillValueCells(spillStack);
auto const numSpillSrcs = spillVals.size();
for (int32_t i = 0; i < numSpillSrcs; i++) {
const int64_t offset = -(i + 1) + baseOffset;
assert(spillVals[i]->getType() != Type::ActRec);
IRInstruction* srcInst = spillVals[i]->getInstruction();
// If our value came from a LdStack on the same sp and offset,
// we don't need to spill it.
if (srcInst->getOpcode() == LdStack && srcInst->getSrc(0) == sp &&
srcInst->getSrc(1)->getValInt() == offset) {
spillVals[i] = m_tb->genDefNone();
}
}
// Note: although the instruction might have been modified above, we still
// need to return nullptr so that it gets cloned later if it's stack-allocated
return nullptr;
}
示例2: hoistConditionalJumps
// If main trace ends with a conditional jump with no side-effects on exit,
// hook it to the exitTrace and make it a TraceExitType::NormalCc
static void hoistConditionalJumps(Trace* trace, IRFactory* irFactory) {
IRInstruction::List& instList = trace->getInstructionList();
IRInstruction::Iterator tail = instList.end();
IRInstruction* jccInst = nullptr;
IRInstruction* exitInst = nullptr;
IRInstruction* exitCcInst = nullptr;
Opcode opc = OpAdd;
// Normally Jcc comes before a Marker
for (int idx = 3; idx >= 0; idx--) {
tail--; // go back to the previous instruction
IRInstruction* inst = *tail;
opc = inst->getOpcode();
if (opc == ExitTrace) {
exitInst = inst;
continue;
}
if (opc == Marker) {
continue;
}
if (jccCanBeDirectExit(opc)) {
jccInst = inst;
break;
}
break;
}
if (jccCanBeDirectExit(opc)) {
SSATmp* dst = jccInst->getDst();
Trace* targetTrace = jccInst->getLabel()->getParent();
IRInstruction::List& targetInstList = targetTrace->getInstructionList();
IRInstruction::Iterator targetInstIter = targetInstList.begin();
targetInstIter++; // skip over label
// Check for a NormalCc exit with no side effects
for (IRInstruction::Iterator it = targetInstIter;
it != targetInstList.end();
++it) {
IRInstruction* instr = (*it);
// Extend to support ExitSlow, ExitSlowNoProgress, ...
Opcode opc = instr->getOpcode();
if (opc == ExitTraceCc) {
exitCcInst = instr;
break;
} else if (opc == Marker) {
continue;
} else {
// Do not optimize if there are other instructions
break;
}
}
if (exitInst && exitCcInst) {
// Found both exits, link them to Jcc for codegen
assert(dst);
exitCcInst->appendSrc(irFactory->arena(), dst);
exitInst->appendSrc(irFactory->arena(), dst);
// Set flag so Jcc and exits know this is active
dst->setTCA(kIRDirectJccJmpActive);
}
}
}
示例3: sinkStores
void MemMap::sinkStores(StoreList& stores) {
// sink dead stores into exit edges that occur between the dead store and the
// next store
StoreList::reverse_iterator it, end;
for (it = stores.rbegin(), end = stores.rend(); it != end; ++it) {
IRInstruction* store = it->first;
if (store->getId() != DEAD) {
continue;
}
std::vector<IRInstruction*>::iterator i, e;
for (i = it->second.begin(), e = it->second.end(); i != e; ++i) {
IRInstruction* guard = *i;
IRInstruction* clone = store->clone(factory);
if (store->getDst() != NULL) {
factory->getSSATmp(clone);
}
guard->getLabel()->getParent()->prependInstruction(clone);
}
// StRefs cannot just be removed, they have to be converted into Movs
// as the destination of the StRef still has the DecRef attached to it.
if (store->getOpcode() == StRef || store->getOpcode() == StRefNT) {
store->setOpcode(Mov);
store->setSrc(1, NULL);
store->setNumSrcs(1);
store->setId(LIVE);
}
}
}
示例4: initInstructions
void initInstructions(Trace* trace, IRInstruction::List& wl) {
IRInstruction::List instructions = trace->getInstructionList();
IRInstruction::Iterator it;
bool unreachable = false;
TRACE(5, "DCE:vvvvvvvvvvvvvvvvvvvv\n");
for (it = instructions.begin(); it != instructions.end(); it++) {
IRInstruction* inst = *it;
ASSERT(inst->getParent() == trace);
Simplifier::copyProp(inst);
// if this is a load that does not generate a guard, then get rid
// of its label so that its not an essential control-flow
// instruction
if (isUnguardedLoad(inst)) {
// LdStack and LdLoc instructions that produce generic types
// and LdStack instruction that produce Cell types will not
// generate guards, so remove the label from this instruction so
// that its no longer an essential control-flow instruction
inst->setLabel(NULL);
}
Opcode opc = inst->getOpcode();
// decref of anything that isn't ref counted is a nop
if ((opc == DecRef || opc == DecRefNZ) && !isRefCounted(inst->getSrc(0))) {
inst->setId(DEAD);
continue;
}
if (!unreachable && inst->isControlFlowInstruction()) {
// mark the destination label so that the destination trace
// is marked reachable
inst->getLabel()->setId(LIVE);
}
if (!unreachable && isEssential(inst)) {
inst->setId(LIVE);
wl.push_back(inst);
} else {
if (moduleEnabled(HPHP::Trace::hhir, 5)) {
std::ostringstream ss1;
inst->printSrcs(ss1);
TRACE(5, "DCE: %s\n", ss1.str().c_str());
std::ostringstream ss2;
inst->print(ss2);
TRACE(5, "DCE: %s\n", ss2.str().c_str());
}
inst->setId(DEAD);
}
if (inst->getOpcode() == Jmp_) {
unreachable = true;
}
}
TRACE(5, "DCE:^^^^^^^^^^^^^^^^^^^^\n");
}
示例5: simplifyNot
SSATmp* Simplifier::simplifyNot(SSATmp* src) {
// const XORs are handled in simplifyXor()
assert(!src->isConst());
assert(src->getType() == Type::Bool);
IRInstruction* inst = src->getInstruction()->getSrc(0)->getInstruction();
Opcode op = inst->getOpcode();
// TODO: Add more algebraic simplification rules for NOT
switch (op) {
case OpXor: {
// !!X --> bool(X)
if (isNotInst(inst->getSrc(0))) {
return m_tb->genConvToBool(inst->getSrc(0));
}
break;
}
// !(X cmp Y) --> X opposite_cmp Y
case OpLt:
case OpLte:
case OpGt:
case OpGte:
case OpEq:
case OpNeq:
case OpSame:
case OpNSame:
return m_tb->genCmp(negateQueryOp(op), inst->getSrc(0), inst->getSrc(1));
// TODO !(X | non_zero) --> 0
default: (void)op;
}
return NULL;
}
示例6: elimUnconditionalJump
// If main trace ends with an unconditional jump, and the target is not
// reached by any other branch, then copy the target of the jump to the
// end of the trace
static void elimUnconditionalJump(Trace* trace, IRFactory* irFactory) {
boost::dynamic_bitset<> isJoin(irFactory->numLabels());
boost::dynamic_bitset<> havePred(irFactory->numLabels());
IRInstruction::List& instList = trace->getInstructionList();
for (IRInstruction* inst : instList) {
if (inst->isControlFlowInstruction()) {
auto id = inst->getLabel()->getLabelId();
isJoin[id] = havePred[id];
havePred[id] = 1;
}
}
IRInstruction::Iterator lastInst = instList.end();
--lastInst; // go back to the last instruction
IRInstruction* jmp = *lastInst;
if (jmp->getOpcode() == Jmp_ && !isJoin[jmp->getLabel()->getLabelId()]) {
Trace* targetTrace = jmp->getLabel()->getParent();
IRInstruction::List& targetInstList = targetTrace->getInstructionList();
IRInstruction::Iterator instIter = targetInstList.begin();
instIter++; // skip over label
// update the parent trace of the moved instructions
for (IRInstruction::Iterator it = instIter;
it != targetInstList.end();
++it) {
(*it)->setParent(trace);
}
instList.splice(lastInst, targetInstList, instIter, targetInstList.end());
// delete the jump instruction
instList.erase(lastInst);
}
}
示例7: removeUnusedSpillsAux
void LinearScan::removeUnusedSpillsAux(Trace* trace) {
IRInstruction::List& instList = trace->getInstructionList();
for (IRInstruction::Iterator it = instList.begin();
it != instList.end(); ) {
IRInstruction::Iterator next = it; ++next;
IRInstruction* inst = *it;
if (inst->getOpcode() == Spill && inst->getDst()->getUseCount() == 0) {
instList.erase(it);
SSATmp* src = inst->getSrc(0);
if (src->decUseCount() == 0) {
Opcode srcOpc = src->getInstruction()->getOpcode();
// Not all instructions are able to take noreg as its dest
// reg. We pick LdLoc and IncRef because they occur often.
if (srcOpc == IncRef || srcOpc == LdLoc) {
for (int locIndex = 0;
locIndex < src->numNeededRegs();
++locIndex) {
src->setReg(InvalidReg, locIndex);
}
}
}
}
it = next;
}
}
示例8: hoistConditionalJumps
/**
* If main trace ends with a conditional jump with no side-effects on exit,
* hook it to the exitTrace and make it a TraceExitType::NormalCc.
*
* This function essentially looks for the following code pattern:
*
* Main Trace:
* ----------
* L1: // jccBlock
* ...
* Jcc ... -> L3
* L2: // lastBlock
* DefLabel
* [Marker]
* ExitTrace
*
* Exit Trace:
* ----------
* L3: // targetBlock
* DefLabel
* [Marker]
* ExitTraceCc
*
* If the pattern is found, Jcc's dst operand is linked to the ExitTrace and
* ExitTraceCc instructions and it's flagged with kIRDirectJccJmpActive. This
* then triggers CodeGenerator to emit a REQ_BIND_JMPCC_FIRST service request.
*
*/
static void hoistConditionalJumps(Trace* trace, IRFactory* irFactory) {
IRInstruction* exitInst = nullptr;
IRInstruction* exitCcInst = nullptr;
Opcode opc = OpAdd;
// Normally Jcc comes before a Marker
auto& blocks = trace->getBlocks();
if (blocks.size() < 2) return;
auto it = blocks.end();
Block* lastBlock = *(--it);
Block* jccBlock = *(--it);
IRInstruction& jccInst = *(jccBlock->back());
if (!jccCanBeDirectExit(jccInst.getOpcode())) return;
for (auto it = lastBlock->skipLabel(), end = lastBlock->end(); it != end;
it++) {
IRInstruction& inst = *it;
opc = inst.getOpcode();
if (opc == ExitTrace) {
exitInst = &inst;
break;
}
if (opc != Marker) {
// Found real instruction on the last block
return;
}
}
if (exitInst) {
SSATmp* dst = jccInst.getDst();
Block* targetBlock = jccInst.getTaken();
auto targetInstIter = targetBlock->skipLabel();
// Check for a NormalCc exit with no side effects
for (auto it = targetInstIter, end = targetBlock->end(); it != end; ++it) {
IRInstruction* instr = &*it;
// Extend to support ExitSlow, ExitSlowNoProgress, ...
Opcode opc = instr->getOpcode();
if (opc == ExitTraceCc) {
exitCcInst = instr;
break;
} else if (opc != Marker) {
// Do not optimize if there are other instructions
break;
}
}
if (exitCcInst) {
// Found both exits, link them to Jcc for codegen
assert(dst);
exitCcInst->appendSrc(irFactory->arena(), dst);
exitInst->appendSrc(irFactory->arena(), dst);
// Set flag so Jcc and exits know this is active
dst->setTCA(kIRDirectJccJmpActive);
}
}
}
示例9: sinkStores
void MemMap::sinkStores(StoreList& stores) {
// sink dead stores into exit edges that occur between the dead store and the
// next store
StoreList::reverse_iterator it, end;
for (it = stores.rbegin(), end = stores.rend(); it != end; ++it) {
IRInstruction* store = it->first;
if (isLive(store)) continue;
for (IRInstruction* guard : it->second) {
Block* exit = guard->getTaken();
exit->prepend(store->clone(m_factory));
}
// StRefs cannot just be removed, they have to be converted into Movs
// as the destination of the StRef still has the DecRef attached to it.
if (store->getOpcode() == StRef || store->getOpcode() == StRefNT) {
store->setOpcode(Mov);
store->setSrc(1, nullptr);
store->setNumSrcs(1);
setLive(*store, true);
}
}
}
示例10: optimizeRefCount
// Perform the following transformations:
// 1) Change all unconsumed IncRefs to Mov.
// 2) Mark a conditionally dead DecRefNZ as live if its corresponding IncRef
// cannot be eliminated.
void optimizeRefCount(Trace* trace) {
IRInstruction::List& instList = trace->getInstructionList();
for (IRInstruction::Iterator it = instList.begin();
it != instList.end();
++it) {
IRInstruction* inst = *it;
if (inst->getOpcode() == IncRef &&
inst->getId() != REFCOUNT_CONSUMED &&
inst->getId() != REFCOUNT_CONSUMED_OFF_TRACE) {
inst->setOpcode(Mov);
inst->setId(DEAD);
}
if (inst->getOpcode() == DecRefNZ) {
IRInstruction* srcInst = inst->getSrc(0)->getInstruction();
if (srcInst->getId() == REFCOUNT_CONSUMED ||
srcInst->getId() == REFCOUNT_CONSUMED_OFF_TRACE) {
inst->setId(LIVE);
}
}
// Do copyProp at last. When processing DecRefNZs, we still need to look at
// its source which should not be trampled over.
Simplifier::copyProp(inst);
}
}
示例11: simplifyNot
SSATmp* Simplifier::simplifyNot(SSATmp* src) {
IRInstruction* inst = src->getInstruction();
Opcode op = inst->getOpcode();
// TODO: Add more algebraic simplification rules for NOT
switch (op) {
case ConvToBool:
return simplifyNot(inst->getSrc(0));
case OpXor: {
// !!X --> bool(X)
if (isNotInst(inst->getSrc(0))) {
return m_tb->genConvToBool(inst->getSrc(0));
}
break;
}
// !(X cmp Y) --> X opposite_cmp Y
case OpLt:
case OpLte:
case OpGt:
case OpGte:
case OpEq:
case OpNeq:
case OpSame:
case OpNSame:
// XXX: this could technically be losing a ConvToBool, except
// that we kinda know "not" instructions (Xor with 1) are always
// going to be followed by ConvToBool.
//
// TODO(#2058865): This would make more sense with a real Not
// instruction and allowing boolean output types for query ops.
return m_tb->genCmp(negateQueryOp(op),
inst->getSrc(0),
inst->getSrc(1));
case InstanceOf:
case NInstanceOf:
case InstanceOfBitmask:
case NInstanceOfBitmask:
// TODO: combine this with the above check and use isQueryOp or
// add an isNegatable.
return m_tb->gen(negateQueryOp(op),
inst->getNumSrcs(),
inst->getSrcs().begin());
// TODO !(X | non_zero) --> 0
default: (void)op;
}
return nullptr;
}
示例12: allocRegsToTraceAux
void LinearScan::allocRegsToTraceAux(Trace* trace) {
IRInstruction::List& instructionList = trace->getInstructionList();
IRInstruction::Iterator it;
for (it = instructionList.begin();
it != instructionList.end();
it++) {
IRInstruction* inst = *it;
allocRegToInstruction(trace, it);
if (RuntimeOption::EvalDumpIR > 3) {
std::cout << "--- allocated to instruction: ";
inst->print(std::cout);
std::cout << "\n";
}
if (inst->isControlFlowInstruction()) {
// This instruction may transfer control to another trace
// If this is the last instruction in the trace that can branch
// to this target trace, then allocate registers to the target
// trace, effectively linearizing the target trace after inst.
LabelInstruction* label = inst->getLabel();
if (label != NULL && label->getId() == inst->getId() + 1) {
allocRegsToTraceAux(label->getTrace());
}
}
}
// Insert spill instructions.
// Reload instructions are already added in <allocRegsToTrace>.
for (it = instructionList.begin(); it != instructionList.end(); ) {
IRInstruction::Iterator next = it; ++next;
IRInstruction* inst = *it;
if (inst->getOpcode() != Reload) {
// Reloaded SSATmps needn't be spilled again.
if (SSATmp* dst = inst->getDst()) {
int32 slotId = dst->getSpillSlot();
if (slotId != -1) {
// If this instruction is marked to be spilled,
// add a spill right afterwards.
IRInstruction* spillInst =
m_slots[slotId].m_slotTmp->getInstruction();
instructionList.insert(next, spillInst);
spillInst->setParent(trace);
}
}
}
it = next;
}
}
示例13: hoistGuardToLoad
/*
* Looks for whether the value in tmp was defined by a load, and if
* so, changes that load into a load that guards on the given
* type. Returns true if it succeeds.
*/
static bool hoistGuardToLoad(SSATmp* tmp, Type type) {
IRInstruction* inst = tmp->getInstruction();
switch (inst->getOpcode()) {
case Mov:
case IncRef:
{
// if inst is an incref or move, then chase down its src
if (hoistGuardToLoad(inst->getSrc(0), type)) {
// guard was successfully attached to a load instruction
// refine the type of this mov/incref
// Note: We can also further simplify incref's here if type is not
// ref-counted
tmp->setType(type);
inst->setTypeParam(type);
return true;
}
break;
}
case LdLoc:
case LdStack:
case LdMem:
case LdProp:
case LdRef:
case LdClsCns:
{
if (!inst->getTaken()) {
// Not a control flow instruction, so can't give it check semantics
break;
}
Type instType = tmp->getType();
if (instType == Type::Gen ||
(instType == Type::Cell && !type.isBoxed())) {
tmp->setType(type);
inst->setTypeParam(type);
return true;
}
break;
}
default:
break;
}
return false;
}
示例14: hoistGuardJumps
// If main trace starts with guards, have them generate a patchable jump
// to the anchor trace
static void hoistGuardJumps(Trace* trace, IRFactory* irFactory) {
LabelInstruction* guardLabel = nullptr;
IRInstruction::List& instList = trace->getInstructionList();
// Check the beginning of the trace for guards
for (IRInstruction* inst : instList) {
Opcode opc = inst->getOpcode();
if (inst->getLabel() &&
(opc == LdLoc || opc == LdStack ||
opc == GuardLoc || opc == GuardStk)) {
LabelInstruction* exitLabel = inst->getLabel();
// Find the GuardFailure's label and confirm this branches there
if (!guardLabel && exitLabel->getParent() != trace) {
Trace* exitTrace = exitLabel->getParent();
IRInstruction::List& xList = exitTrace->getInstructionList();
IRInstruction::Iterator instIter = xList.begin();
instIter++; // skip over label
// Confirm this is a GuardExit
for (IRInstruction::Iterator it = instIter; it != xList.end(); ++it) {
IRInstruction* i = *it;
Opcode op = i->getOpcode();
if (op == Marker) {
continue;
}
if (op == ExitGuardFailure) {
guardLabel = exitLabel;
}
// Do not optimize if other instructions are on exit trace
break;
}
}
if (exitLabel == guardLabel) {
inst->setTCA(kIRDirectGuardActive);
continue;
}
break;
}
if (opc == Marker || opc == DefLabel || opc == DefSP || opc == DefFP ||
opc == LdStack) {
continue;
}
break;
}
}
示例15: hoistGuardJumps
// If main trace starts with guards, have them generate a patchable jump
// to the anchor trace
static void hoistGuardJumps(Trace* trace, IRFactory* irFactory) {
Block* guardLabel = nullptr;
// Check the beginning of the trace for guards
for (Block* block : trace->getBlocks()) {
for (IRInstruction& instr : *block) {
IRInstruction* inst = &instr;
Opcode opc = inst->getOpcode();
if (inst->getTaken() &&
(opc == LdLoc || opc == LdStack ||
opc == GuardLoc || opc == GuardStk)) {
Block* exitLabel = inst->getTaken();
// Find the GuardFailure's label and confirm this branches there
if (!guardLabel && exitLabel->getTrace() != trace) {
auto instIter = exitLabel->skipLabel();
// Confirm this is a GuardExit
for (auto it = instIter, end = exitLabel->end(); it != end; ++it) {
Opcode op = it->getOpcode();
if (op == Marker) {
continue;
}
if (op == ExitGuardFailure) {
guardLabel = exitLabel;
}
// Do not optimize if other instructions are on exit trace
break;
}
}
if (exitLabel == guardLabel) {
inst->setTCA(kIRDirectGuardActive);
continue;
}
return; // terminate search
}
if (opc == Marker || opc == DefLabel || opc == DefSP || opc == DefFP ||
opc == LdStack) {
continue;
}
return; // terminate search
}
}
}