LCOV - code coverage report
Current view: top level - src/compiler - dead-code-elimination.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 66 66 100.0 %
Date: 2017-10-20 Functions: 8 8 100.0 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/compiler/dead-code-elimination.h"
       6             : 
       7             : #include "src/compiler/common-operator.h"
       8             : #include "src/compiler/graph.h"
       9             : #include "src/compiler/node-properties.h"
      10             : #include "src/compiler/operator-properties.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : namespace compiler {
      15             : 
      16     2672029 : DeadCodeElimination::DeadCodeElimination(Editor* editor, Graph* graph,
      17             :                                          CommonOperatorBuilder* common)
      18             :     : AdvancedReducer(editor),
      19             :       graph_(graph),
      20             :       common_(common),
      21     5344061 :       dead_(graph->NewNode(common->Dead())) {
      22             :   NodeProperties::SetType(dead_, Type::None());
      23     2672032 : }
      24             : 
      25   262218719 : Reduction DeadCodeElimination::Reduce(Node* node) {
      26   262218719 :   switch (node->opcode()) {
      27             :     case IrOpcode::kEnd:
      28     2776519 :       return ReduceEnd(node);
      29             :     case IrOpcode::kLoop:
      30             :     case IrOpcode::kMerge:
      31     6067673 :       return ReduceLoopOrMerge(node);
      32             :     case IrOpcode::kLoopExit:
      33      233291 :       return ReduceLoopExit(node);
      34             :     default:
      35   253141236 :       return ReduceNode(node);
      36             :   }
      37             :   UNREACHABLE();
      38             : }
      39             : 
      40             : 
      41     2851926 : Reduction DeadCodeElimination::ReduceEnd(Node* node) {
      42             :   DCHECK_EQ(IrOpcode::kEnd, node->opcode());
      43             :   Node::Inputs inputs = node->inputs();
      44             :   DCHECK_LE(1, inputs.count());
      45             :   int live_input_count = 0;
      46     9929469 :   for (int i = 0; i < inputs.count(); ++i) {
      47     7152955 :     Node* const input = inputs[i];
      48             :     // Skip dead inputs.
      49     7152955 :     if (input->opcode() == IrOpcode::kDead) continue;
      50             :     // Compact live inputs.
      51     7035754 :     if (i != live_input_count) node->ReplaceInput(live_input_count, input);
      52     7035757 :     ++live_input_count;
      53             :   }
      54     2776514 :   if (live_input_count == 0) {
      55             :     return Replace(dead());
      56     2776499 :   } else if (live_input_count < inputs.count()) {
      57       75400 :     node->TrimInputCount(live_input_count);
      58      150800 :     NodeProperties::ChangeOp(node, common()->End(live_input_count));
      59             :     return Changed(node);
      60             :   }
      61             :   DCHECK_EQ(inputs.count(), live_input_count);
      62             :   return NoChange();
      63             : }
      64             : 
      65             : 
      66    12155033 : Reduction DeadCodeElimination::ReduceLoopOrMerge(Node* node) {
      67             :   DCHECK(IrOpcode::IsMergeOpcode(node->opcode()));
      68             :   Node::Inputs inputs = node->inputs();
      69             :   DCHECK_LE(1, inputs.count());
      70             :   // Count the number of live inputs to {node} and compact them on the fly, also
      71             :   // compacting the inputs of the associated {Phi} and {EffectPhi} uses at the
      72             :   // same time.  We consider {Loop}s dead even if only the first control input
      73             :   // is dead.
      74             :   int live_input_count = 0;
      75     6521014 :   if (node->opcode() != IrOpcode::kLoop ||
      76      453290 :       node->InputAt(0)->opcode() != IrOpcode::kDead) {
      77    16278392 :     for (int i = 0; i < inputs.count(); ++i) {
      78    16278333 :       Node* const input = inputs[i];
      79             :       // Skip dead inputs.
      80    16278333 :       if (input->opcode() == IrOpcode::kDead) continue;
      81             :       // Compact live inputs.
      82    15850218 :       if (live_input_count != i) {
      83      426069 :         node->ReplaceInput(live_input_count, input);
      84     2042169 :         for (Node* const use : node->uses()) {
      85     1616041 :           if (NodeProperties::IsPhi(use)) {
      86             :             DCHECK_EQ(inputs.count() + 1, use->InputCount());
      87      886004 :             use->ReplaceInput(live_input_count, use->InputAt(i));
      88             :           }
      89             :         }
      90             :       }
      91    15850277 :       ++live_input_count;
      92             :     }
      93             :   }
      94     6067783 :   if (live_input_count == 0) {
      95             :     return Replace(dead());
      96     6056159 :   } else if (live_input_count == 1) {
      97             :     // Due to compaction above, the live input is at offset 0.
      98     2117219 :     for (Node* const use : node->uses()) {
      99     1576047 :       if (NodeProperties::IsPhi(use)) {
     100      485714 :         Replace(use, use->InputAt(0));
     101     1273053 :       } else if (use->opcode() == IrOpcode::kLoopExit &&
     102             :                  use->InputAt(1) == node) {
     103        3216 :         RemoveLoopExit(use);
     104     1264794 :       } else if (use->opcode() == IrOpcode::kTerminate) {
     105             :         DCHECK_EQ(IrOpcode::kLoop, node->opcode());
     106             :         Replace(use, dead());
     107             :       }
     108             :     }
     109             :     return Replace(node->InputAt(0));
     110             :   }
     111             :   DCHECK_LE(2, live_input_count);
     112             :   DCHECK_LE(live_input_count, inputs.count());
     113             :   // Trim input count for the {Merge} or {Loop} node.
     114     5514986 :   if (live_input_count < inputs.count()) {
     115             :     // Trim input counts for all phi uses and revisit them.
     116      518246 :     for (Node* const use : node->uses()) {
     117      396353 :       if (NodeProperties::IsPhi(use)) {
     118      169716 :         use->ReplaceInput(live_input_count, node);
     119      169716 :         TrimMergeOrPhi(use, live_input_count);
     120             :         Revisit(use);
     121             :       }
     122             :     }
     123      121893 :     TrimMergeOrPhi(node, live_input_count);
     124             :     return Changed(node);
     125             :   }
     126             :   return NoChange();
     127             : }
     128             : 
     129       23653 : Reduction DeadCodeElimination::RemoveLoopExit(Node* node) {
     130             :   DCHECK_EQ(IrOpcode::kLoopExit, node->opcode());
     131      214093 :   for (Node* const use : node->uses()) {
     132       95220 :     if (use->opcode() == IrOpcode::kLoopExitValue ||
     133             :         use->opcode() == IrOpcode::kLoopExitEffect) {
     134       95082 :       Replace(use, use->InputAt(0));
     135             :     }
     136             :   }
     137       23653 :   Node* control = NodeProperties::GetControlInput(node, 0);
     138             :   Replace(node, control);
     139       23653 :   return Replace(control);
     140             : }
     141             : 
     142   253185951 : Reduction DeadCodeElimination::ReduceNode(Node* node) {
     143             :   // If {node} has exactly one control input and this is {Dead},
     144             :   // replace {node} with {Dead}.
     145   253185951 :   int const control_input_count = node->op()->ControlInputCount();
     146   253185951 :   if (control_input_count == 0) return NoChange();
     147             :   DCHECK_EQ(1, control_input_count);
     148   124211575 :   Node* control = NodeProperties::GetControlInput(node);
     149   124207650 :   if (control->opcode() == IrOpcode::kDead) return Replace(control);
     150             :   return NoChange();
     151             : }
     152             : 
     153      233291 : Reduction DeadCodeElimination::ReduceLoopExit(Node* node) {
     154      466582 :   Node* control = NodeProperties::GetControlInput(node, 0);
     155      446168 :   Node* loop = NodeProperties::GetControlInput(node, 1);
     156      446168 :   if (control->opcode() == IrOpcode::kDead ||
     157             :       loop->opcode() == IrOpcode::kDead) {
     158       20437 :     return RemoveLoopExit(node);
     159             :   }
     160             :   return NoChange();
     161             : }
     162             : 
     163      291609 : void DeadCodeElimination::TrimMergeOrPhi(Node* node, int size) {
     164      291609 :   const Operator* const op = common()->ResizeMergeOrPhi(node->op(), size);
     165      291609 :   node->TrimInputCount(OperatorProperties::GetTotalInputCount(op));
     166      291609 :   NodeProperties::ChangeOp(node, op);
     167      291609 : }
     168             : 
     169             : }  // namespace compiler
     170             : }  // namespace internal
     171             : }  // namespace v8

Generated by: LCOV version 1.10