blob: 88931f5df7eaa18019138869c00c3ab3b7990b4d [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/compiler/simplified-lowering.h"
6
Emily Bernierd0a1eb72015-03-24 16:35:39 -04007#include <limits>
8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include "src/base/bits.h"
10#include "src/code-factory.h"
11#include "src/compiler/common-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040012#include "src/compiler/diamond.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040013#include "src/compiler/linkage.h"
14#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/compiler/node-properties.h"
16#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000017#include "src/compiler/representation-change.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000018#include "src/compiler/simplified-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019#include "src/compiler/source-position.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021#include "src/type-cache.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000022
23namespace v8 {
24namespace internal {
25namespace compiler {
26
27// Macro for outputting trace information from representation inference.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028#define TRACE(...) \
29 do { \
30 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \
31 } while (false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032
33// Representation selection and lowering of {Simplified} operators to machine
34// operators are interwined. We use a fixpoint calculation to compute both the
35// output representation and the best possible lowering for {Simplified} nodes.
36// Representation change insertion ensures that all values are in the correct
37// machine representation after this phase, as dictated by the machine
38// operators themselves.
39enum Phase {
40 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
41 // backwards from uses to definitions, around cycles in phis, according
42 // to local rules for each operator.
43 // During this phase, the usage information for a node determines the best
44 // possible lowering for each operator so far, and that in turn determines
45 // the output representation.
46 // Therefore, to be correct, this phase must iterate to a fixpoint before
47 // the next phase can begin.
48 PROPAGATE,
49
50 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some
51 // operators for some nodes, expanding some nodes to multiple nodes, or
52 // removing some (redundant) nodes.
53 // During this phase, use the {RepresentationChanger} to insert
54 // representation changes between uses that demand a particular
55 // representation and nodes that produce a different representation.
56 LOWER
57};
58
59
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060namespace {
61
62// The {UseInfo} class is used to describe a use of an input of a node.
63//
64// This information is used in two different ways, based on the phase:
65//
66// 1. During propagation, the use info is used to inform the input node
67// about what part of the input is used (we call this truncation) and what
68// is the preferred representation.
69//
70// 2. During lowering, the use info is used to properly convert the input
71// to the preferred representation. The preferred representation might be
72// insufficient to do the conversion (e.g. word32->float64 conv), so we also
73// need the signedness information to produce the correct value.
74class UseInfo {
75 public:
76 UseInfo(MachineRepresentation preferred, Truncation truncation)
77 : preferred_(preferred), truncation_(truncation) {}
78 static UseInfo TruncatingWord32() {
79 return UseInfo(MachineRepresentation::kWord32, Truncation::Word32());
80 }
81 static UseInfo TruncatingWord64() {
82 return UseInfo(MachineRepresentation::kWord64, Truncation::Word64());
83 }
84 static UseInfo Bool() {
85 return UseInfo(MachineRepresentation::kBit, Truncation::Bool());
86 }
87 static UseInfo Float32() {
88 return UseInfo(MachineRepresentation::kFloat32, Truncation::Float32());
89 }
90 static UseInfo Float64() {
91 return UseInfo(MachineRepresentation::kFloat64, Truncation::Float64());
92 }
93 static UseInfo PointerInt() {
94 return kPointerSize == 4 ? TruncatingWord32() : TruncatingWord64();
95 }
96 static UseInfo AnyTagged() {
97 return UseInfo(MachineRepresentation::kTagged, Truncation::Any());
98 }
99
100 // Undetermined representation.
101 static UseInfo Any() {
102 return UseInfo(MachineRepresentation::kNone, Truncation::Any());
103 }
104 static UseInfo None() {
105 return UseInfo(MachineRepresentation::kNone, Truncation::None());
106 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 static UseInfo AnyTruncatingToBool() {
108 return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
109 }
110
111 MachineRepresentation preferred() const { return preferred_; }
112 Truncation truncation() const { return truncation_; }
113
114 private:
115 MachineRepresentation preferred_;
116 Truncation truncation_;
117};
118
119
120UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
121 switch (rep) {
122 case MachineRepresentation::kTagged:
123 return UseInfo::AnyTagged();
124 case MachineRepresentation::kFloat64:
125 return UseInfo::Float64();
126 case MachineRepresentation::kFloat32:
127 return UseInfo::Float32();
128 case MachineRepresentation::kWord64:
129 return UseInfo::TruncatingWord64();
130 case MachineRepresentation::kWord8:
131 case MachineRepresentation::kWord16:
132 case MachineRepresentation::kWord32:
133 return UseInfo::TruncatingWord32();
134 case MachineRepresentation::kBit:
135 return UseInfo::Bool();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100136 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 case MachineRepresentation::kNone:
138 break;
139 }
140 UNREACHABLE();
141 return UseInfo::None();
142}
143
144
145UseInfo UseInfoForBasePointer(const FieldAccess& access) {
146 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
147}
148
149
150UseInfo UseInfoForBasePointer(const ElementAccess& access) {
151 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
152}
153
154
155#ifdef DEBUG
156// Helpers for monotonicity checking.
157bool MachineRepresentationIsSubtype(MachineRepresentation r1,
158 MachineRepresentation r2) {
159 switch (r1) {
160 case MachineRepresentation::kNone:
161 return true;
162 case MachineRepresentation::kBit:
163 return r2 == MachineRepresentation::kBit ||
164 r2 == MachineRepresentation::kTagged;
165 case MachineRepresentation::kWord8:
166 return r2 == MachineRepresentation::kWord8 ||
167 r2 == MachineRepresentation::kWord16 ||
168 r2 == MachineRepresentation::kWord32 ||
169 r2 == MachineRepresentation::kWord64 ||
170 r2 == MachineRepresentation::kFloat32 ||
171 r2 == MachineRepresentation::kFloat64 ||
172 r2 == MachineRepresentation::kTagged;
173 case MachineRepresentation::kWord16:
174 return r2 == MachineRepresentation::kWord16 ||
175 r2 == MachineRepresentation::kWord32 ||
176 r2 == MachineRepresentation::kWord64 ||
177 r2 == MachineRepresentation::kFloat32 ||
178 r2 == MachineRepresentation::kFloat64 ||
179 r2 == MachineRepresentation::kTagged;
180 case MachineRepresentation::kWord32:
181 return r2 == MachineRepresentation::kWord32 ||
182 r2 == MachineRepresentation::kWord64 ||
183 r2 == MachineRepresentation::kFloat64 ||
184 r2 == MachineRepresentation::kTagged;
185 case MachineRepresentation::kWord64:
186 return r2 == MachineRepresentation::kWord64;
187 case MachineRepresentation::kFloat32:
188 return r2 == MachineRepresentation::kFloat32 ||
189 r2 == MachineRepresentation::kFloat64 ||
190 r2 == MachineRepresentation::kTagged;
191 case MachineRepresentation::kFloat64:
192 return r2 == MachineRepresentation::kFloat64 ||
193 r2 == MachineRepresentation::kTagged;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100194 case MachineRepresentation::kSimd128:
195 return r2 == MachineRepresentation::kSimd128 ||
196 r2 == MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000197 case MachineRepresentation::kTagged:
198 return r2 == MachineRepresentation::kTagged;
199 }
200 UNREACHABLE();
201 return false;
202}
203
204
205class InputUseInfos {
206 public:
207 explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
208
209 void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
210 if (input_use_infos_.empty()) {
211 input_use_infos_.resize(node->InputCount(), UseInfo::None());
212 }
213 // Check that the new use informatin is a super-type of the old
214 // one.
215 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
216 input_use_infos_[index] = use_info;
217 }
218
219 private:
220 ZoneVector<UseInfo> input_use_infos_;
221
222 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
223 return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) &&
224 use1.truncation().IsLessGeneralThan(use2.truncation());
225 }
226};
227
228#endif // DEBUG
229
230} // namespace
231
232
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233class RepresentationSelector {
234 public:
235 // Information for each node tracked during the fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 class NodeInfo {
237 public:
238 // Adds new use to the node. Returns true if something has changed
239 // and the node has to be requeued.
240 bool AddUse(UseInfo info) {
241 Truncation old_truncation = truncation_;
242 truncation_ = Truncation::Generalize(truncation_, info.truncation());
243 return truncation_ != old_truncation;
244 }
245
246 void set_queued(bool value) { queued_ = value; }
247 bool queued() const { return queued_; }
248 void set_visited() { visited_ = true; }
249 bool visited() const { return visited_; }
250 Truncation truncation() const { return truncation_; }
Ben Murdochda12d292016-06-02 14:46:10 +0100251 void set_output(MachineRepresentation output) { representation_ = output; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252
Ben Murdochda12d292016-06-02 14:46:10 +0100253 MachineRepresentation representation() const { return representation_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254
255 private:
Ben Murdochda12d292016-06-02 14:46:10 +0100256 bool queued_ = false; // Bookkeeping for the traversal.
257 bool visited_ = false; // Bookkeeping for the traversal.
258 MachineRepresentation representation_ =
259 MachineRepresentation::kNone; // Output representation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260 Truncation truncation_ = Truncation::None(); // Information about uses.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 };
262
263 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 RepresentationChanger* changer,
265 SourcePositionTable* source_positions)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 : jsgraph_(jsgraph),
267 count_(jsgraph->graph()->NodeCount()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 info_(count_, zone),
269#ifdef DEBUG
270 node_input_use_infos_(count_, InputUseInfos(zone), zone),
271#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 nodes_(zone),
273 replacements_(zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 phase_(PROPAGATE),
275 changer_(changer),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 queue_(zone),
277 source_positions_(source_positions),
278 type_cache_(TypeCache::Get()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 }
280
281 void Run(SimplifiedLowering* lowering) {
282 // Run propagation phase to a fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 TRACE("--{Propagation phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 phase_ = PROPAGATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 EnqueueInitial(jsgraph_->graph()->end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 // Process nodes from the queue until it is empty.
287 while (!queue_.empty()) {
288 Node* node = queue_.front();
289 NodeInfo* info = GetInfo(node);
290 queue_.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000291 info->set_queued(false);
292 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
293 VisitNode(node, info->truncation(), nullptr);
294 TRACE(" ==> output ");
295 PrintOutputInfo(info);
296 TRACE("\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 }
298
299 // Run lowering and change insertion phase.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300 TRACE("--{Simplified lowering phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301 phase_ = LOWER;
302 // Process nodes from the collected {nodes_} vector.
303 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
304 Node* node = *i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000305 NodeInfo* info = GetInfo(node);
306 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 // Reuse {VisitNode()} so the representation rules are in one place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 SourcePositionTable::Scope scope(
309 source_positions_, source_positions_->GetSourcePosition(node));
310 VisitNode(node, info->truncation(), lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000311 }
312
313 // Perform the final replacements.
314 for (NodeVector::iterator i = replacements_.begin();
315 i != replacements_.end(); ++i) {
316 Node* node = *i;
317 Node* replacement = *(++i);
318 node->ReplaceUses(replacement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000319 // We also need to replace the node in the rest of the vector.
320 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
321 ++j;
322 if (*j == node) *j = replacement;
323 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000324 }
325 }
326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 void EnqueueInitial(Node* node) {
328 NodeInfo* info = GetInfo(node);
329 info->set_visited();
330 info->set_queued(true);
331 nodes_.push_back(node);
332 queue_.push(node);
333 }
334
335 // Enqueue {use_node}'s {index} input if the {use} contains new information
336 // for that input node. Add the input to {nodes_} if this is the first time
337 // it's been visited.
338 void EnqueueInput(Node* use_node, int index,
339 UseInfo use_info = UseInfo::None()) {
340 Node* node = use_node->InputAt(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 if (phase_ != PROPAGATE) return;
342 NodeInfo* info = GetInfo(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343#ifdef DEBUG
344 // Check monotonicity of input requirements.
345 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
346 use_info);
347#endif // DEBUG
348 if (!info->visited()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000349 // First visit of this node.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 info->set_visited();
351 info->set_queued(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 nodes_.push_back(node);
353 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354 TRACE(" initial: ");
355 info->AddUse(use_info);
356 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000357 return;
358 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 TRACE(" queue?: ");
360 PrintTruncation(info->truncation());
361 if (info->AddUse(use_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 // New usage information for the node is available.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 if (!info->queued()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365 info->set_queued(true);
366 TRACE(" added: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000367 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 TRACE(" inqueue: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000371 }
372 }
373
374 bool lower() { return phase_ == LOWER; }
375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 void EnqueueUses(Node* node) {
377 for (Edge edge : node->use_edges()) {
378 if (NodeProperties::IsValueEdge(edge)) {
379 Node* const user = edge.from();
380 if (user->id() < count_) {
381 // New type information for the node is available.
382 NodeInfo* info = GetInfo(user);
383 // Enqueue the node only if we are sure it is reachable from
384 // the end and it has not been queued yet.
385 if (info->visited() && !info->queued()) {
386 queue_.push(user);
387 info->set_queued(true);
388 }
389 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400390 }
391 }
392 }
393
Ben Murdochda12d292016-06-02 14:46:10 +0100394 void SetOutput(Node* node, MachineRepresentation representation) {
395 NodeInfo* info = GetInfo(node);
396 DCHECK(
397 MachineRepresentationIsSubtype(info->representation(), representation));
398 info->set_output(representation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 }
400
Ben Murdochda12d292016-06-02 14:46:10 +0100401 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402
403 bool BothInputsAreSigned32(Node* node) {
404 DCHECK_EQ(2, node->InputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100405 return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) &&
406 GetUpperBound(node->InputAt(1))->Is(Type::Signed32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000407 }
408
409 bool BothInputsAreUnsigned32(Node* node) {
410 DCHECK_EQ(2, node->InputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100411 return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) &&
412 GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000413 }
414
415 bool BothInputsAre(Node* node, Type* type) {
416 DCHECK_EQ(2, node->InputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100417 return GetUpperBound(node->InputAt(0))->Is(type) &&
418 GetUpperBound(node->InputAt(1))->Is(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 }
420
421 void ConvertInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000422 Node* input = node->InputAt(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 // In the change phase, insert a change before the use if necessary.
424 if (use.preferred() == MachineRepresentation::kNone)
425 return; // No input requirement on the use.
426 NodeInfo* input_info = GetInfo(input);
427 MachineRepresentation input_rep = input_info->representation();
428 if (input_rep != use.preferred()) {
429 // Output representation doesn't match usage.
430 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
431 index, input->id(), input->op()->mnemonic());
432 TRACE(" from ");
433 PrintOutputInfo(input_info);
434 TRACE(" to ");
435 PrintUseInfo(use);
436 TRACE("\n");
437 Node* n = changer_->GetRepresentationFor(
Ben Murdochda12d292016-06-02 14:46:10 +0100438 input, input_info->representation(), GetUpperBound(input),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 use.preferred(), use.truncation());
440 node->ReplaceInput(index, n);
441 }
442 }
443
444 void ProcessInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445 if (phase_ == PROPAGATE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 EnqueueInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000447 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000448 ConvertInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000449 }
450 }
451
452 void ProcessRemainingInputs(Node* node, int index) {
453 DCHECK_GE(index, NodeProperties::PastValueIndex(node));
454 DCHECK_GE(index, NodeProperties::PastContextIndex(node));
455 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
456 i < NodeProperties::PastEffectIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 EnqueueInput(node, i); // Effect inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000458 }
459 for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
460 i < NodeProperties::PastControlIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 EnqueueInput(node, i); // Control inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462 }
463 }
464
465 // The default, most general visitation case. For {node}, process all value,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 // context, frame state, effect, and control inputs, assuming that value
467 // inputs should have {kRepTagged} representation and can observe all output
468 // values {kTypeAny}.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 void VisitInputs(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470 int tagged_count = node->op()->ValueInputCount() +
471 OperatorProperties::GetContextInputCount(node->op());
472 // Visit value and context inputs as tagged.
473 for (int i = 0; i < tagged_count; i++) {
474 ProcessInput(node, i, UseInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 // Only enqueue other inputs (framestates, effects, control).
477 for (int i = tagged_count; i < node->InputCount(); i++) {
478 EnqueueInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000479 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000480 }
481
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482 // Helper for binops of the R x L -> O variety.
483 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
Ben Murdochda12d292016-06-02 14:46:10 +0100484 MachineRepresentation output) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000485 DCHECK_EQ(2, node->op()->ValueInputCount());
486 ProcessInput(node, 0, left_use);
487 ProcessInput(node, 1, right_use);
488 for (int i = 2; i < node->InputCount(); i++) {
489 EnqueueInput(node, i);
490 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000491 SetOutput(node, output);
492 }
493
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 // Helper for binops of the I x I -> O variety.
Ben Murdochda12d292016-06-02 14:46:10 +0100495 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 VisitBinop(node, input_use, input_use, output);
497 }
498
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 // Helper for unops of the I -> O variety.
Ben Murdochda12d292016-06-02 14:46:10 +0100500 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000501 DCHECK_EQ(1, node->InputCount());
502 ProcessInput(node, 0, input_use);
503 SetOutput(node, output);
504 }
505
506 // Helper for leaf nodes.
Ben Murdochda12d292016-06-02 14:46:10 +0100507 void VisitLeaf(Node* node, MachineRepresentation output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000508 DCHECK_EQ(0, node->InputCount());
509 SetOutput(node, output);
510 }
511
512 // Helpers for specific types of binops.
513 void VisitFloat64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100514 VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000515 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 void VisitInt32Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100517 VisitBinop(node, UseInfo::TruncatingWord32(),
518 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519 }
520 void VisitWord32TruncatingBinop(Node* node) {
521 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100522 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000524 void VisitUint32Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100525 VisitBinop(node, UseInfo::TruncatingWord32(),
526 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000527 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 void VisitInt64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100529 VisitBinop(node, UseInfo::TruncatingWord64(),
530 MachineRepresentation::kWord64);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000531 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000532 void VisitUint64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100533 VisitBinop(node, UseInfo::TruncatingWord64(),
534 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 void VisitFloat64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100537 VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000538 }
539 void VisitInt32Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100540 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000541 }
542 void VisitUint32Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100543 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 }
545 void VisitInt64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100546 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000547 }
548 void VisitUint64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100549 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000550 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400552 // Infer representation for phi-like nodes.
Ben Murdochda12d292016-06-02 14:46:10 +0100553 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 // Compute the representation.
Ben Murdochda12d292016-06-02 14:46:10 +0100555 Type* type = GetUpperBound(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 if (type->Is(Type::None())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100557 return MachineRepresentation::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100559 return MachineRepresentation::kWord32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 } else if (use.TruncatesToWord32()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100561 return MachineRepresentation::kWord32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562 } else if (type->Is(Type::Boolean())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100563 return MachineRepresentation::kBit;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000564 } else if (type->Is(Type::Number())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100565 return MachineRepresentation::kFloat64;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 } else if (type->Is(Type::Internal())) {
567 // We mark (u)int64 as Type::Internal.
568 // TODO(jarin) This is a workaround for our lack of (u)int64
569 // types. This can be removed once we can represent (u)int64
570 // unambiguously. (At the moment internal objects, such as the hole,
571 // are also Type::Internal()).
572 bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
573 MachineRepresentation::kWord64;
574#ifdef DEBUG
575 // Check that all the inputs agree on being Word64.
576 for (int i = 1; i < node->op()->ValueInputCount(); i++) {
577 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
578 MachineRepresentation::kWord64);
579 }
580#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100581 return is_word64 ? MachineRepresentation::kWord64
582 : MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 }
Ben Murdochda12d292016-06-02 14:46:10 +0100584 return MachineRepresentation::kTagged;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400585 }
586
587 // Helper for handling selects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 void VisitSelect(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590 ProcessInput(node, 0, UseInfo::Bool());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400591
Ben Murdochda12d292016-06-02 14:46:10 +0100592 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 SetOutput(node, output);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000594
595 if (lower()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400596 // Update the select operator.
597 SelectParameters p = SelectParametersOf(node->op());
Ben Murdochda12d292016-06-02 14:46:10 +0100598 if (output != p.representation()) {
599 NodeProperties::ChangeOp(node,
600 lowering->common()->Select(output, p.hint()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400601 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400602 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 // Convert inputs to the output representation of this phi, pass the
604 // truncation truncation along.
Ben Murdochda12d292016-06-02 14:46:10 +0100605 UseInfo input_use(output, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606 ProcessInput(node, 1, input_use);
607 ProcessInput(node, 2, input_use);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 }
609
610 // Helper for handling phis.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 void VisitPhi(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400612 SimplifiedLowering* lowering) {
Ben Murdochda12d292016-06-02 14:46:10 +0100613 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614 SetOutput(node, output);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400615
616 int values = node->op()->ValueInputCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400617 if (lower()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 // Update the phi operator.
Ben Murdochda12d292016-06-02 14:46:10 +0100619 if (output != PhiRepresentationOf(node->op())) {
620 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000621 }
622 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623
624 // Convert inputs to the output representation of this phi, pass the
625 // truncation truncation along.
Ben Murdochda12d292016-06-02 14:46:10 +0100626 UseInfo input_use(output, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 for (int i = 0; i < node->InputCount(); i++) {
628 ProcessInput(node, i, i < values ? input_use : UseInfo::None());
629 }
630 }
631
632 void VisitCall(Node* node, SimplifiedLowering* lowering) {
633 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op());
634 const MachineSignature* sig = desc->GetMachineSignature();
635 int params = static_cast<int>(sig->parameter_count());
636 // Propagate representation information from call descriptor.
637 for (int i = 0; i < node->InputCount(); i++) {
638 if (i == 0) {
639 // The target of the call.
640 ProcessInput(node, i, UseInfo::None());
641 } else if ((i - 1) < params) {
642 ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
643 sig->GetParam(i - 1).representation()));
644 } else {
645 ProcessInput(node, i, UseInfo::None());
646 }
647 }
648
649 if (sig->return_count() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100650 SetOutput(node,
651 desc->GetMachineSignature()->GetReturn().representation());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000652 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100653 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000654 }
655 }
656
657 MachineSemantic DeoptValueSemanticOf(Type* type) {
658 CHECK(!type->Is(Type::None()));
659 // We only need signedness to do deopt correctly.
660 if (type->Is(Type::Signed32())) {
661 return MachineSemantic::kInt32;
662 } else if (type->Is(Type::Unsigned32())) {
663 return MachineSemantic::kUint32;
664 } else {
665 return MachineSemantic::kAny;
666 }
667 }
668
669 void VisitStateValues(Node* node) {
670 if (phase_ == PROPAGATE) {
671 for (int i = 0; i < node->InputCount(); i++) {
672 EnqueueInput(node, i, UseInfo::Any());
673 }
674 } else {
675 Zone* zone = jsgraph_->zone();
676 ZoneVector<MachineType>* types =
677 new (zone->New(sizeof(ZoneVector<MachineType>)))
678 ZoneVector<MachineType>(node->InputCount(), zone);
679 for (int i = 0; i < node->InputCount(); i++) {
Ben Murdochda12d292016-06-02 14:46:10 +0100680 Node* input = node->InputAt(i);
681 NodeInfo* input_info = GetInfo(input);
682 MachineType machine_type(input_info->representation(),
683 DeoptValueSemanticOf(GetUpperBound(input)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000684 DCHECK(machine_type.representation() !=
685 MachineRepresentation::kWord32 ||
686 machine_type.semantic() == MachineSemantic::kInt32 ||
687 machine_type.semantic() == MachineSemantic::kUint32);
688 (*types)[i] = machine_type;
689 }
690 NodeProperties::ChangeOp(node,
691 jsgraph_->common()->TypedStateValues(types));
692 }
Ben Murdochda12d292016-06-02 14:46:10 +0100693 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694 }
695
696 const Operator* Int32Op(Node* node) {
697 return changer_->Int32OperatorFor(node->opcode());
698 }
699
700 const Operator* Uint32Op(Node* node) {
701 return changer_->Uint32OperatorFor(node->opcode());
702 }
703
704 const Operator* Float64Op(Node* node) {
705 return changer_->Float64OperatorFor(node->opcode());
706 }
707
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000708 // Dispatching routine for visiting the node {node} with the usage {use}.
709 // Depending on the operator, propagate new usage info to the inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 void VisitNode(Node* node, Truncation truncation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000711 SimplifiedLowering* lowering) {
712 switch (node->opcode()) {
713 //------------------------------------------------------------------
714 // Common operators.
715 //------------------------------------------------------------------
716 case IrOpcode::kStart:
717 case IrOpcode::kDead:
Ben Murdochda12d292016-06-02 14:46:10 +0100718 return VisitLeaf(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000719 case IrOpcode::kParameter: {
720 // TODO(titzer): use representation from linkage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 ProcessInput(node, 0, UseInfo::None());
Ben Murdochda12d292016-06-02 14:46:10 +0100722 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000723 return;
724 }
725 case IrOpcode::kInt32Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100726 return VisitLeaf(node, MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000727 case IrOpcode::kInt64Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100728 return VisitLeaf(node, MachineRepresentation::kWord64);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729 case IrOpcode::kFloat32Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100730 return VisitLeaf(node, MachineRepresentation::kFloat32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731 case IrOpcode::kFloat64Constant:
Ben Murdochda12d292016-06-02 14:46:10 +0100732 return VisitLeaf(node, MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000733 case IrOpcode::kExternalConstant:
Ben Murdochda12d292016-06-02 14:46:10 +0100734 return VisitLeaf(node, MachineType::PointerRepresentation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735 case IrOpcode::kNumberConstant:
Ben Murdochda12d292016-06-02 14:46:10 +0100736 return VisitLeaf(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000737 case IrOpcode::kHeapConstant:
Ben Murdochda12d292016-06-02 14:46:10 +0100738 return VisitLeaf(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739
Ben Murdochda12d292016-06-02 14:46:10 +0100740 case IrOpcode::kDeoptimizeIf:
741 case IrOpcode::kDeoptimizeUnless:
742 ProcessInput(node, 0, UseInfo::Bool());
743 ProcessInput(node, 1, UseInfo::AnyTagged());
744 ProcessRemainingInputs(node, 2);
745 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 case IrOpcode::kBranch:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000747 ProcessInput(node, 0, UseInfo::Bool());
748 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
749 break;
750 case IrOpcode::kSwitch:
751 ProcessInput(node, 0, UseInfo::TruncatingWord32());
752 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400754 case IrOpcode::kSelect:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 return VisitSelect(node, truncation, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 case IrOpcode::kPhi:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000757 return VisitPhi(node, truncation, lowering);
758 case IrOpcode::kCall:
759 return VisitCall(node, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000760
761//------------------------------------------------------------------
762// JavaScript operators.
763//------------------------------------------------------------------
764// For now, we assume that all JS operators were too complex to lower
765// to Simplified and that they will always require tagged value inputs
766// and produce tagged value outputs.
767// TODO(turbofan): it might be possible to lower some JSOperators here,
768// but that responsibility really lies in the typed lowering phase.
769#define DEFINE_JS_CASE(x) case IrOpcode::k##x:
770 JS_OP_LIST(DEFINE_JS_CASE)
771#undef DEFINE_JS_CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000772 VisitInputs(node);
Ben Murdochda12d292016-06-02 14:46:10 +0100773 return SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000774
775 //------------------------------------------------------------------
776 // Simplified operators.
777 //------------------------------------------------------------------
778 case IrOpcode::kBooleanNot: {
779 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780 NodeInfo* input_info = GetInfo(node->InputAt(0));
781 if (input_info->representation() == MachineRepresentation::kBit) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400782 // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000783 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000784 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000785 } else {
786 // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000787 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000788 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 }
790 } else {
791 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000792 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
Ben Murdochda12d292016-06-02 14:46:10 +0100793 SetOutput(node, MachineRepresentation::kBit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 }
795 break;
796 }
797 case IrOpcode::kBooleanToNumber: {
798 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000799 NodeInfo* input_info = GetInfo(node->InputAt(0));
800 if (input_info->representation() == MachineRepresentation::kBit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 // BooleanToNumber(x: kRepBit) => x
802 DeferReplacement(node, node->InputAt(0));
803 } else {
804 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000805 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000806 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000807 }
808 } else {
809 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000810 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
Ben Murdochda12d292016-06-02 14:46:10 +0100811 SetOutput(node, MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 }
813 break;
814 }
815 case IrOpcode::kNumberEqual:
816 case IrOpcode::kNumberLessThan:
817 case IrOpcode::kNumberLessThanOrEqual: {
818 // Number comparisons reduce to integer comparisons for integer inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819 if (BothInputsAreSigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820 // => signed Int32Cmp
821 VisitInt32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000822 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
823 } else if (BothInputsAreUnsigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000824 // => unsigned Int32Cmp
825 VisitUint32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000826 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827 } else {
828 // => Float64Cmp
829 VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831 }
832 break;
833 }
834 case IrOpcode::kNumberAdd:
835 case IrOpcode::kNumberSubtract: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836 if (BothInputsAre(node, Type::Signed32()) &&
837 NodeProperties::GetType(node)->Is(Type::Signed32())) {
838 // int32 + int32 = int32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 // => signed Int32Add/Sub
840 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
842 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
843 truncation.TruncatesToWord32()) {
844 // safe-int + safe-int = x (truncated to int32)
845 // => signed Int32Add/Sub (truncated)
846 VisitWord32TruncatingBinop(node);
847 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 } else {
849 // => Float64Add/Sub
850 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 }
853 break;
854 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400855 case IrOpcode::kNumberMultiply: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856 if (BothInputsAreSigned32(node)) {
857 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
858 // Multiply reduces to Int32Mul if the inputs and the output
859 // are integers.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400860 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
862 break;
863 }
864 if (truncation.TruncatesToWord32() &&
865 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
866 // Multiply reduces to Int32Mul if the inputs are integers,
867 // the uses are truncating and the result is in the safe
868 // integer range.
869 VisitWord32TruncatingBinop(node);
870 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400871 break;
872 }
873 }
874 // => Float64Mul
875 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400877 break;
878 }
879 case IrOpcode::kNumberDivide: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 if (BothInputsAreSigned32(node)) {
881 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400882 // => signed Int32Div
883 VisitInt32Binop(node);
884 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
885 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 }
887 if (truncation.TruncatesToWord32()) {
888 // => signed Int32Div
889 VisitWord32TruncatingBinop(node);
890 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
891 break;
892 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400893 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400895 // => unsigned Uint32Div
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400897 if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
898 break;
899 }
900 // => Float64Div
901 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400903 break;
904 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000905 case IrOpcode::kNumberModulus: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000906 if (BothInputsAreSigned32(node)) {
907 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
908 // => signed Int32Mod
909 VisitInt32Binop(node);
910 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
911 break;
912 }
913 if (truncation.TruncatesToWord32()) {
914 // => signed Int32Mod
915 VisitWord32TruncatingBinop(node);
916 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
917 break;
918 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400919 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 // => unsigned Uint32Mod
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000922 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400923 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
924 break;
925 }
926 // => Float64Mod
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000928 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000929 break;
930 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 case IrOpcode::kNumberBitwiseOr:
932 case IrOpcode::kNumberBitwiseXor:
933 case IrOpcode::kNumberBitwiseAnd: {
934 VisitInt32Binop(node);
935 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
936 break;
937 }
938 case IrOpcode::kNumberShiftLeft: {
Ben Murdochda12d292016-06-02 14:46:10 +0100939 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100941 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000942 if (lower()) {
943 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000944 }
945 break;
946 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000947 case IrOpcode::kNumberShiftRight: {
Ben Murdochda12d292016-06-02 14:46:10 +0100948 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100950 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 if (lower()) {
952 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
953 }
954 break;
955 }
956 case IrOpcode::kNumberShiftRightLogical: {
Ben Murdochda12d292016-06-02 14:46:10 +0100957 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000958 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100959 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 if (lower()) {
961 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
962 }
963 break;
964 }
Ben Murdochda12d292016-06-02 14:46:10 +0100965 case IrOpcode::kNumberImul: {
966 VisitBinop(node, UseInfo::TruncatingWord32(),
967 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
968 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
969 break;
970 }
971 case IrOpcode::kNumberClz32: {
972 VisitUnop(node, UseInfo::TruncatingWord32(),
973 MachineRepresentation::kWord32);
974 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
975 break;
976 }
977 case IrOpcode::kNumberCeil: {
978 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
979 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
980 break;
981 }
982 case IrOpcode::kNumberFloor: {
983 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
984 if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
985 break;
986 }
987 case IrOpcode::kNumberRound: {
988 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
989 if (lower()) DeferReplacement(node, lowering->Float64Round(node));
990 break;
991 }
992 case IrOpcode::kNumberTrunc: {
993 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
994 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
995 break;
996 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 case IrOpcode::kNumberToInt32: {
998 // Just change representation if necessary.
Ben Murdochda12d292016-06-02 14:46:10 +0100999 VisitUnop(node, UseInfo::TruncatingWord32(),
1000 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 if (lower()) DeferReplacement(node, node->InputAt(0));
1002 break;
1003 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 case IrOpcode::kNumberToUint32: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 // Just change representation if necessary.
Ben Murdochda12d292016-06-02 14:46:10 +01001006 VisitUnop(node, UseInfo::TruncatingWord32(),
1007 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 if (lower()) DeferReplacement(node, node->InputAt(0));
1009 break;
1010 }
1011 case IrOpcode::kNumberIsHoleNaN: {
Ben Murdochda12d292016-06-02 14:46:10 +01001012 VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 if (lower()) {
1014 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
1015 // #HoleNaNLower32)
1016 node->ReplaceInput(0,
1017 jsgraph_->graph()->NewNode(
1018 lowering->machine()->Float64ExtractLowWord32(),
1019 node->InputAt(0)));
1020 node->AppendInput(jsgraph_->zone(),
1021 jsgraph_->Int32Constant(kHoleNanLower32));
1022 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal());
1023 }
1024 break;
1025 }
1026 case IrOpcode::kPlainPrimitiveToNumber: {
Ben Murdochda12d292016-06-02 14:46:10 +01001027 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001028 if (lower()) {
1029 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
1030 Operator::Properties properties = node->op()->properties();
1031 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate());
1032 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1033 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1034 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1035 flags, properties);
1036 node->InsertInput(jsgraph_->zone(), 0,
1037 jsgraph_->HeapConstant(callable.code()));
1038 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1039 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001040 }
1041 break;
1042 }
1043 case IrOpcode::kReferenceEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001044 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045 if (lower()) {
1046 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1047 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 break;
1049 }
1050 case IrOpcode::kStringEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001051 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1052 if (lower()) {
1053 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
1054 Operator::Properties properties = node->op()->properties();
1055 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
1056 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1057 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1058 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1059 flags, properties);
1060 node->InsertInput(jsgraph_->zone(), 0,
1061 jsgraph_->HeapConstant(callable.code()));
1062 node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
1063 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1064 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065 break;
1066 }
1067 case IrOpcode::kStringLessThan: {
Ben Murdochda12d292016-06-02 14:46:10 +01001068 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1069 if (lower()) {
1070 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
1071 Operator::Properties properties = node->op()->properties();
1072 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
1073 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1074 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1075 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1076 flags, properties);
1077 node->InsertInput(jsgraph_->zone(), 0,
1078 jsgraph_->HeapConstant(callable.code()));
1079 node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
1080 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1081 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001082 break;
1083 }
1084 case IrOpcode::kStringLessThanOrEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001085 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1086 if (lower()) {
1087 // StringLessThanOrEqual(x, y)
1088 // => Call(StringLessThanOrEqualStub, x, y, no-context)
1089 Operator::Properties properties = node->op()->properties();
1090 Callable callable =
1091 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
1092 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1093 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1094 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1095 flags, properties);
1096 node->InsertInput(jsgraph_->zone(), 0,
1097 jsgraph_->HeapConstant(callable.code()));
1098 node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
1099 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1100 }
1101 break;
1102 }
1103 case IrOpcode::kStringToNumber: {
1104 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1105 if (lower()) {
1106 // StringToNumber(x) => Call(StringToNumberStub, x, no-context)
1107 Operator::Properties properties = node->op()->properties();
1108 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
1109 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1110 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1111 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1112 flags, properties);
1113 node->InsertInput(jsgraph_->zone(), 0,
1114 jsgraph_->HeapConstant(callable.code()));
1115 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1116 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1117 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118 break;
1119 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001120 case IrOpcode::kAllocate: {
1121 ProcessInput(node, 0, UseInfo::AnyTagged());
1122 ProcessRemainingInputs(node, 1);
Ben Murdochda12d292016-06-02 14:46:10 +01001123 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001124 break;
1125 }
1126 case IrOpcode::kLoadField: {
1127 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128 ProcessInput(node, 0, UseInfoForBasePointer(access));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129 ProcessRemainingInputs(node, 1);
Ben Murdochda12d292016-06-02 14:46:10 +01001130 SetOutput(node, access.machine_type.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 break;
1132 }
1133 case IrOpcode::kStoreField: {
1134 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001135 ProcessInput(node, 0, UseInfoForBasePointer(access));
1136 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
1137 access.machine_type.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001138 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001139 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001140 break;
1141 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001142 case IrOpcode::kLoadBuffer: {
1143 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1145 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1146 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001148
Ben Murdochda12d292016-06-02 14:46:10 +01001149 MachineRepresentation output;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 if (truncation.TruncatesUndefinedToZeroOrNaN()) {
1151 if (truncation.TruncatesNaNToZero()) {
1152 // If undefined is truncated to a non-NaN number, we can use
1153 // the load's representation.
Ben Murdochda12d292016-06-02 14:46:10 +01001154 output = access.machine_type().representation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001155 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156 // If undefined is truncated to a number, but the use can
1157 // observe NaN, we need to output at least the float32
1158 // representation.
1159 if (access.machine_type().representation() ==
1160 MachineRepresentation::kFloat32) {
Ben Murdochda12d292016-06-02 14:46:10 +01001161 output = access.machine_type().representation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001162 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001163 if (access.machine_type().representation() !=
1164 MachineRepresentation::kFloat64) {
1165 // TODO(bmeurer): See comment on abort_compilation_.
1166 if (lower()) lowering->abort_compilation_ = true;
1167 }
Ben Murdochda12d292016-06-02 14:46:10 +01001168 output = MachineRepresentation::kFloat64;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001170 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001171 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001172 // TODO(bmeurer): See comment on abort_compilation_.
1173 if (lower()) lowering->abort_compilation_ = true;
1174
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 // If undefined is not truncated away, we need to have the tagged
1176 // representation.
Ben Murdochda12d292016-06-02 14:46:10 +01001177 output = MachineRepresentation::kTagged;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001178 }
Ben Murdochda12d292016-06-02 14:46:10 +01001179 SetOutput(node, output);
1180 if (lower()) lowering->DoLoadBuffer(node, output, changer_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001181 break;
1182 }
1183 case IrOpcode::kStoreBuffer: {
1184 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1186 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1187 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1188 ProcessInput(node, 3,
1189 TruncatingUseInfoFromRepresentation(
1190 access.machine_type().representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001191 ProcessRemainingInputs(node, 4);
Ben Murdochda12d292016-06-02 14:46:10 +01001192 SetOutput(node, MachineRepresentation::kNone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001193 if (lower()) lowering->DoStoreBuffer(node);
1194 break;
1195 }
1196 case IrOpcode::kLoadElement: {
1197 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1199 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001200 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001201 SetOutput(node, access.machine_type.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001202 break;
1203 }
1204 case IrOpcode::kStoreElement: {
1205 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1207 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1208 ProcessInput(node, 2,
1209 TruncatingUseInfoFromRepresentation(
1210 access.machine_type.representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001211 ProcessRemainingInputs(node, 3);
Ben Murdochda12d292016-06-02 14:46:10 +01001212 SetOutput(node, MachineRepresentation::kNone);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 break;
1214 }
Ben Murdochda12d292016-06-02 14:46:10 +01001215 case IrOpcode::kObjectIsNumber:
1216 case IrOpcode::kObjectIsReceiver:
1217 case IrOpcode::kObjectIsSmi:
1218 case IrOpcode::kObjectIsUndetectable: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 ProcessInput(node, 0, UseInfo::AnyTagged());
Ben Murdochda12d292016-06-02 14:46:10 +01001220 SetOutput(node, MachineRepresentation::kBit);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001221 break;
1222 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001223
1224 //------------------------------------------------------------------
1225 // Machine-level operators.
1226 //------------------------------------------------------------------
1227 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 // TODO(jarin) Eventually, we should get rid of all machine stores
1229 // from the high-level phases, then this becomes UNREACHABLE.
1230 LoadRepresentation rep = LoadRepresentationOf(node->op());
1231 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1232 ProcessInput(node, 1, UseInfo::PointerInt()); // index
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001233 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001234 SetOutput(node, rep.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235 break;
1236 }
1237 case IrOpcode::kStore: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 // TODO(jarin) Eventually, we should get rid of all machine stores
1239 // from the high-level phases, then this becomes UNREACHABLE.
1240 StoreRepresentation rep = StoreRepresentationOf(node->op());
1241 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1242 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1243 ProcessInput(node, 2,
1244 TruncatingUseInfoFromRepresentation(rep.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001245 ProcessRemainingInputs(node, 3);
Ben Murdochda12d292016-06-02 14:46:10 +01001246 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001247 break;
1248 }
1249 case IrOpcode::kWord32Shr:
1250 // We output unsigned int32 for shift right because JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001251 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001252 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001253 case IrOpcode::kWord32And:
1254 case IrOpcode::kWord32Or:
1255 case IrOpcode::kWord32Xor:
1256 case IrOpcode::kWord32Shl:
1257 case IrOpcode::kWord32Sar:
1258 // We use signed int32 as the output type for these word32 operations,
1259 // though the machine bits are the same for either signed or unsigned,
1260 // because JavaScript considers the result from these operations signed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001261 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001262 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001263 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001264 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001265 MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001266
1267 case IrOpcode::kWord32Clz:
1268 return VisitUnop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001269 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001270
1271 case IrOpcode::kInt32Add:
1272 case IrOpcode::kInt32Sub:
1273 case IrOpcode::kInt32Mul:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001274 case IrOpcode::kInt32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 case IrOpcode::kInt32Div:
1276 case IrOpcode::kInt32Mod:
1277 return VisitInt32Binop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001278 case IrOpcode::kUint32Div:
1279 case IrOpcode::kUint32Mod:
1280 case IrOpcode::kUint32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 return VisitUint32Binop(node);
1282 case IrOpcode::kInt32LessThan:
1283 case IrOpcode::kInt32LessThanOrEqual:
1284 return VisitInt32Cmp(node);
1285
1286 case IrOpcode::kUint32LessThan:
1287 case IrOpcode::kUint32LessThanOrEqual:
1288 return VisitUint32Cmp(node);
1289
1290 case IrOpcode::kInt64Add:
1291 case IrOpcode::kInt64Sub:
1292 case IrOpcode::kInt64Mul:
1293 case IrOpcode::kInt64Div:
1294 case IrOpcode::kInt64Mod:
1295 return VisitInt64Binop(node);
1296 case IrOpcode::kInt64LessThan:
1297 case IrOpcode::kInt64LessThanOrEqual:
1298 return VisitInt64Cmp(node);
1299
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300 case IrOpcode::kUint64LessThan:
1301 return VisitUint64Cmp(node);
1302
1303 case IrOpcode::kUint64Div:
1304 case IrOpcode::kUint64Mod:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001305 return VisitUint64Binop(node);
1306
1307 case IrOpcode::kWord64And:
1308 case IrOpcode::kWord64Or:
1309 case IrOpcode::kWord64Xor:
1310 case IrOpcode::kWord64Shl:
1311 case IrOpcode::kWord64Shr:
1312 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001313 return VisitBinop(node, UseInfo::TruncatingWord64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001314 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001315 case IrOpcode::kWord64Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 return VisitBinop(node, UseInfo::TruncatingWord64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001317 MachineRepresentation::kBit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001318
1319 case IrOpcode::kChangeInt32ToInt64:
Ben Murdochda12d292016-06-02 14:46:10 +01001320 return VisitUnop(node, UseInfo::TruncatingWord32(),
1321 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322 case IrOpcode::kChangeUint32ToUint64:
Ben Murdochda12d292016-06-02 14:46:10 +01001323 return VisitUnop(node, UseInfo::TruncatingWord32(),
1324 MachineRepresentation::kWord64);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001325 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdochda12d292016-06-02 14:46:10 +01001326 return VisitUnop(node, UseInfo::Float64(),
1327 MachineRepresentation::kFloat32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 case IrOpcode::kTruncateFloat64ToInt32:
Ben Murdochda12d292016-06-02 14:46:10 +01001329 return VisitUnop(node, UseInfo::Float64(),
1330 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001332 case IrOpcode::kChangeFloat32ToFloat64:
Ben Murdochda12d292016-06-02 14:46:10 +01001333 return VisitUnop(node, UseInfo::Float32(),
1334 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdochda12d292016-06-02 14:46:10 +01001336 return VisitUnop(node, UseInfo::TruncatingWord32(),
1337 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 return VisitUnop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001340 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 case IrOpcode::kFloat64Add:
1342 case IrOpcode::kFloat64Sub:
1343 case IrOpcode::kFloat64Mul:
1344 case IrOpcode::kFloat64Div:
1345 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346 case IrOpcode::kFloat64Min:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001347 return VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001348 case IrOpcode::kFloat64Abs:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350 case IrOpcode::kFloat64RoundDown:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001351 case IrOpcode::kFloat64RoundTruncate:
1352 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001353 case IrOpcode::kFloat64RoundUp:
Ben Murdochda12d292016-06-02 14:46:10 +01001354 return VisitUnop(node, UseInfo::Float64(),
1355 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 case IrOpcode::kFloat64Equal:
1357 case IrOpcode::kFloat64LessThan:
1358 case IrOpcode::kFloat64LessThanOrEqual:
1359 return VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001360 case IrOpcode::kFloat64ExtractLowWord32:
1361 case IrOpcode::kFloat64ExtractHighWord32:
Ben Murdochda12d292016-06-02 14:46:10 +01001362 return VisitUnop(node, UseInfo::Float64(),
1363 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364 case IrOpcode::kFloat64InsertLowWord32:
1365 case IrOpcode::kFloat64InsertHighWord32:
1366 return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001367 MachineRepresentation::kFloat64);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001368 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001370 case IrOpcode::kLoadParentFramePointer:
Ben Murdochda12d292016-06-02 14:46:10 +01001371 return VisitLeaf(node, MachineType::PointerRepresentation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001372 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373 VisitStateValues(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001374 break;
Ben Murdochda12d292016-06-02 14:46:10 +01001375
1376 // The following opcodes are not produced before representation
1377 // inference runs, so we do not have any real test coverage.
1378 // Simply fail here.
1379 case IrOpcode::kChangeFloat64ToInt32:
1380 case IrOpcode::kChangeFloat64ToUint32:
1381 case IrOpcode::kTruncateInt64ToInt32:
1382 FATAL("Representation inference: unsupported opcodes.");
1383
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001384 default:
1385 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 // Assume the output is tagged.
Ben Murdochda12d292016-06-02 14:46:10 +01001387 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388 break;
1389 }
1390 }
1391
1392 void DeferReplacement(Node* node, Node* replacement) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001393 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
1394 node->op()->mnemonic(), replacement->id(),
1395 replacement->op()->mnemonic());
1396
1397 if (replacement->id() < count_ &&
Ben Murdochda12d292016-06-02 14:46:10 +01001398 GetUpperBound(node)->Is(GetUpperBound(replacement))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 // Replace with a previously existing node eagerly only if the type is the
1400 // same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001401 node->ReplaceUses(replacement);
1402 } else {
1403 // Otherwise, we are replacing a node with a representation change.
1404 // Such a substitution must be done after all lowering is done, because
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001405 // changing the type could confuse the representation change
1406 // insertion for uses of the node.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 replacements_.push_back(node);
1408 replacements_.push_back(replacement);
1409 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001410 node->NullAllInputs(); // Node is now dead.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001411 }
1412
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001413 void PrintOutputInfo(NodeInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001414 if (FLAG_trace_representation) {
1415 OFStream os(stdout);
Ben Murdochda12d292016-06-02 14:46:10 +01001416 os << info->representation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001417 }
1418 }
1419
1420 void PrintRepresentation(MachineRepresentation rep) {
1421 if (FLAG_trace_representation) {
1422 OFStream os(stdout);
1423 os << rep;
1424 }
1425 }
1426
1427 void PrintTruncation(Truncation truncation) {
1428 if (FLAG_trace_representation) {
1429 OFStream os(stdout);
1430 os << truncation.description();
1431 }
1432 }
1433
1434 void PrintUseInfo(UseInfo info) {
1435 if (FLAG_trace_representation) {
1436 OFStream os(stdout);
1437 os << info.preferred() << ":" << info.truncation().description();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001438 }
1439 }
1440
1441 private:
1442 JSGraph* jsgraph_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001443 size_t const count_; // number of nodes in the graph
1444 ZoneVector<NodeInfo> info_; // node id -> usage information
1445#ifdef DEBUG
1446 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
1447 // requirements on inputs.
1448#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449 NodeVector nodes_; // collected nodes
1450 NodeVector replacements_; // replacements to be done after lowering
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001451 Phase phase_; // current phase of algorithm
1452 RepresentationChanger* changer_; // for inserting representation changes
1453 ZoneQueue<Node*> queue_; // queue for traversing the graph
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001454 // TODO(danno): RepresentationSelector shouldn't know anything about the
1455 // source positions table, but must for now since there currently is no other
1456 // way to pass down source position information to nodes created during
1457 // lowering. Once this phase becomes a vanilla reducer, it should get source
1458 // position information via the SourcePositionWrapper like all other reducers.
1459 SourcePositionTable* source_positions_;
1460 TypeCache const& type_cache_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461
1462 NodeInfo* GetInfo(Node* node) {
1463 DCHECK(node->id() >= 0);
1464 DCHECK(node->id() < count_);
1465 return &info_[node->id()];
1466 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001467};
1468
1469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001470SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
1471 SourcePositionTable* source_positions)
1472 : jsgraph_(jsgraph),
1473 zone_(zone),
1474 type_cache_(TypeCache::Get()),
1475 source_positions_(source_positions) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476
1477
1478void SimplifiedLowering::LowerAllNodes() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001479 RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
1480 RepresentationSelector selector(jsgraph(), zone_, &changer,
1481 source_positions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001482 selector.Run(this);
1483}
1484
1485
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001486void SimplifiedLowering::DoLoadBuffer(Node* node,
1487 MachineRepresentation output_rep,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001488 RepresentationChanger* changer) {
1489 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001490 DCHECK_NE(MachineRepresentation::kNone, output_rep);
1491 MachineType const access_type = BufferAccessOf(node->op()).machine_type();
1492 if (output_rep != access_type.representation()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001493 Node* const buffer = node->InputAt(0);
1494 Node* const offset = node->InputAt(1);
1495 Node* const length = node->InputAt(2);
1496 Node* const effect = node->InputAt(3);
1497 Node* const control = node->InputAt(4);
1498 Node* const index =
1499 machine()->Is64()
1500 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
1501 : offset;
1502
1503 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
1504 Node* branch =
1505 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1506
1507 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001508 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
1509 effect, if_true);
1510 Node* vtrue = changer->GetRepresentationFor(
1511 etrue, access_type.representation(), NodeProperties::GetType(node),
1512 output_rep, Truncation::None());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001513
1514 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1515 Node* efalse = effect;
1516 Node* vfalse;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001517 if (output_rep == MachineRepresentation::kTagged) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001518 vfalse = jsgraph()->UndefinedConstant();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519 } else if (output_rep == MachineRepresentation::kFloat64) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001520 vfalse =
1521 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001522 } else if (output_rep == MachineRepresentation::kFloat32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001523 vfalse =
1524 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
1525 } else {
1526 vfalse = jsgraph()->Int32Constant(0);
1527 }
1528
1529 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
1530 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
1531
1532 // Replace effect uses of {node} with the {ephi}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001533 NodeProperties::ReplaceUses(node, node, ephi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001534
1535 // Turn the {node} into a Phi.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001536 node->ReplaceInput(0, vtrue);
1537 node->ReplaceInput(1, vfalse);
1538 node->ReplaceInput(2, merge);
1539 node->TrimInputCount(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001540 NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001541 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001543 }
1544}
1545
1546
1547void SimplifiedLowering::DoStoreBuffer(Node* node) {
1548 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001549 MachineRepresentation const rep =
1550 BufferAccessOf(node->op()).machine_type().representation();
1551 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552}
1553
Ben Murdochda12d292016-06-02 14:46:10 +01001554Node* SimplifiedLowering::Float64Ceil(Node* const node) {
1555 Node* const one = jsgraph()->Float64Constant(1.0);
1556 Node* const zero = jsgraph()->Float64Constant(0.0);
1557 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
1558 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
1559 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
1560 Node* const input = node->InputAt(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001561
Ben Murdochda12d292016-06-02 14:46:10 +01001562 // Use fast hardware instruction if available.
1563 if (machine()->Float64RoundUp().IsSupported()) {
1564 return graph()->NewNode(machine()->Float64RoundUp().op(), input);
1565 }
1566
1567 // General case for ceil.
1568 //
1569 // if 0.0 < input then
1570 // if 2^52 <= input then
1571 // input
1572 // else
1573 // let temp1 = (2^52 + input) - 2^52 in
1574 // if temp1 < input then
1575 // temp1 + 1
1576 // else
1577 // temp1
1578 // else
1579 // if input == 0 then
1580 // input
1581 // else
1582 // if input <= -2^52 then
1583 // input
1584 // else
1585 // let temp1 = -0 - input in
1586 // let temp2 = (2^52 + temp1) - 2^52 in
1587 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
1588 // -0 - temp3
1589 //
1590 // Note: We do not use the Diamond helper class here, because it really hurts
1591 // readability with nested diamonds.
1592
1593 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
1594 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1595 graph()->start());
1596
1597 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1598 Node* vtrue0;
1599 {
1600 Node* check1 =
1601 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
1602 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1603
1604 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1605 Node* vtrue1 = input;
1606
1607 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1608 Node* vfalse1;
1609 {
1610 Node* temp1 = graph()->NewNode(
1611 machine()->Float64Sub(),
1612 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
1613 vfalse1 = graph()->NewNode(
1614 common()->Select(MachineRepresentation::kFloat64),
1615 graph()->NewNode(machine()->Float64LessThan(), temp1, input),
1616 graph()->NewNode(machine()->Float64Add(), temp1, one), temp1);
1617 }
1618
1619 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1620 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1621 vtrue1, vfalse1, if_true0);
1622 }
1623
1624 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1625 Node* vfalse0;
1626 {
1627 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
1628 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1629 check1, if_false0);
1630
1631 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1632 Node* vtrue1 = input;
1633
1634 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1635 Node* vfalse1;
1636 {
1637 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
1638 input, minus_two_52);
1639 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1640 check2, if_false1);
1641
1642 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1643 Node* vtrue2 = input;
1644
1645 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1646 Node* vfalse2;
1647 {
1648 Node* temp1 =
1649 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
1650 Node* temp2 = graph()->NewNode(
1651 machine()->Float64Sub(),
1652 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
1653 Node* temp3 = graph()->NewNode(
1654 common()->Select(MachineRepresentation::kFloat64),
1655 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
1656 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
1657 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
1658 }
1659
1660 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
1661 vfalse1 =
1662 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1663 vtrue2, vfalse2, if_false1);
1664 }
1665
1666 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1667 vfalse0 =
1668 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1669 vtrue1, vfalse1, if_false0);
1670 }
1671
1672 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1673 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1674 vtrue0, vfalse0, merge0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001675}
1676
Ben Murdochda12d292016-06-02 14:46:10 +01001677Node* SimplifiedLowering::Float64Floor(Node* const node) {
1678 Node* const one = jsgraph()->Float64Constant(1.0);
1679 Node* const zero = jsgraph()->Float64Constant(0.0);
1680 Node* const minus_one = jsgraph()->Float64Constant(-1.0);
1681 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
1682 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
1683 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
1684 Node* const input = node->InputAt(0);
1685
1686 // Use fast hardware instruction if available.
1687 if (machine()->Float64RoundDown().IsSupported()) {
1688 return graph()->NewNode(machine()->Float64RoundDown().op(), input);
1689 }
1690
1691 // General case for floor.
1692 //
1693 // if 0.0 < input then
1694 // if 2^52 <= input then
1695 // input
1696 // else
1697 // let temp1 = (2^52 + input) - 2^52 in
1698 // if input < temp1 then
1699 // temp1 - 1
1700 // else
1701 // temp1
1702 // else
1703 // if input == 0 then
1704 // input
1705 // else
1706 // if input <= -2^52 then
1707 // input
1708 // else
1709 // let temp1 = -0 - input in
1710 // let temp2 = (2^52 + temp1) - 2^52 in
1711 // if temp2 < temp1 then
1712 // -1 - temp2
1713 // else
1714 // -0 - temp2
1715 //
1716 // Note: We do not use the Diamond helper class here, because it really hurts
1717 // readability with nested diamonds.
1718
1719 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
1720 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1721 graph()->start());
1722
1723 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1724 Node* vtrue0;
1725 {
1726 Node* check1 =
1727 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
1728 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1729
1730 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1731 Node* vtrue1 = input;
1732
1733 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1734 Node* vfalse1;
1735 {
1736 Node* temp1 = graph()->NewNode(
1737 machine()->Float64Sub(),
1738 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
1739 vfalse1 = graph()->NewNode(
1740 common()->Select(MachineRepresentation::kFloat64),
1741 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
1742 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
1743 }
1744
1745 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1746 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1747 vtrue1, vfalse1, if_true0);
1748 }
1749
1750 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1751 Node* vfalse0;
1752 {
1753 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
1754 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1755 check1, if_false0);
1756
1757 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1758 Node* vtrue1 = input;
1759
1760 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1761 Node* vfalse1;
1762 {
1763 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
1764 input, minus_two_52);
1765 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1766 check2, if_false1);
1767
1768 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1769 Node* vtrue2 = input;
1770
1771 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1772 Node* vfalse2;
1773 {
1774 Node* temp1 =
1775 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
1776 Node* temp2 = graph()->NewNode(
1777 machine()->Float64Sub(),
1778 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
1779 vfalse2 = graph()->NewNode(
1780 common()->Select(MachineRepresentation::kFloat64),
1781 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1),
1782 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2),
1783 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2));
1784 }
1785
1786 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
1787 vfalse1 =
1788 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1789 vtrue2, vfalse2, if_false1);
1790 }
1791
1792 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1793 vfalse0 =
1794 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1795 vtrue1, vfalse1, if_false0);
1796 }
1797
1798 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1799 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1800 vtrue0, vfalse0, merge0);
1801}
1802
1803Node* SimplifiedLowering::Float64Round(Node* const node) {
1804 Node* const one = jsgraph()->Float64Constant(1.0);
1805 Node* const one_half = jsgraph()->Float64Constant(0.5);
1806 Node* const input = node->InputAt(0);
1807
1808 // Round up towards Infinity, and adjust if the difference exceeds 0.5.
1809 Node* result = Float64Ceil(node);
1810 return graph()->NewNode(
1811 common()->Select(MachineRepresentation::kFloat64),
1812 graph()->NewNode(
1813 machine()->Float64LessThanOrEqual(),
1814 graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
1815 result, graph()->NewNode(machine()->Float64Sub(), result, one));
1816}
1817
1818Node* SimplifiedLowering::Float64Trunc(Node* const node) {
1819 Node* const one = jsgraph()->Float64Constant(1.0);
1820 Node* const zero = jsgraph()->Float64Constant(0.0);
1821 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
1822 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
1823 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
1824 Node* const input = node->InputAt(0);
1825
1826 // Use fast hardware instruction if available.
1827 if (machine()->Float64RoundTruncate().IsSupported()) {
1828 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
1829 }
1830
1831 // General case for trunc.
1832 //
1833 // if 0.0 < input then
1834 // if 2^52 <= input then
1835 // input
1836 // else
1837 // let temp1 = (2^52 + input) - 2^52 in
1838 // if input < temp1 then
1839 // temp1 - 1
1840 // else
1841 // temp1
1842 // else
1843 // if input == 0 then
1844 // input
1845 // else
1846 // if input <= -2^52 then
1847 // input
1848 // else
1849 // let temp1 = -0 - input in
1850 // let temp2 = (2^52 + temp1) - 2^52 in
1851 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
1852 // -0 - temp3
1853 //
1854 // Note: We do not use the Diamond helper class here, because it really hurts
1855 // readability with nested diamonds.
1856
1857 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
1858 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1859 graph()->start());
1860
1861 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1862 Node* vtrue0;
1863 {
1864 Node* check1 =
1865 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
1866 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1867
1868 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1869 Node* vtrue1 = input;
1870
1871 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1872 Node* vfalse1;
1873 {
1874 Node* temp1 = graph()->NewNode(
1875 machine()->Float64Sub(),
1876 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
1877 vfalse1 = graph()->NewNode(
1878 common()->Select(MachineRepresentation::kFloat64),
1879 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
1880 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
1881 }
1882
1883 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1884 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1885 vtrue1, vfalse1, if_true0);
1886 }
1887
1888 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1889 Node* vfalse0;
1890 {
1891 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
1892 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1893 check1, if_false0);
1894
1895 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1896 Node* vtrue1 = input;
1897
1898 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1899 Node* vfalse1;
1900 {
1901 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
1902 input, minus_two_52);
1903 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1904 check2, if_false1);
1905
1906 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1907 Node* vtrue2 = input;
1908
1909 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1910 Node* vfalse2;
1911 {
1912 Node* temp1 =
1913 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
1914 Node* temp2 = graph()->NewNode(
1915 machine()->Float64Sub(),
1916 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
1917 Node* temp3 = graph()->NewNode(
1918 common()->Select(MachineRepresentation::kFloat64),
1919 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
1920 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
1921 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
1922 }
1923
1924 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
1925 vfalse1 =
1926 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1927 vtrue2, vfalse2, if_false1);
1928 }
1929
1930 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
1931 vfalse0 =
1932 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1933 vtrue1, vfalse1, if_false0);
1934 }
1935
1936 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
1937 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
1938 vtrue0, vfalse0, merge0);
1939}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001940
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001941Node* SimplifiedLowering::Int32Div(Node* const node) {
1942 Int32BinopMatcher m(node);
1943 Node* const zero = jsgraph()->Int32Constant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001944 Node* const minus_one = jsgraph()->Int32Constant(-1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001945 Node* const lhs = m.left().node();
1946 Node* const rhs = m.right().node();
1947
1948 if (m.right().Is(-1)) {
1949 return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
1950 } else if (m.right().Is(0)) {
1951 return rhs;
1952 } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
1953 return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
1954 }
1955
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001956 // General case for signed integer division.
1957 //
1958 // if 0 < rhs then
1959 // lhs / rhs
1960 // else
1961 // if rhs < -1 then
1962 // lhs / rhs
1963 // else if rhs == 0 then
1964 // 0
1965 // else
1966 // 0 - lhs
1967 //
1968 // Note: We do not use the Diamond helper class here, because it really hurts
1969 // readability with nested diamonds.
1970 const Operator* const merge_op = common()->Merge(2);
1971 const Operator* const phi_op =
1972 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001974 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1975 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1976 graph()->start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001977
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001978 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1979 Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
1980
1981 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1982 Node* false0;
1983 {
1984 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
1985 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
1986
1987 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1988 Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
1989
1990 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1991 Node* false1;
1992 {
1993 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1994 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
1995
1996 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1997 Node* true2 = zero;
1998
1999 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2000 Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
2001
2002 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2003 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2004 }
2005
2006 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2007 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2008 }
2009
2010 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2011 return graph()->NewNode(phi_op, true0, false0, merge0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002012}
2013
2014
2015Node* SimplifiedLowering::Int32Mod(Node* const node) {
2016 Int32BinopMatcher m(node);
2017 Node* const zero = jsgraph()->Int32Constant(0);
2018 Node* const minus_one = jsgraph()->Int32Constant(-1);
2019 Node* const lhs = m.left().node();
2020 Node* const rhs = m.right().node();
2021
2022 if (m.right().Is(-1) || m.right().Is(0)) {
2023 return zero;
2024 } else if (m.right().HasValue()) {
2025 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
2026 }
2027
2028 // General case for signed integer modulus, with optimization for (unknown)
2029 // power of 2 right hand side.
2030 //
2031 // if 0 < rhs then
2032 // msk = rhs - 1
2033 // if rhs & msk != 0 then
2034 // lhs % rhs
2035 // else
2036 // if lhs < 0 then
2037 // -(-lhs & msk)
2038 // else
2039 // lhs & msk
2040 // else
2041 // if rhs < -1 then
2042 // lhs % rhs
2043 // else
2044 // zero
2045 //
2046 // Note: We do not use the Diamond helper class here, because it really hurts
2047 // readability with nested diamonds.
2048 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002049 const Operator* const phi_op =
2050 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002051
2052 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
2053 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2054 graph()->start());
2055
2056 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2057 Node* true0;
2058 {
2059 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
2060
2061 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
2062 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2063
2064 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2065 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
2066
2067 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2068 Node* false1;
2069 {
2070 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
2071 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2072 check2, if_false1);
2073
2074 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2075 Node* true2 = graph()->NewNode(
2076 machine()->Int32Sub(), zero,
2077 graph()->NewNode(machine()->Word32And(),
2078 graph()->NewNode(machine()->Int32Sub(), zero, lhs),
2079 msk));
2080
2081 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2082 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
2083
2084 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2085 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2086 }
2087
2088 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
2089 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
2090 }
2091
2092 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2093 Node* false0;
2094 {
2095 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
2096 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2097 check1, if_false0);
2098
2099 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2100 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
2101
2102 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2103 Node* false1 = zero;
2104
2105 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2106 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2107 }
2108
2109 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2110 return graph()->NewNode(phi_op, true0, false0, merge0);
2111}
2112
2113
2114Node* SimplifiedLowering::Uint32Div(Node* const node) {
2115 Uint32BinopMatcher m(node);
2116 Node* const zero = jsgraph()->Uint32Constant(0);
2117 Node* const lhs = m.left().node();
2118 Node* const rhs = m.right().node();
2119
2120 if (m.right().Is(0)) {
2121 return zero;
2122 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
2123 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
2124 }
2125
2126 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
2127 Diamond d(graph(), common(), check, BranchHint::kFalse);
2128 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002129 return d.Phi(MachineRepresentation::kWord32, zero, div);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002130}
2131
2132
2133Node* SimplifiedLowering::Uint32Mod(Node* const node) {
2134 Uint32BinopMatcher m(node);
2135 Node* const minus_one = jsgraph()->Int32Constant(-1);
2136 Node* const zero = jsgraph()->Uint32Constant(0);
2137 Node* const lhs = m.left().node();
2138 Node* const rhs = m.right().node();
2139
2140 if (m.right().Is(0)) {
2141 return zero;
2142 } else if (m.right().HasValue()) {
2143 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
2144 }
2145
2146 // General case for unsigned integer modulus, with optimization for (unknown)
2147 // power of 2 right hand side.
2148 //
2149 // if rhs then
2150 // msk = rhs - 1
2151 // if rhs & msk != 0 then
2152 // lhs % rhs
2153 // else
2154 // lhs & msk
2155 // else
2156 // zero
2157 //
2158 // Note: We do not use the Diamond helper class here, because it really hurts
2159 // readability with nested diamonds.
2160 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002161 const Operator* const phi_op =
2162 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002163
2164 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
2165 graph()->start());
2166
2167 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2168 Node* true0;
2169 {
2170 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
2171
2172 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
2173 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2174
2175 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2176 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
2177
2178 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2179 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
2180
2181 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
2182 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
2183 }
2184
2185 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2186 Node* false0 = zero;
2187
2188 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2189 return graph()->NewNode(phi_op, true0, false0, merge0);
2190}
2191
2192
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002193void SimplifiedLowering::DoShift(Node* node, Operator const* op,
2194 Type* rhs_type) {
2195 Node* const rhs = NodeProperties::GetValueInput(node, 1);
2196 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
2197 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
2198 jsgraph()->Int32Constant(0x1f)));
2199 }
2200 NodeProperties::ChangeOp(node, op);
2201}
2202
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002203} // namespace compiler
2204} // namespace internal
2205} // namespace v8