// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/compiler/loop-peeling.h" #include "src/compiler/common-operator.h" #include "src/compiler/compiler-source-position-table.h" #include "src/compiler/graph.h" #include "src/compiler/loop-analysis.h" #include "src/compiler/node-marker.h" #include "src/compiler/node-origin-table.h" #include "src/compiler/node-properties.h" #include "src/compiler/node.h" #include "src/zone/zone.h" // Loop peeling is an optimization that copies the body of a loop, creating // a new copy of the body called the "peeled iteration" that represents the // first iteration. Beginning with a loop as follows: // E // | A // | | (backedges) // | +---------------|---------------------------------+ // | | +-------------|-------------------------------+ | // | | | | +--------+ | | // | | | | | +----+ | | | // | | | | | | | | | | // ( Loop )<-------- ( phiA ) | | | | // | | | | | | // ((======P=================U=======|=|=====)) | | // (( | | )) | | // (( X <---------------------+ | )) | | // (( | )) | | // (( body | )) | | // (( | )) | | // (( Y <-----------------------+ )) | | // (( )) | | // ((===K====L====M==========================)) | | // | | | | | // | | +-----------------------------------------+ | // | +------------------------------------------------+ // | // exit // The body of the loop is duplicated so that all nodes considered "inside" // the loop (e.g. {P, U, X, Y, K, L, M}) have a corresponding copies in the // peeled iteration (e.g. {P', U', X', Y', K', L', M'}). What were considered // backedges of the loop correspond to edges from the peeled iteration to // the main loop body, with multiple backedges requiring a merge. // Similarly, any exits from the loop body need to be merged with "exits" // from the peeled iteration, resulting in the graph as follows: // E // | A // | | // ((=====P'================U'===============)) // (( )) // (( X'<-------------+ )) // (( | )) // (( peeled iteration | )) // (( | )) // (( Y'<-----------+ | )) // (( | | )) // ((===K'===L'====M'======|=|===============)) // | | | | | // +--------+ +-+ +-+ | | // | | | | | // | Merge <------phi // | | | // | +-----+ | // | | | (backedges) // | | +---------------|---------------------------------+ // | | | +-------------|-------------------------------+ | // | | | | | +--------+ | | // | | | | | | +----+ | | | // | | | | | | | | | | | // | ( Loop )<-------- ( phiA ) | | | | // | | | | | | | // | ((======P=================U=======|=|=====)) | | // | (( | | )) | | // | (( X <---------------------+ | )) | | // | (( | )) | | // | (( body | )) | | // | (( | )) | | // | (( Y <-----------------------+ )) | | // | (( )) | | // | ((===K====L====M==========================)) | | // | | | | | | // | | | +-----------------------------------------+ | // | | +------------------------------------------------+ // | | // | | // +----+ +-+ // | | // Merge // | // exit // Note that the boxes ((===)) above are not explicitly represented in the // graph, but are instead computed by the {LoopFinder}. namespace v8 { namespace internal { namespace compiler { class PeeledIterationImpl : public PeeledIteration { … }; Node* PeeledIteration::map(Node* node) { … } PeeledIteration* LoopPeeler::Peel(LoopTree::Loop* loop) { … } void LoopPeeler::PeelInnerLoops(LoopTree::Loop* loop) { … } void LoopPeeler::EliminateLoopExit(Node* node) { … } void LoopPeeler::PeelInnerLoopsOfTree() { … } // static void LoopPeeler::EliminateLoopExits(Graph* graph, Zone* tmp_zone) { … } } // namespace compiler } // namespace internal } // namespace v8