5 #include "src/compiler/loop-peeling.h" 6 #include "src/compiler/common-operator.h" 7 #include "src/compiler/compiler-source-position-table.h" 8 #include "src/compiler/graph.h" 9 #include "src/compiler/node-marker.h" 10 #include "src/compiler/node-origin-table.h" 11 #include "src/compiler/node-properties.h" 12 #include "src/compiler/node.h" 13 #include "src/zone/zone.h" 113 : node_map(graph, static_cast<uint32_t>(max)), pairs(p) {}
116 if (node_map.Get(node) == 0)
return node;
117 return pairs->at(node_map.Get(node));
120 void Insert(
Node* original,
Node* copy) {
121 node_map.Set(original, 1 + pairs->size());
122 pairs->push_back(original);
123 pairs->push_back(copy);
131 for (
Node* node : nodes) {
133 source_positions, source_positions->GetSourcePosition(node));
136 for (
Node* input : node->inputs()) {
137 inputs.push_back(map(input));
139 Node* copy = graph->NewNode(node->op(), node->InputCount(), &inputs[0]);
140 if (NodeProperties::IsTyped(node)) {
141 NodeProperties::SetType(copy, NodeProperties::GetType(node));
147 for (
Node* original : nodes) {
148 Node* copy = pairs->at(node_map.Get(original));
149 for (
int i = 0;
i < copy->InputCount();
i++) {
150 copy->ReplaceInput(
i, map(original->InputAt(
i)));
155 bool Marked(
Node* node) {
return node_map.Get(node) > 0; }
166 Node* PeeledIteration::map(
Node* node) {
170 for (
size_t i = 0;
i < impl->node_pairs_.size();
i += 2) {
171 if (impl->node_pairs_[
i] == node)
return impl->node_pairs_[
i + 1];
176 bool LoopPeeler::CanPeel(LoopTree::Loop* loop) {
179 Node* loop_node = loop_tree_->GetLoopControl(loop);
180 for (Node* node : loop_tree_->LoopNodes(loop)) {
181 for (Node* use : node->uses()) {
182 if (!loop_tree_->Contains(loop, use)) {
184 switch (node->opcode()) {
185 case IrOpcode::kLoopExit:
186 unmarked_exit = (node->InputAt(1) != loop_node);
188 case IrOpcode::kLoopExitValue:
189 case IrOpcode::kLoopExitEffect:
190 unmarked_exit = (node->InputAt(1)->InputAt(1) != loop_node);
193 unmarked_exit = (use->opcode() != IrOpcode::kTerminate);
196 if (FLAG_trace_turbo_loop) {
197 Node* loop_node = loop_tree_->GetLoopControl(loop);
199 "Cannot peel loop %i. Loop exit without explicit mark: Node %i " 201 "loop, but its use %i (%s) is outside.\n",
202 loop_node->id(), node->id(), node->op()->mnemonic(), use->id(),
203 use->op()->mnemonic());
213 PeeledIteration* LoopPeeler::Peel(LoopTree::Loop* loop) {
214 if (!CanPeel(loop))
return nullptr;
219 PeeledIterationImpl* iter =
new (tmp_zone_) PeeledIterationImpl(tmp_zone_);
220 size_t estimated_peeled_size = 5 + (loop->TotalSize()) * 2;
221 Peeling peeling(graph_, estimated_peeled_size, &iter->node_pairs_);
223 Node* dead = graph_->NewNode(common_->Dead());
226 for (Node* node : loop_tree_->HeaderNodes(loop)) {
227 peeling.Insert(node, node->InputAt(kAssumedLoopEntryIndex));
231 peeling.CopyNodes(graph_, tmp_zone_, dead, loop_tree_->BodyNodes(loop),
232 source_positions_, node_origins_);
237 Node* loop_node = loop_tree_->GetLoopControl(loop);
239 int backedges = loop_node->InputCount() - 1;
243 NodeVector inputs(tmp_zone_);
244 for (
int i = 1;
i < loop_node->InputCount();
i++) {
245 inputs.push_back(peeling.map(loop_node->InputAt(
i)));
248 graph_->NewNode(common_->Merge(backedges), backedges, &inputs[0]);
251 for (Node* node : loop_tree_->HeaderNodes(loop)) {
252 if (node->opcode() == IrOpcode::kLoop)
continue;
254 for (
int i = 0;
i < backedges;
i++) {
255 inputs.push_back(peeling.map(node->InputAt(1 +
i)));
257 for (Node* input : inputs) {
258 if (input != inputs[0]) {
259 inputs.push_back(merge);
260 const Operator* op = common_->ResizeMergeOrPhi(node->op(), backedges);
261 Node* phi = graph_->NewNode(op, backedges + 1, &inputs[0]);
262 node->ReplaceInput(0, phi);
271 for (Node* node : loop_tree_->HeaderNodes(loop)) {
272 node->ReplaceInput(0, peeling.map(node->InputAt(1)));
274 new_entry = peeling.map(loop_node->InputAt(1));
276 loop_node->ReplaceInput(0, new_entry);
281 for (Node* exit : loop_tree_->ExitNodes(loop)) {
282 switch (exit->opcode()) {
283 case IrOpcode::kLoopExit:
285 exit->ReplaceInput(1, peeling.map(exit->InputAt(0)));
286 NodeProperties::ChangeOp(exit, common_->Merge(2));
288 case IrOpcode::kLoopExitValue:
290 exit->InsertInput(graph_->zone(), 1, peeling.map(exit->InputAt(0)));
291 NodeProperties::ChangeOp(
292 exit, common_->Phi(MachineRepresentation::kTagged, 2));
294 case IrOpcode::kLoopExitEffect:
296 exit->InsertInput(graph_->zone(), 1, peeling.map(exit->InputAt(0)));
297 NodeProperties::ChangeOp(exit, common_->EffectPhi(2));
306 void LoopPeeler::PeelInnerLoops(LoopTree::Loop* loop) {
308 if (!loop->children().empty()) {
309 for (LoopTree::Loop* inner_loop : loop->children()) {
310 PeelInnerLoops(inner_loop);
315 if (loop->TotalSize() > LoopPeeler::kMaxPeeledNodes)
return;
316 if (FLAG_trace_turbo_loop) {
317 PrintF(
"Peeling loop with header: ");
318 for (Node* node : loop_tree_->HeaderNodes(loop)) {
319 PrintF(
"%i ", node->id());
329 void EliminateLoopExit(Node* node) {
330 DCHECK_EQ(IrOpcode::kLoopExit, node->opcode());
333 for (Edge edge : node->use_edges()) {
334 if (NodeProperties::IsControlEdge(edge)) {
335 Node* marker = edge.from();
336 if (marker->opcode() == IrOpcode::kLoopExitValue) {
337 NodeProperties::ReplaceUses(marker, marker->InputAt(0));
339 }
else if (marker->opcode() == IrOpcode::kLoopExitEffect) {
340 NodeProperties::ReplaceUses(marker,
nullptr,
341 NodeProperties::GetEffectInput(marker));
346 NodeProperties::ReplaceUses(node,
nullptr,
nullptr,
347 NodeProperties::GetControlInput(node, 0));
353 void LoopPeeler::PeelInnerLoopsOfTree() {
354 for (LoopTree::Loop* loop : loop_tree_->outer_loops()) {
355 PeelInnerLoops(loop);
358 EliminateLoopExits(graph_, tmp_zone_);
362 void LoopPeeler::EliminateLoopExits(Graph* graph, Zone* tmp_zone) {
363 ZoneQueue<Node*> queue(tmp_zone);
364 ZoneVector<bool> visited(graph->NodeCount(),
false, tmp_zone);
365 queue.push(graph->end());
366 while (!queue.empty()) {
367 Node* node = queue.front();
370 if (node->opcode() == IrOpcode::kLoopExit) {
371 Node* control = NodeProperties::GetControlInput(node);
372 EliminateLoopExit(node);
373 if (!visited[control->id()]) {
374 visited[control->id()] =
true;
378 for (
int i = 0;
i < node->op()->ControlInputCount();
i++) {
379 Node* control = NodeProperties::GetControlInput(node,
i);
380 if (!visited[control->id()]) {
381 visited[control->id()] =
true;