bool PlaceBackedgeSafepointsImpl::runOnLoop(Loop *L) { // Loop through all loop latches (branches controlling backedges). We need // to place a safepoint on every backedge (potentially). // Note: In common usage, there will be only one edge due to LoopSimplify // having run sometime earlier in the pipeline, but this code must be correct // w.r.t. loops with multiple backedges. BasicBlock *header = L->getHeader(); SmallVector<BasicBlock*, 16> LoopLatches; L->getLoopLatches(LoopLatches); for (BasicBlock *pred : LoopLatches) { assert(L->contains(pred)); // Make a policy decision about whether this loop needs a safepoint or // not. Note that this is about unburdening the optimizer in loops, not // avoiding the runtime cost of the actual safepoint. if (!AllBackedges) { if (mustBeFiniteCountedLoop(L, SE, pred)) { if (TraceLSP) errs() << "skipping safepoint placement in finite loop\n"; FiniteExecution++; continue; } if (CallSafepointsEnabled && containsUnconditionalCallSafepoint(L, header, pred, *DT)) { // Note: This is only semantically legal since we won't do any further // IPO or inlining before the actual call insertion.. If we hadn't, we // might latter loose this call safepoint. if (TraceLSP) errs() << "skipping safepoint placement due to unconditional call\n"; CallInLoop++; continue; } } // TODO: We can create an inner loop which runs a finite number of // iterations with an outer loop which contains a safepoint. This would // not help runtime performance that much, but it might help our ability to // optimize the inner loop. // Safepoint insertion would involve creating a new basic block (as the // target of the current backedge) which does the safepoint (of all live // variables) and branches to the true header TerminatorInst *term = pred->getTerminator(); if (TraceLSP) { errs() << "[LSP] terminator instruction: "; term->dump(); } PollLocations.push_back(term); } return false; }
bool PlaceBackedgeSafepointsImpl::runOnLoop(Loop *L, LPPassManager &LPM) { ScalarEvolution *SE = &getAnalysis<ScalarEvolution>(); // Loop through all predecessors of the loop header and identify all // backedges. We need to place a safepoint on every backedge (potentially). // Note: Due to LoopSimplify there should only be one. Assert? Or can we // relax this? BasicBlock *header = L->getHeader(); // TODO: Use the analysis pass infrastructure for this. There is no reason // to recalculate this here. DominatorTree DT; DT.recalculate(*header->getParent()); bool modified = false; for (pred_iterator PI = pred_begin(header), E = pred_end(header); PI != E; PI++) { BasicBlock *pred = *PI; if (!L->contains(pred)) { // This is not a backedge, it's coming from outside the loop continue; } // Make a policy decision about whether this loop needs a safepoint or // not. Note that this is about unburdening the optimizer in loops, not // avoiding the runtime cost of the actual safepoint. if (!AllBackedges) { if (mustBeFiniteCountedLoop(L, SE, pred)) { if (TraceLSP) errs() << "skipping safepoint placement in finite loop\n"; FiniteExecution++; continue; } if (CallSafepointsEnabled && containsUnconditionalCallSafepoint(L, header, pred, DT)) { // Note: This is only semantically legal since we won't do any further // IPO or inlining before the actual call insertion.. If we hadn't, we // might latter loose this call safepoint. if (TraceLSP) errs() << "skipping safepoint placement due to unconditional call\n"; CallInLoop++; continue; } } // TODO: We can create an inner loop which runs a finite number of // iterations with an outer loop which contains a safepoint. This would // not help runtime performance that much, but it might help our ability to // optimize the inner loop. // We're unconditionally going to modify this loop. modified = true; // Safepoint insertion would involve creating a new basic block (as the // target of the current backedge) which does the safepoint (of all live // variables) and branches to the true header TerminatorInst *term = pred->getTerminator(); if (TraceLSP) { errs() << "[LSP] terminator instruction: "; term->dump(); } PollLocations.push_back(term); } return modified; }