// VI is an in-loop instruction that uses Visitor.V, a loop invariant. Check whether any // iteration will require the value. Assume it is used if we're synthesising an unspecialised // copy of the loop for any reason. void PeelIteration::visitVariant(ShadowInstructionInvar* VI, DIVisitor& Visitor) { const ShadowLoopInvar* immediateChild = immediateChildLoop(L, VI->parent->outerScope); PeelAttempt* LPA = getPeelAttempt(immediateChild); if(LPA && LPA->isEnabled()) LPA->visitVariant(VI, Visitor); else Visitor.notifyUsersMissed(); }
void IntegrationAttempt::visitUser(ShadowInstIdx& User, DIVisitor& Visitor) { // Figure out what context cares about this value. The only possibilities are: this loop iteration, the next iteration of this loop (latch edge of header phi), // a child loop (defer to it to decide what to do), or a parent loop (again defer). // Note that nested cases (e.g. this is an invariant two children deep) are taken care of in the immediate child or parent's logic. if(User.blockIdx == INVALID_BLOCK_IDX || User.instIdx == INVALID_INSTRUCTION_IDX) return; ShadowInstructionInvar* SII = getInstInvar(User.blockIdx, User.instIdx); const ShadowLoopInvar* UserL = SII->parent->outerScope; if(UserL == L) { if(!visitNextIterationPHI(SII, Visitor)) { // Just an ordinary user in the same iteration (or out of any loop!). Visitor.visit(getInst(User.blockIdx, User.instIdx), this, User.blockIdx, User.instIdx); } } else { if((!L) || L->contains(UserL)) { const ShadowLoopInvar* outermostChildLoop = immediateChildLoop(L, UserL); // Used in a child loop. Check if that child exists at all and defer to it. PeelAttempt* LPA = getPeelAttempt(outermostChildLoop); if(LPA && LPA->isEnabled()) LPA->visitVariant(SII, Visitor); else if((!getBB(outermostChildLoop->headerIdx))) Visitor.visit(0, this, User.blockIdx, User.instIdx); // Loop not explored, but a failed version may exist else Visitor.notifyUsersMissed(); } else { visitExitPHI(SII, Visitor); } } }