blob: ed7fe9d14b0913d8149a68518e4a424af89f4d1e [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 }
107
108 // Truncation to a representation that is smaller than the preferred
109 // one.
110 static UseInfo Float64TruncatingToWord32() {
111 return UseInfo(MachineRepresentation::kFloat64, Truncation::Word32());
112 }
113 static UseInfo Word64TruncatingToWord32() {
114 return UseInfo(MachineRepresentation::kWord64, Truncation::Word32());
115 }
116 static UseInfo AnyTruncatingToBool() {
117 return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
118 }
119
120 MachineRepresentation preferred() const { return preferred_; }
121 Truncation truncation() const { return truncation_; }
122
123 private:
124 MachineRepresentation preferred_;
125 Truncation truncation_;
126};
127
128
129UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
130 switch (rep) {
131 case MachineRepresentation::kTagged:
132 return UseInfo::AnyTagged();
133 case MachineRepresentation::kFloat64:
134 return UseInfo::Float64();
135 case MachineRepresentation::kFloat32:
136 return UseInfo::Float32();
137 case MachineRepresentation::kWord64:
138 return UseInfo::TruncatingWord64();
139 case MachineRepresentation::kWord8:
140 case MachineRepresentation::kWord16:
141 case MachineRepresentation::kWord32:
142 return UseInfo::TruncatingWord32();
143 case MachineRepresentation::kBit:
144 return UseInfo::Bool();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100145 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000146 case MachineRepresentation::kNone:
147 break;
148 }
149 UNREACHABLE();
150 return UseInfo::None();
151}
152
153
154UseInfo UseInfoForBasePointer(const FieldAccess& access) {
155 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
156}
157
158
159UseInfo UseInfoForBasePointer(const ElementAccess& access) {
160 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
161}
162
163
164#ifdef DEBUG
165// Helpers for monotonicity checking.
166bool MachineRepresentationIsSubtype(MachineRepresentation r1,
167 MachineRepresentation r2) {
168 switch (r1) {
169 case MachineRepresentation::kNone:
170 return true;
171 case MachineRepresentation::kBit:
172 return r2 == MachineRepresentation::kBit ||
173 r2 == MachineRepresentation::kTagged;
174 case MachineRepresentation::kWord8:
175 return r2 == MachineRepresentation::kWord8 ||
176 r2 == MachineRepresentation::kWord16 ||
177 r2 == MachineRepresentation::kWord32 ||
178 r2 == MachineRepresentation::kWord64 ||
179 r2 == MachineRepresentation::kFloat32 ||
180 r2 == MachineRepresentation::kFloat64 ||
181 r2 == MachineRepresentation::kTagged;
182 case MachineRepresentation::kWord16:
183 return r2 == MachineRepresentation::kWord16 ||
184 r2 == MachineRepresentation::kWord32 ||
185 r2 == MachineRepresentation::kWord64 ||
186 r2 == MachineRepresentation::kFloat32 ||
187 r2 == MachineRepresentation::kFloat64 ||
188 r2 == MachineRepresentation::kTagged;
189 case MachineRepresentation::kWord32:
190 return r2 == MachineRepresentation::kWord32 ||
191 r2 == MachineRepresentation::kWord64 ||
192 r2 == MachineRepresentation::kFloat64 ||
193 r2 == MachineRepresentation::kTagged;
194 case MachineRepresentation::kWord64:
195 return r2 == MachineRepresentation::kWord64;
196 case MachineRepresentation::kFloat32:
197 return r2 == MachineRepresentation::kFloat32 ||
198 r2 == MachineRepresentation::kFloat64 ||
199 r2 == MachineRepresentation::kTagged;
200 case MachineRepresentation::kFloat64:
201 return r2 == MachineRepresentation::kFloat64 ||
202 r2 == MachineRepresentation::kTagged;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100203 case MachineRepresentation::kSimd128:
204 return r2 == MachineRepresentation::kSimd128 ||
205 r2 == MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 case MachineRepresentation::kTagged:
207 return r2 == MachineRepresentation::kTagged;
208 }
209 UNREACHABLE();
210 return false;
211}
212
213
214class InputUseInfos {
215 public:
216 explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
217
218 void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
219 if (input_use_infos_.empty()) {
220 input_use_infos_.resize(node->InputCount(), UseInfo::None());
221 }
222 // Check that the new use informatin is a super-type of the old
223 // one.
224 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
225 input_use_infos_[index] = use_info;
226 }
227
228 private:
229 ZoneVector<UseInfo> input_use_infos_;
230
231 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
232 return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) &&
233 use1.truncation().IsLessGeneralThan(use2.truncation());
234 }
235};
236
237#endif // DEBUG
238
239} // namespace
240
241
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000242class RepresentationSelector {
243 public:
244 // Information for each node tracked during the fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 class NodeOutputInfo {
246 public:
247 NodeOutputInfo(MachineRepresentation representation, Type* type)
248 : type_(type), representation_(representation) {}
249 NodeOutputInfo()
250 : type_(Type::None()), representation_(MachineRepresentation::kNone) {}
251
252 MachineRepresentation representation() const { return representation_; }
253 Type* type() const { return type_; }
254
255 static NodeOutputInfo None() {
256 return NodeOutputInfo(MachineRepresentation::kNone, Type::None());
257 }
258
259 static NodeOutputInfo Float32() {
260 return NodeOutputInfo(MachineRepresentation::kFloat32, Type::Number());
261 }
262
263 static NodeOutputInfo Float64() {
264 return NodeOutputInfo(MachineRepresentation::kFloat64, Type::Number());
265 }
266
267 static NodeOutputInfo NumberTruncatedToWord32() {
268 return NodeOutputInfo(MachineRepresentation::kWord32, Type::Number());
269 }
270
271 static NodeOutputInfo Int32() {
272 return NodeOutputInfo(MachineRepresentation::kWord32, Type::Signed32());
273 }
274
275 static NodeOutputInfo Uint32() {
276 return NodeOutputInfo(MachineRepresentation::kWord32, Type::Unsigned32());
277 }
278
279 static NodeOutputInfo Bool() {
280 return NodeOutputInfo(MachineRepresentation::kBit, Type::Boolean());
281 }
282
283 static NodeOutputInfo Int64() {
284 // TODO(jarin) Fix once we have a real int64 type.
285 return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
286 }
287
288 static NodeOutputInfo Uint64() {
289 // TODO(jarin) Fix once we have a real uint64 type.
290 return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
291 }
292
293 static NodeOutputInfo AnyTagged() {
294 return NodeOutputInfo(MachineRepresentation::kTagged, Type::Any());
295 }
296
297 static NodeOutputInfo NumberTagged() {
298 return NodeOutputInfo(MachineRepresentation::kTagged, Type::Number());
299 }
300
301 static NodeOutputInfo Pointer() {
302 return NodeOutputInfo(MachineType::PointerRepresentation(), Type::Any());
303 }
304
305 private:
306 Type* type_;
307 MachineRepresentation representation_;
308 };
309
310 class NodeInfo {
311 public:
312 // Adds new use to the node. Returns true if something has changed
313 // and the node has to be requeued.
314 bool AddUse(UseInfo info) {
315 Truncation old_truncation = truncation_;
316 truncation_ = Truncation::Generalize(truncation_, info.truncation());
317 return truncation_ != old_truncation;
318 }
319
320 void set_queued(bool value) { queued_ = value; }
321 bool queued() const { return queued_; }
322 void set_visited() { visited_ = true; }
323 bool visited() const { return visited_; }
324 Truncation truncation() const { return truncation_; }
325 void set_output_type(NodeOutputInfo output) { output_ = output; }
326
327 Type* output_type() const { return output_.type(); }
328 MachineRepresentation representation() const {
329 return output_.representation();
330 }
331
332 private:
333 bool queued_ = false; // Bookkeeping for the traversal.
334 bool visited_ = false; // Bookkeeping for the traversal.
335 NodeOutputInfo output_; // Output type and representation.
336 Truncation truncation_ = Truncation::None(); // Information about uses.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 };
338
339 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 RepresentationChanger* changer,
341 SourcePositionTable* source_positions)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000342 : jsgraph_(jsgraph),
343 count_(jsgraph->graph()->NodeCount()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 info_(count_, zone),
345#ifdef DEBUG
346 node_input_use_infos_(count_, InputUseInfos(zone), zone),
347#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000348 nodes_(zone),
349 replacements_(zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 phase_(PROPAGATE),
351 changer_(changer),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 queue_(zone),
353 source_positions_(source_positions),
354 type_cache_(TypeCache::Get()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000355 }
356
357 void Run(SimplifiedLowering* lowering) {
358 // Run propagation phase to a fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 TRACE("--{Propagation phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 phase_ = PROPAGATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000361 EnqueueInitial(jsgraph_->graph()->end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000362 // Process nodes from the queue until it is empty.
363 while (!queue_.empty()) {
364 Node* node = queue_.front();
365 NodeInfo* info = GetInfo(node);
366 queue_.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 info->set_queued(false);
368 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
369 VisitNode(node, info->truncation(), nullptr);
370 TRACE(" ==> output ");
371 PrintOutputInfo(info);
372 TRACE("\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 }
374
375 // Run lowering and change insertion phase.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 TRACE("--{Simplified lowering phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000377 phase_ = LOWER;
378 // Process nodes from the collected {nodes_} vector.
379 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
380 Node* node = *i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 NodeInfo* info = GetInfo(node);
382 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383 // Reuse {VisitNode()} so the representation rules are in one place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 SourcePositionTable::Scope scope(
385 source_positions_, source_positions_->GetSourcePosition(node));
386 VisitNode(node, info->truncation(), lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000387 }
388
389 // Perform the final replacements.
390 for (NodeVector::iterator i = replacements_.begin();
391 i != replacements_.end(); ++i) {
392 Node* node = *i;
393 Node* replacement = *(++i);
394 node->ReplaceUses(replacement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 // We also need to replace the node in the rest of the vector.
396 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
397 ++j;
398 if (*j == node) *j = replacement;
399 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000400 }
401 }
402
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000403 void EnqueueInitial(Node* node) {
404 NodeInfo* info = GetInfo(node);
405 info->set_visited();
406 info->set_queued(true);
407 nodes_.push_back(node);
408 queue_.push(node);
409 }
410
411 // Enqueue {use_node}'s {index} input if the {use} contains new information
412 // for that input node. Add the input to {nodes_} if this is the first time
413 // it's been visited.
414 void EnqueueInput(Node* use_node, int index,
415 UseInfo use_info = UseInfo::None()) {
416 Node* node = use_node->InputAt(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 if (phase_ != PROPAGATE) return;
418 NodeInfo* info = GetInfo(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419#ifdef DEBUG
420 // Check monotonicity of input requirements.
421 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
422 use_info);
423#endif // DEBUG
424 if (!info->visited()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000425 // First visit of this node.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426 info->set_visited();
427 info->set_queued(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000428 nodes_.push_back(node);
429 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 TRACE(" initial: ");
431 info->AddUse(use_info);
432 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 return;
434 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 TRACE(" queue?: ");
436 PrintTruncation(info->truncation());
437 if (info->AddUse(use_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 // New usage information for the node is available.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 if (!info->queued()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000440 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000441 info->set_queued(true);
442 TRACE(" added: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444 TRACE(" inqueue: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000445 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000447 }
448 }
449
450 bool lower() { return phase_ == LOWER; }
451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 void EnqueueUses(Node* node) {
453 for (Edge edge : node->use_edges()) {
454 if (NodeProperties::IsValueEdge(edge)) {
455 Node* const user = edge.from();
456 if (user->id() < count_) {
457 // New type information for the node is available.
458 NodeInfo* info = GetInfo(user);
459 // Enqueue the node only if we are sure it is reachable from
460 // the end and it has not been queued yet.
461 if (info->visited() && !info->queued()) {
462 queue_.push(user);
463 info->set_queued(true);
464 }
465 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400466 }
467 }
468 }
469
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000470 void SetOutputFromMachineType(Node* node, MachineType machine_type) {
471 Type* type = Type::None();
472 switch (machine_type.semantic()) {
473 case MachineSemantic::kNone:
474 type = Type::None();
475 break;
476 case MachineSemantic::kBool:
477 type = Type::Boolean();
478 break;
479 case MachineSemantic::kInt32:
480 type = Type::Signed32();
481 break;
482 case MachineSemantic::kUint32:
483 type = Type::Unsigned32();
484 break;
485 case MachineSemantic::kInt64:
486 // TODO(jarin) Fix once we have proper int64.
487 type = Type::Internal();
488 break;
489 case MachineSemantic::kUint64:
490 // TODO(jarin) Fix once we have proper uint64.
491 type = Type::Internal();
492 break;
493 case MachineSemantic::kNumber:
494 type = Type::Number();
495 break;
496 case MachineSemantic::kAny:
497 type = Type::Any();
498 break;
499 }
500 return SetOutput(node, NodeOutputInfo(machine_type.representation(), type));
501 }
502
503 void SetOutput(Node* node, NodeOutputInfo output_info) {
504 // Every node should have at most one output representation. Note that
505 // phis can have 0, if they have not been used in a representation-inducing
506 // instruction.
507 Type* output_type = output_info.type();
508 if (NodeProperties::IsTyped(node)) {
509 output_type = Type::Intersect(NodeProperties::GetType(node),
510 output_info.type(), jsgraph_->zone());
511 }
512 NodeInfo* info = GetInfo(node);
513 DCHECK(info->output_type()->Is(output_type));
514 DCHECK(MachineRepresentationIsSubtype(info->representation(),
515 output_info.representation()));
516 if (!output_type->Is(info->output_type()) ||
517 output_info.representation() != info->representation()) {
518 EnqueueUses(node);
519 }
520 info->set_output_type(
521 NodeOutputInfo(output_info.representation(), output_type));
522 }
523
524 bool BothInputsAreSigned32(Node* node) {
525 DCHECK_EQ(2, node->InputCount());
526 return GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32()) &&
527 GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32());
528 }
529
530 bool BothInputsAreUnsigned32(Node* node) {
531 DCHECK_EQ(2, node->InputCount());
532 return GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32()) &&
533 GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32());
534 }
535
536 bool BothInputsAre(Node* node, Type* type) {
537 DCHECK_EQ(2, node->InputCount());
538 return GetInfo(node->InputAt(0))->output_type()->Is(type) &&
539 GetInfo(node->InputAt(1))->output_type()->Is(type);
540 }
541
542 void ConvertInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543 Node* input = node->InputAt(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000544 // In the change phase, insert a change before the use if necessary.
545 if (use.preferred() == MachineRepresentation::kNone)
546 return; // No input requirement on the use.
547 NodeInfo* input_info = GetInfo(input);
548 MachineRepresentation input_rep = input_info->representation();
549 if (input_rep != use.preferred()) {
550 // Output representation doesn't match usage.
551 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
552 index, input->id(), input->op()->mnemonic());
553 TRACE(" from ");
554 PrintOutputInfo(input_info);
555 TRACE(" to ");
556 PrintUseInfo(use);
557 TRACE("\n");
558 Node* n = changer_->GetRepresentationFor(
559 input, input_info->representation(), input_info->output_type(),
560 use.preferred(), use.truncation());
561 node->ReplaceInput(index, n);
562 }
563 }
564
565 void ProcessInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 if (phase_ == PROPAGATE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000567 EnqueueInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 ConvertInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570 }
571 }
572
573 void ProcessRemainingInputs(Node* node, int index) {
574 DCHECK_GE(index, NodeProperties::PastValueIndex(node));
575 DCHECK_GE(index, NodeProperties::PastContextIndex(node));
576 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
577 i < NodeProperties::PastEffectIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 EnqueueInput(node, i); // Effect inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 }
580 for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
581 i < NodeProperties::PastControlIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 EnqueueInput(node, i); // Control inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 }
584 }
585
586 // The default, most general visitation case. For {node}, process all value,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 // context, frame state, effect, and control inputs, assuming that value
588 // inputs should have {kRepTagged} representation and can observe all output
589 // values {kTypeAny}.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000590 void VisitInputs(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 int tagged_count = node->op()->ValueInputCount() +
592 OperatorProperties::GetContextInputCount(node->op());
593 // Visit value and context inputs as tagged.
594 for (int i = 0; i < tagged_count; i++) {
595 ProcessInput(node, i, UseInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000597 // Only enqueue other inputs (framestates, effects, control).
598 for (int i = tagged_count; i < node->InputCount(); i++) {
599 EnqueueInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000600 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601 }
602
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000603 // Helper for binops of the R x L -> O variety.
604 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
605 NodeOutputInfo output) {
606 DCHECK_EQ(2, node->op()->ValueInputCount());
607 ProcessInput(node, 0, left_use);
608 ProcessInput(node, 1, right_use);
609 for (int i = 2; i < node->InputCount(); i++) {
610 EnqueueInput(node, i);
611 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612 SetOutput(node, output);
613 }
614
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615 // Helper for binops of the I x I -> O variety.
616 void VisitBinop(Node* node, UseInfo input_use, NodeOutputInfo output) {
617 VisitBinop(node, input_use, input_use, output);
618 }
619
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000620 // Helper for unops of the I -> O variety.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 void VisitUnop(Node* node, UseInfo input_use, NodeOutputInfo output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 DCHECK_EQ(1, node->InputCount());
623 ProcessInput(node, 0, input_use);
624 SetOutput(node, output);
625 }
626
627 // Helper for leaf nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 void VisitLeaf(Node* node, NodeOutputInfo output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 DCHECK_EQ(0, node->InputCount());
630 SetOutput(node, output);
631 }
632
633 // Helpers for specific types of binops.
634 void VisitFloat64Binop(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000636 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 void VisitInt32Binop(Node* node) {
638 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
639 }
640 void VisitWord32TruncatingBinop(Node* node) {
641 VisitBinop(node, UseInfo::TruncatingWord32(),
642 NodeOutputInfo::NumberTruncatedToWord32());
643 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000644 void VisitUint32Binop(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000645 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 void VisitInt64Binop(Node* node) {
648 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Int64());
649 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650 void VisitUint64Binop(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Uint64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000653 void VisitFloat64Cmp(Node* node) {
654 VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
655 }
656 void VisitInt32Cmp(Node* node) {
657 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
658 }
659 void VisitUint32Cmp(Node* node) {
660 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
661 }
662 void VisitInt64Cmp(Node* node) {
663 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
664 }
665 void VisitUint64Cmp(Node* node) {
666 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
667 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400669 // Infer representation for phi-like nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 NodeOutputInfo GetOutputInfoForPhi(Node* node, Truncation use) {
671 // Compute the type.
672 Type* type = GetInfo(node->InputAt(0))->output_type();
673 for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
674 type = Type::Union(type, GetInfo(node->InputAt(i))->output_type(),
675 jsgraph_->zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400676 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000677
678 // Compute the representation.
679 MachineRepresentation rep = MachineRepresentation::kTagged;
680 if (type->Is(Type::None())) {
681 rep = MachineRepresentation::kNone;
682 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
683 rep = MachineRepresentation::kWord32;
684 } else if (use.TruncatesToWord32()) {
685 rep = MachineRepresentation::kWord32;
686 } else if (type->Is(Type::Boolean())) {
687 rep = MachineRepresentation::kBit;
688 } else if (type->Is(Type::Number())) {
689 rep = MachineRepresentation::kFloat64;
690 } else if (type->Is(Type::Internal())) {
691 // We mark (u)int64 as Type::Internal.
692 // TODO(jarin) This is a workaround for our lack of (u)int64
693 // types. This can be removed once we can represent (u)int64
694 // unambiguously. (At the moment internal objects, such as the hole,
695 // are also Type::Internal()).
696 bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
697 MachineRepresentation::kWord64;
698#ifdef DEBUG
699 // Check that all the inputs agree on being Word64.
700 for (int i = 1; i < node->op()->ValueInputCount(); i++) {
701 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
702 MachineRepresentation::kWord64);
703 }
704#endif
705 rep = is_word64 ? MachineRepresentation::kWord64
706 : MachineRepresentation::kTagged;
707 }
708 return NodeOutputInfo(rep, type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400709 }
710
711 // Helper for handling selects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 void VisitSelect(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400713 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 ProcessInput(node, 0, UseInfo::Bool());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400715
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
717 SetOutput(node, output);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718
719 if (lower()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400720 // Update the select operator.
721 SelectParameters p = SelectParametersOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 if (output.representation() != p.representation()) {
723 NodeProperties::ChangeOp(node, lowering->common()->Select(
724 output.representation(), p.hint()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400725 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400726 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000727 // Convert inputs to the output representation of this phi, pass the
728 // truncation truncation along.
729 UseInfo input_use(output.representation(), truncation);
730 ProcessInput(node, 1, input_use);
731 ProcessInput(node, 2, input_use);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400732 }
733
734 // Helper for handling phis.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 void VisitPhi(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400736 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
738 SetOutput(node, output);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400739
740 int values = node->op()->ValueInputCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400741 if (lower()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742 // Update the phi operator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 if (output.representation() != PhiRepresentationOf(node->op())) {
744 NodeProperties::ChangeOp(
745 node, lowering->common()->Phi(output.representation(), values));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 }
747 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000748
749 // Convert inputs to the output representation of this phi, pass the
750 // truncation truncation along.
751 UseInfo input_use(output.representation(), truncation);
752 for (int i = 0; i < node->InputCount(); i++) {
753 ProcessInput(node, i, i < values ? input_use : UseInfo::None());
754 }
755 }
756
757 void VisitCall(Node* node, SimplifiedLowering* lowering) {
758 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op());
759 const MachineSignature* sig = desc->GetMachineSignature();
760 int params = static_cast<int>(sig->parameter_count());
761 // Propagate representation information from call descriptor.
762 for (int i = 0; i < node->InputCount(); i++) {
763 if (i == 0) {
764 // The target of the call.
765 ProcessInput(node, i, UseInfo::None());
766 } else if ((i - 1) < params) {
767 ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
768 sig->GetParam(i - 1).representation()));
769 } else {
770 ProcessInput(node, i, UseInfo::None());
771 }
772 }
773
774 if (sig->return_count() > 0) {
775 SetOutputFromMachineType(node, desc->GetMachineSignature()->GetReturn());
776 } else {
777 SetOutput(node, NodeOutputInfo::AnyTagged());
778 }
779 }
780
781 MachineSemantic DeoptValueSemanticOf(Type* type) {
782 CHECK(!type->Is(Type::None()));
783 // We only need signedness to do deopt correctly.
784 if (type->Is(Type::Signed32())) {
785 return MachineSemantic::kInt32;
786 } else if (type->Is(Type::Unsigned32())) {
787 return MachineSemantic::kUint32;
788 } else {
789 return MachineSemantic::kAny;
790 }
791 }
792
793 void VisitStateValues(Node* node) {
794 if (phase_ == PROPAGATE) {
795 for (int i = 0; i < node->InputCount(); i++) {
796 EnqueueInput(node, i, UseInfo::Any());
797 }
798 } else {
799 Zone* zone = jsgraph_->zone();
800 ZoneVector<MachineType>* types =
801 new (zone->New(sizeof(ZoneVector<MachineType>)))
802 ZoneVector<MachineType>(node->InputCount(), zone);
803 for (int i = 0; i < node->InputCount(); i++) {
804 NodeInfo* input_info = GetInfo(node->InputAt(i));
805 MachineType machine_type(
806 input_info->representation(),
807 DeoptValueSemanticOf(input_info->output_type()));
808 DCHECK(machine_type.representation() !=
809 MachineRepresentation::kWord32 ||
810 machine_type.semantic() == MachineSemantic::kInt32 ||
811 machine_type.semantic() == MachineSemantic::kUint32);
812 (*types)[i] = machine_type;
813 }
814 NodeProperties::ChangeOp(node,
815 jsgraph_->common()->TypedStateValues(types));
816 }
817 SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000818 }
819
820 const Operator* Int32Op(Node* node) {
821 return changer_->Int32OperatorFor(node->opcode());
822 }
823
824 const Operator* Uint32Op(Node* node) {
825 return changer_->Uint32OperatorFor(node->opcode());
826 }
827
828 const Operator* Float64Op(Node* node) {
829 return changer_->Float64OperatorFor(node->opcode());
830 }
831
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 // Dispatching routine for visiting the node {node} with the usage {use}.
833 // Depending on the operator, propagate new usage info to the inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 void VisitNode(Node* node, Truncation truncation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000835 SimplifiedLowering* lowering) {
836 switch (node->opcode()) {
837 //------------------------------------------------------------------
838 // Common operators.
839 //------------------------------------------------------------------
840 case IrOpcode::kStart:
841 case IrOpcode::kDead:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 return VisitLeaf(node, NodeOutputInfo::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000843 case IrOpcode::kParameter: {
844 // TODO(titzer): use representation from linkage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000845 Type* type = NodeProperties::GetType(node);
846 ProcessInput(node, 0, UseInfo::None());
847 SetOutput(node, NodeOutputInfo(MachineRepresentation::kTagged, type));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 return;
849 }
850 case IrOpcode::kInt32Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000851 return VisitLeaf(node, NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 case IrOpcode::kInt64Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 return VisitLeaf(node, NodeOutputInfo::Int64());
854 case IrOpcode::kFloat32Constant:
855 return VisitLeaf(node, NodeOutputInfo::Float32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 case IrOpcode::kFloat64Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857 return VisitLeaf(node, NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858 case IrOpcode::kExternalConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 return VisitLeaf(node, NodeOutputInfo::Pointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860 case IrOpcode::kNumberConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 return VisitLeaf(node, NodeOutputInfo::NumberTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000862 case IrOpcode::kHeapConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000863 return VisitLeaf(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000864
865 case IrOpcode::kBranch:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 ProcessInput(node, 0, UseInfo::Bool());
867 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
868 break;
869 case IrOpcode::kSwitch:
870 ProcessInput(node, 0, UseInfo::TruncatingWord32());
871 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000872 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400873 case IrOpcode::kSelect:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000874 return VisitSelect(node, truncation, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875 case IrOpcode::kPhi:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 return VisitPhi(node, truncation, lowering);
877 case IrOpcode::kCall:
878 return VisitCall(node, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879
880//------------------------------------------------------------------
881// JavaScript operators.
882//------------------------------------------------------------------
883// For now, we assume that all JS operators were too complex to lower
884// to Simplified and that they will always require tagged value inputs
885// and produce tagged value outputs.
886// TODO(turbofan): it might be possible to lower some JSOperators here,
887// but that responsibility really lies in the typed lowering phase.
888#define DEFINE_JS_CASE(x) case IrOpcode::k##x:
889 JS_OP_LIST(DEFINE_JS_CASE)
890#undef DEFINE_JS_CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000891 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 return SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893
894 //------------------------------------------------------------------
895 // Simplified operators.
896 //------------------------------------------------------------------
897 case IrOpcode::kBooleanNot: {
898 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 NodeInfo* input_info = GetInfo(node->InputAt(0));
900 if (input_info->representation() == MachineRepresentation::kBit) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400901 // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904 } else {
905 // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 }
909 } else {
910 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000911 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
912 SetOutput(node, NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 }
914 break;
915 }
916 case IrOpcode::kBooleanToNumber: {
917 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000918 NodeInfo* input_info = GetInfo(node->InputAt(0));
919 if (input_info->representation() == MachineRepresentation::kBit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920 // BooleanToNumber(x: kRepBit) => x
921 DeferReplacement(node, node->InputAt(0));
922 } else {
923 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000924 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926 }
927 } else {
928 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
930 SetOutput(node, NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000931 }
932 break;
933 }
934 case IrOpcode::kNumberEqual:
935 case IrOpcode::kNumberLessThan:
936 case IrOpcode::kNumberLessThanOrEqual: {
937 // Number comparisons reduce to integer comparisons for integer inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000938 if (BothInputsAreSigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 // => signed Int32Cmp
940 VisitInt32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
942 } else if (BothInputsAreUnsigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000943 // => unsigned Int32Cmp
944 VisitUint32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 } else {
947 // => Float64Cmp
948 VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000949 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 }
951 break;
952 }
953 case IrOpcode::kNumberAdd:
954 case IrOpcode::kNumberSubtract: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000955 if (BothInputsAre(node, Type::Signed32()) &&
956 NodeProperties::GetType(node)->Is(Type::Signed32())) {
957 // int32 + int32 = int32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000958 // => signed Int32Add/Sub
959 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
961 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
962 truncation.TruncatesToWord32()) {
963 // safe-int + safe-int = x (truncated to int32)
964 // => signed Int32Add/Sub (truncated)
965 VisitWord32TruncatingBinop(node);
966 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 } else {
968 // => Float64Add/Sub
969 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000971 }
972 break;
973 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400974 case IrOpcode::kNumberMultiply: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975 if (BothInputsAreSigned32(node)) {
976 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
977 // Multiply reduces to Int32Mul if the inputs and the output
978 // are integers.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400979 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
981 break;
982 }
983 if (truncation.TruncatesToWord32() &&
984 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
985 // Multiply reduces to Int32Mul if the inputs are integers,
986 // the uses are truncating and the result is in the safe
987 // integer range.
988 VisitWord32TruncatingBinop(node);
989 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400990 break;
991 }
992 }
993 // => Float64Mul
994 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400996 break;
997 }
998 case IrOpcode::kNumberDivide: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 if (BothInputsAreSigned32(node)) {
1000 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001001 // => signed Int32Div
1002 VisitInt32Binop(node);
1003 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1004 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 }
1006 if (truncation.TruncatesToWord32()) {
1007 // => signed Int32Div
1008 VisitWord32TruncatingBinop(node);
1009 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1010 break;
1011 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001014 // => unsigned Uint32Div
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001015 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001016 if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
1017 break;
1018 }
1019 // => Float64Div
1020 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001022 break;
1023 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001024 case IrOpcode::kNumberModulus: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001025 if (BothInputsAreSigned32(node)) {
1026 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1027 // => signed Int32Mod
1028 VisitInt32Binop(node);
1029 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1030 break;
1031 }
1032 if (truncation.TruncatesToWord32()) {
1033 // => signed Int32Mod
1034 VisitWord32TruncatingBinop(node);
1035 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1036 break;
1037 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001038 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001039 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001040 // => unsigned Uint32Mod
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001042 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1043 break;
1044 }
1045 // => Float64Mod
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001046 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001048 break;
1049 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001050 case IrOpcode::kNumberBitwiseOr:
1051 case IrOpcode::kNumberBitwiseXor:
1052 case IrOpcode::kNumberBitwiseAnd: {
1053 VisitInt32Binop(node);
1054 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1055 break;
1056 }
1057 case IrOpcode::kNumberShiftLeft: {
1058 Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
1059 VisitBinop(node, UseInfo::TruncatingWord32(),
1060 UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
1061 if (lower()) {
1062 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001063 }
1064 break;
1065 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001066 case IrOpcode::kNumberShiftRight: {
1067 Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
1068 VisitBinop(node, UseInfo::TruncatingWord32(),
1069 UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
1070 if (lower()) {
1071 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1072 }
1073 break;
1074 }
1075 case IrOpcode::kNumberShiftRightLogical: {
1076 Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
1077 VisitBinop(node, UseInfo::TruncatingWord32(),
1078 UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
1079 if (lower()) {
1080 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
1081 }
1082 break;
1083 }
1084 case IrOpcode::kNumberToInt32: {
1085 // Just change representation if necessary.
1086 VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
1087 if (lower()) DeferReplacement(node, node->InputAt(0));
1088 break;
1089 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001090 case IrOpcode::kNumberToUint32: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001091 // Just change representation if necessary.
1092 VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
1093 if (lower()) DeferReplacement(node, node->InputAt(0));
1094 break;
1095 }
1096 case IrOpcode::kNumberIsHoleNaN: {
1097 VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
1098 if (lower()) {
1099 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
1100 // #HoleNaNLower32)
1101 node->ReplaceInput(0,
1102 jsgraph_->graph()->NewNode(
1103 lowering->machine()->Float64ExtractLowWord32(),
1104 node->InputAt(0)));
1105 node->AppendInput(jsgraph_->zone(),
1106 jsgraph_->Int32Constant(kHoleNanLower32));
1107 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal());
1108 }
1109 break;
1110 }
1111 case IrOpcode::kPlainPrimitiveToNumber: {
1112 VisitUnop(node, UseInfo::AnyTagged(), NodeOutputInfo::NumberTagged());
1113 if (lower()) {
1114 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
1115 Operator::Properties properties = node->op()->properties();
1116 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate());
1117 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1118 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1119 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1120 flags, properties);
1121 node->InsertInput(jsgraph_->zone(), 0,
1122 jsgraph_->HeapConstant(callable.code()));
1123 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1124 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001125 }
1126 break;
1127 }
1128 case IrOpcode::kReferenceEqual: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001129 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
1130 if (lower()) {
1131 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1132 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 break;
1134 }
1135 case IrOpcode::kStringEqual: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 if (lower()) lowering->DoStringEqual(node);
1138 break;
1139 }
1140 case IrOpcode::kStringLessThan: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001141 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001142 if (lower()) lowering->DoStringLessThan(node);
1143 break;
1144 }
1145 case IrOpcode::kStringLessThanOrEqual: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 if (lower()) lowering->DoStringLessThanOrEqual(node);
1148 break;
1149 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001150 case IrOpcode::kAllocate: {
1151 ProcessInput(node, 0, UseInfo::AnyTagged());
1152 ProcessRemainingInputs(node, 1);
1153 SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001154 break;
1155 }
1156 case IrOpcode::kLoadField: {
1157 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001158 ProcessInput(node, 0, UseInfoForBasePointer(access));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001159 ProcessRemainingInputs(node, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 SetOutputFromMachineType(node, access.machine_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 break;
1162 }
1163 case IrOpcode::kStoreField: {
1164 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 ProcessInput(node, 0, UseInfoForBasePointer(access));
1166 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
1167 access.machine_type.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 ProcessRemainingInputs(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001169 SetOutput(node, NodeOutputInfo::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001170 break;
1171 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001172 case IrOpcode::kLoadBuffer: {
1173 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1175 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1176 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001178
1179 NodeOutputInfo output_info;
1180 if (truncation.TruncatesUndefinedToZeroOrNaN()) {
1181 if (truncation.TruncatesNaNToZero()) {
1182 // If undefined is truncated to a non-NaN number, we can use
1183 // the load's representation.
1184 output_info = NodeOutputInfo(access.machine_type().representation(),
1185 NodeProperties::GetType(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001186 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 // If undefined is truncated to a number, but the use can
1188 // observe NaN, we need to output at least the float32
1189 // representation.
1190 if (access.machine_type().representation() ==
1191 MachineRepresentation::kFloat32) {
1192 output_info =
1193 NodeOutputInfo(access.machine_type().representation(),
1194 NodeProperties::GetType(node));
1195 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001196 if (access.machine_type().representation() !=
1197 MachineRepresentation::kFloat64) {
1198 // TODO(bmeurer): See comment on abort_compilation_.
1199 if (lower()) lowering->abort_compilation_ = true;
1200 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001201 output_info = NodeOutputInfo::Float64();
1202 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001203 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001204 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001205 // TODO(bmeurer): See comment on abort_compilation_.
1206 if (lower()) lowering->abort_compilation_ = true;
1207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001208 // If undefined is not truncated away, we need to have the tagged
1209 // representation.
1210 output_info = NodeOutputInfo::AnyTagged();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001211 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001212 SetOutput(node, output_info);
1213 if (lower())
1214 lowering->DoLoadBuffer(node, output_info.representation(), changer_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001215 break;
1216 }
1217 case IrOpcode::kStoreBuffer: {
1218 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001219 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1220 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1221 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1222 ProcessInput(node, 3,
1223 TruncatingUseInfoFromRepresentation(
1224 access.machine_type().representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001225 ProcessRemainingInputs(node, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 SetOutput(node, NodeOutputInfo::None());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001227 if (lower()) lowering->DoStoreBuffer(node);
1228 break;
1229 }
1230 case IrOpcode::kLoadElement: {
1231 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1233 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001234 ProcessRemainingInputs(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001235 SetOutputFromMachineType(node, access.machine_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001236 break;
1237 }
1238 case IrOpcode::kStoreElement: {
1239 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001240 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1241 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1242 ProcessInput(node, 2,
1243 TruncatingUseInfoFromRepresentation(
1244 access.machine_type.representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001245 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246 SetOutput(node, NodeOutputInfo::None());
1247 break;
1248 }
1249 case IrOpcode::kObjectIsNumber: {
1250 ProcessInput(node, 0, UseInfo::AnyTagged());
1251 SetOutput(node, NodeOutputInfo::Bool());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001252 break;
1253 }
1254 case IrOpcode::kObjectIsReceiver: {
1255 ProcessInput(node, 0, UseInfo::AnyTagged());
1256 SetOutput(node, NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001257 break;
1258 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001259 case IrOpcode::kObjectIsSmi: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 ProcessInput(node, 0, UseInfo::AnyTagged());
1261 SetOutput(node, NodeOutputInfo::Bool());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001262 break;
1263 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001264
1265 //------------------------------------------------------------------
1266 // Machine-level operators.
1267 //------------------------------------------------------------------
1268 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 // TODO(jarin) Eventually, we should get rid of all machine stores
1270 // from the high-level phases, then this becomes UNREACHABLE.
1271 LoadRepresentation rep = LoadRepresentationOf(node->op());
1272 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1273 ProcessInput(node, 1, UseInfo::PointerInt()); // index
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001274 ProcessRemainingInputs(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001275 SetOutputFromMachineType(node, rep);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001276 break;
1277 }
1278 case IrOpcode::kStore: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001279 // TODO(jarin) Eventually, we should get rid of all machine stores
1280 // from the high-level phases, then this becomes UNREACHABLE.
1281 StoreRepresentation rep = StoreRepresentationOf(node->op());
1282 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1283 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1284 ProcessInput(node, 2,
1285 TruncatingUseInfoFromRepresentation(rep.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001286 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 SetOutput(node, NodeOutputInfo::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001288 break;
1289 }
1290 case IrOpcode::kWord32Shr:
1291 // We output unsigned int32 for shift right because JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001292 return VisitBinop(node, UseInfo::TruncatingWord32(),
1293 NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001294 case IrOpcode::kWord32And:
1295 case IrOpcode::kWord32Or:
1296 case IrOpcode::kWord32Xor:
1297 case IrOpcode::kWord32Shl:
1298 case IrOpcode::kWord32Sar:
1299 // We use signed int32 as the output type for these word32 operations,
1300 // though the machine bits are the same for either signed or unsigned,
1301 // because JavaScript considers the result from these operations signed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001302 return VisitBinop(node, UseInfo::TruncatingWord32(),
1303 NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001304 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001305 return VisitBinop(node, UseInfo::TruncatingWord32(),
1306 NodeOutputInfo::Bool());
1307
1308 case IrOpcode::kWord32Clz:
1309 return VisitUnop(node, UseInfo::TruncatingWord32(),
1310 NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001311
1312 case IrOpcode::kInt32Add:
1313 case IrOpcode::kInt32Sub:
1314 case IrOpcode::kInt32Mul:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001315 case IrOpcode::kInt32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316 case IrOpcode::kInt32Div:
1317 case IrOpcode::kInt32Mod:
1318 return VisitInt32Binop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001319 case IrOpcode::kUint32Div:
1320 case IrOpcode::kUint32Mod:
1321 case IrOpcode::kUint32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001322 return VisitUint32Binop(node);
1323 case IrOpcode::kInt32LessThan:
1324 case IrOpcode::kInt32LessThanOrEqual:
1325 return VisitInt32Cmp(node);
1326
1327 case IrOpcode::kUint32LessThan:
1328 case IrOpcode::kUint32LessThanOrEqual:
1329 return VisitUint32Cmp(node);
1330
1331 case IrOpcode::kInt64Add:
1332 case IrOpcode::kInt64Sub:
1333 case IrOpcode::kInt64Mul:
1334 case IrOpcode::kInt64Div:
1335 case IrOpcode::kInt64Mod:
1336 return VisitInt64Binop(node);
1337 case IrOpcode::kInt64LessThan:
1338 case IrOpcode::kInt64LessThanOrEqual:
1339 return VisitInt64Cmp(node);
1340
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001341 case IrOpcode::kUint64LessThan:
1342 return VisitUint64Cmp(node);
1343
1344 case IrOpcode::kUint64Div:
1345 case IrOpcode::kUint64Mod:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001346 return VisitUint64Binop(node);
1347
1348 case IrOpcode::kWord64And:
1349 case IrOpcode::kWord64Or:
1350 case IrOpcode::kWord64Xor:
1351 case IrOpcode::kWord64Shl:
1352 case IrOpcode::kWord64Shr:
1353 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001354 return VisitBinop(node, UseInfo::TruncatingWord64(),
1355 NodeOutputInfo::Int64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001356 case IrOpcode::kWord64Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001357 return VisitBinop(node, UseInfo::TruncatingWord64(),
1358 NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001359
1360 case IrOpcode::kChangeInt32ToInt64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001361 return VisitUnop(
1362 node, UseInfo::TruncatingWord32(),
1363 NodeOutputInfo(MachineRepresentation::kWord64, Type::Signed32()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 case IrOpcode::kChangeUint32ToUint64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001365 return VisitUnop(
1366 node, UseInfo::TruncatingWord32(),
1367 NodeOutputInfo(MachineRepresentation::kWord64, Type::Unsigned32()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001368 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float32());
1370 case IrOpcode::kTruncateFloat64ToInt32:
1371 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 case IrOpcode::kTruncateInt64ToInt32:
1373 // TODO(titzer): Is kTypeInt32 correct here?
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 return VisitUnop(node, UseInfo::Word64TruncatingToWord32(),
1375 NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001377 case IrOpcode::kChangeFloat32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001378 return VisitUnop(node, UseInfo::Float32(), NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001379 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 return VisitUnop(
1381 node, UseInfo::TruncatingWord32(),
1382 NodeOutputInfo(MachineRepresentation::kFloat64, Type::Signed32()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 return VisitUnop(node, UseInfo::TruncatingWord32(),
1385 NodeOutputInfo(MachineRepresentation::kFloat64,
1386 Type::Unsigned32()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 case IrOpcode::kChangeFloat64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
1389 NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001390 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
1392 NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001393
1394 case IrOpcode::kFloat64Add:
1395 case IrOpcode::kFloat64Sub:
1396 case IrOpcode::kFloat64Mul:
1397 case IrOpcode::kFloat64Div:
1398 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 case IrOpcode::kFloat64Min:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001400 return VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 case IrOpcode::kFloat64Abs:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001403 case IrOpcode::kFloat64RoundDown:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001404 case IrOpcode::kFloat64RoundTruncate:
1405 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001406 case IrOpcode::kFloat64RoundUp:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001407 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 case IrOpcode::kFloat64Equal:
1409 case IrOpcode::kFloat64LessThan:
1410 case IrOpcode::kFloat64LessThanOrEqual:
1411 return VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001412 case IrOpcode::kFloat64ExtractLowWord32:
1413 case IrOpcode::kFloat64ExtractHighWord32:
1414 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
1415 case IrOpcode::kFloat64InsertLowWord32:
1416 case IrOpcode::kFloat64InsertHighWord32:
1417 return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
1418 NodeOutputInfo::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001419 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001420 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001421 case IrOpcode::kLoadParentFramePointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 return VisitLeaf(node, NodeOutputInfo::Pointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001423 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001424 VisitStateValues(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001425 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 default:
1427 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001428 // Assume the output is tagged.
1429 SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001430 break;
1431 }
1432 }
1433
1434 void DeferReplacement(Node* node, Node* replacement) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
1436 node->op()->mnemonic(), replacement->id(),
1437 replacement->op()->mnemonic());
1438
1439 if (replacement->id() < count_ &&
1440 GetInfo(node)->output_type()->Is(GetInfo(replacement)->output_type())) {
1441 // Replace with a previously existing node eagerly only if the type is the
1442 // same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001443 node->ReplaceUses(replacement);
1444 } else {
1445 // Otherwise, we are replacing a node with a representation change.
1446 // Such a substitution must be done after all lowering is done, because
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001447 // changing the type could confuse the representation change
1448 // insertion for uses of the node.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001449 replacements_.push_back(node);
1450 replacements_.push_back(replacement);
1451 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452 node->NullAllInputs(); // Node is now dead.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001453 }
1454
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001455 void PrintOutputInfo(NodeInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001456 if (FLAG_trace_representation) {
1457 OFStream os(stdout);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001458 os << info->representation() << " (";
1459 info->output_type()->PrintTo(os, Type::SEMANTIC_DIM);
1460 os << ")";
1461 }
1462 }
1463
1464 void PrintRepresentation(MachineRepresentation rep) {
1465 if (FLAG_trace_representation) {
1466 OFStream os(stdout);
1467 os << rep;
1468 }
1469 }
1470
1471 void PrintTruncation(Truncation truncation) {
1472 if (FLAG_trace_representation) {
1473 OFStream os(stdout);
1474 os << truncation.description();
1475 }
1476 }
1477
1478 void PrintUseInfo(UseInfo info) {
1479 if (FLAG_trace_representation) {
1480 OFStream os(stdout);
1481 os << info.preferred() << ":" << info.truncation().description();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001482 }
1483 }
1484
1485 private:
1486 JSGraph* jsgraph_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001487 size_t const count_; // number of nodes in the graph
1488 ZoneVector<NodeInfo> info_; // node id -> usage information
1489#ifdef DEBUG
1490 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
1491 // requirements on inputs.
1492#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001493 NodeVector nodes_; // collected nodes
1494 NodeVector replacements_; // replacements to be done after lowering
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495 Phase phase_; // current phase of algorithm
1496 RepresentationChanger* changer_; // for inserting representation changes
1497 ZoneQueue<Node*> queue_; // queue for traversing the graph
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001498 // TODO(danno): RepresentationSelector shouldn't know anything about the
1499 // source positions table, but must for now since there currently is no other
1500 // way to pass down source position information to nodes created during
1501 // lowering. Once this phase becomes a vanilla reducer, it should get source
1502 // position information via the SourcePositionWrapper like all other reducers.
1503 SourcePositionTable* source_positions_;
1504 TypeCache const& type_cache_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001505
1506 NodeInfo* GetInfo(Node* node) {
1507 DCHECK(node->id() >= 0);
1508 DCHECK(node->id() < count_);
1509 return &info_[node->id()];
1510 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001511};
1512
1513
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001514SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
1515 SourcePositionTable* source_positions)
1516 : jsgraph_(jsgraph),
1517 zone_(zone),
1518 type_cache_(TypeCache::Get()),
1519 source_positions_(source_positions) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001520
1521
1522void SimplifiedLowering::LowerAllNodes() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001523 RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
1524 RepresentationSelector selector(jsgraph(), zone_, &changer,
1525 source_positions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001526 selector.Run(this);
1527}
1528
1529
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530void SimplifiedLowering::DoLoadBuffer(Node* node,
1531 MachineRepresentation output_rep,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001532 RepresentationChanger* changer) {
1533 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001534 DCHECK_NE(MachineRepresentation::kNone, output_rep);
1535 MachineType const access_type = BufferAccessOf(node->op()).machine_type();
1536 if (output_rep != access_type.representation()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001537 Node* const buffer = node->InputAt(0);
1538 Node* const offset = node->InputAt(1);
1539 Node* const length = node->InputAt(2);
1540 Node* const effect = node->InputAt(3);
1541 Node* const control = node->InputAt(4);
1542 Node* const index =
1543 machine()->Is64()
1544 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
1545 : offset;
1546
1547 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
1548 Node* branch =
1549 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1550
1551 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001552 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
1553 effect, if_true);
1554 Node* vtrue = changer->GetRepresentationFor(
1555 etrue, access_type.representation(), NodeProperties::GetType(node),
1556 output_rep, Truncation::None());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001557
1558 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1559 Node* efalse = effect;
1560 Node* vfalse;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001561 if (output_rep == MachineRepresentation::kTagged) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001562 vfalse = jsgraph()->UndefinedConstant();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001563 } else if (output_rep == MachineRepresentation::kFloat64) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001564 vfalse =
1565 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001566 } else if (output_rep == MachineRepresentation::kFloat32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001567 vfalse =
1568 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
1569 } else {
1570 vfalse = jsgraph()->Int32Constant(0);
1571 }
1572
1573 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
1574 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
1575
1576 // Replace effect uses of {node} with the {ephi}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 NodeProperties::ReplaceUses(node, node, ephi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001578
1579 // Turn the {node} into a Phi.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001580 node->ReplaceInput(0, vtrue);
1581 node->ReplaceInput(1, vfalse);
1582 node->ReplaceInput(2, merge);
1583 node->TrimInputCount(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001584 NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001585 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001586 NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001587 }
1588}
1589
1590
1591void SimplifiedLowering::DoStoreBuffer(Node* node) {
1592 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001593 MachineRepresentation const rep =
1594 BufferAccessOf(node->op()).machine_type().representation();
1595 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001596}
1597
1598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001599Node* SimplifiedLowering::StringComparison(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001600 Operator::Properties properties = node->op()->properties();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001601 Callable callable = CodeFactory::StringCompare(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001603 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001604 isolate(), zone(), callable.descriptor(), 0, flags, properties);
1605 return graph()->NewNode(
1606 common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1607 NodeProperties::GetValueInput(node, 0),
1608 NodeProperties::GetValueInput(node, 1), jsgraph()->NoContextConstant(),
1609 NodeProperties::GetEffectInput(node),
1610 NodeProperties::GetControlInput(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001611}
1612
1613
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001614Node* SimplifiedLowering::Int32Div(Node* const node) {
1615 Int32BinopMatcher m(node);
1616 Node* const zero = jsgraph()->Int32Constant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001617 Node* const minus_one = jsgraph()->Int32Constant(-1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001618 Node* const lhs = m.left().node();
1619 Node* const rhs = m.right().node();
1620
1621 if (m.right().Is(-1)) {
1622 return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
1623 } else if (m.right().Is(0)) {
1624 return rhs;
1625 } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
1626 return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
1627 }
1628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001629 // General case for signed integer division.
1630 //
1631 // if 0 < rhs then
1632 // lhs / rhs
1633 // else
1634 // if rhs < -1 then
1635 // lhs / rhs
1636 // else if rhs == 0 then
1637 // 0
1638 // else
1639 // 0 - lhs
1640 //
1641 // Note: We do not use the Diamond helper class here, because it really hurts
1642 // readability with nested diamonds.
1643 const Operator* const merge_op = common()->Merge(2);
1644 const Operator* const phi_op =
1645 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001646
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001647 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1648 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1649 graph()->start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001650
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1652 Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
1653
1654 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1655 Node* false0;
1656 {
1657 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
1658 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
1659
1660 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1661 Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
1662
1663 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1664 Node* false1;
1665 {
1666 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1667 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
1668
1669 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1670 Node* true2 = zero;
1671
1672 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1673 Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
1674
1675 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
1676 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
1677 }
1678
1679 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
1680 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
1681 }
1682
1683 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1684 return graph()->NewNode(phi_op, true0, false0, merge0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001685}
1686
1687
1688Node* SimplifiedLowering::Int32Mod(Node* const node) {
1689 Int32BinopMatcher m(node);
1690 Node* const zero = jsgraph()->Int32Constant(0);
1691 Node* const minus_one = jsgraph()->Int32Constant(-1);
1692 Node* const lhs = m.left().node();
1693 Node* const rhs = m.right().node();
1694
1695 if (m.right().Is(-1) || m.right().Is(0)) {
1696 return zero;
1697 } else if (m.right().HasValue()) {
1698 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
1699 }
1700
1701 // General case for signed integer modulus, with optimization for (unknown)
1702 // power of 2 right hand side.
1703 //
1704 // if 0 < rhs then
1705 // msk = rhs - 1
1706 // if rhs & msk != 0 then
1707 // lhs % rhs
1708 // else
1709 // if lhs < 0 then
1710 // -(-lhs & msk)
1711 // else
1712 // lhs & msk
1713 // else
1714 // if rhs < -1 then
1715 // lhs % rhs
1716 // else
1717 // zero
1718 //
1719 // Note: We do not use the Diamond helper class here, because it really hurts
1720 // readability with nested diamonds.
1721 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001722 const Operator* const phi_op =
1723 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001724
1725 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1726 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1727 graph()->start());
1728
1729 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1730 Node* true0;
1731 {
1732 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
1733
1734 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
1735 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1736
1737 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1738 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1739
1740 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1741 Node* false1;
1742 {
1743 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
1744 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1745 check2, if_false1);
1746
1747 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1748 Node* true2 = graph()->NewNode(
1749 machine()->Int32Sub(), zero,
1750 graph()->NewNode(machine()->Word32And(),
1751 graph()->NewNode(machine()->Int32Sub(), zero, lhs),
1752 msk));
1753
1754 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1755 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1756
1757 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
1758 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
1759 }
1760
1761 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
1762 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
1763 }
1764
1765 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1766 Node* false0;
1767 {
1768 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
1769 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1770 check1, if_false0);
1771
1772 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1773 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1774
1775 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1776 Node* false1 = zero;
1777
1778 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
1779 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
1780 }
1781
1782 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1783 return graph()->NewNode(phi_op, true0, false0, merge0);
1784}
1785
1786
1787Node* SimplifiedLowering::Uint32Div(Node* const node) {
1788 Uint32BinopMatcher m(node);
1789 Node* const zero = jsgraph()->Uint32Constant(0);
1790 Node* const lhs = m.left().node();
1791 Node* const rhs = m.right().node();
1792
1793 if (m.right().Is(0)) {
1794 return zero;
1795 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
1796 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
1797 }
1798
1799 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1800 Diamond d(graph(), common(), check, BranchHint::kFalse);
1801 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001802 return d.Phi(MachineRepresentation::kWord32, zero, div);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001803}
1804
1805
1806Node* SimplifiedLowering::Uint32Mod(Node* const node) {
1807 Uint32BinopMatcher m(node);
1808 Node* const minus_one = jsgraph()->Int32Constant(-1);
1809 Node* const zero = jsgraph()->Uint32Constant(0);
1810 Node* const lhs = m.left().node();
1811 Node* const rhs = m.right().node();
1812
1813 if (m.right().Is(0)) {
1814 return zero;
1815 } else if (m.right().HasValue()) {
1816 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
1817 }
1818
1819 // General case for unsigned integer modulus, with optimization for (unknown)
1820 // power of 2 right hand side.
1821 //
1822 // if rhs then
1823 // msk = rhs - 1
1824 // if rhs & msk != 0 then
1825 // lhs % rhs
1826 // else
1827 // lhs & msk
1828 // else
1829 // zero
1830 //
1831 // Note: We do not use the Diamond helper class here, because it really hurts
1832 // readability with nested diamonds.
1833 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001834 const Operator* const phi_op =
1835 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001836
1837 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
1838 graph()->start());
1839
1840 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1841 Node* true0;
1842 {
1843 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
1844
1845 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
1846 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1847
1848 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1849 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
1850
1851 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1852 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1853
1854 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
1855 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
1856 }
1857
1858 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1859 Node* false0 = zero;
1860
1861 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1862 return graph()->NewNode(phi_op, true0, false0, merge0);
1863}
1864
1865
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001866void SimplifiedLowering::DoShift(Node* node, Operator const* op,
1867 Type* rhs_type) {
1868 Node* const rhs = NodeProperties::GetValueInput(node, 1);
1869 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
1870 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
1871 jsgraph()->Int32Constant(0x1f)));
1872 }
1873 NodeProperties::ChangeOp(node, op);
1874}
1875
1876
1877namespace {
1878
1879void ReplaceEffectUses(Node* node, Node* replacement) {
1880 // Requires distinguishing between value and effect edges.
1881 DCHECK(replacement->op()->EffectOutputCount() > 0);
1882 for (Edge edge : node->use_edges()) {
1883 if (NodeProperties::IsEffectEdge(edge)) {
1884 edge.UpdateTo(replacement);
1885 } else {
1886 DCHECK(NodeProperties::IsValueEdge(edge));
1887 }
1888 }
1889}
1890
1891} // namespace
1892
1893
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001894void SimplifiedLowering::DoStringEqual(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001895 Node* comparison = StringComparison(node);
1896 ReplaceEffectUses(node, comparison);
1897 node->ReplaceInput(0, comparison);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001898 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001899 node->TrimInputCount(2);
1900 NodeProperties::ChangeOp(node, machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001901}
1902
1903
1904void SimplifiedLowering::DoStringLessThan(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001905 Node* comparison = StringComparison(node);
1906 ReplaceEffectUses(node, comparison);
1907 node->ReplaceInput(0, comparison);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001908 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001909 node->TrimInputCount(2);
1910 NodeProperties::ChangeOp(node, machine()->IntLessThan());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001911}
1912
1913
1914void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001915 Node* comparison = StringComparison(node);
1916 ReplaceEffectUses(node, comparison);
1917 node->ReplaceInput(0, comparison);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001918 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001919 node->TrimInputCount(2);
1920 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001921}
1922
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001923} // namespace compiler
1924} // namespace internal
1925} // namespace v8