22      dead_(js_graph->Dead()),
 
 
   28  switch (node->opcode()) {
 
   31    case IrOpcode::kDeoptimizeIf:
 
   32    case IrOpcode::kDeoptimizeUnless:
 
   34    case IrOpcode::kMerge:
 
   38    case IrOpcode::kBranch:
 
   40    case IrOpcode::kIfFalse:
 
   42    case IrOpcode::kIfTrue:
 
   44    case IrOpcode::kTrapIf:
 
   45    case IrOpcode::kTrapUnless:
 
   47    case IrOpcode::kStart:
 
   50      if (node->op()->ControlOutputCount() > 0) {
 
 
   87  auto SemanticsOf = [phase = this->
phase_](
Node* branch) {
 
   89    if (branch->
opcode() == IrOpcode::kBranch) {
 
  101  if (merge->
opcode() != IrOpcode::kMerge) 
return;
 
  109  int input_count = inputs.
count();
 
  110  for (
int i = 0; 
i != input_count; ++
i) {
 
  111    Node* input = inputs[
i];
 
  115    if (!branch_condition.
IsSet()) 
return;
 
  116    if (SemanticsOf(branch_condition.
branch) != semantics) 
return;
 
  117    bool condition_value = branch_condition.
is_true;
 
  135                     input_count + 1, &phi_inputs.
at(0));
 
 
  164  DCHECK_EQ(phi->opcode(), IrOpcode::kPhi);
 
  167  if (!phi->OwnedBy(branch)) 
return false;
 
  168  if (phi->InputCount() != 3) 
return false;
 
  169  if (phi->InputAt(2) != merge) 
return false;
 
  170  if (merge->
UseCount() != 2) 
return false;
 
  173  Node* first_value = phi_inputs[0];
 
  174  Node* second_value = phi_inputs[1];
 
  175  if (first_value->
opcode() != IrOpcode::kInt32Constant ||
 
  176      second_value->
opcode() != IrOpcode::kInt32Constant) {
 
  180  Node* predecessor0 = merge_inputs[0];
 
  181  Node* predecessor1 = merge_inputs[1];
 
  183  Node** projections = zone()->AllocateArray<
Node*>(2);
 
  185  Node* branch_true = projections[0];
 
  186  Node* branch_false = projections[1];
 
  193  Node* predecessor_true = 
nullptr;
 
  194  Node* predecessor_false = 
nullptr;
 
  195  if (mfirst_value.
Is(1) && msecond_value.
Is(0)) {
 
  196    predecessor_true = predecessor0;
 
  197    predecessor_false = predecessor1;
 
  198  } 
else if (mfirst_value.
Is(0) && msecond_value.
Is(1)) {
 
  199    predecessor_true = predecessor1;
 
  200    predecessor_false = predecessor0;
 
  207    edge.UpdateTo(predecessor_true);
 
  210    edge.UpdateTo(predecessor_false);
 
  214  branch_false->
Kill();
 
 
  224  if (!IsReduced(control_input)) 
return NoChange();
 
  228  if (branch_condition.
IsSet()) {
 
  229    bool condition_value = branch_condition.
is_true;
 
  230    for (
Node* 
const use : node->
uses()) {
 
  231      switch (use->opcode()) {
 
  232        case IrOpcode::kIfTrue:
 
  233          Replace(use, condition_value ? control_input : 
dead());
 
  235        case IrOpcode::kIfFalse:
 
  236          Replace(use, condition_value ? 
dead() : control_input);
 
  242    return Replace(
dead());
 
  246  if (
condition->opcode() == IrOpcode::kPhi &&
 
  247      control_input->
opcode() == IrOpcode::kMerge) {
 
  249      return Replace(
dead());
 
  254  for (
Node* 
const use : node->
uses()) {
 
  257  return TakeStatesFromFirstControl(node);
 
 
  261  DCHECK(node->opcode() == IrOpcode::kTrapIf ||
 
  262         node->opcode() == IrOpcode::kTrapUnless);
 
  263  bool trapping_condition = node->opcode() == IrOpcode::kTrapIf;
 
  269  if (!IsReduced(control_input)) 
return NoChange();
 
  274  if (branch_condition.
IsSet()) {
 
  275    bool condition_value = branch_condition.
is_true;
 
  276    if (condition_value == trapping_condition) {
 
  282      return Changed(node);
 
  285      RelaxEffectsAndControls(node);
 
  288      return Replace(control);  
 
  292                            !trapping_condition, 
false);
 
 
  296  DCHECK(node->opcode() == IrOpcode::kDeoptimizeIf ||
 
  297         node->opcode() == IrOpcode::kDeoptimizeUnless);
 
  298  bool condition_is_true = node->opcode() == IrOpcode::kDeoptimizeUnless;
 
  307  if (!IsReduced(control)) {
 
  313  if (branch_condition.
IsSet()) {
 
  315    bool condition_value = branch_condition.
is_true;
 
  316    if (condition_is_true == condition_value) {
 
  319      ReplaceWithValue(node, 
dead(), effect, control);
 
  322                                 frame_state, effect, control);
 
  325    return Replace(
dead());
 
  328                            condition_is_true, 
false);
 
 
  338  if (!IsReduced(branch)) {
 
  343                            is_true_branch, 
true);
 
 
  350  return TakeStatesFromFirstControl(node);
 
 
  357  for (
Node* input : inputs) {
 
  358    if (!IsReduced(input)) {
 
  363  auto input_it = inputs.
begin();
 
  371  auto input_end = inputs.
end();
 
  372  for (; input_it != input_end; ++input_it) {
 
  378  return UpdateStates(node, conditions);
 
 
  386  DCHECK_EQ(1, node->op()->ControlInputCount());
 
  387  return TakeStatesFromFirstControl(node);
 
 
void emplace_back(Args &&... args)
Reduction UpdateStatesHelper(Node *node, ControlPathConditions prev_conditions, Node *current_condition, Node *current_branch, bool is_true_branch, bool in_new_block)
Isolate * isolate() const
Reduction Reduce(Node *node) final
void SimplifyBranchCondition(Node *branch)
bool TryEliminateBranchWithPhiCondition(Node *branch, Node *phi, Node *merge)
Reduction ReduceLoop(Node *node)
Reduction ReduceBranch(Node *node)
JSGraph * jsgraph() const
Reduction ReduceOtherControl(Node *node)
Reduction ReduceMerge(Node *node)
Reduction ReduceIf(Node *node, bool is_true_branch)
Reduction ReduceDeoptimizeConditional(Node *node)
ControlPathState< BranchCondition, kUniqueInstance > ControlPathConditions
BranchElimination(Editor *editor, JSGraph *js_graph, Zone *zone, Phase phase=kLATE)
Reduction ReduceTrapConditional(Node *node)
CommonOperatorBuilder * common() const
Reduction ReduceStart(Node *node)
~BranchElimination() final
void ResetToCommonAncestor(ControlPathState other)
NodeState LookupState(Node *node) const
DeoptimizeReason reason() const
const FeedbackSource & feedback() const
Isolate * isolate() const
CommonOperatorBuilder * common() const
static Node * GetEffectInput(Node *node, int index=0)
static void CollectControlProjections(Node *node, Node **proj, size_t count)
static Node * GetValueInput(Node *node, int index)
static void ReplaceValueInput(Node *node, Node *value, int index)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
const Operator * op() const
Node * InputAt(int index) const
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
const BranchParameters & BranchParametersOf(const Operator *const op)
template bool DefaultConstruct< bool >(Zone *zone)
DeoptimizeParameters const & DeoptimizeParametersOf(Operator const *const op)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
bool Is(const T &value) const