1bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
2bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// found in the LICENSE file.
4bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
5bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/effect-control-linearizer.h"
6bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
7bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/code-factory.h"
8bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/access-builder.h"
9c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/compiler/compiler-source-position-table.h"
10bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/js-graph.h"
11bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/linkage.h"
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler/node-matchers.h"
13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/node-properties.h"
14bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/node.h"
15bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/compiler/schedule.h"
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
17bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
18bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace v8 {
19bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace internal {
20bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace compiler {
21bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
22c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochEffectControlLinearizer::EffectControlLinearizer(
23c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    JSGraph* js_graph, Schedule* schedule, Zone* temp_zone,
24c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    SourcePositionTable* source_positions)
25c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    : js_graph_(js_graph),
26c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      schedule_(schedule),
27c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      temp_zone_(temp_zone),
2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      source_positions_(source_positions),
2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      graph_assembler_(js_graph, nullptr, nullptr, temp_zone) {}
30bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
31bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochGraph* EffectControlLinearizer::graph() const { return js_graph_->graph(); }
32bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochCommonOperatorBuilder* EffectControlLinearizer::common() const {
33bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return js_graph_->common();
34bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
35bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochSimplifiedOperatorBuilder* EffectControlLinearizer::simplified() const {
36bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return js_graph_->simplified();
37bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
38bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochMachineOperatorBuilder* EffectControlLinearizer::machine() const {
39bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return js_graph_->machine();
40bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
41bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
42bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace {
43bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
44bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochstruct BlockEffectControlData {
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* current_effect = nullptr;       // New effect.
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* current_control = nullptr;      // New control.
4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* current_frame_state = nullptr;  // New frame state.
48bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch};
49bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass BlockEffectControlMap {
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch public:
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  explicit BlockEffectControlMap(Zone* temp_zone) : map_(temp_zone) {}
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) {
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return map_[std::make_pair(from->rpo_number(), to->rpo_number())];
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
58f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  const BlockEffectControlData& For(BasicBlock* from, BasicBlock* to) const {
59f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return map_.at(std::make_pair(from->rpo_number(), to->rpo_number()));
60f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
61f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
62f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch private:
63f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef std::pair<int32_t, int32_t> Key;
64f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  typedef ZoneMap<Key, BlockEffectControlData> Map;
65f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
66f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Map map_;
67f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch};
68f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
69bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch// Effect phis that need to be updated after the first pass.
70bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochstruct PendingEffectPhi {
71bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* effect_phi;
72bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  BasicBlock* block;
73bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
74bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  PendingEffectPhi(Node* effect_phi, BasicBlock* block)
75bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      : effect_phi(effect_phi), block(block) {}
76bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch};
77bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
78bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid UpdateEffectPhi(Node* node, BasicBlock* block,
79f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                     BlockEffectControlMap* block_effects) {
80bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Update all inputs to an effect phi with the effects from the given
81bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // block->effect map.
82bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK_EQ(IrOpcode::kEffectPhi, node->opcode());
83c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK_EQ(static_cast<size_t>(node->op()->EffectInputCount()),
84c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            block->PredecessorCount());
85bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (int i = 0; i < node->op()->EffectInputCount(); i++) {
86bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* input = node->InputAt(i);
87bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const BlockEffectControlData& block_effect =
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        block_effects->For(predecessor, block);
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (input != block_effect.current_effect) {
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      node->ReplaceInput(i, block_effect.current_effect);
92bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
93bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
94bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
95bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
96bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid UpdateBlockControl(BasicBlock* block,
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                        BlockEffectControlMap* block_effects) {
98bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* control = block->NodeAt(0);
99bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(NodeProperties::IsControl(control));
100bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
101bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Do not rewire the end node.
102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (control->opcode() == IrOpcode::kEnd) return;
103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Update all inputs to the given control node with the correct control.
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK(control->opcode() == IrOpcode::kMerge ||
106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch         static_cast<size_t>(control->op()->ControlInputCount()) ==
107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch             block->PredecessorCount());
108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (static_cast<size_t>(control->op()->ControlInputCount()) !=
109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      block->PredecessorCount()) {
110f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return;  // We already re-wired the control inputs of this node.
111f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
112bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (int i = 0; i < control->op()->ControlInputCount(); i++) {
113bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* input = NodeProperties::GetControlInput(control, i);
114bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    BasicBlock* predecessor = block->PredecessorAt(static_cast<size_t>(i));
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    const BlockEffectControlData& block_effect =
116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        block_effects->For(predecessor, block);
117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (input != block_effect.current_control) {
118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::ReplaceControlInput(control, block_effect.current_control,
119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                          i);
120bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochbool HasIncomingBackEdges(BasicBlock* block) {
125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (BasicBlock* pred : block->predecessors()) {
126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (pred->rpo_number() >= block->rpo_number()) {
127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return true;
128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return false;
131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid RemoveRegionNode(Node* node) {
134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  DCHECK(IrOpcode::kFinishRegion == node->opcode() ||
135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch         IrOpcode::kBeginRegion == node->opcode());
136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Update the value/context uses to the value input of the finish node and
137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // the effect uses to the effect input.
138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (Edge edge : node->use_edges()) {
139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(!edge.from()->IsDead());
140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (NodeProperties::IsEffectEdge(edge)) {
141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      edge.UpdateTo(NodeProperties::GetEffectInput(node));
142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!NodeProperties::IsControlEdge(edge));
144bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!NodeProperties::IsFrameStateEdge(edge));
145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      edge.UpdateTo(node->InputAt(0));
146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
147bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
148bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  node->Kill();
149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid TryCloneBranch(Node* node, BasicBlock* block, Graph* graph,
152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    CommonOperatorBuilder* common,
153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                    BlockEffectControlMap* block_effects,
154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                    SourcePositionTable* source_positions) {
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_EQ(IrOpcode::kBranch, node->opcode());
156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // This optimization is a special case of (super)block cloning. It takes an
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // input graph as shown below and clones the Branch node for every predecessor
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // to the Merge, essentially removing the Merge completely. This avoids
160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // materializing the bit for the Phi and may offer potential for further
161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // branch folding optimizations (i.e. because one or more inputs to the Phi is
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // a constant). Note that there may be more Phi nodes hanging off the Merge,
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // but we can only a certain subset of them currently (actually only Phi and
164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // EffectPhi nodes whose uses have either the IfTrue or IfFalse as control
165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // input).
166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   Control1 ... ControlN
168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      ^            ^
169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      |            |   Cond1 ... CondN
170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      +----+  +----+     ^         ^
171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //           |  |          |         |
172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //           |  |     +----+         |
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //          Merge<--+ | +------------+
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //            ^      \|/
175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //            |      Phi
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //            |       |
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //          Branch----+
178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //            ^
179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //            |
180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      +-----+-----+
181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      |           |
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //    IfTrue     IfFalse
183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      ^           ^
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      |           |
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // The resulting graph (modulo the Phi and EffectPhi nodes) looks like this:
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Control1 Cond1 ... ControlN CondN
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //    ^      ^           ^      ^
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //    \      /           \      /
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     Branch     ...     Branch
192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       ^                  ^
193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       |                  |
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   +---+---+          +---+----+
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   |       |          |        |
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // IfTrue IfFalse ... IfTrue  IfFalse
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   ^       ^          ^        ^
198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   |       |          |        |
199f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   +--+ +-------------+        |
200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      | |  +--------------+ +--+
201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //      | |                 | |
202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     Merge               Merge
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       ^                   ^
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       |                   |
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  SourcePositionTable::Scope scope(source_positions,
207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   source_positions->GetSourcePosition(node));
208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* branch = node;
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* cond = NodeProperties::GetValueInput(branch, 0);
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!cond->OwnedBy(branch) || cond->opcode() != IrOpcode::kPhi) return;
211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* merge = NodeProperties::GetControlInput(branch);
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (merge->opcode() != IrOpcode::kMerge ||
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      NodeProperties::GetControlInput(cond) != merge) {
214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return;
215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Grab the IfTrue/IfFalse projections of the Branch.
217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BranchMatcher matcher(branch);
218f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check/collect other Phi/EffectPhi nodes hanging off the Merge.
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NodeVector phis(graph->zone());
220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (Node* const use : merge->uses()) {
221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (use == branch || use == cond) continue;
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // We cannot currently deal with non-Phi/EffectPhi nodes hanging off the
223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Merge. Ideally, we would just clone the nodes (and everything that
224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // depends on it to some distant join point), but that requires knowledge
225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // about dominance/post-dominance.
226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!NodeProperties::IsPhi(use)) return;
227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (Edge edge : use->use_edges()) {
228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Right now we can only handle Phi/EffectPhi nodes whose uses are
229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // directly control-dependend on either the IfTrue or the IfFalse
230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // successor, because we know exactly how to update those uses.
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (edge.from()->op()->ControlInputCount() != 1) return;
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* control = NodeProperties::GetControlInput(edge.from());
233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (NodeProperties::IsPhi(edge.from())) {
234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        control = NodeProperties::GetControlInput(control, edge.index());
235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (control != matcher.IfTrue() && control != matcher.IfFalse()) return;
237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    phis.push_back(use);
239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BranchHint const hint = BranchHintOf(branch->op());
241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int const input_count = merge->op()->ControlInputCount();
242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_LE(1, input_count);
243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node** const inputs = graph->zone()->NewArray<Node*>(2 * input_count);
244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node** const merge_true_inputs = &inputs[0];
245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node** const merge_false_inputs = &inputs[input_count];
246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (int index = 0; index < input_count; ++index) {
247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* cond1 = NodeProperties::GetValueInput(cond, index);
248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* control1 = NodeProperties::GetControlInput(merge, index);
249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* branch1 = graph->NewNode(common->Branch(hint), cond1, control1);
250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    merge_true_inputs[index] = graph->NewNode(common->IfTrue(), branch1);
251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    merge_false_inputs[index] = graph->NewNode(common->IfFalse(), branch1);
252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* const merge_true = matcher.IfTrue();
254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* const merge_false = matcher.IfFalse();
255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  merge_true->TrimInputCount(0);
256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  merge_false->TrimInputCount(0);
257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (int i = 0; i < input_count; ++i) {
258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    merge_true->AppendInput(graph->zone(), merge_true_inputs[i]);
259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    merge_false->AppendInput(graph->zone(), merge_false_inputs[i]);
260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK_EQ(2u, block->SuccessorCount());
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NodeProperties::ChangeOp(matcher.IfTrue(), common->Merge(input_count));
263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  NodeProperties::ChangeOp(matcher.IfFalse(), common->Merge(input_count));
264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int const true_index =
265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      block->SuccessorAt(0)->NodeAt(0) == matcher.IfTrue() ? 0 : 1;
266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BlockEffectControlData* true_block_data =
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      &block_effects->For(block, block->SuccessorAt(true_index));
268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BlockEffectControlData* false_block_data =
269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      &block_effects->For(block, block->SuccessorAt(true_index ^ 1));
270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  for (Node* const phi : phis) {
271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (int index = 0; index < input_count; ++index) {
272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      inputs[index] = phi->InputAt(index);
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[input_count] = merge_true;
275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* phi_true = graph->NewNode(phi->op(), input_count + 1, inputs);
276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    inputs[input_count] = merge_false;
277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* phi_false = graph->NewNode(phi->op(), input_count + 1, inputs);
278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (phi->UseCount() == 0) {
279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_EQ(phi->opcode(), IrOpcode::kEffectPhi);
280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      for (Edge edge : phi->use_edges()) {
282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Node* control = NodeProperties::GetControlInput(edge.from());
283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (NodeProperties::IsPhi(edge.from())) {
284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          control = NodeProperties::GetControlInput(control, edge.index());
285f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        }
286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        DCHECK(control == matcher.IfTrue() || control == matcher.IfFalse());
287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        edge.UpdateTo((control == matcher.IfTrue()) ? phi_true : phi_false);
288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
289f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (phi->opcode() == IrOpcode::kEffectPhi) {
291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      true_block_data->current_effect = phi_true;
292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      false_block_data->current_effect = phi_false;
293f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    phi->Kill();
295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Fix up IfTrue and IfFalse and kill all dead nodes.
297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (branch == block->control_input()) {
298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    true_block_data->current_control = merge_true;
299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    false_block_data->current_control = merge_false;
300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  branch->Kill();
302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  cond->Kill();
303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  merge->Kill();
304f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
305bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace
306bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
307bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid EffectControlLinearizer::Run() {
308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BlockEffectControlMap block_effects(temp_zone());
309bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ZoneVector<PendingEffectPhi> pending_effect_phis(temp_zone());
310bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  ZoneVector<BasicBlock*> pending_block_controls(temp_zone());
311bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  NodeVector inputs_buffer(temp_zone());
312bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
313bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (BasicBlock* block : *(schedule()->rpo_order())) {
314bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    size_t instr = 0;
315bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
316bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The control node should be the first.
317bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* control = block->NodeAt(instr);
318bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(NodeProperties::IsControl(control));
319bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Update the control inputs.
320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (HasIncomingBackEdges(block)) {
321bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // If there are back edges, we need to update later because we have not
322bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // computed the control yet. This should only happen for loops.
323bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK_EQ(IrOpcode::kLoop, control->opcode());
324bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      pending_block_controls.push_back(block);
325bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    } else {
326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // If there are no back edges, we can update now.
327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      UpdateBlockControl(block, &block_effects);
328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
329bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    instr++;
330bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
331bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Iterate over the phis and update the effect phis.
332bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* effect = nullptr;
333bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* terminate = nullptr;
334bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    for (; instr < block->NodeCount(); instr++) {
335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Node* node = block->NodeAt(instr);
336bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // Only go through the phis and effect phis.
337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (node->opcode() == IrOpcode::kEffectPhi) {
338bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // There should be at most one effect phi in a block.
339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        DCHECK_NULL(effect);
340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // IfException blocks should not have effect phis.
341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        DCHECK_NE(IrOpcode::kIfException, control->opcode());
342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        effect = node;
343bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
344bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // Make sure we update the inputs to the incoming blocks' effects.
345bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        if (HasIncomingBackEdges(block)) {
346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // In case of loops, we do not update the effect phi immediately
347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // because the back predecessor has not been handled yet. We just
348bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // record the effect phi for later processing.
349bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          pending_effect_phis.push_back(PendingEffectPhi(node, block));
350bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else {
351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          UpdateEffectPhi(node, block, &block_effects);
352bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        }
353bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else if (node->opcode() == IrOpcode::kPhi) {
354bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // Just skip phis.
355bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else if (node->opcode() == IrOpcode::kTerminate) {
356bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        DCHECK(terminate == nullptr);
357bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        terminate = node;
358bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
360bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
361bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
362bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (effect == nullptr) {
364bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // There was no effect phi.
365bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK(!HasIncomingBackEdges(block));
366bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (block == schedule()->start()) {
367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // Start block => effect is start.
368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        DCHECK_EQ(graph()->start(), control);
369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        effect = graph()->start();
370bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else if (control->opcode() == IrOpcode::kEnd) {
371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        // End block is just a dummy, no effect needed.
372bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        DCHECK_EQ(BasicBlock::kNone, block->control());
373bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        DCHECK_EQ(1u, block->size());
374bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        effect = nullptr;
375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // If all the predecessors have the same effect, we can use it as our
377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        // current effect.
378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        effect =
379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            block_effects.For(block->PredecessorAt(0), block).current_effect;
380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        for (size_t i = 1; i < block->PredecessorCount(); ++i) {
381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          if (block_effects.For(block->PredecessorAt(i), block)
382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                  .current_effect != effect) {
383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            effect = nullptr;
384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            break;
385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          }
386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        }
387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        if (effect == nullptr) {
388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          DCHECK_NE(IrOpcode::kIfException, control->opcode());
389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // The input blocks do not have the same effect. We have
390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // to create an effect phi node.
391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          inputs_buffer.clear();
392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          inputs_buffer.resize(block->PredecessorCount(), jsgraph()->Dead());
393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          inputs_buffer.push_back(control);
394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          effect = graph()->NewNode(
395bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              common()->EffectPhi(static_cast<int>(block->PredecessorCount())),
396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch              static_cast<int>(inputs_buffer.size()), &(inputs_buffer.front()));
397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          // For loops, we update the effect phi node later to break cycles.
398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          if (control->opcode() == IrOpcode::kLoop) {
399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            pending_effect_phis.push_back(PendingEffectPhi(effect, block));
400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          } else {
401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            UpdateEffectPhi(effect, block, &block_effects);
402f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        } else if (control->opcode() == IrOpcode::kIfException) {
404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // The IfException is connected into the effect chain, so we need
405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // to update the effect here.
406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          NodeProperties::ReplaceEffectInput(control, effect);
407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          effect = control;
408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        }
409bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Fixup the Terminate node.
413bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (terminate != nullptr) {
414bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      NodeProperties::ReplaceEffectInput(terminate, effect);
415bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
416bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
41713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // The frame state at block entry is determined by the frame states leaving
41813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // all predecessors. In case there is no frame state dominating this block,
41913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // we can rely on a checkpoint being present before the next deoptimization.
42013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
42113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // once deoptimizing nodes roam freely through the schedule.
42213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Node* frame_state = nullptr;
42313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (block != schedule()->start()) {
42413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // If all the predecessors have the same effect, we can use it
42513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      // as our current effect.
426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      frame_state =
427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          block_effects.For(block->PredecessorAt(0), block).current_frame_state;
42813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      for (size_t i = 1; i < block->PredecessorCount(); i++) {
429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (block_effects.For(block->PredecessorAt(i), block)
430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                .current_frame_state != frame_state) {
43113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          frame_state = nullptr;
43213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch          break;
43313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        }
43413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
43513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
43613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
437bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Process the ordinary instructions.
438bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    for (; instr < block->NodeCount(); instr++) {
439bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      Node* node = block->NodeAt(instr);
44013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      ProcessNode(node, &frame_state, &effect, &control);
441bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
442bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
443bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    switch (block->control()) {
444bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kGoto:
445bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kNone:
446bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
447bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
448bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kCall:
449bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kTailCall:
450bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kSwitch:
451bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kReturn:
452bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kDeoptimize:
453bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      case BasicBlock::kThrow:
45413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        ProcessNode(block->control_input(), &frame_state, &effect, &control);
455bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        break;
456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      case BasicBlock::kBranch:
458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        ProcessNode(block->control_input(), &frame_state, &effect, &control);
459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        TryCloneBranch(block->control_input(), block, graph(), common(),
460c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                       &block_effects, source_positions_);
461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        break;
462bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
463bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Store the effect, control and frame state for later use.
465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (BasicBlock* successor : block->successors()) {
466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      BlockEffectControlData* data = &block_effects.For(block, successor);
467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (data->current_effect == nullptr) {
468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        data->current_effect = effect;
469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (data->current_control == nullptr) {
471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        data->current_control = control;
472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      data->current_frame_state = frame_state;
474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
475bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
476bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
477bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Update the incoming edges of the effect phis that could not be processed
478bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // during the first pass (because they could have incoming back edges).
479bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
480bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
481bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    &block_effects);
482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
483bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (BasicBlock* pending_block_control : pending_block_controls) {
484bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UpdateBlockControl(pending_block_control, &block_effects);
485bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
486bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
487bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
488bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochnamespace {
489bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
490bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdochvoid TryScheduleCallIfSuccess(Node* node, Node** control) {
491bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Schedule the call's IfSuccess node if there is no exception use.
492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (!NodeProperties::IsExceptionalCall(node)) {
493bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    for (Edge edge : node->use_edges()) {
494bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (NodeProperties::IsControlEdge(edge) &&
495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          edge.from()->opcode() == IrOpcode::kIfSuccess) {
496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        *control = edge.from();
497bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
498bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
499bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
500bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
501bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
502bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace
503bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
50413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochvoid EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
50513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                          Node** effect, Node** control) {
506c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  SourcePositionTable::Scope scope(source_positions_,
507c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   source_positions_->GetSourcePosition(node));
508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
509bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // If the node needs to be wired into the effect/control chain, do this
51013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // here. Pass current frame state for lowering to eager deoptimization.
51113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (TryWireInStateEffect(node, *frame_state, effect, control)) {
512bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return;
513bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
514bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
51513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // If the node has a visible effect, then there must be a checkpoint in the
51613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // effect chain before we are allowed to place another eager deoptimization
51713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // point. We zap the frame state to ensure this invariant is maintained.
51813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (region_observability_ == RegionObservability::kObservable &&
51913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      !node->op()->HasProperty(Operator::kNoWrite)) {
52013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    *frame_state = nullptr;
52113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
52213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
523bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Remove the end markers of 'atomic' allocation region because the
524bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // region should be wired-in now.
52513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (node->opcode() == IrOpcode::kFinishRegion) {
52613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Reset the current region observability.
52713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    region_observability_ = RegionObservability::kObservable;
52813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Update the value uses to the value input of the finish node and
52913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // the effect uses to the effect input.
53013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return RemoveRegionNode(node);
53113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
53213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (node->opcode() == IrOpcode::kBeginRegion) {
53313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Determine the observability for this region and use that for all
53413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // nodes inside the region (i.e. ignore the absence of kNoWrite on
53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // StoreField and other operators).
53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_NE(RegionObservability::kNotObservable, region_observability_);
53713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    region_observability_ = RegionObservabilityOf(node->op());
538bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Update the value uses to the value input of the finish node and
539bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // the effect uses to the effect input.
540bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return RemoveRegionNode(node);
541bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
542bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
54313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Special treatment for checkpoint nodes.
54413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (node->opcode() == IrOpcode::kCheckpoint) {
545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // Unlink the check point; effect uses will be updated to the incoming
54613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // effect that is passed. The frame state is preserved for lowering.
54713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    DCHECK_EQ(RegionObservability::kObservable, region_observability_);
548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    *frame_state = NodeProperties::GetFrameStateInput(node);
549bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return;
550bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
551bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
552bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (node->opcode() == IrOpcode::kIfSuccess) {
553bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // We always schedule IfSuccess with its call, so skip it here.
554bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
555bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // The IfSuccess node should not belong to an exceptional call node
556bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // because such IfSuccess nodes should only start a basic block (and
557bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // basic block start nodes are not handled in the ProcessNode method).
558bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(!NodeProperties::IsExceptionalCall(node->InputAt(0)));
559bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return;
560bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
561bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
562bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // If the node takes an effect, replace with the current one.
563bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (node->op()->EffectInputCount() > 0) {
564bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK_EQ(1, node->op()->EffectInputCount());
565bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Node* input_effect = NodeProperties::GetEffectInput(node);
566bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
567bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (input_effect != *effect) {
568bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      NodeProperties::ReplaceEffectInput(node, *effect);
569bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
570bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
571bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // If the node produces an effect, update our current effect. (However,
572bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // ignore new effect chains started with ValueEffect.)
573bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (node->op()->EffectOutputCount() > 0) {
574bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      DCHECK_EQ(1, node->op()->EffectOutputCount());
575bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      *effect = node;
576bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
577bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  } else {
578bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // New effect chain is only started with a Start or ValueEffect node.
579bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(node->op()->EffectOutputCount() == 0 ||
580bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           node->opcode() == IrOpcode::kStart);
581bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
582bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
583bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Rewire control inputs.
584bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  for (int i = 0; i < node->op()->ControlInputCount(); i++) {
585bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    NodeProperties::ReplaceControlInput(node, *control, i);
586bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
587bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Update the current control and wire IfSuccess right after calls.
588bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (node->op()->ControlOutputCount() > 0) {
589bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    *control = node;
590bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    if (node->opcode() == IrOpcode::kCall) {
591bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // Schedule the call's IfSuccess node (if there is no exception use).
592bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      TryScheduleCallIfSuccess(node, control);
593bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
594bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
595bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
596bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
59713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochbool EffectControlLinearizer::TryWireInStateEffect(Node* node,
59813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                   Node* frame_state,
59913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                                   Node** effect,
600bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                                   Node** control) {
60162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  gasm()->Reset(*effect, *control);
60262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* result = nullptr;
603bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  switch (node->opcode()) {
604bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeBitToTagged:
60562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeBitToTagged(node);
606bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
607bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeInt31ToTaggedSigned:
60862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeInt31ToTaggedSigned(node);
609bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeInt32ToTagged:
61162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeInt32ToTagged(node);
612bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
613bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeUint32ToTagged:
61462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeUint32ToTagged(node);
615bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
616bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeFloat64ToTagged:
61762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeFloat64ToTagged(node);
618bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case IrOpcode::kChangeFloat64ToTaggedPointer:
62062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeFloat64ToTaggedPointer(node);
621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      break;
622bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeTaggedSignedToInt32:
62362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeTaggedSignedToInt32(node);
624bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
625bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeTaggedToBit:
62662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeTaggedToBit(node);
627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
628bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeTaggedToInt32:
62962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeTaggedToInt32(node);
630bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeTaggedToUint32:
63262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeTaggedToUint32(node);
633bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kChangeTaggedToFloat64:
63562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeTaggedToFloat64(node);
63662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
63762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kChangeTaggedToTaggedSigned:
63862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerChangeTaggedToTaggedSigned(node);
639bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
640f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kTruncateTaggedToBit:
64162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerTruncateTaggedToBit(node);
642f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
64313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kTruncateTaggedToFloat64:
64462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerTruncateTaggedToFloat64(node);
64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
64613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckBounds:
64762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckBounds(node, frame_state);
64813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
649f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckMaps:
65062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckMaps(node, frame_state);
651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckNumber:
65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckNumber(node, frame_state);
65462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
65562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kCheckReceiver:
65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckReceiver(node, frame_state);
657f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
658f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckString:
65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckString(node, frame_state);
66062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kCheckInternalizedString:
66262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckInternalizedString(node, frame_state);
663f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
664f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckIf:
66562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckIf(node, frame_state);
666f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
66713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckedInt32Add:
66862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedInt32Add(node, frame_state);
66913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
67013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckedInt32Sub:
67162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedInt32Sub(node, frame_state);
67213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedInt32Div:
67462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedInt32Div(node, frame_state);
675f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
676f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedInt32Mod:
67762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedInt32Mod(node, frame_state);
678f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedUint32Div:
68062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedUint32Div(node, frame_state);
681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedUint32Mod:
68362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedUint32Mod(node, frame_state);
684f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
685f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedInt32Mul:
68662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedInt32Mul(node, frame_state);
687f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
688f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kCheckedInt32ToTaggedSigned:
68962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedInt32ToTaggedSigned(node, frame_state);
690f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
69113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckedUint32ToInt32:
69262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedUint32ToInt32(node, frame_state);
69313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
694f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kCheckedUint32ToTaggedSigned:
69562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedUint32ToTaggedSigned(node, frame_state);
696f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
69713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckedFloat64ToInt32:
69862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedFloat64ToInt32(node, frame_state);
69913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedTaggedSignedToInt32:
70162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedTaggedSignedToInt32(node, frame_state);
702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
70313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckedTaggedToInt32:
70462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedTaggedToInt32(node, frame_state);
70513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
70613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckedTaggedToFloat64:
70762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedTaggedToFloat64(node, frame_state);
70813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
709f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kCheckedTaggedToTaggedSigned:
71062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedTaggedToTaggedSigned(node, frame_state);
711f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
712c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case IrOpcode::kCheckedTaggedToTaggedPointer:
71362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedTaggedToTaggedPointer(node, frame_state);
714c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      break;
715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kTruncateTaggedToWord32:
71662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerTruncateTaggedToWord32(node);
717bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kCheckedTruncateTaggedToWord32:
71962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckedTruncateTaggedToWord32(node, frame_state);
72062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
72162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kObjectIsDetectableCallable:
72262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsDetectableCallable(node);
723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
72462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kObjectIsNonCallable:
72562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsNonCallable(node);
726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kObjectIsNumber:
72862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsNumber(node);
729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kObjectIsReceiver:
73162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsReceiver(node);
732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
733bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kObjectIsSmi:
73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsSmi(node);
735bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kObjectIsString:
73762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsString(node);
738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
739bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    case IrOpcode::kObjectIsUndetectable:
74062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerObjectIsUndetectable(node);
74162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
74262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kNewRestParameterElements:
74362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerNewRestParameterElements(node);
74462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
74562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kNewUnmappedArgumentsElements:
74662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerNewUnmappedArgumentsElements(node);
747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      break;
748f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kArrayBufferWasNeutered:
74962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerArrayBufferWasNeutered(node);
750f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
75113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kStringFromCharCode:
75262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringFromCharCode(node);
75313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
754f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kStringFromCodePoint:
75562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringFromCodePoint(node);
75662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
75762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kStringIndexOf:
75862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringIndexOf(node);
75962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
76062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case IrOpcode::kStringCharAt:
76162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringCharAt(node);
762f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
763f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kStringCharCodeAt:
76462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringCharCodeAt(node);
765f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
766f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kStringEqual:
76762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringEqual(node);
768f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
769f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kStringLessThan:
77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringLessThan(node);
771f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
772f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    case IrOpcode::kStringLessThanOrEqual:
77362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerStringLessThanOrEqual(node);
774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      break;
77513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckFloat64Hole:
77662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckFloat64Hole(node, frame_state);
77713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
77813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kCheckTaggedHole:
77962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerCheckTaggedHole(node, frame_state);
78013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
781f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kConvertTaggedHoleToUndefined:
78262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerConvertTaggedHoleToUndefined(node);
783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
78413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kPlainPrimitiveToNumber:
78562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerPlainPrimitiveToNumber(node);
78613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
78713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kPlainPrimitiveToWord32:
78862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerPlainPrimitiveToWord32(node);
78913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
79013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    case IrOpcode::kPlainPrimitiveToFloat64:
79162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerPlainPrimitiveToFloat64(node);
79213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      break;
793f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kEnsureWritableFastElements:
79462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerEnsureWritableFastElements(node);
795f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
796f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kMaybeGrowFastElements:
79762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerMaybeGrowFastElements(node, frame_state);
798f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
799f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kTransitionElementsKind:
80062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      LowerTransitionElementsKind(node);
801f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
802f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kLoadTypedElement:
80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      result = LowerLoadTypedElement(node);
804f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
805f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kStoreTypedElement:
80662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      LowerStoreTypedElement(node);
807f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kFloat64RoundUp:
80962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!LowerFloat64RoundUp(node).To(&result)) {
81062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return false;
81162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
813f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kFloat64RoundDown:
81462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!LowerFloat64RoundDown(node).To(&result)) {
81562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return false;
81662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
817f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
818f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case IrOpcode::kFloat64RoundTruncate:
81962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!LowerFloat64RoundTruncate(node).To(&result)) {
82062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return false;
82162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
822f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
823c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    case IrOpcode::kFloat64RoundTiesEven:
82462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!LowerFloat64RoundTiesEven(node).To(&result)) {
82562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return false;
82662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      break;
828bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    default:
829bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return false;
830bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
83162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  *effect = gasm()->ExtractCurrentEffect();
83262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  *control = gasm()->ExtractCurrentControl();
83362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  NodeProperties::ReplaceUses(node, result, *effect, *control);
834bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return true;
835bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
836bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
83762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#define __ gasm()->
83862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
83962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeFloat64ToTagged(Node* node) {
840bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
84162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return AllocateHeapNumberWithValue(value);
842bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
843bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
84462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeFloat64ToTaggedPointer(Node* node) {
845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* value = node->InputAt(0);
84662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return AllocateHeapNumberWithValue(value);
847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
84962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeBitToTagged(Node* node) {
850bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
851bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
85262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_true = __ MakeLabel<1>();
85362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
854bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
85562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(value, &if_true);
85662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ FalseConstant());
857bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
85862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_true);
85962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ TrueConstant());
860bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
86162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
86262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
863bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
864bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
86562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeInt31ToTaggedSigned(Node* node) {
866bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
86762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeInt32ToSmi(value);
868bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
869bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
87062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeInt32ToTagged(Node* node) {
871bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
872bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
873bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (machine()->Is64()) {
87462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return ChangeInt32ToSmi(value);
875bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
876bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
87762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_overflow = __ MakeDeferredLabel<1>();
87862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
879bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
88062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* add = __ Int32AddWithOverflow(value, value);
88162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* ovf = __ Projection(1, add);
88262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(ovf, &if_overflow);
88362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Projection(0, add));
884bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
88562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_overflow);
88662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = AllocateHeapNumberWithValue(__ ChangeInt32ToFloat64(value));
88762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, number);
888bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
88962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
89062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
891bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
892bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
89362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeUint32ToTagged(Node* node) {
894bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
895bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
89662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_in_smi_range = __ MakeDeferredLabel<1>();
89762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
898bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
89962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
90062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_in_smi_range);
90162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeUint32ToSmi(value));
902bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
90362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_in_smi_range);
90462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = AllocateHeapNumberWithValue(__ ChangeUint32ToFloat64(value));
905bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
90662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, number);
90762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
908bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
90962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
910bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
911bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
91262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedSignedToInt32(Node* node) {
913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
91462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeSmiToInt32(value);
915bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
916bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
91762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToBit(Node* node) {
918bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
91962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ WordEqual(value, __ TrueConstant());
920bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
921bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
92262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerTruncateTaggedToBit(Node* node) {
923f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value = node->InputAt(0);
924f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
92562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeDeferredLabel<1>();
92662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_heapnumber = __ MakeDeferredLabel<1>();
92762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<6>(MachineRepresentation::kBit);
92862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
92962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* zero = __ Int32Constant(0);
93062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* fzero = __ Float64Constant(0.0);
93162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
93262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if {value} is false.
93362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(__ WordEqual(value, __ FalseConstant()), &done, zero);
934f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
935f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {value} is a Smi.
936f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* check_smi = ObjectIsSmi(value);
93762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check_smi, &if_smi);
938f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
93962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if {value} is the empty string.
94062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(__ WordEqual(value, __ EmptyStringConstant()), &done, zero);
94162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
94262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Load the map of {value}.
94362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
94462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
94562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check if the {value} is undetectable and immediately return false.
94662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map_bitfield =
94762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapBitField(), value_map);
94862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(
94962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Word32Equal(__ Word32And(value_map_bitfield,
95062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  __ Int32Constant(1 << Map::kIsUndetectable)),
95162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     zero),
95262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      &done, zero);
953f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
954f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {value} is a HeapNumber.
95562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(__ WordEqual(value_map, __ HeapNumberMapConstant()),
95662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            &if_heapnumber);
95762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
95862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // All other values that reach here are true.
95962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(1));
96062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
96162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_heapnumber);
962f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
96362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // For HeapNumber {value}, just check that its value is not 0.0, -0.0 or
96462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // NaN.
96562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value_value =
96662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
96762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, __ Float64LessThan(fzero, __ Float64Abs(value_value)));
968f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
969f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
97062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
97262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // If {value} is a Smi, then we only need to check that it's not zero.
97362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done,
97462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            __ Word32Equal(__ WordEqual(value, __ IntPtrConstant(0)), zero));
975f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
97762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
97862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
98162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToInt32(Node* node) {
982bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
983bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
98462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
98562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
986bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
98762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
98862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
98962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(value));
990bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
99162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
99262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
99362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
99462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vfalse = __ ChangeFloat64ToInt32(vfalse);
99562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
996bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
99762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
99862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
999bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1000bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
100162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToUint32(Node* node) {
1002bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1003bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
100462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
100562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1006bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
100762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
100862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
100962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(value));
1010bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
101162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
101262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
101362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
101462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vfalse = __ ChangeFloat64ToUint32(vfalse);
101562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
1016bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
101762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
101862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1019bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1020bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
102162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToFloat64(Node* node) {
102262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return LowerTruncateTaggedToFloat64(node);
102313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
102413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
102562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerChangeTaggedToTaggedSigned(Node* node) {
1026bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1027bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
102862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
102962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
103062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1031bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* check = ObjectIsSmi(value);
103262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
103362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, value);
1034bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
103562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
103662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
103762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
103862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vfalse = __ ChangeFloat64ToInt32(vfalse);
103962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vfalse = ChangeInt32ToSmi(vfalse);
104062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
1041bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
104262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
104362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
104462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
104562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
104662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node) {
104762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
1048bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
104962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
105062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64);
1051bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
105262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
105362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
105462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vtrue = ChangeSmiToInt32(value);
105562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vtrue = __ ChangeInt32ToFloat64(vtrue);
105662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vtrue);
105762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
105862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
105962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
106062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
106162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
106262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
106362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
106462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1065bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1066bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
106762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckBounds(Node* node, Node* frame_state) {
106813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* index = node->InputAt(0);
106913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* limit = node->InputAt(1);
107013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
107162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Uint32LessThan(index, limit);
107262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check, frame_state);
107362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return index;
107413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
107513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
107662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckMaps(Node* node, Node* frame_state) {
107762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CheckMapsParameters const& p = CheckMapsParametersOf(node->op());
1078f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
1079f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
108062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ZoneHandleSet<Map> const& maps = p.maps();
108162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  size_t const map_count = maps.size();
1082f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
108362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (p.flags() & CheckMapsFlag::kTryMigrateInstance) {
108462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto done =
108562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count * 2);
108662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto migrate = __ MakeDeferredLabel<1>();
1087f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
108862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Load the current map of the {value}.
108962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1090f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
109162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Perform the map checks.
109262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = 0; i < map_count; ++i) {
109362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* map = __ HeapConstant(maps[i]);
109462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check = __ WordEqual(value_map, map);
109562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (i == map_count - 1) {
109662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ GotoUnless(check, &migrate);
109762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Goto(&done);
109862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      } else {
109962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ GotoIf(check, &done);
110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
1101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
110362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Perform the (deferred) instance migration.
110462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&migrate);
110562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    {
110662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // If map is not deprecated the migration attempt does not make sense.
110762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* bitfield3 =
110862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ LoadField(AccessBuilder::ForMapBitField3(), value_map);
110962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* if_not_deprecated = __ WordEqual(
111062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ Word32And(bitfield3, __ Int32Constant(Map::Deprecated::kMask)),
111162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ Int32Constant(0));
111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ DeoptimizeIf(DeoptimizeReason::kWrongMap, if_not_deprecated,
111362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      frame_state);
111462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
111562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
111662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Runtime::FunctionId id = Runtime::kTryMigrateInstance;
111762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
111862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
111962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* result =
112062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ Call(desc, __ CEntryStubConstant(1), value,
112162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  __ ExternalConstant(ExternalReference(id, isolate())),
112262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  __ Int32Constant(1), __ NoContextConstant());
112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check = ObjectIsSmi(result);
112462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ DeoptimizeIf(DeoptimizeReason::kInstanceMigrationFailed, check,
112562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      frame_state);
112662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
1127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
112862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Reload the current map of the {value}.
112962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    value_map = __ LoadField(AccessBuilder::ForMap(), value);
1130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
113162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Perform the map checks again.
113262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = 0; i < map_count; ++i) {
113362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* map = __ HeapConstant(maps[i]);
113462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check = __ WordEqual(value_map, map);
113562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (i == map_count - 1) {
113662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state);
113762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      } else {
113862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ GotoIf(check, &done);
113962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
114062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
1141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
114262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done);
114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&done);
114462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  } else {
114562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto done =
114662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, map_count);
1147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Load the current map of the {value}.
114962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
1150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
115162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (size_t i = 0; i < map_count; ++i) {
115262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* map = __ HeapConstant(maps[i]);
115362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check = __ WordEqual(value_map, map);
115462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (i == map_count - 1) {
115562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ DeoptimizeUnless(DeoptimizeReason::kWrongMap, check, frame_state);
115662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      } else {
115762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ GotoIf(check, &done);
115862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
115962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
116062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done);
116162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&done);
1162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
116362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
116662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckNumber(Node* node, Node* frame_state) {
1167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
1168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
116962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
117062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>();
117162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check0 = ObjectIsSmi(value);
117362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_smi);
117462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done);
117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
117662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
117762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
117862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = __ WordEqual(value_map, __ HeapNumberMapConstant());
117962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check1, frame_state);
118062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done);
1181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
118262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
118362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
118462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
118562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
118662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckReceiver(Node* node,
118762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                  Node* frame_state) {
118862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
1189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
119162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_instance_type =
119262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
119462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
119562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Uint32LessThanOrEqual(
119662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
119762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kNotAJavaScriptObject, check,
119862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      frame_state);
119962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1201f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
120262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckString(Node* node, Node* frame_state) {
1203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
1204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
120562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
120662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_instance_type =
120762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
120962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Uint32LessThan(value_instance_type,
121062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  __ Uint32Constant(FIRST_NONSTRING_TYPE));
121162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state);
121262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
121562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckInternalizedString(Node* node,
121662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                            Node* frame_state) {
121762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
121813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
121962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
122062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_instance_type =
122162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
122213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
122362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Word32Equal(
122462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Word32And(value_instance_type,
122562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   __ Int32Constant(kIsNotStringMask | kIsNotInternalizedMask)),
122662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Int32Constant(kInternalizedTag));
122762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kWrongInstanceType, check, frame_state);
122813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
122962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
123062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
123113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
123262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state) {
123362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
123462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeKind::kEager, DeoptimizeReason::kNoReason,
123562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      value, frame_state);
123662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
123713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
123813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
123962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Add(Node* node,
124062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* frame_state) {
124113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* lhs = node->InputAt(0);
124213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* rhs = node->InputAt(1);
124313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
124462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = __ Int32AddWithOverflow(lhs, rhs);
124562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Projection(1, value);
124662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
124762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Projection(0, value);
124862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
124913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
125062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Sub(Node* node,
125162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* frame_state) {
125262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* lhs = node->InputAt(0);
125362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* rhs = node->InputAt(1);
125413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
125562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = __ Int32SubWithOverflow(lhs, rhs);
125662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Projection(1, value);
125762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
125862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Projection(0, value);
125913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
126013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
126162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Div(Node* node,
126262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* frame_state) {
1263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* lhs = node->InputAt(0);
1264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rhs = node->InputAt(1);
126513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
126662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_positive = __ MakeDeferredLabel<1>();
126762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_is_minint = __ MakeDeferredLabel<1>();
126862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
126962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto minint_check_done = __ MakeLabel<2>();
127062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
127162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* zero = __ Int32Constant(0);
127262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {rhs} is positive (and not zero).
127462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Int32LessThan(zero, rhs);
127562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_positive);
127613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
127762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Fast case, no additional checking required.
127862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Div(lhs, rhs));
1279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
128162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_not_positive);
128262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if {rhs} is zero.
128462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check = __ Word32Equal(rhs, zero);
128562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
1286f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1287f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if {lhs} is zero, as that would produce minus zero.
128862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    check = __ Word32Equal(lhs, zero);
128962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
1290f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
1292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // to return -kMinInt, which is not representable.
129362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* minint = __ Int32Constant(std::numeric_limits<int32_t>::min());
1294f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_is_minint);
129662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&minint_check_done);
129713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
129862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_is_minint);
129962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Check if {rhs} is -1.
130062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* minusone = __ Int32Constant(-1);
130162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* is_minus_one = __ Word32Equal(rhs, minusone);
130262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kOverflow, is_minus_one, frame_state);
130362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&minint_check_done);
130413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
130562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&minint_check_done);
1306f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Perform the actual integer division.
130762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, __ Int32Div(lhs, rhs));
1308f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
130913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
131062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
131162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = done.PhiAt(0);
131213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1313f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if the remainder is non-zero.
131462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
131562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
131613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
131813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
131913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
132062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Mod(Node* node,
132162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* frame_state) {
1322f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // General case for signed integer modulus, with optimization for (unknown)
1323f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // power of 2 right hand side.
1324f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
1325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   if rhs <= 0 then
1326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     rhs = -rhs
1327f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     deopt if rhs == 0
1328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   if lhs < 0 then
1329f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     let res = lhs % rhs in
1330f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     deopt if res == 0
1331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     res
1332f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   else
1333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     let msk = rhs - 1 in
1334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     if rhs & msk == 0 then
1335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       lhs & msk
1336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     else
1337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       lhs % rhs
1338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
1339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* lhs = node->InputAt(0);
1340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rhs = node->InputAt(1);
134113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_rhs_not_positive = __ MakeDeferredLabel<1>();
134362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_lhs_negative = __ MakeDeferredLabel<1>();
134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_power_of_two = __ MakeLabel<1>();
134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto rhs_checked = __ MakeLabel<2>(MachineRepresentation::kWord32);
134662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<3>(MachineRepresentation::kWord32);
134762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
134862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* zero = __ Int32Constant(0);
134962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {rhs} is not strictly positive.
135162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Int32LessThanOrEqual(rhs, zero);
135262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check0, &if_rhs_not_positive);
135362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&rhs_checked, rhs);
135413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
135562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_rhs_not_positive);
1356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
1357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Negate {rhs}, might still produce a negative result in case of
1358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // -2^31, but that is handled safely below.
135962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* vtrue0 = __ Int32Sub(zero, rhs);
1360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
136262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check = __ Word32Equal(vtrue0, zero);
136362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
136462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&rhs_checked, vtrue0);
1365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
136613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
136762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&rhs_checked);
136862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  rhs = rhs_checked.PhiAt(0);
136913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {lhs} is negative.
137162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = __ Int32LessThan(lhs, zero);
137262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check1, &if_lhs_negative);
137313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
137462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // {lhs} non-negative.
1375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
137662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* one = __ Int32Constant(1);
137762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* msk = __ Int32Sub(rhs, one);
1378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if {rhs} minus one is a valid mask.
138062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check2 = __ Word32Equal(__ Word32And(rhs, msk), zero);
138162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check2, &if_power_of_two);
138262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Compute the remainder using the generic {lhs % rhs}.
138362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, __ Int32Mod(lhs, rhs));
1384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
138562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_power_of_two);
1386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Compute the remainder using {lhs & msk}.
138762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, __ Word32And(lhs, msk));
138862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
1389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
139062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_lhs_negative);
139162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Compute the remainder using {lhs % msk}.
139362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* vtrue1 = __ Int32Mod(lhs, rhs);
139413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Check if we would have to return -0.
139662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check = __ Word32Equal(vtrue1, zero);
139762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check, frame_state);
139862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, vtrue1);
1399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
140162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
140262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
140313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
140413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
140562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32Div(Node* node,
140662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     Node* frame_state) {
1407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* lhs = node->InputAt(0);
1408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rhs = node->InputAt(1);
140913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
141062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* zero = __ Int32Constant(0);
141162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
141362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Word32Equal(rhs, zero);
141462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
141513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Perform the actual unsigned integer division.
141762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = __ Uint32Div(lhs, rhs);
1418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if the remainder is non-zero.
142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  check = __ Word32Equal(lhs, __ Int32Mul(rhs, value));
142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
142262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
142562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32Mod(Node* node,
142662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     Node* frame_state) {
1427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* lhs = node->InputAt(0);
1428f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rhs = node->InputAt(1);
1429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
143062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* zero = __ Int32Constant(0);
143162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
143362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Word32Equal(rhs, zero);
143462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kDivisionByZero, check, frame_state);
1435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Perform the actual unsigned integer modulus.
143762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Uint32Mod(lhs, rhs);
1438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
144062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32Mul(Node* node,
144162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* frame_state) {
1442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* lhs = node->InputAt(0);
1444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* rhs = node->InputAt(1);
1445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* projection = __ Int32MulWithOverflow(lhs, rhs);
144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Projection(1, projection);
144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
1449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
145062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = __ Projection(0, projection);
1451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
145362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto if_zero = __ MakeDeferredLabel<1>();
145462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto check_done = __ MakeLabel<2>();
145562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* zero = __ Int32Constant(0);
145662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check_zero = __ Word32Equal(value, zero);
145762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check_zero, &if_zero);
145862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&check_done);
1459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
146062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_zero);
146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // We may need to return negative zero.
146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check_or = __ Int32LessThan(__ Word32Or(lhs, rhs), zero);
146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_or, frame_state);
146462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&check_done);
1465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
146662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&check_done);
1467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
146962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
147262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedInt32ToTaggedSigned(
147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* frame_state) {
1474f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK(SmiValuesAre31Bits());
1475f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value = node->InputAt(0);
1476f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
147762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* add = __ Int32AddWithOverflow(value, value);
147862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Projection(1, add);
147962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kOverflow, check, frame_state);
148062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Projection(0, add);
1481f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
1482f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
148362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
148462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                         Node* frame_state) {
1485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
148662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* max_int = __ Int32Constant(std::numeric_limits<int32_t>::max());
148762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* is_safe = __ Uint32LessThanOrEqual(value, max_int);
148862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, is_safe, frame_state);
148962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedUint32ToTaggedSigned(
149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* frame_state) {
1494f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value = node->InputAt(0);
149562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Uint32LessThanOrEqual(value, SmiMaxValueConstant());
149662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kLostPrecision, check, frame_state);
149762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeUint32ToSmi(value);
149862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
149962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
150062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::BuildCheckedFloat64ToInt32(
150162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CheckForMinusZeroMode mode, Node* value, Node* frame_state) {
150262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value32 = __ RoundFloat64ToInt32(value);
150362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check_same = __ Float64Equal(value, __ ChangeInt32ToFloat64(value32));
150462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kLostPrecisionOrNaN, check_same,
150562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      frame_state);
1506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (mode == CheckForMinusZeroMode::kCheckForMinusZero) {
1508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if {value} is -0.
150962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto if_zero = __ MakeDeferredLabel<1>();
151062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    auto check_done = __ MakeLabel<2>();
1511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
151262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check_zero = __ Word32Equal(value32, __ Int32Constant(0));
151362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check_zero, &if_zero);
151462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&check_done);
1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
151662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_zero);
1517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // In case of 0, we need to check the high bits for the IEEE -0 pattern.
151862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check_negative = __ Int32LessThan(__ Float64ExtractHighWord32(value),
151962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                            __ Int32Constant(0));
152062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kMinusZero, check_negative, frame_state);
152162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&check_done);
1522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
152362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&check_done);
152462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
152562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value32;
1526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1527f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
152862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
152962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                          Node* frame_state) {
1530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
153262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return BuildCheckedFloat64ToInt32(mode, value, frame_state);
1533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
153562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedSignedToInt32(
153662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* frame_state) {
1537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
1538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* check = ObjectIsSmi(value);
153962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state);
154062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ChangeSmiToInt32(value);
1541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
154362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
154462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                         Node* frame_state) {
1545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CheckForMinusZeroMode mode = CheckMinusZeroModeOf(node->op());
1546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
1547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
154862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
154962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1550f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
155162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
155262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
1553f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // In the Smi case, just convert to int32.
155462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(value));
1555f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // In the non-Smi case, check the heap numberness, load the number and convert
1557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // to int32.
155862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
155962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
156062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check_map = __ WordEqual(value_map, __ HeapNumberMapConstant());
156162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_map,
156262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      frame_state);
156362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
156462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vfalse = BuildCheckedFloat64ToInt32(mode, vfalse, frame_state);
156562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
156662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
156762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
156862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
156962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
157062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
157162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
157262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CheckTaggedInputMode mode, Node* value, Node* frame_state) {
157362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
157462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check_number = __ WordEqual(value_map, __ HeapNumberMapConstant());
1575f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  switch (mode) {
1576f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case CheckTaggedInputMode::kNumber: {
157762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ DeoptimizeUnless(DeoptimizeReason::kNotAHeapNumber, check_number,
157862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          frame_state);
1579f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
1580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    case CheckTaggedInputMode::kNumberOrOddball: {
158262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      auto check_done = __ MakeLabel<2>();
1583f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
158462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoIf(check_number, &check_done);
1585f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // For oddballs also contain the numeric value, let us just check that
1586f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // we have an oddball here.
158762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* instance_type =
158862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
1589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Node* check_oddball =
159062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ Word32Equal(instance_type, __ Int32Constant(ODDBALL_TYPE));
159162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ DeoptimizeUnless(DeoptimizeReason::kNotANumberOrOddball, check_oddball,
159262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          frame_state);
1593f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
159462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&check_done);
1595f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
159662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Bind(&check_done);
1597f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      break;
1598f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
1599f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
160062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
160113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
160213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
160362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
160462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                           Node* frame_state) {
1605f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  CheckTaggedInputMode mode = CheckTaggedInputModeOf(node->op());
160613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
160713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
160862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeLabel<1>();
160962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kFloat64);
161062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
161113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* check = ObjectIsSmi(value);
161262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check, &if_smi);
161313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
161413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // In the Smi case, just convert to int32 and then float64.
161513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Otherwise, check heap numberness and load the number.
161662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number =
161762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      BuildCheckedHeapNumberOrOddballToFloat64(mode, value, frame_state);
161862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, number);
1619f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
162062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
162162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* from_smi = ChangeSmiToInt32(value);
162262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  from_smi = __ ChangeInt32ToFloat64(from_smi);
162362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, from_smi);
1624f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
162562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
162662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1627f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
1628f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
162962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToTaggedSigned(
163062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* frame_state) {
1631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* value = node->InputAt(0);
1632c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* check = ObjectIsSmi(value);
163462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeUnless(DeoptimizeReason::kNotASmi, check, frame_state);
1635c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
163662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
1637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
163962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTaggedToTaggedPointer(
164062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* frame_state) {
1641bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1642bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1643bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* check = ObjectIsSmi(value);
164462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kSmi, check, frame_state);
164562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
164662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1647bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
164862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerTruncateTaggedToWord32(Node* node) {
164962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
1650bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
165162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
165262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
165362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
165462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
165562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
165662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(value));
1657bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
165862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
165962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(HeapNumber::kValueOffset == Oddball::kToNumberRawOffset);
166062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ LoadField(AccessBuilder::ForHeapNumberValue(), value);
166162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  vfalse = __ TruncateFloat64ToWord32(vfalse);
166262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
1663bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
166462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
166562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
166862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckedTruncateTaggedToWord32(
166962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* node, Node* frame_state) {
1670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
1671f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
167262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeLabel<1>();
167362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kWord32);
1674f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
167562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
167662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_smi);
1677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // In the Smi case, just convert to int32.
167862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(value));
1679f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1680f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Otherwise, check that it's a heap number or oddball and truncate the value
1681f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // to int32.
168262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
168362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = BuildCheckedHeapNumberOrOddballToFloat64(
168462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CheckTaggedInputMode::kNumberOrOddball, value, frame_state);
168562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  number = __ TruncateFloat64ToWord32(number);
168662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, number);
168762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
168862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
168962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
169062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
169162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
169262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsDetectableCallable(Node* node) {
1693bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1694bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
169562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeDeferredLabel<1>();
169662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
169762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1698bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* check = ObjectIsSmi(value);
169962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check, &if_smi);
1700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
170162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
170262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_bit_field =
170362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapBitField(), value_map);
170462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ Word32Equal(
170562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Int32Constant(1 << Map::kIsCallable),
170662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Word32And(value_bit_field,
170762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   __ Int32Constant((1 << Map::kIsCallable) |
170862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                    (1 << Map::kIsUndetectable))));
170962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
1710bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
171262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(0));
1713bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
171462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
171562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1716bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1717bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
171862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsNonCallable(Node* node) {
1719bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1720bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
172162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_primitive = __ MakeDeferredLabel<2>();
172262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
172362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
172462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = ObjectIsSmi(value);
172562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check0, &if_primitive);
1726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
172762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
172862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_instance_type =
172962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
173062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
173162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = __ Uint32LessThanOrEqual(
173262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
173362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check1, &if_primitive);
1734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
173562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_bit_field =
173662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapBitField(), value_map);
173762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check2 = __ Word32Equal(
173862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Int32Constant(0),
173962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Word32And(value_bit_field, __ Int32Constant(1 << Map::kIsCallable)));
174062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, check2);
1741bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
174262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_primitive);
174362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(0));
1744bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
174562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
174662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1747bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
174962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsNumber(Node* node) {
1750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1751bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
175262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeLabel<1>();
175362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
175562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(ObjectIsSmi(value), &if_smi);
175662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
175762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ WordEqual(value_map, __ HeapNumberMapConstant()));
1758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
175962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
176062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(1));
1761bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
176262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
176362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1764bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
176662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsReceiver(Node* node) {
1767bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
1768bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
176962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeDeferredLabel<1>();
177062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1771bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
177262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(ObjectIsSmi(value), &if_smi);
1773bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
177462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
177562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
177662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_instance_type =
177762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
177862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* result = __ Uint32LessThanOrEqual(
177962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Uint32Constant(FIRST_JS_RECEIVER_TYPE), value_instance_type);
178062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, result);
1781bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
178262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
178362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(0));
1784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
178562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
178662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1787bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
178962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsSmi(Node* node) {
1790bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Node* value = node->InputAt(0);
179162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return ObjectIsSmi(value);
179262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
179462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsString(Node* node) {
179562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
1796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
179762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeDeferredLabel<1>();
179862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1799bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
180062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
180162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check, &if_smi);
180262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
180362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_instance_type =
180462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
180562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ Uint32LessThan(value_instance_type,
180662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                   __ Uint32Constant(FIRST_NONSTRING_TYPE));
180762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
1808bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
180962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
181062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(0));
1811bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
181262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
181362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
1814bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
1815bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
181662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerObjectIsUndetectable(Node* node) {
1817f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value = node->InputAt(0);
1818f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
181962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_smi = __ MakeDeferredLabel<1>();
182062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kBit);
1821f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
182262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = ObjectIsSmi(value);
182362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check, &if_smi);
1824f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
182562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
182662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_bit_field =
182762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForMapBitField(), value_map);
182862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* vfalse = __ Word32Equal(
182962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Word32Equal(__ Int32Constant(0),
183062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     __ Word32And(value_bit_field,
183162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  __ Int32Constant(1 << Map::kIsUndetectable))),
183262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Int32Constant(0));
183362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, vfalse);
1834f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
183562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_smi);
183662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Int32Constant(0));
1837f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
183862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
183962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
184062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
184262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerNewRestParameterElements(Node* node) {
184362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int const formal_parameter_count = ParameterCountOf(node->op());
1844f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
184562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable const callable = CodeFactory::NewRestParameterElements(isolate());
184662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator::Properties const properties = node->op()->properties();
184762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
184862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
184962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
185062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Call(desc, __ HeapConstant(callable.code()),
185162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ IntPtrConstant(formal_parameter_count),
185262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ NoContextConstant());
185362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1854f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
185562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerNewUnmappedArgumentsElements(Node* node) {
185662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int const formal_parameter_count = ParameterCountOf(node->op());
1857f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
185862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable const callable =
185962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CodeFactory::NewUnmappedArgumentsElements(isolate());
186062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator::Properties const properties = node->op()->properties();
186162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
186262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
186362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
186462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Call(desc, __ HeapConstant(callable.code()),
186562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ IntPtrConstant(formal_parameter_count),
186662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ NoContextConstant());
186762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1868f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
186962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerArrayBufferWasNeutered(Node* node) {
187062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = node->InputAt(0);
1871f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
187262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value_bit_field =
187362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadField(AccessBuilder::ForJSArrayBufferBitField(), value);
187462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Word32Equal(
187562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Word32Equal(
187662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ Word32And(value_bit_field,
187762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       __ Int32Constant(JSArrayBuffer::WasNeutered::kMask)),
187862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ Int32Constant(0)),
187962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Int32Constant(0));
188062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1881f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
188262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringCharAt(Node* node) {
188362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver = node->InputAt(0);
188462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* position = node->InputAt(1);
1885f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
188662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable const callable = CodeFactory::StringCharAt(isolate());
188762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
188862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
188962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
189062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
189162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
189262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ NoContextConstant());
1893f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
1894f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
189562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringCharCodeAt(Node* node) {
189662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver = node->InputAt(0);
189762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* position = node->InputAt(1);
189862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
189962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable const callable = CodeFactory::StringCharCodeAt(isolate());
190062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite;
190162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
190262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
190362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties,
190462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      MachineType::TaggedSigned());
190562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Call(desc, __ HeapConstant(callable.code()), receiver, position,
190662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ NoContextConstant());
190762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
190862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
190962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringFromCharCode(Node* node) {
191013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
191113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
191262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto runtime_call = __ MakeDeferredLabel<2>();
191362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_undefined = __ MakeDeferredLabel<1>();
191462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
191562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
191613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Compute the character code.
191762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* code = __ Word32And(value, __ Int32Constant(String::kMaxUtf16CodeUnit));
191813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
191913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Check if the {code} is a one-byte char code.
192062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Int32LessThanOrEqual(
192162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      code, __ Int32Constant(String::kMaxOneByteCharCode));
192262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &runtime_call);
192313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1924c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Load the isolate wide single character string cache.
192562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* cache = __ HeapConstant(factory()->single_character_string_cache());
192613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Compute the {cache} index for {code}.
192862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
192913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1930c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Check if we have an entry for the {code} in the single character string
1931c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // cache already.
193262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* entry =
193362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
1934c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
193562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = __ WordEqual(entry, __ UndefinedConstant());
193662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check1, &runtime_call);
193762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, entry);
1938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Let %StringFromCharCode handle this case.
1940c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // TODO(turbofan): At some point we may consider adding a stub for this
1941c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // deferred case, so that we don't need to call to C++ here.
194262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&runtime_call);
194313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
1944c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
1945c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Runtime::FunctionId id = Runtime::kStringCharFromCode;
1946c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
1947c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags);
194862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* vtrue1 =
194962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Call(desc, __ CEntryStubConstant(1), ChangeInt32ToSmi(code),
195062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                __ ExternalConstant(ExternalReference(id, isolate())),
195162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                __ Int32Constant(1), __ NoContextConstant());
195262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, vtrue1);
195313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
195462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
195562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
195613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
195713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
195862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringFromCodePoint(Node* node) {
1959f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* value = node->InputAt(0);
1960f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Node* code = value;
1961f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
196262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_single_code = __ MakeDeferredLabel<1>();
196362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_one_byte = __ MakeDeferredLabel<1>();
196462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto cache_miss = __ MakeDeferredLabel<1>();
196562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<4>(MachineRepresentation::kTagged);
1966f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1967f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {code} is a single code unit
196862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Uint32LessThanOrEqual(code, __ Uint32Constant(0xFFFF));
196962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_single_code);
1970f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1971f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
1972f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Check if the {code} is a one byte character
197362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Uint32LessThanOrEqual(
197462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        code, __ Uint32Constant(String::kMaxOneByteCharCode));
197562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoUnless(check1, &if_not_one_byte);
1976f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    {
1977f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Load the isolate wide single character string cache.
197862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* cache = __ HeapConstant(factory()->single_character_string_cache());
1979f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1980f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Compute the {cache} index for {code}.
198162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* index = machine()->Is32() ? code : __ ChangeUint32ToUint64(code);
1982f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1983f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Check if we have an entry for the {code} in the single character string
1984f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // cache already.
198562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* entry =
198662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ LoadElement(AccessBuilder::ForFixedArrayElement(), cache, index);
198762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
198862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check2 = __ WordEqual(entry, __ UndefinedConstant());
198962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoIf(check2, &cache_miss);
199062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
199162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Use the {entry} from the {cache}.
199262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, entry);
199362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
199462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Bind(&cache_miss);
1995f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      {
1996f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        // Allocate a new SeqOneByteString for {code}.
199762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* vtrue2 = __ Allocate(
199862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            NOT_TENURED, __ Int32Constant(SeqOneByteString::SizeFor(1)));
199962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ StoreField(AccessBuilder::ForMap(), vtrue2,
200062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      __ HeapConstant(factory()->one_byte_string_map()));
200162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ StoreField(AccessBuilder::ForNameHashField(), vtrue2,
200262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      __ IntPtrConstant(Name::kEmptyHashField));
200362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ StoreField(AccessBuilder::ForStringLength(), vtrue2,
200462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      __ SmiConstant(1));
200562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Store(
200662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            StoreRepresentation(MachineRepresentation::kWord8, kNoWriteBarrier),
200762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            vtrue2,
200862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            __ IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
200962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            code);
2010f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2011f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        // Remember it in the {cache}.
201262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ StoreElement(AccessBuilder::ForFixedArrayElement(), cache, index,
201362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        vtrue2);
201462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ Goto(&done, vtrue2);
2015f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
2016f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
2017f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
201862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_not_one_byte);
2019f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    {
2020f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      // Allocate a new SeqTwoByteString for {code}.
202162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* vfalse1 = __ Allocate(
202262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          NOT_TENURED, __ Int32Constant(SeqTwoByteString::SizeFor(1)));
202362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ StoreField(AccessBuilder::ForMap(), vfalse1,
202462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    __ HeapConstant(factory()->string_map()));
202562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ StoreField(AccessBuilder::ForNameHashField(), vfalse1,
202662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    __ IntPtrConstant(Name::kEmptyHashField));
202762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ StoreField(AccessBuilder::ForStringLength(), vfalse1,
202862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    __ SmiConstant(1));
202962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Store(
203062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          StoreRepresentation(MachineRepresentation::kWord16, kNoWriteBarrier),
203162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          vfalse1,
203262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
203362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          code);
203462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, vfalse1);
2035f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
2036f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
2037f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
203862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_single_code);
2039f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Generate surrogate pair string
2040f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  {
2041f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    switch (UnicodeEncodingOf(node->op())) {
2042f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case UnicodeEncoding::UTF16:
2043f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
2044f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2045f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      case UnicodeEncoding::UTF32: {
2046f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
204762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* lead_offset = __ Int32Constant(0xD800 - (0x10000 >> 10));
2048f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2049f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        // lead = (codepoint >> 10) + LEAD_OFFSET
2050f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        Node* lead =
205162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            __ Int32Add(__ Word32Shr(code, __ Int32Constant(10)), lead_offset);
2052f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2053f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        // trail = (codepoint & 0x3FF) + 0xDC00;
205462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* trail = __ Int32Add(__ Word32And(code, __ Int32Constant(0x3FF)),
205562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                  __ Int32Constant(0xDC00));
2056f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2057f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        // codpoint = (trail << 16) | lead;
205862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        code = __ Word32Or(__ Word32Shl(trail, __ Int32Constant(16)), lead);
2059f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        break;
2060f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      }
2061f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    }
2062f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2063f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // Allocate a new SeqTwoByteString for {code}.
206462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* vfalse0 = __ Allocate(NOT_TENURED,
206562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                __ Int32Constant(SeqTwoByteString::SizeFor(2)));
206662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ StoreField(AccessBuilder::ForMap(), vfalse0,
206762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  __ HeapConstant(factory()->string_map()));
206862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ StoreField(AccessBuilder::ForNameHashField(), vfalse0,
206962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  __ IntPtrConstant(Name::kEmptyHashField));
207062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ StoreField(AccessBuilder::ForStringLength(), vfalse0, __ SmiConstant(2));
207162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Store(
207262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        StoreRepresentation(MachineRepresentation::kWord32, kNoWriteBarrier),
207362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        vfalse0,
207462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
207562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        code);
207662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, vfalse0);
207762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
207862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
207962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
208062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
208162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
208262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
208362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringIndexOf(Node* node) {
208462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* subject = node->InputAt(0);
208562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* search_string = node->InputAt(1);
208662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* position = node->InputAt(2);
2087f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
208862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable callable = CodeFactory::StringIndexOf(isolate());
208962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator::Properties properties = Operator::kEliminatable;
209062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
209162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
209262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
209362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Call(desc, __ HeapConstant(callable.code()), subject, search_string,
209462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 position, __ NoContextConstant());
2095f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2096f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
209762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringComparison(Callable const& callable,
209862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     Node* node) {
209962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* lhs = node->InputAt(0);
210062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* rhs = node->InputAt(1);
210162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Operator::Properties properties = Operator::kEliminatable;
2103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
2104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
2105f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
210662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Call(desc, __ HeapConstant(callable.code()), lhs, rhs,
210762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 __ NoContextConstant());
2108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
211062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringEqual(Node* node) {
211162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return LowerStringComparison(CodeFactory::StringEqual(isolate()), node);
2112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
211462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringLessThan(Node* node) {
211562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return LowerStringComparison(CodeFactory::StringLessThan(isolate()), node);
2116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
211862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerStringLessThanOrEqual(Node* node) {
2119f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  return LowerStringComparison(CodeFactory::StringLessThanOrEqual(isolate()),
212062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               node);
2121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
2122f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
212362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckFloat64Hole(Node* node,
212462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     Node* frame_state) {
212513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // If we reach this point w/o eliminating the {node} that's marked
212613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // with allow-return-hole, we cannot do anything, so just deoptimize
212713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // in case of the hole NaN (similar to Crankshaft).
212813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
212962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ Word32Equal(__ Float64ExtractHighWord32(value),
213062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               __ Int32Constant(kHoleNanUpper32));
213162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
213262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
213313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
213413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
213562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerCheckTaggedHole(Node* node,
213662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* frame_state) {
213713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
213862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ WordEqual(value, __ TheHoleConstant());
213962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ DeoptimizeIf(DeoptimizeReason::kHole, check, frame_state);
214062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return value;
2141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
214362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerConvertTaggedHoleToUndefined(Node* node) {
2144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(0);
214513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
214662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_is_hole = __ MakeDeferredLabel<1>();
214762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
2148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
214962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ WordEqual(value, __ TheHoleConstant());
215062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check, &if_is_hole);
215162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, value);
2152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
215362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_is_hole);
215462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ UndefinedConstant());
215513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
215662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
215762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
215813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
215913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
216062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value) {
216162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* result = __ Allocate(NOT_TENURED, __ Int32Constant(HeapNumber::kSize));
216262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ StoreField(AccessBuilder::ForMap(), result, __ HeapNumberMapConstant());
216362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ StoreField(AccessBuilder::ForHeapNumberValue(), result, value);
216462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return result;
2165bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2166bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2167bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
2168bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (machine()->Is64()) {
216962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    value = __ ChangeInt32ToInt64(value);
2170bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
217162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ WordShl(value, SmiShiftBitsConstant());
2172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
2175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (machine()->Is64()) {
217662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    value = __ ChangeUint32ToUint64(value);
2177bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
217862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ WordShl(value, SmiShiftBitsConstant());
2179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
218262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  value = __ WordSar(value, SmiShiftBitsConstant());
2183bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  if (machine()->Is64()) {
218462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    value = __ TruncateInt64ToInt32(value);
2185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
2186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  return value;
2187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
218862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2189bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::ObjectIsSmi(Node* value) {
219062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ WordEqual(__ WordAnd(value, __ IntPtrConstant(kSmiTagMask)),
219162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      __ IntPtrConstant(kSmiTag));
2192bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::SmiMaxValueConstant() {
219562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ Int32Constant(Smi::kMaxValue);
2196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben MurdochNode* EffectControlLinearizer::SmiShiftBitsConstant() {
219962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ IntPtrConstant(kSmiShiftSize + kSmiTagSize);
2200bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}
2201bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
220262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerPlainPrimitiveToNumber(Node* node) {
220313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
220462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ ToNumber(value);
220513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
220613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
220762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerPlainPrimitiveToWord32(Node* node) {
220813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
220913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
221062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
221162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_to_number_smi = __ MakeLabel<1>();
221262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<3>(MachineRepresentation::kWord32);
221313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
221462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = ObjectIsSmi(value);
221562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_smi);
221662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(value));
221713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
221862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
221962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* to_number = __ ToNumber(value);
222013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
222162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = ObjectIsSmi(to_number);
222262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check1, &if_to_number_smi);
222362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
222462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ TruncateFloat64ToWord32(number));
222513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
222662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_to_number_smi);
222762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, ChangeSmiToInt32(to_number));
222813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
222962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
223062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
223113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
223213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
223362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerPlainPrimitiveToFloat64(Node* node) {
223413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* value = node->InputAt(0);
223513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
223662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_smi = __ MakeDeferredLabel<1>();
223762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_to_number_smi = __ MakeLabel<1>();
223862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<3>(MachineRepresentation::kFloat64);
223913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
224062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = ObjectIsSmi(value);
224162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_smi);
224262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* from_smi = ChangeSmiToInt32(value);
224362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ ChangeInt32ToFloat64(from_smi));
224413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
224562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_smi);
224662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* to_number = __ ToNumber(value);
224762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = ObjectIsSmi(to_number);
224862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check1, &if_to_number_smi);
224913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
225062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = __ LoadField(AccessBuilder::ForHeapNumberValue(), to_number);
225162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, number);
225213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
225362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_to_number_smi);
225462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number_from_smi = ChangeSmiToInt32(to_number);
225562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  number_from_smi = __ ChangeInt32ToFloat64(number_from_smi);
225662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, number_from_smi);
225713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
225862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
225962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
226013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
226113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
226262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerEnsureWritableFastElements(Node* node) {
2263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* object = node->InputAt(0);
2264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* elements = node->InputAt(1);
2265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
226662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_fixed_array = __ MakeDeferredLabel<1>();
226762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
226862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Load the current map of {elements}.
227062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* elements_map = __ LoadField(AccessBuilder::ForMap(), elements);
2271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {elements} is not a copy-on-write FixedArray.
227362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ WordEqual(elements_map, __ FixedArrayMapConstant());
227462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check, &if_not_fixed_array);
2275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Nothing to do if the {elements} are not copy-on-write.
227662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, elements);
2277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
227862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_fixed_array);
2279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // We need to take a copy of the {elements} and set them up for {object}.
228062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Operator::Properties properties = Operator::kEliminatable;
228162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Callable callable = CodeFactory::CopyFastSmiOrObjectElements(isolate());
228262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
228362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
228462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
228562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* result = __ Call(desc, __ HeapConstant(callable.code()), object,
228662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                         __ NoContextConstant());
228762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, result);
2288f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
228962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
229062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
2291f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2292f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
229362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerMaybeGrowFastElements(Node* node,
229462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                          Node* frame_state) {
2295f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
2296f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* object = node->InputAt(0);
2297f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* elements = node->InputAt(1);
2298f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* index = node->InputAt(2);
2299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* length = node->InputAt(3);
2300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
230162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>(MachineRepresentation::kTagged);
230262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done_grow = __ MakeLabel<2>(MachineRepresentation::kTagged);
230362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_grow = __ MakeDeferredLabel<1>();
230462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_grow = __ MakeLabel<1>();
2305f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
230662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = (flags & GrowFastElementsFlag::kHoleyElements)
230762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     ? __ Uint32LessThanOrEqual(length, index)
230862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     : __ Word32Equal(length, index);
230962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_grow);
2310f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
2311f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Load the length of the {elements} backing store.
231262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* elements_length =
231362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ LoadField(AccessBuilder::ForFixedArrayLength(), elements);
2314f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    elements_length = ChangeSmiToInt32(elements_length);
2315f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2316f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Check if we need to grow the {elements} backing store.
231762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Uint32LessThan(index, elements_length);
231862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoUnless(check1, &if_grow);
231962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done_grow, elements);
2320f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
232162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_grow);
232262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // We need to grow the {elements} for {object}.
232362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Operator::Properties properties = Operator::kEliminatable;
232462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable =
232562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        (flags & GrowFastElementsFlag::kDoubleElements)
232662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            ? CodeFactory::GrowFastDoubleElements(isolate())
232762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            : CodeFactory::GrowFastSmiOrObjectElements(isolate());
232862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallDescriptor::Flags call_flags = CallDescriptor::kNoFlags;
232962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    CallDescriptor const* const desc = Linkage::GetStubCallDescriptor(
233062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), graph()->zone(), callable.descriptor(), 0, call_flags,
233162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        properties);
233262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* new_object = __ Call(desc, __ HeapConstant(callable.code()), object,
233362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               ChangeInt32ToSmi(index), __ NoContextConstant());
233462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
233562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Ensure that we were able to grow the {elements}.
233662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // TODO(turbofan): We use kSmi as reason here similar to Crankshaft,
233762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // but maybe we should just introduce a reason that makes sense.
233862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ DeoptimizeIf(DeoptimizeReason::kSmi, ObjectIsSmi(new_object),
233962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    frame_state);
234062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done_grow, new_object);
234162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
234262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&done_grow);
2343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // For JSArray {object}s we also need to update the "length".
2345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (flags & GrowFastElementsFlag::kArrayObject) {
2346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Compute the new {length}.
234762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* object_length =
234862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          ChangeInt32ToSmi(__ Int32Add(index, __ Int32Constant(1)));
2349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      // Update the "length" property of the {object}.
235162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ StoreField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), object,
235262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    object_length);
2353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
235462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, done_grow.PhiAt(0));
2355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
235762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_grow);
2358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
2359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // In case of non-holey {elements}, we need to verify that the {index} is
2360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // in-bounds, otherwise for holey {elements}, the check above already
2361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // guards the index (and the operator forces {index} to be unsigned).
2362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!(flags & GrowFastElementsFlag::kHoleyElements)) {
236362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check1 = __ Uint32LessThan(index, length);
236462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ DeoptimizeUnless(DeoptimizeReason::kOutOfBounds, check1, frame_state);
2365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
236662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, elements);
2367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
236862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
236962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
2370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
237262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid EffectControlLinearizer::LowerTransitionElementsKind(Node* node) {
2373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ElementsTransition const transition = ElementsTransitionOf(node->op());
2374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* object = node->InputAt(0);
237562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
237662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_map_same = __ MakeDeferredLabel<1>();
237762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<2>();
237862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
237962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* source_map = __ HeapConstant(transition.source());
238062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* target_map = __ HeapConstant(transition.target());
2381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Load the current map of {object}.
238362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* object_map = __ LoadField(AccessBuilder::ForMap(), object);
2384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2385f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if {object_map} is the same as {source_map}.
238662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check = __ WordEqual(object_map, source_map);
238762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check, &if_map_same);
238862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done);
238962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
239062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_map_same);
239162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  switch (transition.mode()) {
239262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case ElementsTransition::kFastTransition:
239362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // In-place migration of {object}, just store the {target_map}.
239462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ StoreField(AccessBuilder::ForMap(), object, target_map);
239562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
239662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    case ElementsTransition::kSlowTransition: {
239762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      // Instance migration, call out to the runtime for {object}.
239862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Operator::Properties properties = Operator::kNoDeopt | Operator::kNoThrow;
239962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Runtime::FunctionId id = Runtime::kTransitionElementsKind;
240062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor(
240162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags);
240262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Call(desc, __ CEntryStubConstant(1), object, target_map,
240362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              __ ExternalConstant(ExternalReference(id, isolate())),
240462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              __ Int32Constant(2), __ NoContextConstant());
240562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      break;
2406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
240862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done);
2409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
241062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
2411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
241362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
2414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
2415f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* buffer = node->InputAt(0);
2416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* base = node->InputAt(1);
2417f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* external = node->InputAt(2);
2418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* index = node->InputAt(3);
2419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2420f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // We need to keep the {buffer} alive so that the GC will not release the
2421f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // ArrayBuffer (if there's any) as long as we are still operating on it.
242262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Retain(buffer);
2423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
242462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Compute the effective storage pointer, handling the case where the
242562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // {external} pointer is the effective storage pointer (i.e. the {base}
242662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // is Smi zero).
242762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
242862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                             base, external);
2429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Perform the actual typed element access.
243162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ LoadElement(AccessBuilder::ForTypedArrayElement(array_type, true),
243262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                        storage, index);
2433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
243562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid EffectControlLinearizer::LowerStoreTypedElement(Node* node) {
2436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
2437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* buffer = node->InputAt(0);
2438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* base = node->InputAt(1);
2439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* external = node->InputAt(2);
2440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* index = node->InputAt(3);
2441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* value = node->InputAt(4);
2442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // We need to keep the {buffer} alive so that the GC will not release the
2444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // ArrayBuffer (if there's any) as long as we are still operating on it.
244562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Retain(buffer);
2446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
244762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Compute the effective storage pointer, handling the case where the
244862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // {external} pointer is the effective storage pointer (i.e. the {base}
244962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // is Smi zero).
245062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* storage = NumberMatcher(base).Is(0) ? external : __ UnsafePointerAdd(
245162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                             base, external);
2452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Perform the actual typed element access.
245462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ StoreElement(AccessBuilder::ForTypedArrayElement(array_type, true),
245562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  storage, index, value);
2456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
245862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundUp(Node* node) {
2459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Nothing to be done if a fast hardware instruction is available.
2460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (machine()->Float64RoundUp().IsSupported()) {
246162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Nothing<Node*>();
2462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* const input = node->InputAt(0);
2465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // General case for ceil.
2467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
2468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   if 0.0 < input then
2469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     if 2^52 <= input then
2470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       input
2471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     else
2472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       let temp1 = (2^52 + input) - 2^52 in
2473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       if temp1 < input then
2474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         temp1 + 1
2475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       else
2476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         temp1
2477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   else
2478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     if input == 0 then
2479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       input
2480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     else
2481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       if input <= -2^52 then
2482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         input
2483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       else
2484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         let temp1 = -0 - input in
2485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         let temp2 = (2^52 + temp1) - 2^52 in
2486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         -0 - temp3
2488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
248962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_positive = __ MakeDeferredLabel<1>();
249062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
249162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
249262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_zero = __ MakeDeferredLabel<1>();
249362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64);
249462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64);
2495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
249662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const zero = __ Float64Constant(0.0);
249762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
249862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const one = __ Float64Constant(1.0);
2499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
250062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Float64LessThan(zero, input);
250162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_positive);
250262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
250362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Float64LessThanOrEqual(two_52, input);
250462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_greater_than_two_52);
2505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
250662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
250762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoUnless(__ Float64LessThan(temp1, input), &done, temp1);
250862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Add(temp1, one));
2509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
251162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_greater_than_two_52);
251262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
251562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_positive);
2516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
251762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Float64Equal(input, zero);
251862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_zero);
2519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
252062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
252162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
252262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check2, &if_less_than_minus_two_52);
2523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
252562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* const minus_zero = __ Float64Constant(-0.0);
252662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp1 = __ Float64Sub(minus_zero, input);
252762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
252862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check3 = __ Float64LessThan(temp1, temp2);
252962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoUnless(check3, &done_temp3, temp2);
253062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done_temp3, __ Float64Sub(temp2, one));
253162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
253262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Bind(&done_temp3);
253362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp3 = done_temp3.PhiAt(0);
253462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Sub(minus_zero, temp3));
2535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
253662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_less_than_minus_two_52);
253762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
253962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_zero);
254062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
254262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
254362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Just(done.PhiAt(0));
2544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
254662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* EffectControlLinearizer::BuildFloat64RoundDown(Node* value) {
254762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* round_down = __ Float64RoundDown(value);
254862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (round_down != nullptr) {
254962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return round_down;
255062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
2551c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
255262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const input = value;
2553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
255462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // General case for floor.
255562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //
255662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //   if 0.0 < input then
255762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //     if 2^52 <= input then
255862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       input
255962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //     else
256062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       let temp1 = (2^52 + input) - 2^52 in
256162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       if input < temp1 then
256262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         temp1 - 1
256362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       else
256462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         temp1
256562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //   else
256662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //     if input == 0 then
256762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       input
256862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //     else
256962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       if input <= -2^52 then
257062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         input
257162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //       else
257262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         let temp1 = -0 - input in
257362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         let temp2 = (2^52 + temp1) - 2^52 in
257462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         if temp2 < temp1 then
257562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //           -1 - temp2
257662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //         else
257762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  //           -0 - temp2
257862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
257962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_positive = __ MakeDeferredLabel<1>();
258062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
258162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
258262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_temp2_lt_temp1 = __ MakeLabel<1>();
258362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_zero = __ MakeDeferredLabel<1>();
258462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<7>(MachineRepresentation::kFloat64);
258562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
258662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const zero = __ Float64Constant(0.0);
258762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
258862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
258962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Float64LessThan(zero, input);
259062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_positive);
259162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
259262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Float64LessThanOrEqual(two_52, input);
259362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_greater_than_two_52);
2594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
259562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* const one = __ Float64Constant(1.0);
259662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
259762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1);
259862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Sub(temp1, one));
259962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
2600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
260162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_greater_than_two_52);
260262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
260362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
2604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
260562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_positive);
260662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
260762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Float64Equal(input, zero);
260862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_zero);
2609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
261062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
261162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
261262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check2, &if_less_than_minus_two_52);
2613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
261462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    {
261562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* const minus_zero = __ Float64Constant(-0.0);
261662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp1 = __ Float64Sub(minus_zero, input);
261762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
261862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check3 = __ Float64LessThan(temp2, temp1);
261962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoIf(check3, &if_temp2_lt_temp1);
262062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Sub(minus_zero, temp2));
262162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
262262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Bind(&if_temp2_lt_temp1);
262362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Sub(__ Float64Constant(-1.0), temp2));
2624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
262562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_less_than_minus_two_52);
262662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
262862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_zero);
262962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2630c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
263162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
263262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return done.PhiAt(0);
2633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
2634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
263562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundDown(Node* node) {
2636f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Nothing to be done if a fast hardware instruction is available.
2637f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (machine()->Float64RoundDown().IsSupported()) {
263862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Nothing<Node*>();
2639f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2640f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Node* const input = node->InputAt(0);
264262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Just(BuildFloat64RoundDown(input));
2643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
2644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
264562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundTiesEven(Node* node) {
2646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Nothing to be done if a fast hardware instruction is available.
2647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (machine()->Float64RoundTiesEven().IsSupported()) {
264862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Nothing<Node*>();
2649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
2650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
2651f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* const input = node->InputAt(0);
2652f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Generate case for round ties to even:
2654f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
2655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //   let value = floor(input) in
2656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //   let temp1 = input - value in
2657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //   if temp1 < 0.5 then
2658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //     value
2659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //   else if 0.5 < temp1 then
2660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //     value + 1.0
2661f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   else
2662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //     let temp2 = value % 2.0 in
2663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //     if temp2 == 0.0 then
2664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //       value
2665f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     else
2666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  //       value + 1.0
2667f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
266862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_is_half = __ MakeLabel<1>();
266962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<4>(MachineRepresentation::kFloat64);
2670f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
267162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = BuildFloat64RoundDown(input);
267262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* temp1 = __ Float64Sub(input, value);
2673f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
267462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const half = __ Float64Constant(0.5);
267562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Float64LessThan(temp1, half);
267662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check0, &done, value);
2677f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
267862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const one = __ Float64Constant(1.0);
267962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check1 = __ Float64LessThan(half, temp1);
268062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check1, &if_is_half);
268162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Float64Add(value, one));
2682f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
268362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_is_half);
268462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* temp2 = __ Float64Mod(value, __ Float64Constant(2.0));
268562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check2 = __ Float64Equal(temp2, __ Float64Constant(0.0));
268662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(check2, &done, value);
268762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Goto(&done, __ Float64Add(value, one));
2688f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
268962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
269062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Just(done.PhiAt(0));
2691f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2692f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
269362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMaybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
2694f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Nothing to be done if a fast hardware instruction is available.
2695f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (machine()->Float64RoundTruncate().IsSupported()) {
269662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Nothing<Node*>();
2697f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2698f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2699f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* const input = node->InputAt(0);
2700f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2701f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // General case for trunc.
2702f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
2703f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   if 0.0 < input then
2704f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     if 2^52 <= input then
2705f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       input
2706f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     else
2707f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       let temp1 = (2^52 + input) - 2^52 in
2708f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       if input < temp1 then
2709f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         temp1 - 1
2710f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       else
2711f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         temp1
2712f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //   else
2713f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     if input == 0 then
2714f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       input
2715f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //     else
2716f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       if input <= -2^52 then
2717f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         input
2718f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //       else
2719f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         let temp1 = -0 - input in
2720f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         let temp2 = (2^52 + temp1) - 2^52 in
2721f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2722f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //         -0 - temp3
2723f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  //
2724f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Note: We do not use the Diamond helper class here, because it really hurts
2725f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // readability with nested diamonds.
2726f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
272762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_not_positive = __ MakeDeferredLabel<1>();
272862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_greater_than_two_52 = __ MakeDeferredLabel<1>();
272962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_less_than_minus_two_52 = __ MakeDeferredLabel<1>();
273062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto if_zero = __ MakeDeferredLabel<1>();
273162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done_temp3 = __ MakeLabel<2>(MachineRepresentation::kFloat64);
273262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  auto done = __ MakeLabel<6>(MachineRepresentation::kFloat64);
2733f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
273462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const zero = __ Float64Constant(0.0);
273562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const two_52 = __ Float64Constant(4503599627370496.0E0);
273662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const one = __ Float64Constant(1.0);
2737f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
273862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* check0 = __ Float64LessThan(zero, input);
273962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoUnless(check0, &if_not_positive);
274062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
274162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Float64LessThanOrEqual(two_52, input);
274262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_greater_than_two_52);
2743f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
274462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp1 = __ Float64Sub(__ Float64Add(two_52, input), two_52);
274562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoUnless(__ Float64LessThan(input, temp1), &done, temp1);
274662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Sub(temp1, one));
2747f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
2748f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
274962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_greater_than_two_52);
275062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2751f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
2752f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
275362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&if_not_positive);
2754f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
275562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check1 = __ Float64Equal(input, zero);
275662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check1, &if_zero);
2757f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
275862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* const minus_two_52 = __ Float64Constant(-4503599627370496.0E0);
275962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* check2 = __ Float64LessThanOrEqual(input, minus_two_52);
276062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIf(check2, &if_less_than_minus_two_52);
2761f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2762f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    {
276362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* const minus_zero = __ Float64Constant(-0.0);
276462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp1 = __ Float64Sub(minus_zero, input);
276562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp2 = __ Float64Sub(__ Float64Add(two_52, temp1), two_52);
276662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* check3 = __ Float64LessThan(temp1, temp2);
276762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ GotoUnless(check3, &done_temp3, temp2);
276862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done_temp3, __ Float64Sub(temp2, one));
276962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
277062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Bind(&done_temp3);
277162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* temp3 = done_temp3.PhiAt(0);
277262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      __ Goto(&done, __ Float64Sub(minus_zero, temp3));
2773f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
277462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_less_than_minus_two_52);
277562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2776f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
277762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Bind(&if_zero);
277862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ Goto(&done, input);
2779f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
278062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&done);
278162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return Just(done.PhiAt(0));
2782f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
2783f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
278462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#undef __
278562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
278613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochFactory* EffectControlLinearizer::factory() const {
278713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return isolate()->factory();
278813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
278913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
279013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochIsolate* EffectControlLinearizer::isolate() const {
279113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return jsgraph()->isolate();
279213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
279313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2794bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace compiler
2795bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace internal
2796bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch}  // namespace v8
2797