11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/compiler/dead-code-elimination.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h"
81cb0ef41Sopenharmony_ci#include "src/compiler/graph.h"
91cb0ef41Sopenharmony_ci#include "src/compiler/js-operator.h"
101cb0ef41Sopenharmony_ci#include "src/compiler/node-properties.h"
111cb0ef41Sopenharmony_ci#include "src/compiler/operator-properties.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_cinamespace internal {
151cb0ef41Sopenharmony_cinamespace compiler {
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ciDeadCodeElimination::DeadCodeElimination(Editor* editor, Graph* graph,
181cb0ef41Sopenharmony_ci                                         CommonOperatorBuilder* common,
191cb0ef41Sopenharmony_ci                                         Zone* temp_zone)
201cb0ef41Sopenharmony_ci    : AdvancedReducer(editor),
211cb0ef41Sopenharmony_ci      graph_(graph),
221cb0ef41Sopenharmony_ci      common_(common),
231cb0ef41Sopenharmony_ci      dead_(graph->NewNode(common->Dead())),
241cb0ef41Sopenharmony_ci      zone_(temp_zone) {
251cb0ef41Sopenharmony_ci  NodeProperties::SetType(dead_, Type::None());
261cb0ef41Sopenharmony_ci}
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_cinamespace {
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci// True if we can guarantee that {node} will never actually produce a value or
311cb0ef41Sopenharmony_ci// effect.
321cb0ef41Sopenharmony_cibool NoReturn(Node* node) {
331cb0ef41Sopenharmony_ci  return node->opcode() == IrOpcode::kDead ||
341cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kUnreachable ||
351cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kDeadValue ||
361cb0ef41Sopenharmony_ci         NodeProperties::GetTypeOrAny(node).IsNone();
371cb0ef41Sopenharmony_ci}
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ciNode* FindDeadInput(Node* node) {
401cb0ef41Sopenharmony_ci  for (Node* input : node->inputs()) {
411cb0ef41Sopenharmony_ci    if (NoReturn(input)) return input;
421cb0ef41Sopenharmony_ci  }
431cb0ef41Sopenharmony_ci  return nullptr;
441cb0ef41Sopenharmony_ci}
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci}  // namespace
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ciReduction DeadCodeElimination::Reduce(Node* node) {
491cb0ef41Sopenharmony_ci  switch (node->opcode()) {
501cb0ef41Sopenharmony_ci    case IrOpcode::kEnd:
511cb0ef41Sopenharmony_ci      return ReduceEnd(node);
521cb0ef41Sopenharmony_ci    case IrOpcode::kLoop:
531cb0ef41Sopenharmony_ci    case IrOpcode::kMerge:
541cb0ef41Sopenharmony_ci      return ReduceLoopOrMerge(node);
551cb0ef41Sopenharmony_ci    case IrOpcode::kLoopExit:
561cb0ef41Sopenharmony_ci      return ReduceLoopExit(node);
571cb0ef41Sopenharmony_ci    case IrOpcode::kUnreachable:
581cb0ef41Sopenharmony_ci    case IrOpcode::kIfException:
591cb0ef41Sopenharmony_ci      return ReduceUnreachableOrIfException(node);
601cb0ef41Sopenharmony_ci    case IrOpcode::kPhi:
611cb0ef41Sopenharmony_ci      return ReducePhi(node);
621cb0ef41Sopenharmony_ci    case IrOpcode::kEffectPhi:
631cb0ef41Sopenharmony_ci      return ReduceEffectPhi(node);
641cb0ef41Sopenharmony_ci    case IrOpcode::kDeoptimize:
651cb0ef41Sopenharmony_ci    case IrOpcode::kReturn:
661cb0ef41Sopenharmony_ci    case IrOpcode::kTerminate:
671cb0ef41Sopenharmony_ci    case IrOpcode::kTailCall:
681cb0ef41Sopenharmony_ci      return ReduceDeoptimizeOrReturnOrTerminateOrTailCall(node);
691cb0ef41Sopenharmony_ci    case IrOpcode::kThrow:
701cb0ef41Sopenharmony_ci      return PropagateDeadControl(node);
711cb0ef41Sopenharmony_ci    case IrOpcode::kBranch:
721cb0ef41Sopenharmony_ci    case IrOpcode::kSwitch:
731cb0ef41Sopenharmony_ci      return ReduceBranchOrSwitch(node);
741cb0ef41Sopenharmony_ci    default:
751cb0ef41Sopenharmony_ci      return ReduceNode(node);
761cb0ef41Sopenharmony_ci  }
771cb0ef41Sopenharmony_ci  UNREACHABLE();
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ciReduction DeadCodeElimination::PropagateDeadControl(Node* node) {
811cb0ef41Sopenharmony_ci  DCHECK_EQ(1, node->op()->ControlInputCount());
821cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node);
831cb0ef41Sopenharmony_ci  if (control->opcode() == IrOpcode::kDead) return Replace(control);
841cb0ef41Sopenharmony_ci  return NoChange();
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceEnd(Node* node) {
881cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kEnd, node->opcode());
891cb0ef41Sopenharmony_ci  Node::Inputs inputs = node->inputs();
901cb0ef41Sopenharmony_ci  DCHECK_LE(1, inputs.count());
911cb0ef41Sopenharmony_ci  int live_input_count = 0;
921cb0ef41Sopenharmony_ci  for (int i = 0; i < inputs.count(); ++i) {
931cb0ef41Sopenharmony_ci    Node* const input = inputs[i];
941cb0ef41Sopenharmony_ci    // Skip dead inputs.
951cb0ef41Sopenharmony_ci    if (input->opcode() == IrOpcode::kDead) continue;
961cb0ef41Sopenharmony_ci    // Compact live inputs.
971cb0ef41Sopenharmony_ci    if (i != live_input_count) node->ReplaceInput(live_input_count, input);
981cb0ef41Sopenharmony_ci    ++live_input_count;
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci  if (live_input_count == 0) {
1011cb0ef41Sopenharmony_ci    return Replace(dead());
1021cb0ef41Sopenharmony_ci  } else if (live_input_count < inputs.count()) {
1031cb0ef41Sopenharmony_ci    node->TrimInputCount(live_input_count);
1041cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, common()->End(live_input_count));
1051cb0ef41Sopenharmony_ci    return Changed(node);
1061cb0ef41Sopenharmony_ci  }
1071cb0ef41Sopenharmony_ci  DCHECK_EQ(inputs.count(), live_input_count);
1081cb0ef41Sopenharmony_ci  return NoChange();
1091cb0ef41Sopenharmony_ci}
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceLoopOrMerge(Node* node) {
1121cb0ef41Sopenharmony_ci  DCHECK(IrOpcode::IsMergeOpcode(node->opcode()));
1131cb0ef41Sopenharmony_ci  Node::Inputs inputs = node->inputs();
1141cb0ef41Sopenharmony_ci  DCHECK_LE(1, inputs.count());
1151cb0ef41Sopenharmony_ci  // Count the number of live inputs to {node} and compact them on the fly, also
1161cb0ef41Sopenharmony_ci  // compacting the inputs of the associated {Phi} and {EffectPhi} uses at the
1171cb0ef41Sopenharmony_ci  // same time.  We consider {Loop}s dead even if only the first control input
1181cb0ef41Sopenharmony_ci  // is dead.
1191cb0ef41Sopenharmony_ci  int live_input_count = 0;
1201cb0ef41Sopenharmony_ci  if (node->opcode() != IrOpcode::kLoop ||
1211cb0ef41Sopenharmony_ci      node->InputAt(0)->opcode() != IrOpcode::kDead) {
1221cb0ef41Sopenharmony_ci    for (int i = 0; i < inputs.count(); ++i) {
1231cb0ef41Sopenharmony_ci      Node* const input = inputs[i];
1241cb0ef41Sopenharmony_ci      // Skip dead inputs.
1251cb0ef41Sopenharmony_ci      if (input->opcode() == IrOpcode::kDead) continue;
1261cb0ef41Sopenharmony_ci      // Compact live inputs.
1271cb0ef41Sopenharmony_ci      if (live_input_count != i) {
1281cb0ef41Sopenharmony_ci        node->ReplaceInput(live_input_count, input);
1291cb0ef41Sopenharmony_ci        for (Node* const use : node->uses()) {
1301cb0ef41Sopenharmony_ci          if (NodeProperties::IsPhi(use)) {
1311cb0ef41Sopenharmony_ci            DCHECK_EQ(inputs.count() + 1, use->InputCount());
1321cb0ef41Sopenharmony_ci            use->ReplaceInput(live_input_count, use->InputAt(i));
1331cb0ef41Sopenharmony_ci          }
1341cb0ef41Sopenharmony_ci        }
1351cb0ef41Sopenharmony_ci      }
1361cb0ef41Sopenharmony_ci      ++live_input_count;
1371cb0ef41Sopenharmony_ci    }
1381cb0ef41Sopenharmony_ci  }
1391cb0ef41Sopenharmony_ci  if (live_input_count == 0) {
1401cb0ef41Sopenharmony_ci    return Replace(dead());
1411cb0ef41Sopenharmony_ci  } else if (live_input_count == 1) {
1421cb0ef41Sopenharmony_ci    NodeVector loop_exits(zone_);
1431cb0ef41Sopenharmony_ci    // Due to compaction above, the live input is at offset 0.
1441cb0ef41Sopenharmony_ci    for (Node* const use : node->uses()) {
1451cb0ef41Sopenharmony_ci      if (NodeProperties::IsPhi(use)) {
1461cb0ef41Sopenharmony_ci        Replace(use, use->InputAt(0));
1471cb0ef41Sopenharmony_ci      } else if (use->opcode() == IrOpcode::kLoopExit &&
1481cb0ef41Sopenharmony_ci                 use->InputAt(1) == node) {
1491cb0ef41Sopenharmony_ci        // Remember the loop exits so that we can mark their loop input dead.
1501cb0ef41Sopenharmony_ci        // This has to be done after the use list iteration so that we do
1511cb0ef41Sopenharmony_ci        // not mutate the use list while it is being iterated.
1521cb0ef41Sopenharmony_ci        loop_exits.push_back(use);
1531cb0ef41Sopenharmony_ci      } else if (use->opcode() == IrOpcode::kTerminate) {
1541cb0ef41Sopenharmony_ci        DCHECK_EQ(IrOpcode::kLoop, node->opcode());
1551cb0ef41Sopenharmony_ci        Replace(use, dead());
1561cb0ef41Sopenharmony_ci      }
1571cb0ef41Sopenharmony_ci    }
1581cb0ef41Sopenharmony_ci    for (Node* loop_exit : loop_exits) {
1591cb0ef41Sopenharmony_ci      loop_exit->ReplaceInput(1, dead());
1601cb0ef41Sopenharmony_ci      Revisit(loop_exit);
1611cb0ef41Sopenharmony_ci    }
1621cb0ef41Sopenharmony_ci    return Replace(node->InputAt(0));
1631cb0ef41Sopenharmony_ci  }
1641cb0ef41Sopenharmony_ci  DCHECK_LE(2, live_input_count);
1651cb0ef41Sopenharmony_ci  DCHECK_LE(live_input_count, inputs.count());
1661cb0ef41Sopenharmony_ci  // Trim input count for the {Merge} or {Loop} node.
1671cb0ef41Sopenharmony_ci  if (live_input_count < inputs.count()) {
1681cb0ef41Sopenharmony_ci    // Trim input counts for all phi uses and revisit them.
1691cb0ef41Sopenharmony_ci    for (Node* const use : node->uses()) {
1701cb0ef41Sopenharmony_ci      if (NodeProperties::IsPhi(use)) {
1711cb0ef41Sopenharmony_ci        use->ReplaceInput(live_input_count, node);
1721cb0ef41Sopenharmony_ci        TrimMergeOrPhi(use, live_input_count);
1731cb0ef41Sopenharmony_ci        Revisit(use);
1741cb0ef41Sopenharmony_ci      }
1751cb0ef41Sopenharmony_ci    }
1761cb0ef41Sopenharmony_ci    TrimMergeOrPhi(node, live_input_count);
1771cb0ef41Sopenharmony_ci    return Changed(node);
1781cb0ef41Sopenharmony_ci  }
1791cb0ef41Sopenharmony_ci  return NoChange();
1801cb0ef41Sopenharmony_ci}
1811cb0ef41Sopenharmony_ci
1821cb0ef41Sopenharmony_ciReduction DeadCodeElimination::RemoveLoopExit(Node* node) {
1831cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kLoopExit, node->opcode());
1841cb0ef41Sopenharmony_ci  for (Node* const use : node->uses()) {
1851cb0ef41Sopenharmony_ci    if (use->opcode() == IrOpcode::kLoopExitValue ||
1861cb0ef41Sopenharmony_ci        use->opcode() == IrOpcode::kLoopExitEffect) {
1871cb0ef41Sopenharmony_ci      Replace(use, use->InputAt(0));
1881cb0ef41Sopenharmony_ci    }
1891cb0ef41Sopenharmony_ci  }
1901cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node, 0);
1911cb0ef41Sopenharmony_ci  Replace(node, control);
1921cb0ef41Sopenharmony_ci  return Replace(control);
1931cb0ef41Sopenharmony_ci}
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceNode(Node* node) {
1961cb0ef41Sopenharmony_ci  DCHECK(!IrOpcode::IsGraphTerminator(node->opcode()));
1971cb0ef41Sopenharmony_ci  int const effect_input_count = node->op()->EffectInputCount();
1981cb0ef41Sopenharmony_ci  int const control_input_count = node->op()->ControlInputCount();
1991cb0ef41Sopenharmony_ci  DCHECK_LE(control_input_count, 1);
2001cb0ef41Sopenharmony_ci  if (control_input_count == 1) {
2011cb0ef41Sopenharmony_ci    Reduction reduction = PropagateDeadControl(node);
2021cb0ef41Sopenharmony_ci    if (reduction.Changed()) return reduction;
2031cb0ef41Sopenharmony_ci  }
2041cb0ef41Sopenharmony_ci  if (effect_input_count == 0 &&
2051cb0ef41Sopenharmony_ci      (control_input_count == 0 || node->op()->ControlOutputCount() == 0)) {
2061cb0ef41Sopenharmony_ci    return ReducePureNode(node);
2071cb0ef41Sopenharmony_ci  }
2081cb0ef41Sopenharmony_ci  if (effect_input_count > 0) {
2091cb0ef41Sopenharmony_ci    return ReduceEffectNode(node);
2101cb0ef41Sopenharmony_ci  }
2111cb0ef41Sopenharmony_ci  return NoChange();
2121cb0ef41Sopenharmony_ci}
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReducePhi(Node* node) {
2151cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kPhi, node->opcode());
2161cb0ef41Sopenharmony_ci  Reduction reduction = PropagateDeadControl(node);
2171cb0ef41Sopenharmony_ci  if (reduction.Changed()) return reduction;
2181cb0ef41Sopenharmony_ci  MachineRepresentation rep = PhiRepresentationOf(node->op());
2191cb0ef41Sopenharmony_ci  if (rep == MachineRepresentation::kNone ||
2201cb0ef41Sopenharmony_ci      NodeProperties::GetTypeOrAny(node).IsNone()) {
2211cb0ef41Sopenharmony_ci    return Replace(DeadValue(node, rep));
2221cb0ef41Sopenharmony_ci  }
2231cb0ef41Sopenharmony_ci  int input_count = node->op()->ValueInputCount();
2241cb0ef41Sopenharmony_ci  for (int i = 0; i < input_count; ++i) {
2251cb0ef41Sopenharmony_ci    Node* input = NodeProperties::GetValueInput(node, i);
2261cb0ef41Sopenharmony_ci    if (input->opcode() == IrOpcode::kDeadValue &&
2271cb0ef41Sopenharmony_ci        DeadValueRepresentationOf(input->op()) != rep) {
2281cb0ef41Sopenharmony_ci      NodeProperties::ReplaceValueInput(node, DeadValue(input, rep), i);
2291cb0ef41Sopenharmony_ci    }
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci  return NoChange();
2321cb0ef41Sopenharmony_ci}
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceEffectPhi(Node* node) {
2351cb0ef41Sopenharmony_ci  DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
2361cb0ef41Sopenharmony_ci  Reduction reduction = PropagateDeadControl(node);
2371cb0ef41Sopenharmony_ci  if (reduction.Changed()) return reduction;
2381cb0ef41Sopenharmony_ci
2391cb0ef41Sopenharmony_ci  Node* merge = NodeProperties::GetControlInput(node);
2401cb0ef41Sopenharmony_ci  DCHECK(merge->opcode() == IrOpcode::kMerge ||
2411cb0ef41Sopenharmony_ci         merge->opcode() == IrOpcode::kLoop);
2421cb0ef41Sopenharmony_ci  int input_count = node->op()->EffectInputCount();
2431cb0ef41Sopenharmony_ci  for (int i = 0; i < input_count; ++i) {
2441cb0ef41Sopenharmony_ci    Node* effect = NodeProperties::GetEffectInput(node, i);
2451cb0ef41Sopenharmony_ci    if (effect->opcode() == IrOpcode::kUnreachable) {
2461cb0ef41Sopenharmony_ci      // If Unreachable hits an effect phi, we can re-connect the effect chain
2471cb0ef41Sopenharmony_ci      // to the graph end and delete the corresponding inputs from the merge and
2481cb0ef41Sopenharmony_ci      // phi nodes.
2491cb0ef41Sopenharmony_ci      Node* control = NodeProperties::GetControlInput(merge, i);
2501cb0ef41Sopenharmony_ci      Node* throw_node = graph_->NewNode(common_->Throw(), effect, control);
2511cb0ef41Sopenharmony_ci      NodeProperties::MergeControlToEnd(graph_, common_, throw_node);
2521cb0ef41Sopenharmony_ci      NodeProperties::ReplaceEffectInput(node, dead_, i);
2531cb0ef41Sopenharmony_ci      NodeProperties::ReplaceControlInput(merge, dead_, i);
2541cb0ef41Sopenharmony_ci      Revisit(merge);
2551cb0ef41Sopenharmony_ci      Revisit(graph_->end());
2561cb0ef41Sopenharmony_ci      reduction = Changed(node);
2571cb0ef41Sopenharmony_ci    }
2581cb0ef41Sopenharmony_ci  }
2591cb0ef41Sopenharmony_ci  return reduction;
2601cb0ef41Sopenharmony_ci}
2611cb0ef41Sopenharmony_ci
2621cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReducePureNode(Node* node) {
2631cb0ef41Sopenharmony_ci  DCHECK_EQ(0, node->op()->EffectInputCount());
2641cb0ef41Sopenharmony_ci  if (node->opcode() == IrOpcode::kDeadValue) return NoChange();
2651cb0ef41Sopenharmony_ci  if (Node* input = FindDeadInput(node)) {
2661cb0ef41Sopenharmony_ci    return Replace(DeadValue(input));
2671cb0ef41Sopenharmony_ci  }
2681cb0ef41Sopenharmony_ci  return NoChange();
2691cb0ef41Sopenharmony_ci}
2701cb0ef41Sopenharmony_ci
2711cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceUnreachableOrIfException(Node* node) {
2721cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kUnreachable ||
2731cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kIfException);
2741cb0ef41Sopenharmony_ci  Reduction reduction = PropagateDeadControl(node);
2751cb0ef41Sopenharmony_ci  if (reduction.Changed()) return reduction;
2761cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node, 0);
2771cb0ef41Sopenharmony_ci  if (effect->opcode() == IrOpcode::kDead) {
2781cb0ef41Sopenharmony_ci    return Replace(effect);
2791cb0ef41Sopenharmony_ci  }
2801cb0ef41Sopenharmony_ci  if (effect->opcode() == IrOpcode::kUnreachable) {
2811cb0ef41Sopenharmony_ci    return Replace(effect);
2821cb0ef41Sopenharmony_ci  }
2831cb0ef41Sopenharmony_ci  return NoChange();
2841cb0ef41Sopenharmony_ci}
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceEffectNode(Node* node) {
2871cb0ef41Sopenharmony_ci  DCHECK_EQ(1, node->op()->EffectInputCount());
2881cb0ef41Sopenharmony_ci  Node* effect = NodeProperties::GetEffectInput(node, 0);
2891cb0ef41Sopenharmony_ci  if (effect->opcode() == IrOpcode::kDead) {
2901cb0ef41Sopenharmony_ci    return Replace(effect);
2911cb0ef41Sopenharmony_ci  }
2921cb0ef41Sopenharmony_ci  if (Node* input = FindDeadInput(node)) {
2931cb0ef41Sopenharmony_ci    if (effect->opcode() == IrOpcode::kUnreachable) {
2941cb0ef41Sopenharmony_ci      RelaxEffectsAndControls(node);
2951cb0ef41Sopenharmony_ci      return Replace(DeadValue(input));
2961cb0ef41Sopenharmony_ci    }
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci    Node* control = node->op()->ControlInputCount() == 1
2991cb0ef41Sopenharmony_ci                        ? NodeProperties::GetControlInput(node, 0)
3001cb0ef41Sopenharmony_ci                        : graph()->start();
3011cb0ef41Sopenharmony_ci    Node* unreachable =
3021cb0ef41Sopenharmony_ci        graph()->NewNode(common()->Unreachable(), effect, control);
3031cb0ef41Sopenharmony_ci    NodeProperties::SetType(unreachable, Type::None());
3041cb0ef41Sopenharmony_ci    ReplaceWithValue(node, DeadValue(input), node, control);
3051cb0ef41Sopenharmony_ci    return Replace(unreachable);
3061cb0ef41Sopenharmony_ci  }
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci  return NoChange();
3091cb0ef41Sopenharmony_ci}
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceDeoptimizeOrReturnOrTerminateOrTailCall(
3121cb0ef41Sopenharmony_ci    Node* node) {
3131cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kDeoptimize ||
3141cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kReturn ||
3151cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kTerminate ||
3161cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kTailCall);
3171cb0ef41Sopenharmony_ci  Reduction reduction = PropagateDeadControl(node);
3181cb0ef41Sopenharmony_ci  if (reduction.Changed()) return reduction;
3191cb0ef41Sopenharmony_ci  // Terminate nodes are not part of actual control flow, so they should never
3201cb0ef41Sopenharmony_ci  // be replaced with Throw.
3211cb0ef41Sopenharmony_ci  if (node->opcode() != IrOpcode::kTerminate &&
3221cb0ef41Sopenharmony_ci      FindDeadInput(node) != nullptr) {
3231cb0ef41Sopenharmony_ci    Node* effect = NodeProperties::GetEffectInput(node, 0);
3241cb0ef41Sopenharmony_ci    Node* control = NodeProperties::GetControlInput(node, 0);
3251cb0ef41Sopenharmony_ci    if (effect->opcode() != IrOpcode::kUnreachable) {
3261cb0ef41Sopenharmony_ci      effect = graph()->NewNode(common()->Unreachable(), effect, control);
3271cb0ef41Sopenharmony_ci      NodeProperties::SetType(effect, Type::None());
3281cb0ef41Sopenharmony_ci    }
3291cb0ef41Sopenharmony_ci    node->TrimInputCount(2);
3301cb0ef41Sopenharmony_ci    node->ReplaceInput(0, effect);
3311cb0ef41Sopenharmony_ci    node->ReplaceInput(1, control);
3321cb0ef41Sopenharmony_ci    NodeProperties::ChangeOp(node, common()->Throw());
3331cb0ef41Sopenharmony_ci    return Changed(node);
3341cb0ef41Sopenharmony_ci  }
3351cb0ef41Sopenharmony_ci  return NoChange();
3361cb0ef41Sopenharmony_ci}
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceLoopExit(Node* node) {
3391cb0ef41Sopenharmony_ci  Node* control = NodeProperties::GetControlInput(node, 0);
3401cb0ef41Sopenharmony_ci  Node* loop = NodeProperties::GetControlInput(node, 1);
3411cb0ef41Sopenharmony_ci  if (control->opcode() == IrOpcode::kDead ||
3421cb0ef41Sopenharmony_ci      loop->opcode() == IrOpcode::kDead) {
3431cb0ef41Sopenharmony_ci    return RemoveLoopExit(node);
3441cb0ef41Sopenharmony_ci  }
3451cb0ef41Sopenharmony_ci  return NoChange();
3461cb0ef41Sopenharmony_ci}
3471cb0ef41Sopenharmony_ci
3481cb0ef41Sopenharmony_ciReduction DeadCodeElimination::ReduceBranchOrSwitch(Node* node) {
3491cb0ef41Sopenharmony_ci  DCHECK(node->opcode() == IrOpcode::kBranch ||
3501cb0ef41Sopenharmony_ci         node->opcode() == IrOpcode::kSwitch);
3511cb0ef41Sopenharmony_ci  Reduction reduction = PropagateDeadControl(node);
3521cb0ef41Sopenharmony_ci  if (reduction.Changed()) return reduction;
3531cb0ef41Sopenharmony_ci  Node* condition = NodeProperties::GetValueInput(node, 0);
3541cb0ef41Sopenharmony_ci  if (condition->opcode() == IrOpcode::kDeadValue) {
3551cb0ef41Sopenharmony_ci    // Branches or switches on {DeadValue} must originate from unreachable code
3561cb0ef41Sopenharmony_ci    // and cannot matter. Due to schedule freedom between the effect and the
3571cb0ef41Sopenharmony_ci    // control chain, they might still appear in reachable code. Remove them by
3581cb0ef41Sopenharmony_ci    // always choosing the first projection.
3591cb0ef41Sopenharmony_ci    size_t const projection_cnt = node->op()->ControlOutputCount();
3601cb0ef41Sopenharmony_ci    Node** projections = zone_->NewArray<Node*>(projection_cnt);
3611cb0ef41Sopenharmony_ci    NodeProperties::CollectControlProjections(node, projections,
3621cb0ef41Sopenharmony_ci                                              projection_cnt);
3631cb0ef41Sopenharmony_ci    Replace(projections[0], NodeProperties::GetControlInput(node));
3641cb0ef41Sopenharmony_ci    return Replace(dead());
3651cb0ef41Sopenharmony_ci  }
3661cb0ef41Sopenharmony_ci  return NoChange();
3671cb0ef41Sopenharmony_ci}
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_civoid DeadCodeElimination::TrimMergeOrPhi(Node* node, int size) {
3701cb0ef41Sopenharmony_ci  const Operator* const op = common()->ResizeMergeOrPhi(node->op(), size);
3711cb0ef41Sopenharmony_ci  node->TrimInputCount(OperatorProperties::GetTotalInputCount(op));
3721cb0ef41Sopenharmony_ci  NodeProperties::ChangeOp(node, op);
3731cb0ef41Sopenharmony_ci}
3741cb0ef41Sopenharmony_ci
3751cb0ef41Sopenharmony_ciNode* DeadCodeElimination::DeadValue(Node* node, MachineRepresentation rep) {
3761cb0ef41Sopenharmony_ci  if (node->opcode() == IrOpcode::kDeadValue) {
3771cb0ef41Sopenharmony_ci    if (rep == DeadValueRepresentationOf(node->op())) return node;
3781cb0ef41Sopenharmony_ci    node = NodeProperties::GetValueInput(node, 0);
3791cb0ef41Sopenharmony_ci  }
3801cb0ef41Sopenharmony_ci  Node* dead_value = graph()->NewNode(common()->DeadValue(rep), node);
3811cb0ef41Sopenharmony_ci  NodeProperties::SetType(dead_value, Type::None());
3821cb0ef41Sopenharmony_ci  return dead_value;
3831cb0ef41Sopenharmony_ci}
3841cb0ef41Sopenharmony_ci
3851cb0ef41Sopenharmony_ci}  // namespace compiler
3861cb0ef41Sopenharmony_ci}  // namespace internal
3871cb0ef41Sopenharmony_ci}  // namespace v8
388