blob: 653fea80eac4f4782316d6405159bfa100699f22 [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();
145 case MachineRepresentation::kNone:
146 break;
147 }
148 UNREACHABLE();
149 return UseInfo::None();
150}
151
152
153UseInfo UseInfoForBasePointer(const FieldAccess& access) {
154 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
155}
156
157
158UseInfo UseInfoForBasePointer(const ElementAccess& access) {
159 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
160}
161
162
163#ifdef DEBUG
164// Helpers for monotonicity checking.
165bool MachineRepresentationIsSubtype(MachineRepresentation r1,
166 MachineRepresentation r2) {
167 switch (r1) {
168 case MachineRepresentation::kNone:
169 return true;
170 case MachineRepresentation::kBit:
171 return r2 == MachineRepresentation::kBit ||
172 r2 == MachineRepresentation::kTagged;
173 case MachineRepresentation::kWord8:
174 return r2 == MachineRepresentation::kWord8 ||
175 r2 == MachineRepresentation::kWord16 ||
176 r2 == MachineRepresentation::kWord32 ||
177 r2 == MachineRepresentation::kWord64 ||
178 r2 == MachineRepresentation::kFloat32 ||
179 r2 == MachineRepresentation::kFloat64 ||
180 r2 == MachineRepresentation::kTagged;
181 case MachineRepresentation::kWord16:
182 return r2 == MachineRepresentation::kWord16 ||
183 r2 == MachineRepresentation::kWord32 ||
184 r2 == MachineRepresentation::kWord64 ||
185 r2 == MachineRepresentation::kFloat32 ||
186 r2 == MachineRepresentation::kFloat64 ||
187 r2 == MachineRepresentation::kTagged;
188 case MachineRepresentation::kWord32:
189 return r2 == MachineRepresentation::kWord32 ||
190 r2 == MachineRepresentation::kWord64 ||
191 r2 == MachineRepresentation::kFloat64 ||
192 r2 == MachineRepresentation::kTagged;
193 case MachineRepresentation::kWord64:
194 return r2 == MachineRepresentation::kWord64;
195 case MachineRepresentation::kFloat32:
196 return r2 == MachineRepresentation::kFloat32 ||
197 r2 == MachineRepresentation::kFloat64 ||
198 r2 == MachineRepresentation::kTagged;
199 case MachineRepresentation::kFloat64:
200 return r2 == MachineRepresentation::kFloat64 ||
201 r2 == MachineRepresentation::kTagged;
202 case MachineRepresentation::kTagged:
203 return r2 == MachineRepresentation::kTagged;
204 }
205 UNREACHABLE();
206 return false;
207}
208
209
210class InputUseInfos {
211 public:
212 explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
213
214 void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
215 if (input_use_infos_.empty()) {
216 input_use_infos_.resize(node->InputCount(), UseInfo::None());
217 }
218 // Check that the new use informatin is a super-type of the old
219 // one.
220 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
221 input_use_infos_[index] = use_info;
222 }
223
224 private:
225 ZoneVector<UseInfo> input_use_infos_;
226
227 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
228 return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) &&
229 use1.truncation().IsLessGeneralThan(use2.truncation());
230 }
231};
232
233#endif // DEBUG
234
235} // namespace
236
237
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238class RepresentationSelector {
239 public:
240 // Information for each node tracked during the fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000241 class NodeOutputInfo {
242 public:
243 NodeOutputInfo(MachineRepresentation representation, Type* type)
244 : type_(type), representation_(representation) {}
245 NodeOutputInfo()
246 : type_(Type::None()), representation_(MachineRepresentation::kNone) {}
247
248 MachineRepresentation representation() const { return representation_; }
249 Type* type() const { return type_; }
250
251 static NodeOutputInfo None() {
252 return NodeOutputInfo(MachineRepresentation::kNone, Type::None());
253 }
254
255 static NodeOutputInfo Float32() {
256 return NodeOutputInfo(MachineRepresentation::kFloat32, Type::Number());
257 }
258
259 static NodeOutputInfo Float64() {
260 return NodeOutputInfo(MachineRepresentation::kFloat64, Type::Number());
261 }
262
263 static NodeOutputInfo NumberTruncatedToWord32() {
264 return NodeOutputInfo(MachineRepresentation::kWord32, Type::Number());
265 }
266
267 static NodeOutputInfo Int32() {
268 return NodeOutputInfo(MachineRepresentation::kWord32, Type::Signed32());
269 }
270
271 static NodeOutputInfo Uint32() {
272 return NodeOutputInfo(MachineRepresentation::kWord32, Type::Unsigned32());
273 }
274
275 static NodeOutputInfo Bool() {
276 return NodeOutputInfo(MachineRepresentation::kBit, Type::Boolean());
277 }
278
279 static NodeOutputInfo Int64() {
280 // TODO(jarin) Fix once we have a real int64 type.
281 return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
282 }
283
284 static NodeOutputInfo Uint64() {
285 // TODO(jarin) Fix once we have a real uint64 type.
286 return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
287 }
288
289 static NodeOutputInfo AnyTagged() {
290 return NodeOutputInfo(MachineRepresentation::kTagged, Type::Any());
291 }
292
293 static NodeOutputInfo NumberTagged() {
294 return NodeOutputInfo(MachineRepresentation::kTagged, Type::Number());
295 }
296
297 static NodeOutputInfo Pointer() {
298 return NodeOutputInfo(MachineType::PointerRepresentation(), Type::Any());
299 }
300
301 private:
302 Type* type_;
303 MachineRepresentation representation_;
304 };
305
306 class NodeInfo {
307 public:
308 // Adds new use to the node. Returns true if something has changed
309 // and the node has to be requeued.
310 bool AddUse(UseInfo info) {
311 Truncation old_truncation = truncation_;
312 truncation_ = Truncation::Generalize(truncation_, info.truncation());
313 return truncation_ != old_truncation;
314 }
315
316 void set_queued(bool value) { queued_ = value; }
317 bool queued() const { return queued_; }
318 void set_visited() { visited_ = true; }
319 bool visited() const { return visited_; }
320 Truncation truncation() const { return truncation_; }
321 void set_output_type(NodeOutputInfo output) { output_ = output; }
322
323 Type* output_type() const { return output_.type(); }
324 MachineRepresentation representation() const {
325 return output_.representation();
326 }
327
328 private:
329 bool queued_ = false; // Bookkeeping for the traversal.
330 bool visited_ = false; // Bookkeeping for the traversal.
331 NodeOutputInfo output_; // Output type and representation.
332 Truncation truncation_ = Truncation::None(); // Information about uses.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 };
334
335 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 RepresentationChanger* changer,
337 SourcePositionTable* source_positions)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000338 : jsgraph_(jsgraph),
339 count_(jsgraph->graph()->NodeCount()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340 info_(count_, zone),
341#ifdef DEBUG
342 node_input_use_infos_(count_, InputUseInfos(zone), zone),
343#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000344 nodes_(zone),
345 replacements_(zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000346 phase_(PROPAGATE),
347 changer_(changer),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348 queue_(zone),
349 source_positions_(source_positions),
350 type_cache_(TypeCache::Get()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000351 }
352
353 void Run(SimplifiedLowering* lowering) {
354 // Run propagation phase to a fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355 TRACE("--{Propagation phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000356 phase_ = PROPAGATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 EnqueueInitial(jsgraph_->graph()->end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 // Process nodes from the queue until it is empty.
359 while (!queue_.empty()) {
360 Node* node = queue_.front();
361 NodeInfo* info = GetInfo(node);
362 queue_.pop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 info->set_queued(false);
364 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
365 VisitNode(node, info->truncation(), nullptr);
366 TRACE(" ==> output ");
367 PrintOutputInfo(info);
368 TRACE("\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 }
370
371 // Run lowering and change insertion phase.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 TRACE("--{Simplified lowering phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 phase_ = LOWER;
374 // Process nodes from the collected {nodes_} vector.
375 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
376 Node* node = *i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377 NodeInfo* info = GetInfo(node);
378 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000379 // Reuse {VisitNode()} so the representation rules are in one place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000380 SourcePositionTable::Scope scope(
381 source_positions_, source_positions_->GetSourcePosition(node));
382 VisitNode(node, info->truncation(), lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000383 }
384
385 // Perform the final replacements.
386 for (NodeVector::iterator i = replacements_.begin();
387 i != replacements_.end(); ++i) {
388 Node* node = *i;
389 Node* replacement = *(++i);
390 node->ReplaceUses(replacement);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000391 // We also need to replace the node in the rest of the vector.
392 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
393 ++j;
394 if (*j == node) *j = replacement;
395 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000396 }
397 }
398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 void EnqueueInitial(Node* node) {
400 NodeInfo* info = GetInfo(node);
401 info->set_visited();
402 info->set_queued(true);
403 nodes_.push_back(node);
404 queue_.push(node);
405 }
406
407 // Enqueue {use_node}'s {index} input if the {use} contains new information
408 // for that input node. Add the input to {nodes_} if this is the first time
409 // it's been visited.
410 void EnqueueInput(Node* use_node, int index,
411 UseInfo use_info = UseInfo::None()) {
412 Node* node = use_node->InputAt(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 if (phase_ != PROPAGATE) return;
414 NodeInfo* info = GetInfo(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415#ifdef DEBUG
416 // Check monotonicity of input requirements.
417 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
418 use_info);
419#endif // DEBUG
420 if (!info->visited()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000421 // First visit of this node.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 info->set_visited();
423 info->set_queued(true);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 nodes_.push_back(node);
425 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426 TRACE(" initial: ");
427 info->AddUse(use_info);
428 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 return;
430 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000431 TRACE(" queue?: ");
432 PrintTruncation(info->truncation());
433 if (info->AddUse(use_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000434 // New usage information for the node is available.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 if (!info->queued()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000436 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000437 info->set_queued(true);
438 TRACE(" added: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 TRACE(" inqueue: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 }
444 }
445
446 bool lower() { return phase_ == LOWER; }
447
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000448 void EnqueueUses(Node* node) {
449 for (Edge edge : node->use_edges()) {
450 if (NodeProperties::IsValueEdge(edge)) {
451 Node* const user = edge.from();
452 if (user->id() < count_) {
453 // New type information for the node is available.
454 NodeInfo* info = GetInfo(user);
455 // Enqueue the node only if we are sure it is reachable from
456 // the end and it has not been queued yet.
457 if (info->visited() && !info->queued()) {
458 queue_.push(user);
459 info->set_queued(true);
460 }
461 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400462 }
463 }
464 }
465
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 void SetOutputFromMachineType(Node* node, MachineType machine_type) {
467 Type* type = Type::None();
468 switch (machine_type.semantic()) {
469 case MachineSemantic::kNone:
470 type = Type::None();
471 break;
472 case MachineSemantic::kBool:
473 type = Type::Boolean();
474 break;
475 case MachineSemantic::kInt32:
476 type = Type::Signed32();
477 break;
478 case MachineSemantic::kUint32:
479 type = Type::Unsigned32();
480 break;
481 case MachineSemantic::kInt64:
482 // TODO(jarin) Fix once we have proper int64.
483 type = Type::Internal();
484 break;
485 case MachineSemantic::kUint64:
486 // TODO(jarin) Fix once we have proper uint64.
487 type = Type::Internal();
488 break;
489 case MachineSemantic::kNumber:
490 type = Type::Number();
491 break;
492 case MachineSemantic::kAny:
493 type = Type::Any();
494 break;
495 }
496 return SetOutput(node, NodeOutputInfo(machine_type.representation(), type));
497 }
498
499 void SetOutput(Node* node, NodeOutputInfo output_info) {
500 // Every node should have at most one output representation. Note that
501 // phis can have 0, if they have not been used in a representation-inducing
502 // instruction.
503 Type* output_type = output_info.type();
504 if (NodeProperties::IsTyped(node)) {
505 output_type = Type::Intersect(NodeProperties::GetType(node),
506 output_info.type(), jsgraph_->zone());
507 }
508 NodeInfo* info = GetInfo(node);
509 DCHECK(info->output_type()->Is(output_type));
510 DCHECK(MachineRepresentationIsSubtype(info->representation(),
511 output_info.representation()));
512 if (!output_type->Is(info->output_type()) ||
513 output_info.representation() != info->representation()) {
514 EnqueueUses(node);
515 }
516 info->set_output_type(
517 NodeOutputInfo(output_info.representation(), output_type));
518 }
519
520 bool BothInputsAreSigned32(Node* node) {
521 DCHECK_EQ(2, node->InputCount());
522 return GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32()) &&
523 GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32());
524 }
525
526 bool BothInputsAreUnsigned32(Node* node) {
527 DCHECK_EQ(2, node->InputCount());
528 return GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32()) &&
529 GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32());
530 }
531
532 bool BothInputsAre(Node* node, Type* type) {
533 DCHECK_EQ(2, node->InputCount());
534 return GetInfo(node->InputAt(0))->output_type()->Is(type) &&
535 GetInfo(node->InputAt(1))->output_type()->Is(type);
536 }
537
538 void ConvertInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000539 Node* input = node->InputAt(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000540 // In the change phase, insert a change before the use if necessary.
541 if (use.preferred() == MachineRepresentation::kNone)
542 return; // No input requirement on the use.
543 NodeInfo* input_info = GetInfo(input);
544 MachineRepresentation input_rep = input_info->representation();
545 if (input_rep != use.preferred()) {
546 // Output representation doesn't match usage.
547 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
548 index, input->id(), input->op()->mnemonic());
549 TRACE(" from ");
550 PrintOutputInfo(input_info);
551 TRACE(" to ");
552 PrintUseInfo(use);
553 TRACE("\n");
554 Node* n = changer_->GetRepresentationFor(
555 input, input_info->representation(), input_info->output_type(),
556 use.preferred(), use.truncation());
557 node->ReplaceInput(index, n);
558 }
559 }
560
561 void ProcessInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000562 if (phase_ == PROPAGATE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563 EnqueueInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000564 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 ConvertInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 }
567 }
568
569 void ProcessRemainingInputs(Node* node, int index) {
570 DCHECK_GE(index, NodeProperties::PastValueIndex(node));
571 DCHECK_GE(index, NodeProperties::PastContextIndex(node));
572 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
573 i < NodeProperties::PastEffectIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000574 EnqueueInput(node, i); // Effect inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575 }
576 for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
577 i < NodeProperties::PastControlIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578 EnqueueInput(node, i); // Control inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579 }
580 }
581
582 // The default, most general visitation case. For {node}, process all value,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 // context, frame state, effect, and control inputs, assuming that value
584 // inputs should have {kRepTagged} representation and can observe all output
585 // values {kTypeAny}.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000586 void VisitInputs(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 int tagged_count = node->op()->ValueInputCount() +
588 OperatorProperties::GetContextInputCount(node->op());
589 // Visit value and context inputs as tagged.
590 for (int i = 0; i < tagged_count; i++) {
591 ProcessInput(node, i, UseInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000592 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 // Only enqueue other inputs (framestates, effects, control).
594 for (int i = tagged_count; i < node->InputCount(); i++) {
595 EnqueueInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000596 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597 }
598
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000599 // Helper for binops of the R x L -> O variety.
600 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
601 NodeOutputInfo output) {
602 DCHECK_EQ(2, node->op()->ValueInputCount());
603 ProcessInput(node, 0, left_use);
604 ProcessInput(node, 1, right_use);
605 for (int i = 2; i < node->InputCount(); i++) {
606 EnqueueInput(node, i);
607 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000608 SetOutput(node, output);
609 }
610
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000611 // Helper for binops of the I x I -> O variety.
612 void VisitBinop(Node* node, UseInfo input_use, NodeOutputInfo output) {
613 VisitBinop(node, input_use, input_use, output);
614 }
615
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000616 // Helper for unops of the I -> O variety.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 void VisitUnop(Node* node, UseInfo input_use, NodeOutputInfo output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000618 DCHECK_EQ(1, node->InputCount());
619 ProcessInput(node, 0, input_use);
620 SetOutput(node, output);
621 }
622
623 // Helper for leaf nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624 void VisitLeaf(Node* node, NodeOutputInfo output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 DCHECK_EQ(0, node->InputCount());
626 SetOutput(node, output);
627 }
628
629 // Helpers for specific types of binops.
630 void VisitFloat64Binop(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000631 VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000632 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 void VisitInt32Binop(Node* node) {
634 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
635 }
636 void VisitWord32TruncatingBinop(Node* node) {
637 VisitBinop(node, UseInfo::TruncatingWord32(),
638 NodeOutputInfo::NumberTruncatedToWord32());
639 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000640 void VisitUint32Binop(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000641 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000642 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000643 void VisitInt64Binop(Node* node) {
644 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Int64());
645 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000646 void VisitUint64Binop(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Uint64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649 void VisitFloat64Cmp(Node* node) {
650 VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
651 }
652 void VisitInt32Cmp(Node* node) {
653 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
654 }
655 void VisitUint32Cmp(Node* node) {
656 VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
657 }
658 void VisitInt64Cmp(Node* node) {
659 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
660 }
661 void VisitUint64Cmp(Node* node) {
662 VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
663 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000664
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400665 // Infer representation for phi-like nodes.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 NodeOutputInfo GetOutputInfoForPhi(Node* node, Truncation use) {
667 // Compute the type.
668 Type* type = GetInfo(node->InputAt(0))->output_type();
669 for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
670 type = Type::Union(type, GetInfo(node->InputAt(i))->output_type(),
671 jsgraph_->zone());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400672 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673
674 // Compute the representation.
675 MachineRepresentation rep = MachineRepresentation::kTagged;
676 if (type->Is(Type::None())) {
677 rep = MachineRepresentation::kNone;
678 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
679 rep = MachineRepresentation::kWord32;
680 } else if (use.TruncatesToWord32()) {
681 rep = MachineRepresentation::kWord32;
682 } else if (type->Is(Type::Boolean())) {
683 rep = MachineRepresentation::kBit;
684 } else if (type->Is(Type::Number())) {
685 rep = MachineRepresentation::kFloat64;
686 } else if (type->Is(Type::Internal())) {
687 // We mark (u)int64 as Type::Internal.
688 // TODO(jarin) This is a workaround for our lack of (u)int64
689 // types. This can be removed once we can represent (u)int64
690 // unambiguously. (At the moment internal objects, such as the hole,
691 // are also Type::Internal()).
692 bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
693 MachineRepresentation::kWord64;
694#ifdef DEBUG
695 // Check that all the inputs agree on being Word64.
696 for (int i = 1; i < node->op()->ValueInputCount(); i++) {
697 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
698 MachineRepresentation::kWord64);
699 }
700#endif
701 rep = is_word64 ? MachineRepresentation::kWord64
702 : MachineRepresentation::kTagged;
703 }
704 return NodeOutputInfo(rep, type);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400705 }
706
707 // Helper for handling selects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000708 void VisitSelect(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400709 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000710 ProcessInput(node, 0, UseInfo::Bool());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400711
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000712 NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
713 SetOutput(node, output);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714
715 if (lower()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400716 // Update the select operator.
717 SelectParameters p = SelectParametersOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 if (output.representation() != p.representation()) {
719 NodeProperties::ChangeOp(node, lowering->common()->Select(
720 output.representation(), p.hint()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400721 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400722 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000723 // Convert inputs to the output representation of this phi, pass the
724 // truncation truncation along.
725 UseInfo input_use(output.representation(), truncation);
726 ProcessInput(node, 1, input_use);
727 ProcessInput(node, 2, input_use);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400728 }
729
730 // Helper for handling phis.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000731 void VisitPhi(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400732 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000733 NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
734 SetOutput(node, output);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400735
736 int values = node->op()->ValueInputCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400737 if (lower()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000738 // Update the phi operator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 if (output.representation() != PhiRepresentationOf(node->op())) {
740 NodeProperties::ChangeOp(
741 node, lowering->common()->Phi(output.representation(), values));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742 }
743 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000744
745 // Convert inputs to the output representation of this phi, pass the
746 // truncation truncation along.
747 UseInfo input_use(output.representation(), truncation);
748 for (int i = 0; i < node->InputCount(); i++) {
749 ProcessInput(node, i, i < values ? input_use : UseInfo::None());
750 }
751 }
752
753 void VisitCall(Node* node, SimplifiedLowering* lowering) {
754 const CallDescriptor* desc = OpParameter<const CallDescriptor*>(node->op());
755 const MachineSignature* sig = desc->GetMachineSignature();
756 int params = static_cast<int>(sig->parameter_count());
757 // Propagate representation information from call descriptor.
758 for (int i = 0; i < node->InputCount(); i++) {
759 if (i == 0) {
760 // The target of the call.
761 ProcessInput(node, i, UseInfo::None());
762 } else if ((i - 1) < params) {
763 ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
764 sig->GetParam(i - 1).representation()));
765 } else {
766 ProcessInput(node, i, UseInfo::None());
767 }
768 }
769
770 if (sig->return_count() > 0) {
771 SetOutputFromMachineType(node, desc->GetMachineSignature()->GetReturn());
772 } else {
773 SetOutput(node, NodeOutputInfo::AnyTagged());
774 }
775 }
776
777 MachineSemantic DeoptValueSemanticOf(Type* type) {
778 CHECK(!type->Is(Type::None()));
779 // We only need signedness to do deopt correctly.
780 if (type->Is(Type::Signed32())) {
781 return MachineSemantic::kInt32;
782 } else if (type->Is(Type::Unsigned32())) {
783 return MachineSemantic::kUint32;
784 } else {
785 return MachineSemantic::kAny;
786 }
787 }
788
789 void VisitStateValues(Node* node) {
790 if (phase_ == PROPAGATE) {
791 for (int i = 0; i < node->InputCount(); i++) {
792 EnqueueInput(node, i, UseInfo::Any());
793 }
794 } else {
795 Zone* zone = jsgraph_->zone();
796 ZoneVector<MachineType>* types =
797 new (zone->New(sizeof(ZoneVector<MachineType>)))
798 ZoneVector<MachineType>(node->InputCount(), zone);
799 for (int i = 0; i < node->InputCount(); i++) {
800 NodeInfo* input_info = GetInfo(node->InputAt(i));
801 MachineType machine_type(
802 input_info->representation(),
803 DeoptValueSemanticOf(input_info->output_type()));
804 DCHECK(machine_type.representation() !=
805 MachineRepresentation::kWord32 ||
806 machine_type.semantic() == MachineSemantic::kInt32 ||
807 machine_type.semantic() == MachineSemantic::kUint32);
808 (*types)[i] = machine_type;
809 }
810 NodeProperties::ChangeOp(node,
811 jsgraph_->common()->TypedStateValues(types));
812 }
813 SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000814 }
815
816 const Operator* Int32Op(Node* node) {
817 return changer_->Int32OperatorFor(node->opcode());
818 }
819
820 const Operator* Uint32Op(Node* node) {
821 return changer_->Uint32OperatorFor(node->opcode());
822 }
823
824 const Operator* Float64Op(Node* node) {
825 return changer_->Float64OperatorFor(node->opcode());
826 }
827
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828 // Dispatching routine for visiting the node {node} with the usage {use}.
829 // Depending on the operator, propagate new usage info to the inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000830 void VisitNode(Node* node, Truncation truncation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831 SimplifiedLowering* lowering) {
832 switch (node->opcode()) {
833 //------------------------------------------------------------------
834 // Common operators.
835 //------------------------------------------------------------------
836 case IrOpcode::kStart:
837 case IrOpcode::kDead:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000838 return VisitLeaf(node, NodeOutputInfo::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000839 case IrOpcode::kParameter: {
840 // TODO(titzer): use representation from linkage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 Type* type = NodeProperties::GetType(node);
842 ProcessInput(node, 0, UseInfo::None());
843 SetOutput(node, NodeOutputInfo(MachineRepresentation::kTagged, type));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844 return;
845 }
846 case IrOpcode::kInt32Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000847 return VisitLeaf(node, NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 case IrOpcode::kInt64Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000849 return VisitLeaf(node, NodeOutputInfo::Int64());
850 case IrOpcode::kFloat32Constant:
851 return VisitLeaf(node, NodeOutputInfo::Float32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000852 case IrOpcode::kFloat64Constant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 return VisitLeaf(node, NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000854 case IrOpcode::kExternalConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 return VisitLeaf(node, NodeOutputInfo::Pointer());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 case IrOpcode::kNumberConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000857 return VisitLeaf(node, NodeOutputInfo::NumberTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000858 case IrOpcode::kHeapConstant:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 return VisitLeaf(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860
861 case IrOpcode::kBranch:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000862 ProcessInput(node, 0, UseInfo::Bool());
863 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
864 break;
865 case IrOpcode::kSwitch:
866 ProcessInput(node, 0, UseInfo::TruncatingWord32());
867 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000868 break;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400869 case IrOpcode::kSelect:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870 return VisitSelect(node, truncation, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871 case IrOpcode::kPhi:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000872 return VisitPhi(node, truncation, lowering);
873 case IrOpcode::kCall:
874 return VisitCall(node, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000875
876//------------------------------------------------------------------
877// JavaScript operators.
878//------------------------------------------------------------------
879// For now, we assume that all JS operators were too complex to lower
880// to Simplified and that they will always require tagged value inputs
881// and produce tagged value outputs.
882// TODO(turbofan): it might be possible to lower some JSOperators here,
883// but that responsibility really lies in the typed lowering phase.
884#define DEFINE_JS_CASE(x) case IrOpcode::k##x:
885 JS_OP_LIST(DEFINE_JS_CASE)
886#undef DEFINE_JS_CASE
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000888 return SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889
890 //------------------------------------------------------------------
891 // Simplified operators.
892 //------------------------------------------------------------------
893 case IrOpcode::kBooleanNot: {
894 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000895 NodeInfo* input_info = GetInfo(node->InputAt(0));
896 if (input_info->representation() == MachineRepresentation::kBit) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400897 // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000898 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900 } else {
901 // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000902 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000903 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904 }
905 } else {
906 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
908 SetOutput(node, NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 }
910 break;
911 }
912 case IrOpcode::kBooleanToNumber: {
913 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 NodeInfo* input_info = GetInfo(node->InputAt(0));
915 if (input_info->representation() == MachineRepresentation::kBit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 // BooleanToNumber(x: kRepBit) => x
917 DeferReplacement(node, node->InputAt(0));
918 } else {
919 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000922 }
923 } else {
924 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
926 SetOutput(node, NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000927 }
928 break;
929 }
930 case IrOpcode::kNumberEqual:
931 case IrOpcode::kNumberLessThan:
932 case IrOpcode::kNumberLessThanOrEqual: {
933 // Number comparisons reduce to integer comparisons for integer inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934 if (BothInputsAreSigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000935 // => signed Int32Cmp
936 VisitInt32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
938 } else if (BothInputsAreUnsigned32(node)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 // => unsigned Int32Cmp
940 VisitUint32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000942 } else {
943 // => Float64Cmp
944 VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000945 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000946 }
947 break;
948 }
949 case IrOpcode::kNumberAdd:
950 case IrOpcode::kNumberSubtract: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951 if (BothInputsAre(node, Type::Signed32()) &&
952 NodeProperties::GetType(node)->Is(Type::Signed32())) {
953 // int32 + int32 = int32
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 // => signed Int32Add/Sub
955 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
957 } else if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
958 truncation.TruncatesToWord32()) {
959 // safe-int + safe-int = x (truncated to int32)
960 // => signed Int32Add/Sub (truncated)
961 VisitWord32TruncatingBinop(node);
962 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000963 } else {
964 // => Float64Add/Sub
965 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000966 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 }
968 break;
969 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400970 case IrOpcode::kNumberMultiply: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 if (BothInputsAreSigned32(node)) {
972 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
973 // Multiply reduces to Int32Mul if the inputs and the output
974 // are integers.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400975 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
977 break;
978 }
979 if (truncation.TruncatesToWord32() &&
980 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger)) {
981 // Multiply reduces to Int32Mul if the inputs are integers,
982 // the uses are truncating and the result is in the safe
983 // integer range.
984 VisitWord32TruncatingBinop(node);
985 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 break;
987 }
988 }
989 // => Float64Mul
990 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000991 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400992 break;
993 }
994 case IrOpcode::kNumberDivide: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000995 if (BothInputsAreSigned32(node)) {
996 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400997 // => signed Int32Div
998 VisitInt32Binop(node);
999 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1000 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 }
1002 if (truncation.TruncatesToWord32()) {
1003 // => signed Int32Div
1004 VisitWord32TruncatingBinop(node);
1005 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
1006 break;
1007 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001008 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001010 // => unsigned Uint32Div
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001012 if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
1013 break;
1014 }
1015 // => Float64Div
1016 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001018 break;
1019 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001020 case IrOpcode::kNumberModulus: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 if (BothInputsAreSigned32(node)) {
1022 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1023 // => signed Int32Mod
1024 VisitInt32Binop(node);
1025 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1026 break;
1027 }
1028 if (truncation.TruncatesToWord32()) {
1029 // => signed Int32Mod
1030 VisitWord32TruncatingBinop(node);
1031 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
1032 break;
1033 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001034 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001035 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001036 // => unsigned Uint32Mod
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001038 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
1039 break;
1040 }
1041 // => Float64Mod
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001042 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001044 break;
1045 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001046 case IrOpcode::kNumberBitwiseOr:
1047 case IrOpcode::kNumberBitwiseXor:
1048 case IrOpcode::kNumberBitwiseAnd: {
1049 VisitInt32Binop(node);
1050 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
1051 break;
1052 }
1053 case IrOpcode::kNumberShiftLeft: {
1054 Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
1055 VisitBinop(node, UseInfo::TruncatingWord32(),
1056 UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
1057 if (lower()) {
1058 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001059 }
1060 break;
1061 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001062 case IrOpcode::kNumberShiftRight: {
1063 Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
1064 VisitBinop(node, UseInfo::TruncatingWord32(),
1065 UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
1066 if (lower()) {
1067 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1068 }
1069 break;
1070 }
1071 case IrOpcode::kNumberShiftRightLogical: {
1072 Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
1073 VisitBinop(node, UseInfo::TruncatingWord32(),
1074 UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
1075 if (lower()) {
1076 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
1077 }
1078 break;
1079 }
1080 case IrOpcode::kNumberToInt32: {
1081 // Just change representation if necessary.
1082 VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
1083 if (lower()) DeferReplacement(node, node->InputAt(0));
1084 break;
1085 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086 case IrOpcode::kNumberToUint32: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001087 // Just change representation if necessary.
1088 VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
1089 if (lower()) DeferReplacement(node, node->InputAt(0));
1090 break;
1091 }
1092 case IrOpcode::kNumberIsHoleNaN: {
1093 VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
1094 if (lower()) {
1095 // NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
1096 // #HoleNaNLower32)
1097 node->ReplaceInput(0,
1098 jsgraph_->graph()->NewNode(
1099 lowering->machine()->Float64ExtractLowWord32(),
1100 node->InputAt(0)));
1101 node->AppendInput(jsgraph_->zone(),
1102 jsgraph_->Int32Constant(kHoleNanLower32));
1103 NodeProperties::ChangeOp(node, jsgraph_->machine()->Word32Equal());
1104 }
1105 break;
1106 }
1107 case IrOpcode::kPlainPrimitiveToNumber: {
1108 VisitUnop(node, UseInfo::AnyTagged(), NodeOutputInfo::NumberTagged());
1109 if (lower()) {
1110 // PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
1111 Operator::Properties properties = node->op()->properties();
1112 Callable callable = CodeFactory::ToNumber(jsgraph_->isolate());
1113 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1114 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1115 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1116 flags, properties);
1117 node->InsertInput(jsgraph_->zone(), 0,
1118 jsgraph_->HeapConstant(callable.code()));
1119 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1120 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001121 }
1122 break;
1123 }
1124 case IrOpcode::kReferenceEqual: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
1126 if (lower()) {
1127 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1128 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129 break;
1130 }
1131 case IrOpcode::kStringEqual: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 if (lower()) lowering->DoStringEqual(node);
1134 break;
1135 }
1136 case IrOpcode::kStringLessThan: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001138 if (lower()) lowering->DoStringLessThan(node);
1139 break;
1140 }
1141 case IrOpcode::kStringLessThanOrEqual: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142 VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001143 if (lower()) lowering->DoStringLessThanOrEqual(node);
1144 break;
1145 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 case IrOpcode::kAllocate: {
1147 ProcessInput(node, 0, UseInfo::AnyTagged());
1148 ProcessRemainingInputs(node, 1);
1149 SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001150 break;
1151 }
1152 case IrOpcode::kLoadField: {
1153 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154 ProcessInput(node, 0, UseInfoForBasePointer(access));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001155 ProcessRemainingInputs(node, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001156 SetOutputFromMachineType(node, access.machine_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001157 break;
1158 }
1159 case IrOpcode::kStoreField: {
1160 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001161 ProcessInput(node, 0, UseInfoForBasePointer(access));
1162 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
1163 access.machine_type.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001164 ProcessRemainingInputs(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001165 SetOutput(node, NodeOutputInfo::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001166 break;
1167 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001168 case IrOpcode::kLoadBuffer: {
1169 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001170 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1171 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1172 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001174
1175 NodeOutputInfo output_info;
1176 if (truncation.TruncatesUndefinedToZeroOrNaN()) {
1177 if (truncation.TruncatesNaNToZero()) {
1178 // If undefined is truncated to a non-NaN number, we can use
1179 // the load's representation.
1180 output_info = NodeOutputInfo(access.machine_type().representation(),
1181 NodeProperties::GetType(node));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001182 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 // If undefined is truncated to a number, but the use can
1184 // observe NaN, we need to output at least the float32
1185 // representation.
1186 if (access.machine_type().representation() ==
1187 MachineRepresentation::kFloat32) {
1188 output_info =
1189 NodeOutputInfo(access.machine_type().representation(),
1190 NodeProperties::GetType(node));
1191 } else {
1192 output_info = NodeOutputInfo::Float64();
1193 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001194 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001195 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 // If undefined is not truncated away, we need to have the tagged
1197 // representation.
1198 output_info = NodeOutputInfo::AnyTagged();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001199 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001200 SetOutput(node, output_info);
1201 if (lower())
1202 lowering->DoLoadBuffer(node, output_info.representation(), changer_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001203 break;
1204 }
1205 case IrOpcode::kStoreBuffer: {
1206 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001207 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1208 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1209 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1210 ProcessInput(node, 3,
1211 TruncatingUseInfoFromRepresentation(
1212 access.machine_type().representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001213 ProcessRemainingInputs(node, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 SetOutput(node, NodeOutputInfo::None());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001215 if (lower()) lowering->DoStoreBuffer(node);
1216 break;
1217 }
1218 case IrOpcode::kLoadElement: {
1219 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001220 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1221 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001222 ProcessRemainingInputs(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001223 SetOutputFromMachineType(node, access.machine_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001224 break;
1225 }
1226 case IrOpcode::kStoreElement: {
1227 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001228 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1229 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1230 ProcessInput(node, 2,
1231 TruncatingUseInfoFromRepresentation(
1232 access.machine_type.representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001233 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 SetOutput(node, NodeOutputInfo::None());
1235 break;
1236 }
1237 case IrOpcode::kObjectIsNumber: {
1238 ProcessInput(node, 0, UseInfo::AnyTagged());
1239 SetOutput(node, NodeOutputInfo::Bool());
1240 if (lower()) lowering->DoObjectIsNumber(node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241 break;
1242 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001243 case IrOpcode::kObjectIsSmi: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001244 ProcessInput(node, 0, UseInfo::AnyTagged());
1245 SetOutput(node, NodeOutputInfo::Bool());
1246 if (lower()) lowering->DoObjectIsSmi(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001247 break;
1248 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001249
1250 //------------------------------------------------------------------
1251 // Machine-level operators.
1252 //------------------------------------------------------------------
1253 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001254 // TODO(jarin) Eventually, we should get rid of all machine stores
1255 // from the high-level phases, then this becomes UNREACHABLE.
1256 LoadRepresentation rep = LoadRepresentationOf(node->op());
1257 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1258 ProcessInput(node, 1, UseInfo::PointerInt()); // index
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 ProcessRemainingInputs(node, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 SetOutputFromMachineType(node, rep);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 break;
1262 }
1263 case IrOpcode::kStore: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001264 // TODO(jarin) Eventually, we should get rid of all machine stores
1265 // from the high-level phases, then this becomes UNREACHABLE.
1266 StoreRepresentation rep = StoreRepresentationOf(node->op());
1267 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1268 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1269 ProcessInput(node, 2,
1270 TruncatingUseInfoFromRepresentation(rep.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001271 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001272 SetOutput(node, NodeOutputInfo::None());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001273 break;
1274 }
1275 case IrOpcode::kWord32Shr:
1276 // We output unsigned int32 for shift right because JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001277 return VisitBinop(node, UseInfo::TruncatingWord32(),
1278 NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279 case IrOpcode::kWord32And:
1280 case IrOpcode::kWord32Or:
1281 case IrOpcode::kWord32Xor:
1282 case IrOpcode::kWord32Shl:
1283 case IrOpcode::kWord32Sar:
1284 // We use signed int32 as the output type for these word32 operations,
1285 // though the machine bits are the same for either signed or unsigned,
1286 // because JavaScript considers the result from these operations signed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 return VisitBinop(node, UseInfo::TruncatingWord32(),
1288 NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 return VisitBinop(node, UseInfo::TruncatingWord32(),
1291 NodeOutputInfo::Bool());
1292
1293 case IrOpcode::kWord32Clz:
1294 return VisitUnop(node, UseInfo::TruncatingWord32(),
1295 NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296
1297 case IrOpcode::kInt32Add:
1298 case IrOpcode::kInt32Sub:
1299 case IrOpcode::kInt32Mul:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300 case IrOpcode::kInt32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001301 case IrOpcode::kInt32Div:
1302 case IrOpcode::kInt32Mod:
1303 return VisitInt32Binop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001304 case IrOpcode::kUint32Div:
1305 case IrOpcode::kUint32Mod:
1306 case IrOpcode::kUint32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001307 return VisitUint32Binop(node);
1308 case IrOpcode::kInt32LessThan:
1309 case IrOpcode::kInt32LessThanOrEqual:
1310 return VisitInt32Cmp(node);
1311
1312 case IrOpcode::kUint32LessThan:
1313 case IrOpcode::kUint32LessThanOrEqual:
1314 return VisitUint32Cmp(node);
1315
1316 case IrOpcode::kInt64Add:
1317 case IrOpcode::kInt64Sub:
1318 case IrOpcode::kInt64Mul:
1319 case IrOpcode::kInt64Div:
1320 case IrOpcode::kInt64Mod:
1321 return VisitInt64Binop(node);
1322 case IrOpcode::kInt64LessThan:
1323 case IrOpcode::kInt64LessThanOrEqual:
1324 return VisitInt64Cmp(node);
1325
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001326 case IrOpcode::kUint64LessThan:
1327 return VisitUint64Cmp(node);
1328
1329 case IrOpcode::kUint64Div:
1330 case IrOpcode::kUint64Mod:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331 return VisitUint64Binop(node);
1332
1333 case IrOpcode::kWord64And:
1334 case IrOpcode::kWord64Or:
1335 case IrOpcode::kWord64Xor:
1336 case IrOpcode::kWord64Shl:
1337 case IrOpcode::kWord64Shr:
1338 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 return VisitBinop(node, UseInfo::TruncatingWord64(),
1340 NodeOutputInfo::Int64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001341 case IrOpcode::kWord64Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001342 return VisitBinop(node, UseInfo::TruncatingWord64(),
1343 NodeOutputInfo::Bool());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001344
1345 case IrOpcode::kChangeInt32ToInt64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346 return VisitUnop(
1347 node, UseInfo::TruncatingWord32(),
1348 NodeOutputInfo(MachineRepresentation::kWord64, Type::Signed32()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001349 case IrOpcode::kChangeUint32ToUint64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001350 return VisitUnop(
1351 node, UseInfo::TruncatingWord32(),
1352 NodeOutputInfo(MachineRepresentation::kWord64, Type::Unsigned32()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001353 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001354 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float32());
1355 case IrOpcode::kTruncateFloat64ToInt32:
1356 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001357 case IrOpcode::kTruncateInt64ToInt32:
1358 // TODO(titzer): Is kTypeInt32 correct here?
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001359 return VisitUnop(node, UseInfo::Word64TruncatingToWord32(),
1360 NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001361
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001362 case IrOpcode::kChangeFloat32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 return VisitUnop(node, UseInfo::Float32(), NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001364 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001365 return VisitUnop(
1366 node, UseInfo::TruncatingWord32(),
1367 NodeOutputInfo(MachineRepresentation::kFloat64, Type::Signed32()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001368 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001369 return VisitUnop(node, UseInfo::TruncatingWord32(),
1370 NodeOutputInfo(MachineRepresentation::kFloat64,
1371 Type::Unsigned32()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 case IrOpcode::kChangeFloat64ToInt32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001373 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
1374 NodeOutputInfo::Int32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001375 case IrOpcode::kChangeFloat64ToUint32:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001376 return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
1377 NodeOutputInfo::Uint32());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001378
1379 case IrOpcode::kFloat64Add:
1380 case IrOpcode::kFloat64Sub:
1381 case IrOpcode::kFloat64Mul:
1382 case IrOpcode::kFloat64Div:
1383 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 case IrOpcode::kFloat64Min:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001385 return VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386 case IrOpcode::kFloat64Abs:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 case IrOpcode::kFloat64RoundDown:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001389 case IrOpcode::kFloat64RoundTruncate:
1390 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 case IrOpcode::kFloat64Equal:
1393 case IrOpcode::kFloat64LessThan:
1394 case IrOpcode::kFloat64LessThanOrEqual:
1395 return VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001396 case IrOpcode::kFloat64ExtractLowWord32:
1397 case IrOpcode::kFloat64ExtractHighWord32:
1398 return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
1399 case IrOpcode::kFloat64InsertLowWord32:
1400 case IrOpcode::kFloat64InsertHighWord32:
1401 return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
1402 NodeOutputInfo::Float64());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001403 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001404 case IrOpcode::kLoadFramePointer:
1405 return VisitLeaf(node, NodeOutputInfo::Pointer());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001406 case IrOpcode::kStateValues:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001407 VisitStateValues(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001408 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001409 default:
1410 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001411 // Assume the output is tagged.
1412 SetOutput(node, NodeOutputInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413 break;
1414 }
1415 }
1416
1417 void DeferReplacement(Node* node, Node* replacement) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001418 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
1419 node->op()->mnemonic(), replacement->id(),
1420 replacement->op()->mnemonic());
1421
1422 if (replacement->id() < count_ &&
1423 GetInfo(node)->output_type()->Is(GetInfo(replacement)->output_type())) {
1424 // Replace with a previously existing node eagerly only if the type is the
1425 // same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426 node->ReplaceUses(replacement);
1427 } else {
1428 // Otherwise, we are replacing a node with a representation change.
1429 // Such a substitution must be done after all lowering is done, because
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001430 // changing the type could confuse the representation change
1431 // insertion for uses of the node.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001432 replacements_.push_back(node);
1433 replacements_.push_back(replacement);
1434 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001435 node->NullAllInputs(); // Node is now dead.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001436 }
1437
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 void PrintOutputInfo(NodeInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001439 if (FLAG_trace_representation) {
1440 OFStream os(stdout);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001441 os << info->representation() << " (";
1442 info->output_type()->PrintTo(os, Type::SEMANTIC_DIM);
1443 os << ")";
1444 }
1445 }
1446
1447 void PrintRepresentation(MachineRepresentation rep) {
1448 if (FLAG_trace_representation) {
1449 OFStream os(stdout);
1450 os << rep;
1451 }
1452 }
1453
1454 void PrintTruncation(Truncation truncation) {
1455 if (FLAG_trace_representation) {
1456 OFStream os(stdout);
1457 os << truncation.description();
1458 }
1459 }
1460
1461 void PrintUseInfo(UseInfo info) {
1462 if (FLAG_trace_representation) {
1463 OFStream os(stdout);
1464 os << info.preferred() << ":" << info.truncation().description();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 }
1466 }
1467
1468 private:
1469 JSGraph* jsgraph_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001470 size_t const count_; // number of nodes in the graph
1471 ZoneVector<NodeInfo> info_; // node id -> usage information
1472#ifdef DEBUG
1473 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
1474 // requirements on inputs.
1475#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476 NodeVector nodes_; // collected nodes
1477 NodeVector replacements_; // replacements to be done after lowering
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001478 Phase phase_; // current phase of algorithm
1479 RepresentationChanger* changer_; // for inserting representation changes
1480 ZoneQueue<Node*> queue_; // queue for traversing the graph
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001481 // TODO(danno): RepresentationSelector shouldn't know anything about the
1482 // source positions table, but must for now since there currently is no other
1483 // way to pass down source position information to nodes created during
1484 // lowering. Once this phase becomes a vanilla reducer, it should get source
1485 // position information via the SourcePositionWrapper like all other reducers.
1486 SourcePositionTable* source_positions_;
1487 TypeCache const& type_cache_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001488
1489 NodeInfo* GetInfo(Node* node) {
1490 DCHECK(node->id() >= 0);
1491 DCHECK(node->id() < count_);
1492 return &info_[node->id()];
1493 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001494};
1495
1496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001497SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
1498 SourcePositionTable* source_positions)
1499 : jsgraph_(jsgraph),
1500 zone_(zone),
1501 type_cache_(TypeCache::Get()),
1502 source_positions_(source_positions) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001503
1504
1505void SimplifiedLowering::LowerAllNodes() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001506 RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
1507 RepresentationSelector selector(jsgraph(), zone_, &changer,
1508 source_positions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001509 selector.Run(this);
1510}
1511
1512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513void SimplifiedLowering::DoLoadBuffer(Node* node,
1514 MachineRepresentation output_rep,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001515 RepresentationChanger* changer) {
1516 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001517 DCHECK_NE(MachineRepresentation::kNone, output_rep);
1518 MachineType const access_type = BufferAccessOf(node->op()).machine_type();
1519 if (output_rep != access_type.representation()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001520 Node* const buffer = node->InputAt(0);
1521 Node* const offset = node->InputAt(1);
1522 Node* const length = node->InputAt(2);
1523 Node* const effect = node->InputAt(3);
1524 Node* const control = node->InputAt(4);
1525 Node* const index =
1526 machine()->Is64()
1527 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
1528 : offset;
1529
1530 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
1531 Node* branch =
1532 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
1533
1534 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001535 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
1536 effect, if_true);
1537 Node* vtrue = changer->GetRepresentationFor(
1538 etrue, access_type.representation(), NodeProperties::GetType(node),
1539 output_rep, Truncation::None());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001540
1541 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1542 Node* efalse = effect;
1543 Node* vfalse;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001544 if (output_rep == MachineRepresentation::kTagged) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001545 vfalse = jsgraph()->UndefinedConstant();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 } else if (output_rep == MachineRepresentation::kFloat64) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001547 vfalse =
1548 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001549 } else if (output_rep == MachineRepresentation::kFloat32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001550 vfalse =
1551 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
1552 } else {
1553 vfalse = jsgraph()->Int32Constant(0);
1554 }
1555
1556 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
1557 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
1558
1559 // Replace effect uses of {node} with the {ephi}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 NodeProperties::ReplaceUses(node, node, ephi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001561
1562 // Turn the {node} into a Phi.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001563 node->ReplaceInput(0, vtrue);
1564 node->ReplaceInput(1, vfalse);
1565 node->ReplaceInput(2, merge);
1566 node->TrimInputCount(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001567 NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001568 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001570 }
1571}
1572
1573
1574void SimplifiedLowering::DoStoreBuffer(Node* node) {
1575 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001576 MachineRepresentation const rep =
1577 BufferAccessOf(node->op()).machine_type().representation();
1578 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001579}
1580
1581
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001582void SimplifiedLowering::DoObjectIsNumber(Node* node) {
1583 Node* input = NodeProperties::GetValueInput(node, 0);
1584 // TODO(bmeurer): Optimize somewhat based on input type.
1585 Node* check =
1586 graph()->NewNode(machine()->WordEqual(),
1587 graph()->NewNode(machine()->WordAnd(), input,
1588 jsgraph()->IntPtrConstant(kSmiTagMask)),
1589 jsgraph()->IntPtrConstant(kSmiTag));
1590 Node* branch = graph()->NewNode(common()->Branch(), check, graph()->start());
1591 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
1592 Node* vtrue = jsgraph()->Int32Constant(1);
1593 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
1594 Node* vfalse = graph()->NewNode(
1595 machine()->WordEqual(),
1596 graph()->NewNode(
1597 machine()->Load(MachineType::AnyTagged()), input,
1598 jsgraph()->IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag),
1599 graph()->start(), if_false),
1600 jsgraph()->HeapConstant(isolate()->factory()->heap_number_map()));
1601 Node* control = graph()->NewNode(common()->Merge(2), if_true, if_false);
1602 node->ReplaceInput(0, vtrue);
1603 node->AppendInput(graph()->zone(), vfalse);
1604 node->AppendInput(graph()->zone(), control);
1605 NodeProperties::ChangeOp(node, common()->Phi(MachineRepresentation::kBit, 2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001606}
1607
1608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001609void SimplifiedLowering::DoObjectIsSmi(Node* node) {
1610 node->ReplaceInput(0,
1611 graph()->NewNode(machine()->WordAnd(), node->InputAt(0),
1612 jsgraph()->IntPtrConstant(kSmiTagMask)));
1613 node->AppendInput(graph()->zone(), jsgraph()->IntPtrConstant(kSmiTag));
1614 NodeProperties::ChangeOp(node, machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001615}
1616
1617
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001618Node* SimplifiedLowering::StringComparison(Node* node) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001619 Operator::Properties properties = node->op()->properties();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620 Callable callable = CodeFactory::StringCompare(isolate());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001622 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001623 isolate(), zone(), callable.descriptor(), 0, flags, properties);
1624 return graph()->NewNode(
1625 common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
1626 NodeProperties::GetValueInput(node, 0),
1627 NodeProperties::GetValueInput(node, 1), jsgraph()->NoContextConstant(),
1628 NodeProperties::GetEffectInput(node),
1629 NodeProperties::GetControlInput(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001630}
1631
1632
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001633Node* SimplifiedLowering::Int32Div(Node* const node) {
1634 Int32BinopMatcher m(node);
1635 Node* const zero = jsgraph()->Int32Constant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001636 Node* const minus_one = jsgraph()->Int32Constant(-1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001637 Node* const lhs = m.left().node();
1638 Node* const rhs = m.right().node();
1639
1640 if (m.right().Is(-1)) {
1641 return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
1642 } else if (m.right().Is(0)) {
1643 return rhs;
1644 } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
1645 return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
1646 }
1647
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 // General case for signed integer division.
1649 //
1650 // if 0 < rhs then
1651 // lhs / rhs
1652 // else
1653 // if rhs < -1 then
1654 // lhs / rhs
1655 // else if rhs == 0 then
1656 // 0
1657 // else
1658 // 0 - lhs
1659 //
1660 // Note: We do not use the Diamond helper class here, because it really hurts
1661 // readability with nested diamonds.
1662 const Operator* const merge_op = common()->Merge(2);
1663 const Operator* const phi_op =
1664 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1667 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1668 graph()->start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1671 Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
1672
1673 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1674 Node* false0;
1675 {
1676 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
1677 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
1678
1679 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1680 Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
1681
1682 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1683 Node* false1;
1684 {
1685 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1686 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
1687
1688 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1689 Node* true2 = zero;
1690
1691 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1692 Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
1693
1694 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
1695 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
1696 }
1697
1698 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
1699 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
1700 }
1701
1702 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1703 return graph()->NewNode(phi_op, true0, false0, merge0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001704}
1705
1706
1707Node* SimplifiedLowering::Int32Mod(Node* const node) {
1708 Int32BinopMatcher m(node);
1709 Node* const zero = jsgraph()->Int32Constant(0);
1710 Node* const minus_one = jsgraph()->Int32Constant(-1);
1711 Node* const lhs = m.left().node();
1712 Node* const rhs = m.right().node();
1713
1714 if (m.right().Is(-1) || m.right().Is(0)) {
1715 return zero;
1716 } else if (m.right().HasValue()) {
1717 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
1718 }
1719
1720 // General case for signed integer modulus, with optimization for (unknown)
1721 // power of 2 right hand side.
1722 //
1723 // if 0 < rhs then
1724 // msk = rhs - 1
1725 // if rhs & msk != 0 then
1726 // lhs % rhs
1727 // else
1728 // if lhs < 0 then
1729 // -(-lhs & msk)
1730 // else
1731 // lhs & msk
1732 // else
1733 // if rhs < -1 then
1734 // lhs % rhs
1735 // else
1736 // zero
1737 //
1738 // Note: We do not use the Diamond helper class here, because it really hurts
1739 // readability with nested diamonds.
1740 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001741 const Operator* const phi_op =
1742 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001743
1744 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
1745 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
1746 graph()->start());
1747
1748 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1749 Node* true0;
1750 {
1751 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
1752
1753 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
1754 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1755
1756 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1757 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1758
1759 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1760 Node* false1;
1761 {
1762 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
1763 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
1764 check2, if_false1);
1765
1766 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1767 Node* true2 = graph()->NewNode(
1768 machine()->Int32Sub(), zero,
1769 graph()->NewNode(machine()->Word32And(),
1770 graph()->NewNode(machine()->Int32Sub(), zero, lhs),
1771 msk));
1772
1773 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
1774 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1775
1776 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
1777 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
1778 }
1779
1780 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
1781 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
1782 }
1783
1784 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1785 Node* false0;
1786 {
1787 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
1788 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
1789 check1, if_false0);
1790
1791 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1792 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
1793
1794 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1795 Node* false1 = zero;
1796
1797 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
1798 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
1799 }
1800
1801 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1802 return graph()->NewNode(phi_op, true0, false0, merge0);
1803}
1804
1805
1806Node* SimplifiedLowering::Uint32Div(Node* const node) {
1807 Uint32BinopMatcher m(node);
1808 Node* const zero = jsgraph()->Uint32Constant(0);
1809 Node* const lhs = m.left().node();
1810 Node* const rhs = m.right().node();
1811
1812 if (m.right().Is(0)) {
1813 return zero;
1814 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
1815 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
1816 }
1817
1818 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
1819 Diamond d(graph(), common(), check, BranchHint::kFalse);
1820 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001821 return d.Phi(MachineRepresentation::kWord32, zero, div);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001822}
1823
1824
1825Node* SimplifiedLowering::Uint32Mod(Node* const node) {
1826 Uint32BinopMatcher m(node);
1827 Node* const minus_one = jsgraph()->Int32Constant(-1);
1828 Node* const zero = jsgraph()->Uint32Constant(0);
1829 Node* const lhs = m.left().node();
1830 Node* const rhs = m.right().node();
1831
1832 if (m.right().Is(0)) {
1833 return zero;
1834 } else if (m.right().HasValue()) {
1835 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
1836 }
1837
1838 // General case for unsigned integer modulus, with optimization for (unknown)
1839 // power of 2 right hand side.
1840 //
1841 // if rhs then
1842 // msk = rhs - 1
1843 // if rhs & msk != 0 then
1844 // lhs % rhs
1845 // else
1846 // lhs & msk
1847 // else
1848 // zero
1849 //
1850 // Note: We do not use the Diamond helper class here, because it really hurts
1851 // readability with nested diamonds.
1852 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001853 const Operator* const phi_op =
1854 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001855
1856 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
1857 graph()->start());
1858
1859 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1860 Node* true0;
1861 {
1862 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
1863
1864 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
1865 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
1866
1867 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1868 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
1869
1870 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
1871 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
1872
1873 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
1874 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
1875 }
1876
1877 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
1878 Node* false0 = zero;
1879
1880 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
1881 return graph()->NewNode(phi_op, true0, false0, merge0);
1882}
1883
1884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001885void SimplifiedLowering::DoShift(Node* node, Operator const* op,
1886 Type* rhs_type) {
1887 Node* const rhs = NodeProperties::GetValueInput(node, 1);
1888 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
1889 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
1890 jsgraph()->Int32Constant(0x1f)));
1891 }
1892 NodeProperties::ChangeOp(node, op);
1893}
1894
1895
1896namespace {
1897
1898void ReplaceEffectUses(Node* node, Node* replacement) {
1899 // Requires distinguishing between value and effect edges.
1900 DCHECK(replacement->op()->EffectOutputCount() > 0);
1901 for (Edge edge : node->use_edges()) {
1902 if (NodeProperties::IsEffectEdge(edge)) {
1903 edge.UpdateTo(replacement);
1904 } else {
1905 DCHECK(NodeProperties::IsValueEdge(edge));
1906 }
1907 }
1908}
1909
1910} // namespace
1911
1912
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001913void SimplifiedLowering::DoStringEqual(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001914 Node* comparison = StringComparison(node);
1915 ReplaceEffectUses(node, comparison);
1916 node->ReplaceInput(0, comparison);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001917 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001918 node->TrimInputCount(2);
1919 NodeProperties::ChangeOp(node, machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001920}
1921
1922
1923void SimplifiedLowering::DoStringLessThan(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001924 Node* comparison = StringComparison(node);
1925 ReplaceEffectUses(node, comparison);
1926 node->ReplaceInput(0, comparison);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001927 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001928 node->TrimInputCount(2);
1929 NodeProperties::ChangeOp(node, machine()->IntLessThan());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001930}
1931
1932
1933void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001934 Node* comparison = StringComparison(node);
1935 ReplaceEffectUses(node, comparison);
1936 node->ReplaceInput(0, comparison);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001937 node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001938 node->TrimInputCount(2);
1939 NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001940}
1941
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001942} // namespace compiler
1943} // namespace internal
1944} // namespace v8