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