本文整理汇总了C++中MInstruction::block方法的典型用法代码示例。如果您正苦于以下问题:C++ MInstruction::block方法的具体用法?C++ MInstruction::block怎么用?C++ MInstruction::block使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类MInstruction
的用法示例。
在下文中一共展示了MInstruction::block方法的7个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: MoveDeferredOperands
// In preparation for hoisting an instruction, hoist any of its operands which
// were too cheap to hoist on their own.
static void
MoveDeferredOperands(MInstruction* ins, MInstruction* hoistPoint, bool hasCalls)
{
// If any of our operands were waiting for a user to be hoisted, make a note
// to hoist them.
for (size_t i = 0, e = ins->numOperands(); i != e; ++i) {
MDefinition* op = ins->getOperand(i);
if (!IsInLoop(op))
continue;
MOZ_ASSERT(RequiresHoistedUse(op, hasCalls),
"Deferred loop-invariant operand is not cheap");
MInstruction* opIns = op->toInstruction();
// Recursively move the operands. Note that the recursion is bounded
// because we require RequiresHoistedUse to be set at each level.
MoveDeferredOperands(opIns, hoistPoint, hasCalls);
#ifdef DEBUG
JitSpew(JitSpew_LICM, " Hoisting %s%u (now that a user will be hoisted)",
opIns->opName(), opIns->id());
#endif
opIns->block()->moveBefore(hoistPoint, opIns);
}
}
示例2:
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;
}
示例3: defs
// This pass annotates every load instruction with the last store instruction
// on which it depends. The algorithm is optimistic in that it ignores explicit
// dependencies and only considers loads and stores.
//
// Loads inside loops only have an implicit dependency on a store before the
// loop header if no instruction inside the loop body aliases it. To calculate
// this efficiently, we maintain a list of maybe-invariant loads and the combined
// alias set for all stores inside the loop. When we see the loop's backedge, this
// information is used to mark every load we wrongly assumed to be loop invariant as
// having an implicit dependency on the last instruction of the loop header, so that
// it's never moved before the loop header.
//
// The algorithm depends on the invariant that both control instructions and effectful
// instructions (stores) are never hoisted.
bool
AliasAnalysis::analyze()
{
Vector<MInstructionVector, AliasSet::NumCategories, JitAllocPolicy> stores(alloc());
// Initialize to the first instruction.
MInstruction* firstIns = *graph_.entryBlock()->begin();
for (unsigned i = 0; i < AliasSet::NumCategories; i++) {
MInstructionVector defs(alloc());
if (!defs.append(firstIns))
return false;
if (!stores.append(Move(defs)))
return false;
}
// Type analysis may have inserted new instructions. Since this pass depends
// on the instruction number ordering, all instructions are renumbered.
uint32_t newId = 0;
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
if (mir->shouldCancel("Alias Analysis (main loop)"))
return false;
if (block->isLoopHeader()) {
JitSpew(JitSpew_Alias, "Processing loop header %d", block->id());
loop_ = new(alloc()) LoopAliasInfo(alloc(), loop_, *block);
}
for (MPhiIterator def(block->phisBegin()), end(block->phisEnd()); def != end; ++def)
def->setId(newId++);
for (MInstructionIterator def(block->begin()), end(block->begin(block->lastIns()));
def != end;
++def)
{
def->setId(newId++);
AliasSet set = def->getAliasSet();
if (set.isNone())
continue;
// For the purposes of alias analysis, all recoverable operations
// are treated as effect free as the memory represented by these
// operations cannot be aliased by others.
if (def->canRecoverOnBailout())
continue;
if (set.isStore()) {
for (AliasSetIterator iter(set); iter; iter++) {
if (!stores[*iter].append(*def))
return false;
}
if (JitSpewEnabled(JitSpew_Alias)) {
Fprinter& out = JitSpewPrinter();
out.printf("Processing store ");
def->printName(out);
out.printf(" (flags %x)\n", set.flags());
}
} else {
// Find the most recent store on which this instruction depends.
MInstruction* lastStore = firstIns;
for (AliasSetIterator iter(set); iter; iter++) {
MInstructionVector& aliasedStores = stores[*iter];
for (int i = aliasedStores.length() - 1; i >= 0; i--) {
MInstruction* store = aliasedStores[i];
if (genericMightAlias(*def, store) != MDefinition::AliasType::NoAlias &&
def->mightAlias(store) != MDefinition::AliasType::NoAlias &&
BlockMightReach(store->block(), *block))
{
if (lastStore->id() < store->id())
lastStore = store;
break;
}
}
}
def->setDependency(lastStore);
IonSpewDependency(*def, lastStore, "depends", "");
// If the last store was before the current loop, we assume this load
// is loop invariant. If a later instruction writes to the same location,
// we will fix this at the end of the loop.
if (loop_ && lastStore->id() < loop_->firstInstruction()->id()) {
if (!loop_->addInvariantLoad(*def))
//.........这里部分代码省略.........
示例4: ShiftToScale
static void
AnalyzeLsh(TempAllocator& alloc, MLsh* lsh)
{
if (lsh->specialization() != MIRType::Int32)
return;
if (lsh->isRecoveredOnBailout())
return;
MDefinition* index = lsh->lhs();
MOZ_ASSERT(index->type() == MIRType::Int32);
MConstant* shiftValue = lsh->rhs()->maybeConstantValue();
if (!shiftValue)
return;
if (shiftValue->type() != MIRType::Int32 || !IsShiftInScaleRange(shiftValue->toInt32()))
return;
Scale scale = ShiftToScale(shiftValue->toInt32());
int32_t displacement = 0;
MInstruction* last = lsh;
MDefinition* base = nullptr;
while (true) {
if (!last->hasOneUse())
break;
MUseIterator use = last->usesBegin();
if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isAdd())
break;
MAdd* add = use->consumer()->toDefinition()->toAdd();
if (add->specialization() != MIRType::Int32 || !add->isTruncated())
break;
MDefinition* other = add->getOperand(1 - add->indexOf(*use));
if (MConstant* otherConst = other->maybeConstantValue()) {
displacement += otherConst->toInt32();
} else {
if (base)
break;
base = other;
}
last = add;
if (last->isRecoveredOnBailout())
return;
}
if (!base) {
uint32_t elemSize = 1 << ScaleToShift(scale);
if (displacement % elemSize != 0)
return;
if (!last->hasOneUse())
return;
MUseIterator use = last->usesBegin();
if (!use->consumer()->isDefinition() || !use->consumer()->toDefinition()->isBitAnd())
return;
MBitAnd* bitAnd = use->consumer()->toDefinition()->toBitAnd();
if (bitAnd->isRecoveredOnBailout())
return;
MDefinition* other = bitAnd->getOperand(1 - bitAnd->indexOf(*use));
MConstant* otherConst = other->maybeConstantValue();
if (!otherConst || otherConst->type() != MIRType::Int32)
return;
uint32_t bitsClearedByShift = elemSize - 1;
uint32_t bitsClearedByMask = ~uint32_t(otherConst->toInt32());
if ((bitsClearedByShift & bitsClearedByMask) != bitsClearedByMask)
return;
bitAnd->replaceAllUsesWith(last);
return;
}
if (base->isRecoveredOnBailout())
return;
MEffectiveAddress* eaddr = MEffectiveAddress::New(alloc, base, index, scale, displacement);
last->replaceAllUsesWith(eaddr);
last->block()->insertAfter(last, eaddr);
}
示例5: operands
bool
Sink(MIRGenerator* mir, MIRGraph& graph)
{
TempAllocator& alloc = graph.alloc();
bool sinkEnabled = mir->optimizationInfo().sinkEnabled();
for (PostorderIterator block = graph.poBegin(); block != graph.poEnd(); block++) {
if (mir->shouldCancel("Sink"))
return false;
for (MInstructionReverseIterator iter = block->rbegin(); iter != block->rend(); ) {
MInstruction* ins = *iter++;
// Only instructions which can be recovered on bailout can be moved
// into the bailout paths.
if (ins->isGuard() || ins->isGuardRangeBailouts() ||
ins->isRecoveredOnBailout() || !ins->canRecoverOnBailout())
{
continue;
}
// Compute a common dominator for all uses of the current
// instruction.
bool hasLiveUses = false;
bool hasUses = false;
MBasicBlock* usesDominator = nullptr;
for (MUseIterator i(ins->usesBegin()), e(ins->usesEnd()); i != e; i++) {
hasUses = true;
MNode* consumerNode = (*i)->consumer();
if (consumerNode->isResumePoint())
continue;
MDefinition* consumer = consumerNode->toDefinition();
if (consumer->isRecoveredOnBailout())
continue;
hasLiveUses = true;
// If the instruction is a Phi, then we should dominate the
// predecessor from which the value is coming from.
MBasicBlock* consumerBlock = consumer->block();
if (consumer->isPhi())
consumerBlock = consumerBlock->getPredecessor(consumer->indexOf(*i));
usesDominator = CommonDominator(usesDominator, consumerBlock);
if (usesDominator == *block)
break;
}
// Leave this instruction for DCE.
if (!hasUses)
continue;
// We have no uses, so sink this instruction in all the bailout
// paths.
if (!hasLiveUses) {
MOZ_ASSERT(!usesDominator);
ins->setRecoveredOnBailout();
JitSpewDef(JitSpew_Sink, " No live uses, recover the instruction on bailout\n", ins);
continue;
}
// This guard is temporarly moved here as the above code deals with
// Dead Code elimination, which got moved into this Sink phase, as
// the Dead Code elimination used to move instructions with no-live
// uses to the bailout path.
if (!sinkEnabled)
continue;
// To move an effectful instruction, we would have to verify that the
// side-effect is not observed. In the mean time, we just inhibit
// this optimization on effectful instructions.
if (ins->isEffectful())
continue;
// If all the uses are under a loop, we might not want to work
// against LICM by moving everything back into the loop, but if the
// loop is it-self inside an if, then we still want to move the
// computation under this if statement.
while (block->loopDepth() < usesDominator->loopDepth()) {
MOZ_ASSERT(usesDominator != usesDominator->immediateDominator());
usesDominator = usesDominator->immediateDominator();
}
// Only move instructions if there is a branch between the dominator
// of the uses and the original instruction. This prevent moving the
// computation of the arguments into an inline function if there is
// no major win.
MBasicBlock* lastJoin = usesDominator;
while (*block != lastJoin && lastJoin->numPredecessors() == 1) {
MOZ_ASSERT(lastJoin != lastJoin->immediateDominator());
MBasicBlock* next = lastJoin->immediateDominator();
if (next->numSuccessors() > 1)
break;
lastJoin = next;
}
if (*block == lastJoin)
continue;
// Skip to the next instruction if we cannot find a common dominator
//.........这里部分代码省略.........
示例6: JitSpew
// Visit |def|.
bool
ValueNumberer::visitDefinition(MDefinition* def)
{
// Nop does not fit in any of the previous optimization, as its only purpose
// is to reduce the register pressure by keeping additional resume
// point. Still, there is no need consecutive list of MNop instructions, and
// this will slow down every other iteration on the Graph.
if (def->isNop()) {
MNop* nop = def->toNop();
MBasicBlock* block = nop->block();
// We look backward to know if we can remove the previous Nop, we do not
// look forward as we would not benefit from the folding made by GVN.
MInstructionReverseIterator iter = ++block->rbegin(nop);
// This nop is at the beginning of the basic block, just replace the
// resume point of the basic block by the one from the resume point.
if (iter == block->rend()) {
JitSpew(JitSpew_GVN, " Removing Nop%u", nop->id());
nop->moveResumePointAsEntry();
block->discard(nop);
return true;
}
// The previous instruction is also a Nop, no need to keep it anymore.
MInstruction* prev = *iter;
if (prev->isNop()) {
JitSpew(JitSpew_GVN, " Removing Nop%u", prev->id());
block->discard(prev);
return true;
}
return true;
}
// If this instruction has a dependency() into an unreachable block, we'll
// need to update AliasAnalysis.
MInstruction* dep = def->dependency();
if (dep != nullptr && (dep->isDiscarded() || dep->block()->isDead())) {
JitSpew(JitSpew_GVN, " AliasAnalysis invalidated");
if (updateAliasAnalysis_ && !dependenciesBroken_) {
// TODO: Recomputing alias-analysis could theoretically expose more
// GVN opportunities.
JitSpew(JitSpew_GVN, " Will recompute!");
dependenciesBroken_ = true;
}
// Temporarily clear its dependency, to protect foldsTo, which may
// wish to use the dependency to do store-to-load forwarding.
def->setDependency(def->toInstruction());
} else {
dep = nullptr;
}
// Look for a simplified form of |def|.
MDefinition* sim = simplified(def);
if (sim != def) {
if (sim == nullptr)
return false;
// If |sim| doesn't belong to a block, insert it next to |def|.
if (sim->block() == nullptr)
def->block()->insertAfter(def->toInstruction(), sim->toInstruction());
#ifdef DEBUG
JitSpew(JitSpew_GVN, " Folded %s%u to %s%u",
def->opName(), def->id(), sim->opName(), sim->id());
#endif
MOZ_ASSERT(!sim->isDiscarded());
ReplaceAllUsesWith(def, sim);
// The node's foldsTo said |def| can be replaced by |rep|. If |def| is a
// guard, then either |rep| is also a guard, or a guard isn't actually
// needed, so we can clear |def|'s guard flag and let it be discarded.
def->setNotGuardUnchecked();
if (DeadIfUnused(def)) {
if (!discardDefsRecursively(def))
return false;
// If that ended up discarding |sim|, then we're done here.
if (sim->isDiscarded())
return true;
}
// Otherwise, procede to optimize with |sim| in place of |def|.
def = sim;
}
// Now that foldsTo is done, re-enable the original dependency. Even though
// it may be pointing into a discarded block, it's still valid for the
// purposes of detecting congruent loads.
if (dep != nullptr)
def->setDependency(dep);
// Look for a dominating def which makes |def| redundant.
MDefinition* rep = leader(def);
if (rep != def) {
if (rep == nullptr)
return false;
//.........这里部分代码省略.........
示例7: while
bool
Loop::hoistInstructions(InstructionQueue &toHoist, InstructionQueue &boundsChecks)
{
// Hoist bounds checks first, so that hoistBoundsCheck can test for
// invariant instructions, but delay actual insertion until the end to
// handle dependencies on loop invariant instructions.
InstructionQueue hoistedChecks;
for (size_t i = 0; i < boundsChecks.length(); i++) {
MBoundsCheck *ins = boundsChecks[i]->toBoundsCheck();
if (isLoopInvariant(ins) || !isInLoop(ins))
continue;
// Try to find a test dominating the bounds check which can be
// transformed into a hoistable check. Stop after the first such check
// which could be transformed (the one which will be the closest to the
// access in the source).
MBasicBlock *block = ins->block();
while (true) {
BranchDirection direction;
MTest *branch = block->immediateDominatorBranch(&direction);
if (branch) {
MInstruction *upper, *lower;
tryHoistBoundsCheck(ins, branch, direction, &upper, &lower);
if (upper && !hoistedChecks.append(upper))
return false;
if (lower && !hoistedChecks.append(lower))
return false;
if (upper || lower) {
ins->block()->discard(ins);
break;
}
}
MBasicBlock *dom = block->immediateDominator();
if (dom == block)
break;
block = dom;
}
}
// 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 (checkHotness(ins->block())) {
ins->block()->moveBefore(preLoop_->lastIns(), ins);
ins->setNotLoopInvariant();
}
}
for (size_t i = 0; i < hoistedChecks.length(); i++) {
MInstruction *ins = hoistedChecks[i];
preLoop_->insertBefore(preLoop_->lastIns(), ins);
}
return true;
}