1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/simplified-lowering.h"
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/common-operator.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/graph-inl.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/node-properties-inl.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/representation-change.h"
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/simplified-lowering.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler/simplified-operator.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/objects.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace compiler {
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Macro for outputting trace information from representation inference.
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define TRACE(x) \
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_trace_representation) PrintF x
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Representation selection and lowering of {Simplified} operators to machine
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// operators are interwined. We use a fixpoint calculation to compute both the
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// output representation and the best possible lowering for {Simplified} nodes.
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Representation change insertion ensures that all values are in the correct
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// machine representation after this phase, as dictated by the machine
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// operators themselves.
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum Phase {
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     backwards from uses to definitions, around cycles in phis, according
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     to local rules for each operator.
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     During this phase, the usage information for a node determines the best
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     possible lowering for each operator so far, and that in turn determines
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     the output representation.
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     Therefore, to be correct, this phase must iterate to a fixpoint before
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     the next phase can begin.
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  PROPAGATE,
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     operators for some nodes, expanding some nodes to multiple nodes, or
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     removing some (redundant) nodes.
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     During this phase, use the {RepresentationChanger} to insert
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     representation changes between uses that demand a particular
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //     representation and nodes that produce a different representation.
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LOWER
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RepresentationSelector {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Information for each node tracked during the fixpoint.
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  struct NodeInfo {
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MachineTypeUnion use : 15;     // Union of all usages for the node.
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool queued : 1;           // Bookkeeping for the traversal.
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool visited : 1;          // Bookkeeping for the traversal.
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MachineTypeUnion output : 15;  // Output type of the node.
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RepresentationSelector(JSGraph* jsgraph, Zone* zone,
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         RepresentationChanger* changer)
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : jsgraph_(jsgraph),
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        count_(jsgraph->graph()->NodeCount()),
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info_(zone->NewArray<NodeInfo>(count_)),
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        nodes_(zone),
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        replacements_(zone),
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        contains_js_nodes_(false),
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        phase_(PROPAGATE),
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        changer_(changer),
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        queue_(zone) {
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    memset(info_, 0, sizeof(NodeInfo) * count_);
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Run(SimplifiedLowering* lowering) {
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Run propagation phase to a fixpoint.
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TRACE(("--{Propagation phase}--\n"));
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    phase_ = PROPAGATE;
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Enqueue(jsgraph_->graph()->end());
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Process nodes from the queue until it is empty.
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (!queue_.empty()) {
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node* node = queue_.front();
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      NodeInfo* info = GetInfo(node);
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      queue_.pop();
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->queued = false;
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TRACE((" visit #%d: %s\n", node->id(), node->op()->mnemonic()));
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitNode(node, info->use, NULL);
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TRACE(("  ==> output "));
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintInfo(info->output);
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TRACE(("\n"));
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Run lowering and change insertion phase.
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TRACE(("--{Simplified lowering phase}--\n"));
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    phase_ = LOWER;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Process nodes from the collected {nodes_} vector.
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node* node = *i;
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TRACE((" visit #%d: %s\n", node->id(), node->op()->mnemonic()));
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Reuse {VisitNode()} so the representation rules are in one place.
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      VisitNode(node, GetUseInfo(node), lowering);
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Perform the final replacements.
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (NodeVector::iterator i = replacements_.begin();
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         i != replacements_.end(); ++i) {
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node* node = *i;
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node* replacement = *(++i);
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      node->ReplaceUses(replacement);
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Enqueue {node} if the {use} contains new information for that node.
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Add {node} to {nodes_} if this is the first time it's been visited.
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Enqueue(Node* node, MachineTypeUnion use = 0) {
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (phase_ != PROPAGATE) return;
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NodeInfo* info = GetInfo(node);
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!info->visited) {
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // First visit of this node.
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->visited = true;
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->queued = true;
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      nodes_.push_back(node);
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      queue_.push(node);
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      TRACE(("  initial: "));
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->use |= use;
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintUseInfo(node);
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return;
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TRACE(("   queue?: "));
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintUseInfo(node);
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if ((info->use & use) != use) {
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // New usage information for the node is available.
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (!info->queued) {
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        queue_.push(node);
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        info->queued = true;
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TRACE(("   added: "));
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TRACE((" inqueue: "));
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      info->use |= use;
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintUseInfo(node);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool lower() { return phase_ == LOWER; }
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Enqueue(Node* node, MachineType use) {
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Enqueue(node, static_cast<MachineTypeUnion>(use));
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetOutput(Node* node, MachineTypeUnion output) {
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Every node should have at most one output representation. Note that
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // phis can have 0, if they have not been used in a representation-inducing
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // instruction.
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK((output & kRepMask) == 0 ||
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           base::bits::IsPowerOfTwo32(output & kRepMask));
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GetInfo(node)->output = output;
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool BothInputsAre(Node* node, Type* type) {
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(2, node->InputCount());
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return NodeProperties::GetBounds(node->InputAt(0)).upper->Is(type) &&
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           NodeProperties::GetBounds(node->InputAt(1)).upper->Is(type);
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessInput(Node* node, int index, MachineTypeUnion use) {
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Node* input = node->InputAt(index);
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (phase_ == PROPAGATE) {
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // In the propagate phase, propagate the usage information backward.
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Enqueue(input, use);
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // In the change phase, insert a change before the use if necessary.
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((use & kRepMask) == 0) return;  // No input requirement on the use.
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MachineTypeUnion output = GetInfo(input)->output;
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if ((output & kRepMask & use) == 0) {
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Output representation doesn't match usage.
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TRACE(("  change: #%d:%s(@%d #%d:%s) ", node->id(),
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               node->op()->mnemonic(), index, input->id(),
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               input->op()->mnemonic()));
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TRACE((" from "));
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PrintInfo(output);
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TRACE((" to "));
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        PrintInfo(use);
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        TRACE(("\n"));
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Node* n = changer_->GetRepresentationFor(input, output, use);
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        node->ReplaceInput(index, n);
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessRemainingInputs(Node* node, int index) {
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_GE(index, NodeProperties::PastValueIndex(node));
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_GE(index, NodeProperties::PastContextIndex(node));
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         i < NodeProperties::PastEffectIndex(node); ++i) {
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Enqueue(node->InputAt(i));  // Effect inputs: just visit
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         i < NodeProperties::PastControlIndex(node); ++i) {
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Enqueue(node->InputAt(i));  // Control inputs: just visit
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The default, most general visitation case. For {node}, process all value,
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // context, effect, and control inputs, assuming that value inputs should have
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // {kRepTagged} representation and can observe all output values {kTypeAny}.
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitInputs(Node* node) {
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    InputIter i = node->inputs().begin();
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int j = OperatorProperties::GetValueInputCount(node->op()); j > 0;
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ++i, j--) {
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ProcessInput(node, i.index(), kMachAnyTagged);  // Value inputs
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int j = OperatorProperties::GetContextInputCount(node->op()); j > 0;
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ++i, j--) {
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      ProcessInput(node, i.index(), kMachAnyTagged);  // Context inputs
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int j = OperatorProperties::GetEffectInputCount(node->op()); j > 0;
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ++i, j--) {
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Enqueue(*i);  // Effect inputs: just visit
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    for (int j = OperatorProperties::GetControlInputCount(node->op()); j > 0;
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         ++i, j--) {
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Enqueue(*i);  // Control inputs: just visit
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetOutput(node, kMachAnyTagged);
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for binops of the I x I -> O variety.
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitBinop(Node* node, MachineTypeUnion input_use,
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                  MachineTypeUnion output) {
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(2, node->InputCount());
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessInput(node, 0, input_use);
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessInput(node, 1, input_use);
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetOutput(node, output);
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for unops of the I -> O variety.
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitUnop(Node* node, MachineTypeUnion input_use,
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 MachineTypeUnion output) {
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(1, node->InputCount());
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessInput(node, 0, input_use);
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetOutput(node, output);
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for leaf nodes.
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitLeaf(Node* node, MachineTypeUnion output) {
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_EQ(0, node->InputCount());
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetOutput(node, output);
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helpers for specific types of binops.
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitFloat64Binop(Node* node) {
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitBinop(node, kMachFloat64, kMachFloat64);
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitInt32Binop(Node* node) { VisitBinop(node, kMachInt32, kMachInt32); }
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitUint32Binop(Node* node) {
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitBinop(node, kMachUint32, kMachUint32);
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitInt64Binop(Node* node) { VisitBinop(node, kMachInt64, kMachInt64); }
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitUint64Binop(Node* node) {
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    VisitBinop(node, kMachUint64, kMachUint64);
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitFloat64Cmp(Node* node) { VisitBinop(node, kMachFloat64, kRepBit); }
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitInt32Cmp(Node* node) { VisitBinop(node, kMachInt32, kRepBit); }
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitUint32Cmp(Node* node) { VisitBinop(node, kMachUint32, kRepBit); }
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitInt64Cmp(Node* node) { VisitBinop(node, kMachInt64, kRepBit); }
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitUint64Cmp(Node* node) { VisitBinop(node, kMachUint64, kRepBit); }
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Helper for handling phis.
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitPhi(Node* node, MachineTypeUnion use,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                SimplifiedLowering* lowering) {
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // First, propagate the usage information to inputs of the phi.
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!lower()) {
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int values = OperatorProperties::GetValueInputCount(node->op());
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Propagate {use} of the phi to value inputs, and 0 to control.
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node::Inputs inputs = node->inputs();
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ++iter, --values) {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(titzer): it'd be nice to have distinguished edge kinds here.
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, iter.index(), values > 0 ? use : 0);
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Phis adapt to whatever output representation their uses demand,
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // pushing representation changes to their inputs.
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MachineTypeUnion use_rep = GetUseInfo(node) & kRepMask;
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MachineTypeUnion use_type = GetUseInfo(node) & kTypeMask;
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MachineTypeUnion rep = 0;
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (use_rep & kRepTagged) {
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rep = kRepTagged;  // Tagged overrides everything.
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (use_rep & kRepFloat64) {
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rep = kRepFloat64;
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (use_rep & kRepWord64) {
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rep = kRepWord64;
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (use_rep & kRepWord32) {
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rep = kRepWord32;
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (use_rep & kRepBit) {
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      rep = kRepBit;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // There was no representation associated with any of the uses.
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // TODO(titzer): Select the best rep using phi's type, not the usage type?
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (use_type & kTypeAny) {
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rep = kRepTagged;
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (use_type & kTypeNumber) {
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rep = kRepFloat64;
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (use_type & kTypeInt64 || use_type & kTypeUint64) {
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rep = kRepWord64;
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (use_type & kTypeInt32 || use_type & kTypeUint32) {
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rep = kRepWord32;
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else if (use_type & kTypeBool) {
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        rep = kRepBit;
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        UNREACHABLE();  // should have at least a usage type!
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Preserve the usage type, but set the representation.
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Type* upper = NodeProperties::GetBounds(node).upper;
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MachineTypeUnion output_type = rep | changer_->TypeFromUpperBound(upper);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SetOutput(node, output_type);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (lower()) {
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int values = OperatorProperties::GetValueInputCount(node->op());
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Update the phi operator.
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MachineType type = static_cast<MachineType>(output_type);
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (type != OpParameter<MachineType>(node)) {
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        node->set_op(lowering->common()->Phi(type, values));
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Convert inputs to the output representation of this phi.
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Node::Inputs inputs = node->inputs();
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      for (Node::Inputs::iterator iter(inputs.begin()); iter != inputs.end();
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           ++iter, --values) {
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(titzer): it'd be nice to have distinguished edge kinds here.
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, iter.index(), values > 0 ? output_type : 0);
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Operator* Int32Op(Node* node) {
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return changer_->Int32OperatorFor(node->opcode());
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Operator* Uint32Op(Node* node) {
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return changer_->Uint32OperatorFor(node->opcode());
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const Operator* Float64Op(Node* node) {
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return changer_->Float64OperatorFor(node->opcode());
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static MachineType AssumeImplicitFloat32Change(MachineType type) {
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(titzer): Assume loads of float32 change representation to float64.
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fix this with full support for float32 representations.
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (type & kRepFloat32) {
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return static_cast<MachineType>((type & ~kRepFloat32) | kRepFloat64);
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return type;
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Dispatching routine for visiting the node {node} with the usage {use}.
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Depending on the operator, propagate new usage info to the inputs.
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VisitNode(Node* node, MachineTypeUnion use,
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                 SimplifiedLowering* lowering) {
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (node->opcode()) {
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //------------------------------------------------------------------
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Common operators.
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //------------------------------------------------------------------
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStart:
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kDead:
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, 0);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kParameter: {
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(titzer): use representation from linkage.
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Type* upper = NodeProperties::GetBounds(node).upper;
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, 0);
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, kRepTagged | changer_->TypeFromUpperBound(upper));
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return;
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Constant:
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, kRepWord32);
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Constant:
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, kRepWord64);
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Constant:
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, kRepFloat64);
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kExternalConstant:
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, kMachPtr);
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberConstant:
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, kRepTagged);
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kHeapConstant:
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitLeaf(node, kRepTagged);
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kEnd:
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kIfTrue:
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kIfFalse:
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kReturn:
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kMerge:
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kThrow:
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitInputs(node);  // default visit for all node inputs.
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kBranch:
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, kRepBit);
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Enqueue(NodeProperties::GetControlInput(node, 0));
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kPhi:
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitPhi(node, use, lowering);
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//------------------------------------------------------------------
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// JavaScript operators.
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//------------------------------------------------------------------
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// For now, we assume that all JS operators were too complex to lower
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to Simplified and that they will always require tagged value inputs
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// and produce tagged value outputs.
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TODO(turbofan): it might be possible to lower some JSOperators here,
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// but that responsibility really lies in the typed lowering phase.
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEFINE_JS_CASE(x) case IrOpcode::k##x:
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        JS_OP_LIST(DEFINE_JS_CASE)
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEFINE_JS_CASE
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        contains_js_nodes_ = true;
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitInputs(node);
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return SetOutput(node, kRepTagged);
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //------------------------------------------------------------------
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Simplified operators.
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //------------------------------------------------------------------
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kBooleanNot: {
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) {
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MachineTypeUnion input = GetInfo(node->InputAt(0))->output;
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (input & kRepBit) {
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // BooleanNot(x: kRepBit) => WordEqual(x, #0)
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->set_op(lowering->machine()->WordEqual());
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->set_op(lowering->machine()->WordEqual());
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // No input representation requirement; adapt during lowering.
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ProcessInput(node, 0, kTypeBool);
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          SetOutput(node, kRepBit);
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kBooleanToNumber: {
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) {
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MachineTypeUnion input = GetInfo(node->InputAt(0))->output;
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (input & kRepBit) {
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // BooleanToNumber(x: kRepBit) => x
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DeferReplacement(node, node->InputAt(0));
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->set_op(lowering->machine()->WordEqual());
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // No input representation requirement; adapt during lowering.
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          ProcessInput(node, 0, kTypeBool);
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          SetOutput(node, kMachInt32);
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberEqual:
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberLessThan:
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberLessThanOrEqual: {
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Number comparisons reduce to integer comparisons for integer inputs.
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (BothInputsAre(node, Type::Signed32())) {
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // => signed Int32Cmp
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitInt32Cmp(node);
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (lower()) node->set_op(Int32Op(node));
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (BothInputsAre(node, Type::Unsigned32())) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // => unsigned Int32Cmp
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitUint32Cmp(node);
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (lower()) node->set_op(Uint32Op(node));
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // => Float64Cmp
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitFloat64Cmp(node);
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (lower()) node->set_op(Float64Op(node));
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberAdd:
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberSubtract: {
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Add and subtract reduce to Int32Add/Sub if the inputs
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // are already integers and all uses are truncating.
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (BothInputsAre(node, Type::Signed32()) &&
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            (use & (kTypeUint32 | kTypeNumber | kTypeAny)) == 0) {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // => signed Int32Add/Sub
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitInt32Binop(node);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (lower()) node->set_op(Int32Op(node));
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else if (BothInputsAre(node, Type::Unsigned32()) &&
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   (use & (kTypeInt32 | kTypeNumber | kTypeAny)) == 0) {
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // => unsigned Int32Add/Sub
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitUint32Binop(node);
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (lower()) node->set_op(Uint32Op(node));
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // => Float64Add/Sub
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitFloat64Binop(node);
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if (lower()) node->set_op(Float64Op(node));
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberMultiply:
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberDivide:
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberModulus: {
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // Float64Mul/Div/Mod
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitFloat64Binop(node);
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) node->set_op(Float64Op(node));
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberToInt32: {
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MachineTypeUnion use_rep = use & kRepMask;
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) {
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MachineTypeUnion in = GetInfo(node->InputAt(0))->output;
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if ((in & kTypeMask) == kTypeInt32 || (in & kRepMask) == kRepWord32) {
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // If the input has type int32, or is already a word32, just change
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // representation if necessary.
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep);
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DeferReplacement(node, node->InputAt(0));
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // Require the input in float64 format and perform truncation.
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // TODO(turbofan): avoid a truncation with a smi check.
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            VisitUnop(node, kTypeInt32 | kRepFloat64, kTypeInt32 | kRepWord32);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->set_op(lowering->machine()->TruncateFloat64ToInt32());
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Propagate a type to the input, but pass through representation.
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitUnop(node, kTypeInt32, kTypeInt32 | use_rep);
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kNumberToUint32: {
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MachineTypeUnion use_rep = use & kRepMask;
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) {
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          MachineTypeUnion in = GetInfo(node->InputAt(0))->output;
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          if ((in & kTypeMask) == kTypeUint32 ||
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              (in & kRepMask) == kRepWord32) {
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // The input has type int32, just change representation.
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep);
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            DeferReplacement(node, node->InputAt(0));
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          } else {
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // Require the input in float64 format to perform truncation.
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            // TODO(turbofan): avoid the truncation with a smi check.
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            VisitUnop(node, kTypeUint32 | kRepFloat64,
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                      kTypeUint32 | kRepWord32);
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            node->set_op(lowering->machine()->TruncateFloat64ToInt32());
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          }
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        } else {
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          // Propagate a type to the input, but pass through representation.
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch          VisitUnop(node, kTypeUint32, kTypeUint32 | use_rep);
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        }
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kReferenceEqual: {
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitBinop(node, kMachAnyTagged, kRepBit);
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) node->set_op(lowering->machine()->WordEqual());
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStringEqual: {
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitBinop(node, kMachAnyTagged, kRepBit);
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoStringEqual(node);
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStringLessThan: {
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitBinop(node, kMachAnyTagged, kRepBit);
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoStringLessThan(node);
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStringLessThanOrEqual: {
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitBinop(node, kMachAnyTagged, kRepBit);
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoStringLessThanOrEqual(node);
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStringAdd: {
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitBinop(node, kMachAnyTagged, kMachAnyTagged);
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoStringAdd(node);
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kLoadField: {
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FieldAccess access = FieldAccessOf(node->op());
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, changer_->TypeForBasePointer(access));
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessRemainingInputs(node, 1);
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, AssumeImplicitFloat32Change(access.machine_type));
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoLoadField(node);
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStoreField: {
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        FieldAccess access = FieldAccessOf(node->op());
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, changer_->TypeForBasePointer(access));
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 1, AssumeImplicitFloat32Change(access.machine_type));
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessRemainingInputs(node, 2);
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, 0);
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoStoreField(node);
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kLoadElement: {
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ElementAccess access = ElementAccessOf(node->op());
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, changer_->TypeForBasePointer(access));
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 1, kMachInt32);  // element index
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 2, kMachInt32);  // length
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessRemainingInputs(node, 3);
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, AssumeImplicitFloat32Change(access.machine_type));
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoLoadElement(node);
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStoreElement: {
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ElementAccess access = ElementAccessOf(node->op());
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, changer_->TypeForBasePointer(access));
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 1, kMachInt32);  // element index
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 2, kMachInt32);  // length
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 3, AssumeImplicitFloat32Change(access.machine_type));
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessRemainingInputs(node, 4);
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, 0);
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        if (lower()) lowering->DoStoreElement(node);
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //------------------------------------------------------------------
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Machine-level operators.
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      //------------------------------------------------------------------
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kLoad: {
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(titzer): machine loads/stores need to know BaseTaggedness!?
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MachineType tBase = kRepTagged;
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        LoadRepresentation rep = OpParameter<LoadRepresentation>(node);
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, tBase);   // pointer or object
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 1, kMachInt32);  // index
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessRemainingInputs(node, 2);
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, rep);
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kStore: {
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(titzer): machine loads/stores need to know BaseTaggedness!?
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        MachineType tBase = kRepTagged;
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        StoreRepresentation rep = OpParameter<StoreRepresentation>(node);
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 0, tBase);   // pointer or object
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 1, kMachInt32);  // index
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessInput(node, 2, rep.machine_type());
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ProcessRemainingInputs(node, 3);
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        SetOutput(node, 0);
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Shr:
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We output unsigned int32 for shift right because JavaScript.
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitBinop(node, kRepWord32, kRepWord32 | kTypeUint32);
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32And:
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Or:
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Xor:
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Shl:
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Sar:
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // We use signed int32 as the output type for these word32 operations,
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // though the machine bits are the same for either signed or unsigned,
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // because JavaScript considers the result from these operations signed.
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitBinop(node, kRepWord32, kRepWord32 | kTypeInt32);
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord32Equal:
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitBinop(node, kRepWord32, kRepBit);
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Add:
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Sub:
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Mul:
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Div:
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32Mod:
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitInt32Binop(node);
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32UDiv:
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32UMod:
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUint32Binop(node);
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32LessThan:
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt32LessThanOrEqual:
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitInt32Cmp(node);
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kUint32LessThan:
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kUint32LessThanOrEqual:
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUint32Cmp(node);
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Add:
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Sub:
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Mul:
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Div:
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64Mod:
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitInt64Binop(node);
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64LessThan:
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64LessThanOrEqual:
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitInt64Cmp(node);
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64UDiv:
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kInt64UMod:
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUint64Binop(node);
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64And:
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64Or:
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64Xor:
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64Shl:
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64Shr:
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64Sar:
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitBinop(node, kRepWord64, kRepWord64);
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kWord64Equal:
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitBinop(node, kRepWord64, kRepBit);
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kChangeInt32ToInt64:
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeInt32 | kRepWord32,
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeInt32 | kRepWord64);
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kChangeUint32ToUint64:
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeUint32 | kRepWord32,
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeUint32 | kRepWord64);
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kTruncateInt64ToInt32:
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        // TODO(titzer): Is kTypeInt32 correct here?
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeInt32 | kRepWord64,
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeInt32 | kRepWord32);
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kChangeInt32ToFloat64:
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeInt32 | kRepWord32,
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeInt32 | kRepFloat64);
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kChangeUint32ToFloat64:
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeUint32 | kRepWord32,
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeUint32 | kRepFloat64);
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kChangeFloat64ToInt32:
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeInt32 | kRepFloat64,
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeInt32 | kRepWord32);
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kChangeFloat64ToUint32:
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kTypeUint32 | kRepFloat64,
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                         kTypeUint32 | kRepWord32);
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Add:
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Sub:
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Mul:
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Div:
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Mod:
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitFloat64Binop(node);
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Sqrt:
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitUnop(node, kMachFloat64, kMachFloat64);
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64Equal:
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64LessThan:
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IrOpcode::kFloat64LessThanOrEqual:
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return VisitFloat64Cmp(node);
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      default:
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        VisitInputs(node);
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        break;
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DeferReplacement(Node* node, Node* replacement) {
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (replacement->id() < count_) {
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Replace with a previously existing node eagerly.
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      node->ReplaceUses(replacement);
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Otherwise, we are replacing a node with a representation change.
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Such a substitution must be done after all lowering is done, because
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // new nodes do not have {NodeInfo} entries, and that would confuse
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // the representation change insertion for uses of it.
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      replacements_.push_back(node);
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      replacements_.push_back(replacement);
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(titzer) node->RemoveAllInputs();  // Node is now dead.
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrintUseInfo(Node* node) {
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TRACE(("#%d:%-20s ", node->id(), node->op()->mnemonic()));
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PrintInfo(GetUseInfo(node));
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TRACE(("\n"));
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrintInfo(MachineTypeUnion info) {
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trace_representation) {
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      OFStream os(stdout);
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      os << static_cast<MachineType>(info);
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSGraph* jsgraph_;
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int count_;                       // number of nodes in the graph
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeInfo* info_;                  // node id -> usage information
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeVector nodes_;                // collected nodes
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeVector replacements_;         // replacements to be done after lowering
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool contains_js_nodes_;          // {true} if a JS operator was seen
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Phase phase_;                     // current phase of algorithm
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RepresentationChanger* changer_;  // for inserting representation changes
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ZoneQueue<Node*> queue_;          // queue for traversing the graph
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  NodeInfo* GetInfo(Node* node) {
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(node->id() >= 0);
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(node->id() < count_);
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return &info_[node->id()];
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MachineTypeUnion GetUseInfo(Node* node) { return GetInfo(node)->use; }
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* SimplifiedLowering::IsTagged(Node* node) {
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(titzer): factor this out to a TaggingScheme abstraction.
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  STATIC_ASSERT(kSmiTagMask == 1);  // Only works if tag is the low bit.
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return graph()->NewNode(machine()->WordAnd(), node,
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          jsgraph()->Int32Constant(kSmiTagMask));
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::LowerAllNodes() {
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SimplifiedOperatorBuilder simplified(graph()->zone());
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RepresentationChanger changer(jsgraph(), &simplified,
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                graph()->zone()->isolate());
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  RepresentationSelector selector(jsgraph(), zone(), &changer);
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  selector.Run(this);
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* SimplifiedLowering::Untag(Node* node) {
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(titzer): factor this out to a TaggingScheme abstraction.
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize);
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return graph()->NewNode(machine()->WordSar(), node, shift_amount);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* SimplifiedLowering::SmiTag(Node* node) {
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(titzer): factor this out to a TaggingScheme abstraction.
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* shift_amount = jsgraph()->Int32Constant(kSmiTagSize + kSmiShiftSize);
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return graph()->NewNode(machine()->WordShl(), node, shift_amount);
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* SimplifiedLowering::OffsetMinusTagConstant(int32_t offset) {
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return jsgraph()->Int32Constant(offset - kHeapObjectTag);
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic WriteBarrierKind ComputeWriteBarrierKind(BaseTaggedness base_is_tagged,
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                MachineType representation,
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                                Type* type) {
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(turbofan): skip write barriers for Smis, etc.
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (base_is_tagged == kTaggedBase &&
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      RepresentationOf(representation) == kRepTagged) {
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Write barriers are only for writes into heap objects (i.e. tagged base).
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return kFullWriteBarrier;
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return kNoWriteBarrier;
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoLoadField(Node* node) {
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const FieldAccess& access = FieldAccessOf(node->op());
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(machine()->Load(access.machine_type));
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->InsertInput(zone(), 1, offset);
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoStoreField(Node* node) {
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const FieldAccess& access = FieldAccessOf(node->op());
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WriteBarrierKind kind = ComputeWriteBarrierKind(
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      access.base_is_tagged, access.machine_type, access.type);
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      machine()->Store(StoreRepresentation(access.machine_type, kind)));
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->InsertInput(zone(), 1, offset);
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* SimplifiedLowering::ComputeIndex(const ElementAccess& access,
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       Node* index) {
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int element_size = ElementSizeOf(access.machine_type);
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (element_size != 1) {
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    index = graph()->NewNode(machine()->Int32Mul(),
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             jsgraph()->Int32Constant(element_size), index);
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int fixed_offset = access.header_size - access.tag();
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (fixed_offset == 0) return index;
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return graph()->NewNode(machine()->Int32Add(), index,
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          jsgraph()->Int32Constant(fixed_offset));
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoLoadElement(Node* node) {
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ElementAccess& access = ElementAccessOf(node->op());
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(machine()->Load(access.machine_type));
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->RemoveInput(2);
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoStoreElement(Node* node) {
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ElementAccess& access = ElementAccessOf(node->op());
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  WriteBarrierKind kind = ComputeWriteBarrierKind(
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      access.base_is_tagged, access.machine_type, access.type);
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      machine()->Store(StoreRepresentation(access.machine_type, kind)));
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(1, ComputeIndex(access, node->InputAt(1)));
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->RemoveInput(2);
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoStringAdd(Node* node) {
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Callable callable = CodeFactory::StringAdd(
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      zone()->isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* desc =
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone());
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(common()->Call(desc));
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(callable.code()));
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->AppendInput(zone(), jsgraph()->UndefinedConstant());
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->AppendInput(zone(), graph()->start());
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->AppendInput(zone(), graph()->start());
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochNode* SimplifiedLowering::StringComparison(Node* node, bool requires_ordering) {
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CEntryStub stub(zone()->isolate(), 1);
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Runtime::FunctionId f =
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      requires_ordering ? Runtime::kStringCompare : Runtime::kStringEquals;
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ExternalReference ref(f, zone()->isolate());
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Operator::Properties props = node->op()->properties();
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(mstarzinger): We should call StringCompareStub here instead, once an
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // interface descriptor is available for it.
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(f, 2, props, zone());
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return graph()->NewNode(common()->Call(desc),
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          jsgraph()->HeapConstant(stub.GetCode()),
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          NodeProperties::GetValueInput(node, 0),
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          NodeProperties::GetValueInput(node, 1),
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          jsgraph()->ExternalConstant(ref),
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          jsgraph()->Int32Constant(2),
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                          jsgraph()->UndefinedConstant());
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoStringEqual(Node* node) {
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(machine()->WordEqual());
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(0, StringComparison(node, false));
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoStringLessThan(Node* node) {
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(machine()->IntLessThan());
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(0, StringComparison(node, true));
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->set_op(machine()->IntLessThanOrEqual());
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(0, StringComparison(node, true));
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace compiler
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace internal
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8
946