blob: c56494ce32ae5bd3070af96becf046c3014093c4 [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 Murdochc5610432016-08-08 18:44:38 +01009#include "src/address-map.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010#include "src/base/bits.h"
11#include "src/code-factory.h"
Ben Murdochc5610432016-08-08 18:44:38 +010012#include "src/compiler/access-builder.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/common-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "src/compiler/diamond.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015#include "src/compiler/linkage.h"
16#include "src/compiler/node-matchers.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017#include "src/compiler/node-properties.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +010018#include "src/compiler/operation-typer.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019#include "src/compiler/operator-properties.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000020#include "src/compiler/representation-change.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000021#include "src/compiler/simplified-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022#include "src/compiler/source-position.h"
Ben Murdochc5610432016-08-08 18:44:38 +010023#include "src/conversions-inl.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000024#include "src/objects.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025#include "src/type-cache.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026
27namespace v8 {
28namespace internal {
29namespace compiler {
30
31// Macro for outputting trace information from representation inference.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032#define TRACE(...) \
33 do { \
34 if (FLAG_trace_representation) PrintF(__VA_ARGS__); \
35 } while (false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036
37// Representation selection and lowering of {Simplified} operators to machine
38// operators are interwined. We use a fixpoint calculation to compute both the
39// output representation and the best possible lowering for {Simplified} nodes.
40// Representation change insertion ensures that all values are in the correct
41// machine representation after this phase, as dictated by the machine
42// operators themselves.
43enum Phase {
44 // 1.) PROPAGATE: Traverse the graph from the end, pushing usage information
45 // backwards from uses to definitions, around cycles in phis, according
46 // to local rules for each operator.
47 // During this phase, the usage information for a node determines the best
48 // possible lowering for each operator so far, and that in turn determines
49 // the output representation.
50 // Therefore, to be correct, this phase must iterate to a fixpoint before
51 // the next phase can begin.
52 PROPAGATE,
53
54 // 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some
55 // operators for some nodes, expanding some nodes to multiple nodes, or
56 // removing some (redundant) nodes.
57 // During this phase, use the {RepresentationChanger} to insert
58 // representation changes between uses that demand a particular
59 // representation and nodes that produce a different representation.
60 LOWER
61};
62
63
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000064namespace {
65
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066
67UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) {
68 switch (rep) {
69 case MachineRepresentation::kTagged:
70 return UseInfo::AnyTagged();
71 case MachineRepresentation::kFloat64:
Ben Murdochc5610432016-08-08 18:44:38 +010072 return UseInfo::TruncatingFloat64();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 case MachineRepresentation::kFloat32:
Ben Murdochc5610432016-08-08 18:44:38 +010074 return UseInfo::TruncatingFloat32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 case MachineRepresentation::kWord64:
Ben Murdochc5610432016-08-08 18:44:38 +010076 return UseInfo::TruncatingWord64();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 case MachineRepresentation::kWord8:
78 case MachineRepresentation::kWord16:
79 case MachineRepresentation::kWord32:
Ben Murdochc5610432016-08-08 18:44:38 +010080 return UseInfo::TruncatingWord32();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 case MachineRepresentation::kBit:
82 return UseInfo::Bool();
Ben Murdoch097c5b22016-05-18 11:27:45 +010083 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 case MachineRepresentation::kNone:
85 break;
86 }
87 UNREACHABLE();
88 return UseInfo::None();
89}
90
91
92UseInfo UseInfoForBasePointer(const FieldAccess& access) {
93 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
94}
95
96
97UseInfo UseInfoForBasePointer(const ElementAccess& access) {
98 return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
99}
100
101
102#ifdef DEBUG
103// Helpers for monotonicity checking.
104bool MachineRepresentationIsSubtype(MachineRepresentation r1,
105 MachineRepresentation r2) {
106 switch (r1) {
107 case MachineRepresentation::kNone:
108 return true;
109 case MachineRepresentation::kBit:
110 return r2 == MachineRepresentation::kBit ||
111 r2 == MachineRepresentation::kTagged;
112 case MachineRepresentation::kWord8:
113 return r2 == MachineRepresentation::kWord8 ||
114 r2 == MachineRepresentation::kWord16 ||
115 r2 == MachineRepresentation::kWord32 ||
116 r2 == MachineRepresentation::kWord64 ||
117 r2 == MachineRepresentation::kFloat32 ||
118 r2 == MachineRepresentation::kFloat64 ||
119 r2 == MachineRepresentation::kTagged;
120 case MachineRepresentation::kWord16:
121 return r2 == MachineRepresentation::kWord16 ||
122 r2 == MachineRepresentation::kWord32 ||
123 r2 == MachineRepresentation::kWord64 ||
124 r2 == MachineRepresentation::kFloat32 ||
125 r2 == MachineRepresentation::kFloat64 ||
126 r2 == MachineRepresentation::kTagged;
127 case MachineRepresentation::kWord32:
128 return r2 == MachineRepresentation::kWord32 ||
129 r2 == MachineRepresentation::kWord64 ||
130 r2 == MachineRepresentation::kFloat64 ||
131 r2 == MachineRepresentation::kTagged;
132 case MachineRepresentation::kWord64:
133 return r2 == MachineRepresentation::kWord64;
134 case MachineRepresentation::kFloat32:
135 return r2 == MachineRepresentation::kFloat32 ||
136 r2 == MachineRepresentation::kFloat64 ||
137 r2 == MachineRepresentation::kTagged;
138 case MachineRepresentation::kFloat64:
139 return r2 == MachineRepresentation::kFloat64 ||
140 r2 == MachineRepresentation::kTagged;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100141 case MachineRepresentation::kSimd128:
142 return r2 == MachineRepresentation::kSimd128 ||
143 r2 == MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144 case MachineRepresentation::kTagged:
145 return r2 == MachineRepresentation::kTagged;
146 }
147 UNREACHABLE();
148 return false;
149}
150
151
152class InputUseInfos {
153 public:
154 explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
155
156 void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
157 if (input_use_infos_.empty()) {
158 input_use_infos_.resize(node->InputCount(), UseInfo::None());
159 }
160 // Check that the new use informatin is a super-type of the old
161 // one.
162 CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
163 input_use_infos_[index] = use_info;
164 }
165
166 private:
167 ZoneVector<UseInfo> input_use_infos_;
168
169 static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100170 return MachineRepresentationIsSubtype(use1.representation(),
171 use2.representation()) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 use1.truncation().IsLessGeneralThan(use2.truncation());
173 }
174};
175
176#endif // DEBUG
177
178} // namespace
179
180
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181class RepresentationSelector {
182 public:
183 // Information for each node tracked during the fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 class NodeInfo {
185 public:
186 // Adds new use to the node. Returns true if something has changed
187 // and the node has to be requeued.
188 bool AddUse(UseInfo info) {
189 Truncation old_truncation = truncation_;
190 truncation_ = Truncation::Generalize(truncation_, info.truncation());
191 return truncation_ != old_truncation;
192 }
193
Ben Murdoch61f157c2016-09-16 13:49:30 +0100194 void set_queued() { state_ = kQueued; }
195 void set_visited() { state_ = kVisited; }
196 void set_pushed() { state_ = kPushed; }
197 void reset_state() { state_ = kUnvisited; }
198 bool visited() const { return state_ == kVisited; }
199 bool queued() const { return state_ == kQueued; }
200 bool unvisited() const { return state_ == kUnvisited; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 Truncation truncation() const { return truncation_; }
Ben Murdochda12d292016-06-02 14:46:10 +0100202 void set_output(MachineRepresentation output) { representation_ = output; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203
Ben Murdochda12d292016-06-02 14:46:10 +0100204 MachineRepresentation representation() const { return representation_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205
Ben Murdoch61f157c2016-09-16 13:49:30 +0100206 // Helpers for feedback typing.
207 void set_feedback_type(Type* type) { feedback_type_ = type; }
208 Type* feedback_type() { return feedback_type_; }
209 void set_weakened() { weakened_ = true; }
210 bool weakened() { return weakened_; }
211 TypeCheckKind type_check() { return type_check_; }
212 void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; }
213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 private:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100215 enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
216 State state_ = kUnvisited;
Ben Murdochda12d292016-06-02 14:46:10 +0100217 MachineRepresentation representation_ =
218 MachineRepresentation::kNone; // Output representation.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000219 Truncation truncation_ = Truncation::None(); // Information about uses.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100220 TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind.
221
222 Type* feedback_type_ = nullptr;
223 bool weakened_ = false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 };
225
226 RepresentationSelector(JSGraph* jsgraph, Zone* zone,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 RepresentationChanger* changer,
228 SourcePositionTable* source_positions)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 : jsgraph_(jsgraph),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100230 zone_(zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 count_(jsgraph->graph()->NodeCount()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 info_(count_, zone),
233#ifdef DEBUG
234 node_input_use_infos_(count_, InputUseInfos(zone), zone),
235#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 nodes_(zone),
237 replacements_(zone),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 phase_(PROPAGATE),
239 changer_(changer),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 queue_(zone),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100241 typing_stack_(zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 source_positions_(source_positions),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100243 type_cache_(TypeCache::Get()),
244 op_typer_(jsgraph->isolate(), graph_zone()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 }
246
Ben Murdoch61f157c2016-09-16 13:49:30 +0100247 // Forward propagation of types from type feedback.
248 void RunTypePropagationPhase() {
249 DCHECK(typing_stack_.empty());
250
251 typing_stack_.push({graph()->end(), 0});
252 GetInfo(graph()->end())->set_pushed();
253 while (!typing_stack_.empty()) {
254 NodeState& current = typing_stack_.top();
255
256 // If there is an unvisited input, push it and continue.
257 bool pushed_unvisited = false;
258 while (current.input_index < current.node->InputCount()) {
259 Node* input = current.node->InputAt(current.input_index);
260 NodeInfo* input_info = GetInfo(input);
261 current.input_index++;
262 if (input_info->unvisited()) {
263 input_info->set_pushed();
264 typing_stack_.push({input, 0});
265 pushed_unvisited = true;
266 break;
267 }
268 }
269 if (pushed_unvisited) continue;
270
271 // Process the top of the stack.
272 Node* node = current.node;
273 typing_stack_.pop();
274 NodeInfo* info = GetInfo(node);
275 info->set_visited();
276 bool updated = UpdateFeedbackType(node);
277 if (updated) {
278 for (Node* const user : node->uses()) {
279 if (GetInfo(user)->visited()) {
280 GetInfo(user)->set_queued();
281 queue_.push(user);
282 }
283 }
284 }
285 }
286
287 // Process the revisit queue.
288 while (!queue_.empty()) {
289 Node* node = queue_.front();
290 queue_.pop();
291 NodeInfo* info = GetInfo(node);
292 info->set_visited();
293 bool updated = UpdateFeedbackType(node);
294 if (updated) {
295 for (Node* const user : node->uses()) {
296 if (GetInfo(user)->visited()) {
297 GetInfo(user)->set_queued();
298 queue_.push(user);
299 }
300 }
301 }
302 }
303 }
304
305 void ResetNodeInfoState() {
306 // Clean up for the next phase.
307 for (NodeInfo& info : info_) {
308 info.reset_state();
309 }
310 }
311
312 Type* TypeOf(Node* node) {
313 Type* type = GetInfo(node)->feedback_type();
314 return type == nullptr ? NodeProperties::GetType(node) : type;
315 }
316
317 Type* FeedbackTypeOf(Node* node) {
318 Type* type = GetInfo(node)->feedback_type();
319 return type == nullptr ? Type::None() : type;
320 }
321
322 Type* TypePhi(Node* node) {
323 int arity = node->op()->ValueInputCount();
324 Type* type = FeedbackTypeOf(node->InputAt(0));
325 for (int i = 1; i < arity; ++i) {
326 type = op_typer_.Merge(type, FeedbackTypeOf(node->InputAt(i)));
327 }
328 return type;
329 }
330
331 Type* TypeSelect(Node* node) {
332 return op_typer_.Merge(FeedbackTypeOf(node->InputAt(1)),
333 FeedbackTypeOf(node->InputAt(2)));
334 }
335
336 static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) {
337 switch (type_check) {
338 case TypeCheckKind::kNone:
339 return Type::Any();
340 case TypeCheckKind::kSigned32:
341 return Type::Signed32();
342 case TypeCheckKind::kNumber:
343 return Type::Number();
344 // Unexpected cases.
345 case TypeCheckKind::kNumberOrUndefined:
346 FATAL("Unexpected checked type.");
347 break;
348 }
349 UNREACHABLE();
350 return nullptr;
351 }
352
353 bool UpdateFeedbackType(Node* node) {
354 if (node->op()->ValueOutputCount() == 0) return false;
355
356 NodeInfo* info = GetInfo(node);
357 Type* type = info->feedback_type();
358 Type* new_type = type;
359
360 switch (node->opcode()) {
361 case IrOpcode::kSpeculativeNumberAdd: {
362 Type* lhs = FeedbackTypeOf(node->InputAt(0));
363 Type* rhs = FeedbackTypeOf(node->InputAt(1));
364 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
365 // TODO(jarin) The ToNumber conversion is too conservative here,
366 // e.g. it will treat true as 1 even though the number check will
367 // fail on a boolean. OperationTyper should have a function that
368 // computes a more precise type.
369 lhs = op_typer_.ToNumber(lhs);
370 rhs = op_typer_.ToNumber(rhs);
371 Type* static_type = op_typer_.NumericAdd(lhs, rhs);
372 if (info->type_check() == TypeCheckKind::kNone) {
373 new_type = static_type;
374 } else {
375 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
376 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
377 }
378 break;
379 }
380
381 case IrOpcode::kSpeculativeNumberSubtract: {
382 Type* lhs = FeedbackTypeOf(node->InputAt(0));
383 Type* rhs = FeedbackTypeOf(node->InputAt(1));
384 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
385 // TODO(jarin) The ToNumber conversion is too conservative here,
386 // e.g. it will treat true as 1 even though the number check will
387 // fail on a boolean. OperationTyper should have a function that
388 // computes a more precise type.
389 lhs = op_typer_.ToNumber(lhs);
390 rhs = op_typer_.ToNumber(rhs);
391 Type* static_type = op_typer_.NumericSubtract(lhs, rhs);
392 if (info->type_check() == TypeCheckKind::kNone) {
393 new_type = static_type;
394 } else {
395 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
396 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
397 }
398 break;
399 }
400
401 case IrOpcode::kSpeculativeNumberMultiply: {
402 Type* lhs = FeedbackTypeOf(node->InputAt(0));
403 Type* rhs = FeedbackTypeOf(node->InputAt(1));
404 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
405 // TODO(jarin) The ToNumber conversion is too conservative here,
406 // e.g. it will treat true as 1 even though the number check will
407 // fail on a boolean. OperationTyper should have a function that
408 // computes a more precise type.
409 lhs = op_typer_.ToNumber(lhs);
410 rhs = op_typer_.ToNumber(rhs);
411 Type* static_type = op_typer_.NumericMultiply(lhs, rhs);
412 if (info->type_check() == TypeCheckKind::kNone) {
413 new_type = static_type;
414 } else {
415 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
416 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
417 }
418 break;
419 }
420
421 case IrOpcode::kSpeculativeNumberDivide: {
422 Type* lhs = FeedbackTypeOf(node->InputAt(0));
423 Type* rhs = FeedbackTypeOf(node->InputAt(1));
424 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
425 // TODO(jarin) The ToNumber conversion is too conservative here,
426 // e.g. it will treat true as 1 even though the number check will
427 // fail on a boolean. OperationTyper should have a function that
428 // computes a more precise type.
429 lhs = op_typer_.ToNumber(lhs);
430 rhs = op_typer_.ToNumber(rhs);
431 Type* static_type = op_typer_.NumericDivide(lhs, rhs);
432 if (info->type_check() == TypeCheckKind::kNone) {
433 new_type = static_type;
434 } else {
435 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
436 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
437 }
438 break;
439 }
440
441 case IrOpcode::kSpeculativeNumberModulus: {
442 Type* lhs = FeedbackTypeOf(node->InputAt(0));
443 Type* rhs = FeedbackTypeOf(node->InputAt(1));
444 if (lhs->Is(Type::None()) || rhs->Is(Type::None())) return false;
445 // TODO(jarin) The ToNumber conversion is too conservative here,
446 // e.g. it will treat true as 1 even though the number check will
447 // fail on a boolean. OperationTyper should have a function that
448 // computes a more precise type.
449 lhs = op_typer_.ToNumber(lhs);
450 rhs = op_typer_.ToNumber(rhs);
451 Type* static_type = op_typer_.NumericModulus(lhs, rhs);
452 if (info->type_check() == TypeCheckKind::kNone) {
453 new_type = static_type;
454 } else {
455 Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
456 new_type = Type::Intersect(static_type, feedback_type, graph_zone());
457 }
458 break;
459 }
460
461 case IrOpcode::kPhi: {
462 new_type = TypePhi(node);
463 if (type != nullptr) {
464 new_type = Weaken(node, type, new_type);
465 }
466 // Recompute the phi representation based on the new type.
467 MachineRepresentation output =
468 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
469 ResetOutput(node, output);
470 break;
471 }
472
473 case IrOpcode::kSelect: {
474 new_type = TypeSelect(node);
475 // Recompute representation based on the new type.
476 MachineRepresentation output =
477 GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
478 ResetOutput(node, output);
479 break;
480 }
481
482 default:
483 // Shortcut for operations that we do not handle.
484 if (type == nullptr) {
485 GetInfo(node)->set_feedback_type(NodeProperties::GetType(node));
486 return true;
487 }
488 return false;
489 }
490 if (type != nullptr && new_type->Is(type)) return false;
491 GetInfo(node)->set_feedback_type(new_type);
492 if (FLAG_trace_representation) {
493 PrintNodeFeedbackType(node);
494 }
495 return true;
496 }
497
498 void PrintNodeFeedbackType(Node* n) {
499 OFStream os(stdout);
500 os << "#" << n->id() << ":" << *n->op() << "(";
501 int j = 0;
502 for (Node* const i : n->inputs()) {
503 if (j++ > 0) os << ", ";
504 os << "#" << i->id() << ":" << i->op()->mnemonic();
505 }
506 os << ")";
507 if (NodeProperties::IsTyped(n)) {
508 os << " [Static type: ";
509 Type* static_type = NodeProperties::GetType(n);
510 static_type->PrintTo(os);
511 Type* feedback_type = GetInfo(n)->feedback_type();
512 if (feedback_type != nullptr && feedback_type != static_type) {
513 os << ", Feedback type: ";
514 feedback_type->PrintTo(os);
515 }
516 os << "]";
517 }
518 os << std::endl;
519 }
520
521 Type* Weaken(Node* node, Type* previous_type, Type* current_type) {
522 // If the types have nothing to do with integers, return the types.
523 Type* const integer = type_cache_.kInteger;
524 if (!previous_type->Maybe(integer)) {
525 return current_type;
526 }
527 DCHECK(current_type->Maybe(integer));
528
529 Type* current_integer =
530 Type::Intersect(current_type, integer, graph_zone());
531 Type* previous_integer =
532 Type::Intersect(previous_type, integer, graph_zone());
533
534 // Once we start weakening a node, we should always weaken.
535 if (!GetInfo(node)->weakened()) {
536 // Only weaken if there is range involved; we should converge quickly
537 // for all other types (the exception is a union of many constants,
538 // but we currently do not increase the number of constants in unions).
539 Type* previous = previous_integer->GetRange();
540 Type* current = current_integer->GetRange();
541 if (current == nullptr || previous == nullptr) {
542 return current_type;
543 }
544 // Range is involved => we are weakening.
545 GetInfo(node)->set_weakened();
546 }
547
548 return Type::Union(current_type,
549 op_typer_.WeakenRange(previous_integer, current_integer),
550 graph_zone());
551 }
552
553 // Backward propagation of truncations.
554 void RunTruncationPropagationPhase() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 // Run propagation phase to a fixpoint.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 TRACE("--{Propagation phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557 phase_ = PROPAGATE;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 EnqueueInitial(jsgraph_->graph()->end());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000559 // Process nodes from the queue until it is empty.
560 while (!queue_.empty()) {
561 Node* node = queue_.front();
562 NodeInfo* info = GetInfo(node);
563 queue_.pop();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100564 info->set_visited();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
566 VisitNode(node, info->truncation(), nullptr);
567 TRACE(" ==> output ");
568 PrintOutputInfo(info);
569 TRACE("\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100571 }
572
573 void Run(SimplifiedLowering* lowering) {
574 RunTruncationPropagationPhase();
575
576 if (lowering->flags() & SimplifiedLowering::kTypeFeedbackEnabled) {
577 ResetNodeInfoState();
578 RunTypePropagationPhase();
579 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000580
581 // Run lowering and change insertion phase.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 TRACE("--{Simplified lowering phase}--\n");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 phase_ = LOWER;
584 // Process nodes from the collected {nodes_} vector.
585 for (NodeVector::iterator i = nodes_.begin(); i != nodes_.end(); ++i) {
586 Node* node = *i;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 NodeInfo* info = GetInfo(node);
588 TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000589 // Reuse {VisitNode()} so the representation rules are in one place.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000590 SourcePositionTable::Scope scope(
591 source_positions_, source_positions_->GetSourcePosition(node));
592 VisitNode(node, info->truncation(), lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000593 }
594
595 // Perform the final replacements.
596 for (NodeVector::iterator i = replacements_.begin();
597 i != replacements_.end(); ++i) {
598 Node* node = *i;
599 Node* replacement = *(++i);
600 node->ReplaceUses(replacement);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100601 node->Kill();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602 // We also need to replace the node in the rest of the vector.
603 for (NodeVector::iterator j = i + 1; j != replacements_.end(); ++j) {
604 ++j;
605 if (*j == node) *j = replacement;
606 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 }
608 }
609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 void EnqueueInitial(Node* node) {
611 NodeInfo* info = GetInfo(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100612 info->set_queued();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000613 nodes_.push_back(node);
614 queue_.push(node);
615 }
616
617 // Enqueue {use_node}'s {index} input if the {use} contains new information
618 // for that input node. Add the input to {nodes_} if this is the first time
619 // it's been visited.
620 void EnqueueInput(Node* use_node, int index,
621 UseInfo use_info = UseInfo::None()) {
622 Node* node = use_node->InputAt(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000623 if (phase_ != PROPAGATE) return;
624 NodeInfo* info = GetInfo(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625#ifdef DEBUG
626 // Check monotonicity of input requirements.
627 node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
628 use_info);
629#endif // DEBUG
Ben Murdoch61f157c2016-09-16 13:49:30 +0100630 if (info->unvisited()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000631 // First visit of this node.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100632 info->set_queued();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000633 nodes_.push_back(node);
634 queue_.push(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000635 TRACE(" initial: ");
636 info->AddUse(use_info);
637 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000638 return;
639 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 TRACE(" queue?: ");
641 PrintTruncation(info->truncation());
642 if (info->AddUse(use_info)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000643 // New usage information for the node is available.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 if (!info->queued()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000645 queue_.push(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100646 info->set_queued();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 TRACE(" added: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000648 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000649 TRACE(" inqueue: ");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651 PrintTruncation(info->truncation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000652 }
653 }
654
655 bool lower() { return phase_ == LOWER; }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100656 bool propagate() { return phase_ == PROPAGATE; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657
Ben Murdoch61f157c2016-09-16 13:49:30 +0100658 void SetOutput(Node* node, MachineRepresentation representation,
659 TypeCheckKind type_check = TypeCheckKind::kNone) {
660 DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(),
661 representation));
662 ResetOutput(node, representation, type_check);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400663 }
664
Ben Murdoch61f157c2016-09-16 13:49:30 +0100665 void ResetOutput(Node* node, MachineRepresentation representation,
666 TypeCheckKind type_check = TypeCheckKind::kNone) {
Ben Murdochda12d292016-06-02 14:46:10 +0100667 NodeInfo* info = GetInfo(node);
Ben Murdochda12d292016-06-02 14:46:10 +0100668 info->set_output(representation);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100669 info->set_type_check(type_check);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 }
671
Ben Murdochda12d292016-06-02 14:46:10 +0100672 Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673
Ben Murdoch61f157c2016-09-16 13:49:30 +0100674 bool InputIs(Node* node, Type* type) {
675 DCHECK_EQ(1, node->op()->ValueInputCount());
676 return GetUpperBound(node->InputAt(0))->Is(type);
677 }
678
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 bool BothInputsAreSigned32(Node* node) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100680 return BothInputsAre(node, Type::Signed32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681 }
682
683 bool BothInputsAreUnsigned32(Node* node) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100684 return BothInputsAre(node, Type::Unsigned32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000685 }
686
687 bool BothInputsAre(Node* node, Type* type) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100688 DCHECK_EQ(2, node->op()->ValueInputCount());
Ben Murdochda12d292016-06-02 14:46:10 +0100689 return GetUpperBound(node->InputAt(0))->Is(type) &&
690 GetUpperBound(node->InputAt(1))->Is(type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 }
692
693 void ConvertInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694 Node* input = node->InputAt(index);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695 // In the change phase, insert a change before the use if necessary.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100696 if (use.representation() == MachineRepresentation::kNone)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000697 return; // No input requirement on the use.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100698 DCHECK_NOT_NULL(input);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000699 NodeInfo* input_info = GetInfo(input);
700 MachineRepresentation input_rep = input_info->representation();
Ben Murdoch61f157c2016-09-16 13:49:30 +0100701 if (input_rep != use.representation() ||
702 use.type_check() != TypeCheckKind::kNone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000703 // Output representation doesn't match usage.
704 TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
705 index, input->id(), input->op()->mnemonic());
706 TRACE(" from ");
707 PrintOutputInfo(input_info);
708 TRACE(" to ");
709 PrintUseInfo(use);
710 TRACE("\n");
711 Node* n = changer_->GetRepresentationFor(
Ben Murdoch61f157c2016-09-16 13:49:30 +0100712 input, input_info->representation(), TypeOf(input), node, use);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000713 node->ReplaceInput(index, n);
714 }
715 }
716
717 void ProcessInput(Node* node, int index, UseInfo use) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000718 if (phase_ == PROPAGATE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719 EnqueueInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000720 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 ConvertInput(node, index, use);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000722 }
723 }
724
725 void ProcessRemainingInputs(Node* node, int index) {
726 DCHECK_GE(index, NodeProperties::PastValueIndex(node));
727 DCHECK_GE(index, NodeProperties::PastContextIndex(node));
728 for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
729 i < NodeProperties::PastEffectIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000730 EnqueueInput(node, i); // Effect inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731 }
732 for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
733 i < NodeProperties::PastControlIndex(node); ++i) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 EnqueueInput(node, i); // Control inputs: just visit
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000735 }
736 }
737
738 // The default, most general visitation case. For {node}, process all value,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 // context, frame state, effect, and control inputs, assuming that value
740 // inputs should have {kRepTagged} representation and can observe all output
741 // values {kTypeAny}.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000742 void VisitInputs(Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000743 int tagged_count = node->op()->ValueInputCount() +
744 OperatorProperties::GetContextInputCount(node->op());
745 // Visit value and context inputs as tagged.
746 for (int i = 0; i < tagged_count; i++) {
747 ProcessInput(node, i, UseInfo::AnyTagged());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000748 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 // Only enqueue other inputs (framestates, effects, control).
750 for (int i = tagged_count; i < node->InputCount(); i++) {
751 EnqueueInput(node, i);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000753 }
754
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 // Helper for binops of the R x L -> O variety.
756 void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100757 MachineRepresentation output,
758 TypeCheckKind type_check = TypeCheckKind::kNone) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 DCHECK_EQ(2, node->op()->ValueInputCount());
760 ProcessInput(node, 0, left_use);
761 ProcessInput(node, 1, right_use);
762 for (int i = 2; i < node->InputCount(); i++) {
763 EnqueueInput(node, i);
764 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100765 SetOutput(node, output, type_check);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 }
767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000768 // Helper for binops of the I x I -> O variety.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100769 void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
770 TypeCheckKind type_check = TypeCheckKind::kNone) {
771 VisitBinop(node, input_use, input_use, output, type_check);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 }
773
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000774 // Helper for unops of the I -> O variety.
Ben Murdochda12d292016-06-02 14:46:10 +0100775 void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100776 DCHECK_EQ(1, node->op()->ValueInputCount());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000777 ProcessInput(node, 0, input_use);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100778 ProcessRemainingInputs(node, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 SetOutput(node, output);
780 }
781
782 // Helper for leaf nodes.
Ben Murdochda12d292016-06-02 14:46:10 +0100783 void VisitLeaf(Node* node, MachineRepresentation output) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000784 DCHECK_EQ(0, node->InputCount());
785 SetOutput(node, output);
786 }
787
788 // Helpers for specific types of binops.
789 void VisitFloat64Binop(Node* node) {
Ben Murdochc5610432016-08-08 18:44:38 +0100790 VisitBinop(node, UseInfo::TruncatingFloat64(),
791 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000793 void VisitInt32Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100794 VisitBinop(node, UseInfo::TruncatingWord32(),
795 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000796 }
797 void VisitWord32TruncatingBinop(Node* node) {
798 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +0100799 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 void VisitUint32Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100802 VisitBinop(node, UseInfo::TruncatingWord32(),
803 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 void VisitInt64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100806 VisitBinop(node, UseInfo::TruncatingWord64(),
807 MachineRepresentation::kWord64);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000808 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000809 void VisitUint64Binop(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100810 VisitBinop(node, UseInfo::TruncatingWord64(),
811 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000812 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000813 void VisitFloat64Cmp(Node* node) {
Ben Murdochc5610432016-08-08 18:44:38 +0100814 VisitBinop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000815 }
816 void VisitInt32Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100817 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000818 }
819 void VisitUint32Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100820 VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000821 }
822 void VisitInt64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100823 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 }
825 void VisitUint64Cmp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100826 VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000828
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400829 // Infer representation for phi-like nodes.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100830 MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use,
831 Type* type = nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000832 // Compute the representation.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100833 if (type == nullptr) {
834 type = TypeOf(node);
835 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000836 if (type->Is(Type::None())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100837 return MachineRepresentation::kNone;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000838 } else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100839 return MachineRepresentation::kWord32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000840 } else if (use.TruncatesToWord32()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100841 return MachineRepresentation::kWord32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000842 } else if (type->Is(Type::Boolean())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100843 return MachineRepresentation::kBit;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000844 } else if (type->Is(Type::Number())) {
Ben Murdochda12d292016-06-02 14:46:10 +0100845 return MachineRepresentation::kFloat64;
Ben Murdochc5610432016-08-08 18:44:38 +0100846 } else if (use.TruncatesToFloat64()) {
847 return MachineRepresentation::kFloat64;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000848 } else if (type->Is(Type::Internal())) {
849 // We mark (u)int64 as Type::Internal.
850 // TODO(jarin) This is a workaround for our lack of (u)int64
851 // types. This can be removed once we can represent (u)int64
852 // unambiguously. (At the moment internal objects, such as the hole,
853 // are also Type::Internal()).
854 bool is_word64 = GetInfo(node->InputAt(0))->representation() ==
855 MachineRepresentation::kWord64;
856#ifdef DEBUG
857 // Check that all the inputs agree on being Word64.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100858 DCHECK_EQ(IrOpcode::kPhi, node->opcode()); // This only works for phis.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 for (int i = 1; i < node->op()->ValueInputCount(); i++) {
860 DCHECK_EQ(is_word64, GetInfo(node->InputAt(i))->representation() ==
861 MachineRepresentation::kWord64);
862 }
863#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100864 return is_word64 ? MachineRepresentation::kWord64
865 : MachineRepresentation::kTagged;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 }
Ben Murdochda12d292016-06-02 14:46:10 +0100867 return MachineRepresentation::kTagged;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400868 }
869
870 // Helper for handling selects.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000871 void VisitSelect(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400872 SimplifiedLowering* lowering) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 ProcessInput(node, 0, UseInfo::Bool());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400874
Ben Murdochda12d292016-06-02 14:46:10 +0100875 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 SetOutput(node, output);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877
878 if (lower()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400879 // Update the select operator.
880 SelectParameters p = SelectParametersOf(node->op());
Ben Murdochda12d292016-06-02 14:46:10 +0100881 if (output != p.representation()) {
882 NodeProperties::ChangeOp(node,
883 lowering->common()->Select(output, p.hint()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400884 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400885 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 // Convert inputs to the output representation of this phi, pass the
887 // truncation truncation along.
Ben Murdochda12d292016-06-02 14:46:10 +0100888 UseInfo input_use(output, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 ProcessInput(node, 1, input_use);
890 ProcessInput(node, 2, input_use);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400891 }
892
893 // Helper for handling phis.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 void VisitPhi(Node* node, Truncation truncation,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400895 SimplifiedLowering* lowering) {
Ben Murdochda12d292016-06-02 14:46:10 +0100896 MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100897 // Only set the output representation if not running with type
898 // feedback. (Feedback typing will set the representation.)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000899 SetOutput(node, output);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400900
901 int values = node->op()->ValueInputCount();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400902 if (lower()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 // Update the phi operator.
Ben Murdochda12d292016-06-02 14:46:10 +0100904 if (output != PhiRepresentationOf(node->op())) {
905 NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 }
907 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908
909 // Convert inputs to the output representation of this phi, pass the
910 // truncation truncation along.
Ben Murdochda12d292016-06-02 14:46:10 +0100911 UseInfo input_use(output, truncation);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912 for (int i = 0; i < node->InputCount(); i++) {
913 ProcessInput(node, i, i < values ? input_use : UseInfo::None());
914 }
915 }
916
917 void VisitCall(Node* node, SimplifiedLowering* lowering) {
Ben Murdochc5610432016-08-08 18:44:38 +0100918 const CallDescriptor* desc = CallDescriptorOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000919 const MachineSignature* sig = desc->GetMachineSignature();
920 int params = static_cast<int>(sig->parameter_count());
921 // Propagate representation information from call descriptor.
922 for (int i = 0; i < node->InputCount(); i++) {
923 if (i == 0) {
924 // The target of the call.
925 ProcessInput(node, i, UseInfo::None());
926 } else if ((i - 1) < params) {
927 ProcessInput(node, i, TruncatingUseInfoFromRepresentation(
928 sig->GetParam(i - 1).representation()));
929 } else {
930 ProcessInput(node, i, UseInfo::None());
931 }
932 }
933
934 if (sig->return_count() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100935 SetOutput(node,
936 desc->GetMachineSignature()->GetReturn().representation());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100938 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000939 }
940 }
941
942 MachineSemantic DeoptValueSemanticOf(Type* type) {
943 CHECK(!type->Is(Type::None()));
944 // We only need signedness to do deopt correctly.
945 if (type->Is(Type::Signed32())) {
946 return MachineSemantic::kInt32;
947 } else if (type->Is(Type::Unsigned32())) {
948 return MachineSemantic::kUint32;
949 } else {
950 return MachineSemantic::kAny;
951 }
952 }
953
954 void VisitStateValues(Node* node) {
955 if (phase_ == PROPAGATE) {
956 for (int i = 0; i < node->InputCount(); i++) {
957 EnqueueInput(node, i, UseInfo::Any());
958 }
959 } else {
960 Zone* zone = jsgraph_->zone();
961 ZoneVector<MachineType>* types =
962 new (zone->New(sizeof(ZoneVector<MachineType>)))
963 ZoneVector<MachineType>(node->InputCount(), zone);
964 for (int i = 0; i < node->InputCount(); i++) {
Ben Murdochda12d292016-06-02 14:46:10 +0100965 Node* input = node->InputAt(i);
966 NodeInfo* input_info = GetInfo(input);
967 MachineType machine_type(input_info->representation(),
Ben Murdoch61f157c2016-09-16 13:49:30 +0100968 DeoptValueSemanticOf(TypeOf(input)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000969 DCHECK(machine_type.representation() !=
970 MachineRepresentation::kWord32 ||
971 machine_type.semantic() == MachineSemantic::kInt32 ||
972 machine_type.semantic() == MachineSemantic::kUint32);
973 (*types)[i] = machine_type;
974 }
975 NodeProperties::ChangeOp(node,
976 jsgraph_->common()->TypedStateValues(types));
977 }
Ben Murdochda12d292016-06-02 14:46:10 +0100978 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000979 }
980
981 const Operator* Int32Op(Node* node) {
982 return changer_->Int32OperatorFor(node->opcode());
983 }
984
Ben Murdoch61f157c2016-09-16 13:49:30 +0100985 const Operator* Int32OverflowOp(Node* node) {
986 return changer_->Int32OverflowOperatorFor(node->opcode());
987 }
988
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000989 const Operator* Uint32Op(Node* node) {
990 return changer_->Uint32OperatorFor(node->opcode());
991 }
992
993 const Operator* Float64Op(Node* node) {
994 return changer_->Float64OperatorFor(node->opcode());
995 }
996
Ben Murdochc5610432016-08-08 18:44:38 +0100997 WriteBarrierKind WriteBarrierKindFor(
998 BaseTaggedness base_taggedness,
999 MachineRepresentation field_representation, Type* field_type,
1000 Node* value) {
1001 if (base_taggedness == kTaggedBase &&
1002 field_representation == MachineRepresentation::kTagged) {
1003 Type* value_type = NodeProperties::GetType(value);
1004 if (field_type->Is(Type::TaggedSigned()) ||
1005 value_type->Is(Type::TaggedSigned())) {
1006 // Write barriers are only for stores of heap objects.
1007 return kNoWriteBarrier;
1008 }
1009 if (field_type->Is(Type::BooleanOrNullOrUndefined()) ||
1010 value_type->Is(Type::BooleanOrNullOrUndefined())) {
1011 // Write barriers are not necessary when storing true, false, null or
1012 // undefined, because these special oddballs are always in the root set.
1013 return kNoWriteBarrier;
1014 }
1015 if (value_type->IsConstant() &&
1016 value_type->AsConstant()->Value()->IsHeapObject()) {
1017 Handle<HeapObject> value_object =
1018 Handle<HeapObject>::cast(value_type->AsConstant()->Value());
1019 RootIndexMap root_index_map(jsgraph_->isolate());
1020 int root_index = root_index_map.Lookup(*value_object);
1021 if (root_index != RootIndexMap::kInvalidRootIndex &&
1022 jsgraph_->isolate()->heap()->RootIsImmortalImmovable(root_index)) {
1023 // Write barriers are unnecessary for immortal immovable roots.
1024 return kNoWriteBarrier;
1025 }
1026 if (value_object->IsMap()) {
1027 // Write barriers for storing maps are cheaper.
1028 return kMapWriteBarrier;
1029 }
1030 }
1031 if (field_type->Is(Type::TaggedPointer()) ||
1032 value_type->Is(Type::TaggedPointer())) {
1033 // Write barriers for heap objects are cheaper.
1034 return kPointerWriteBarrier;
1035 }
1036 NumberMatcher m(value);
1037 if (m.HasValue()) {
1038 if (IsSmiDouble(m.Value())) {
1039 // Storing a smi doesn't need a write barrier.
1040 return kNoWriteBarrier;
1041 }
1042 // The NumberConstant will be represented as HeapNumber.
1043 return kPointerWriteBarrier;
1044 }
1045 return kFullWriteBarrier;
1046 }
1047 return kNoWriteBarrier;
1048 }
1049
1050 WriteBarrierKind WriteBarrierKindFor(
1051 BaseTaggedness base_taggedness,
1052 MachineRepresentation field_representation, int field_offset,
1053 Type* field_type, Node* value) {
1054 if (base_taggedness == kTaggedBase &&
1055 field_offset == HeapObject::kMapOffset) {
1056 return kMapWriteBarrier;
1057 }
1058 return WriteBarrierKindFor(base_taggedness, field_representation,
1059 field_type, value);
1060 }
1061
Ben Murdoch61f157c2016-09-16 13:49:30 +01001062 Graph* graph() const { return jsgraph_->graph(); }
1063 CommonOperatorBuilder* common() const { return jsgraph_->common(); }
1064 SimplifiedOperatorBuilder* simplified() const {
1065 return jsgraph_->simplified();
1066 }
1067
1068 void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) {
1069 for (Edge edge : node->use_edges()) {
1070 if (NodeProperties::IsControlEdge(edge)) {
1071 edge.UpdateTo(control);
1072 } else if (NodeProperties::IsEffectEdge(edge)) {
1073 edge.UpdateTo(effect);
1074 } else {
1075 DCHECK(NodeProperties::IsValueEdge(edge));
1076 }
1077 }
1078 }
1079
1080 void ChangeToPureOp(Node* node, const Operator* new_op) {
1081 if (node->op()->EffectInputCount() > 0) {
1082 DCHECK_LT(0, node->op()->ControlInputCount());
1083 // Disconnect the node from effect and control chains.
1084 Node* control = NodeProperties::GetControlInput(node);
1085 Node* effect = NodeProperties::GetEffectInput(node);
1086 ReplaceEffectControlUses(node, effect, control);
1087 node->TrimInputCount(new_op->ValueInputCount());
1088 } else {
1089 DCHECK_EQ(0, node->op()->ControlInputCount());
1090 }
1091
1092 NodeProperties::ChangeOp(node, new_op);
1093 }
1094
1095 void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) {
1096 NodeProperties::ChangeOp(node, new_op);
1097 }
1098
1099 void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
1100 SimplifiedLowering* lowering) {
1101 if (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) &&
1102 NodeProperties::GetType(node)->Is(Type::Signed32())) {
1103 // int32 + int32 = int32 ==> signed Int32Add/Sub
1104 VisitInt32Binop(node);
1105 if (lower()) ChangeToPureOp(node, Int32Op(node));
1106 return;
1107 }
1108
1109 // Use truncation if available.
1110 if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
1111 truncation.TruncatesToWord32()) {
1112 // safe-int + safe-int = x (truncated to int32)
1113 // => signed Int32Add/Sub (truncated)
1114 VisitWord32TruncatingBinop(node);
1115 if (lower()) ChangeToPureOp(node, Int32Op(node));
1116 return;
1117 }
1118
1119 // Try to use type feedback.
1120 BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op());
1121
1122 // Handle the case when no int32 checks on inputs are necessary
1123 // (but an overflow check is needed on the output).
1124 if (BothInputsAre(node, Type::Signed32()) ||
1125 (BothInputsAre(node, type_cache_.kSigned32OrMinusZero) &&
1126 NodeProperties::GetType(node)->Is(type_cache_.kSafeInteger))) {
1127 // If both the inputs the feedback are int32, use the overflow op.
1128 if (hint == BinaryOperationHints::kSignedSmall ||
1129 hint == BinaryOperationHints::kSigned32) {
1130 VisitBinop(node, UseInfo::TruncatingWord32(),
1131 MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
1132 if (lower()) {
1133 ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
1134 }
1135 return;
1136 }
1137 }
1138
1139 if (hint == BinaryOperationHints::kSignedSmall ||
1140 hint == BinaryOperationHints::kSigned32) {
1141 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
1142 MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
1143 if (lower()) {
1144 ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
1145 }
1146 return;
1147 }
1148
1149 // default case => Float64Add/Sub
1150 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
1151 MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
1152 if (lower()) {
1153 ChangeToPureOp(node, Float64Op(node));
1154 }
1155 return;
1156 }
1157
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001158 // Dispatching routine for visiting the node {node} with the usage {use}.
1159 // Depending on the operator, propagate new usage info to the inputs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 void VisitNode(Node* node, Truncation truncation,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 SimplifiedLowering* lowering) {
1162 switch (node->opcode()) {
1163 //------------------------------------------------------------------
1164 // Common operators.
1165 //------------------------------------------------------------------
1166 case IrOpcode::kStart:
1167 case IrOpcode::kDead:
Ben Murdochda12d292016-06-02 14:46:10 +01001168 return VisitLeaf(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001169 case IrOpcode::kParameter: {
1170 // TODO(titzer): use representation from linkage.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 ProcessInput(node, 0, UseInfo::None());
Ben Murdochda12d292016-06-02 14:46:10 +01001172 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001173 return;
1174 }
1175 case IrOpcode::kInt32Constant:
Ben Murdochda12d292016-06-02 14:46:10 +01001176 return VisitLeaf(node, MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001177 case IrOpcode::kInt64Constant:
Ben Murdochda12d292016-06-02 14:46:10 +01001178 return VisitLeaf(node, MachineRepresentation::kWord64);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 case IrOpcode::kFloat32Constant:
Ben Murdochda12d292016-06-02 14:46:10 +01001180 return VisitLeaf(node, MachineRepresentation::kFloat32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001181 case IrOpcode::kFloat64Constant:
Ben Murdochda12d292016-06-02 14:46:10 +01001182 return VisitLeaf(node, MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001183 case IrOpcode::kExternalConstant:
Ben Murdochda12d292016-06-02 14:46:10 +01001184 return VisitLeaf(node, MachineType::PointerRepresentation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001185 case IrOpcode::kNumberConstant:
Ben Murdochda12d292016-06-02 14:46:10 +01001186 return VisitLeaf(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187 case IrOpcode::kHeapConstant:
Ben Murdochda12d292016-06-02 14:46:10 +01001188 return VisitLeaf(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189
Ben Murdochda12d292016-06-02 14:46:10 +01001190 case IrOpcode::kDeoptimizeIf:
1191 case IrOpcode::kDeoptimizeUnless:
1192 ProcessInput(node, 0, UseInfo::Bool());
1193 ProcessInput(node, 1, UseInfo::AnyTagged());
1194 ProcessRemainingInputs(node, 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001195 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001196 case IrOpcode::kBranch:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001197 ProcessInput(node, 0, UseInfo::Bool());
1198 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001199 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001200 case IrOpcode::kSwitch:
1201 ProcessInput(node, 0, UseInfo::TruncatingWord32());
1202 EnqueueInput(node, NodeProperties::FirstControlIndex(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001203 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001204 case IrOpcode::kSelect:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001205 return VisitSelect(node, truncation, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001206 case IrOpcode::kPhi:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001207 return VisitPhi(node, truncation, lowering);
1208 case IrOpcode::kCall:
1209 return VisitCall(node, lowering);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210
Ben Murdochc5610432016-08-08 18:44:38 +01001211 //------------------------------------------------------------------
1212 // JavaScript operators.
1213 //------------------------------------------------------------------
1214 case IrOpcode::kJSToNumber: {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001215 VisitInputs(node);
Ben Murdochc5610432016-08-08 18:44:38 +01001216 // TODO(bmeurer): Optimize somewhat based on input type?
1217 if (truncation.TruncatesToWord32()) {
1218 SetOutput(node, MachineRepresentation::kWord32);
1219 if (lower()) lowering->DoJSToNumberTruncatesToWord32(node, this);
1220 } else if (truncation.TruncatesToFloat64()) {
1221 SetOutput(node, MachineRepresentation::kFloat64);
1222 if (lower()) lowering->DoJSToNumberTruncatesToFloat64(node, this);
1223 } else {
1224 SetOutput(node, MachineRepresentation::kTagged);
1225 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001226 return;
Ben Murdochc5610432016-08-08 18:44:38 +01001227 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001228
1229 //------------------------------------------------------------------
1230 // Simplified operators.
1231 //------------------------------------------------------------------
1232 case IrOpcode::kBooleanNot: {
1233 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234 NodeInfo* input_info = GetInfo(node->InputAt(0));
1235 if (input_info->representation() == MachineRepresentation::kBit) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001236 // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001237 node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001238 NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001239 } else {
1240 // BooleanNot(x: kRepTagged) => WordEqual(x, #false)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241 node->AppendInput(jsgraph_->zone(), jsgraph_->FalseConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001242 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001243 }
1244 } else {
1245 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001246 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
Ben Murdochda12d292016-06-02 14:46:10 +01001247 SetOutput(node, MachineRepresentation::kBit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001248 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001249 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001250 }
1251 case IrOpcode::kBooleanToNumber: {
1252 if (lower()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001253 NodeInfo* input_info = GetInfo(node->InputAt(0));
1254 if (input_info->representation() == MachineRepresentation::kBit) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001255 // BooleanToNumber(x: kRepBit) => x
1256 DeferReplacement(node, node->InputAt(0));
1257 } else {
1258 // BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001259 node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001260 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001261 }
1262 } else {
1263 // No input representation requirement; adapt during lowering.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001264 ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
Ben Murdochda12d292016-06-02 14:46:10 +01001265 SetOutput(node, MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001266 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001267 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001268 }
1269 case IrOpcode::kNumberEqual:
1270 case IrOpcode::kNumberLessThan:
1271 case IrOpcode::kNumberLessThanOrEqual: {
1272 // Number comparisons reduce to integer comparisons for integer inputs.
Ben Murdoch61f157c2016-09-16 13:49:30 +01001273 if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1274 TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001275 // => signed Int32Cmp
1276 VisitInt32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001277 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001278 } else if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1279 TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001280 // => unsigned Int32Cmp
1281 VisitUint32Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001282 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001283 } else {
1284 // => Float64Cmp
1285 VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001286 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001287 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001288 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001290
1291 case IrOpcode::kSpeculativeNumberAdd:
1292 case IrOpcode::kSpeculativeNumberSubtract:
1293 return VisitSpeculativeAdditiveOp(node, truncation, lowering);
1294
1295 case IrOpcode::kSpeculativeNumberLessThan:
1296 case IrOpcode::kSpeculativeNumberLessThanOrEqual:
1297 case IrOpcode::kSpeculativeNumberEqual: {
1298 // Number comparisons reduce to integer comparisons for integer inputs.
1299 if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
1300 TypeOf(node->InputAt(1))->Is(Type::Signed32())) {
1301 // => signed Int32Cmp
1302 VisitInt32Cmp(node);
1303 if (lower()) ChangeToPureOp(node, Int32Op(node));
1304 return;
1305 } else if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
1306 TypeOf(node->InputAt(1))->Is(Type::Unsigned32())) {
1307 // => unsigned Int32Cmp
1308 VisitUint32Cmp(node);
1309 if (lower()) ChangeToPureOp(node, Uint32Op(node));
1310 return;
1311 }
1312 // Try to use type feedback.
1313 CompareOperationHints::Hint hint = CompareOperationHintOf(node->op());
1314
1315 if (hint == CompareOperationHints::kSignedSmall) {
1316 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
1317 MachineRepresentation::kBit);
1318 if (lower()) ChangeToPureOp(node, Int32Op(node));
1319 return;
1320 }
1321 DCHECK_EQ(CompareOperationHints::kNumber, hint);
1322 // default case => Float64 comparison
1323 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
1324 MachineRepresentation::kBit);
1325 if (lower()) ChangeToPureOp(node, Float64Op(node));
1326 return;
1327 }
1328
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001329 case IrOpcode::kNumberAdd:
1330 case IrOpcode::kNumberSubtract: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001331 if (BothInputsAre(node, Type::Signed32()) &&
1332 NodeProperties::GetType(node)->Is(Type::Signed32())) {
1333 // int32 + int32 = int32
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 // => signed Int32Add/Sub
1335 VisitInt32Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001337 } else if (BothInputsAre(node,
1338 type_cache_.kAdditiveSafeIntegerOrMinusZero) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 truncation.TruncatesToWord32()) {
1340 // safe-int + safe-int = x (truncated to int32)
1341 // => signed Int32Add/Sub (truncated)
1342 VisitWord32TruncatingBinop(node);
1343 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001344 } else {
1345 // => Float64Add/Sub
1346 VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001347 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001348 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001349 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001350 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001351 case IrOpcode::kSpeculativeNumberMultiply:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001352 case IrOpcode::kNumberMultiply: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001353 if (BothInputsAreSigned32(node)) {
1354 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1355 // Multiply reduces to Int32Mul if the inputs and the output
1356 // are integers.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001357 VisitInt32Binop(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001358 if (lower()) ChangeToPureOp(node, Int32Op(node));
1359 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001360 }
1361 if (truncation.TruncatesToWord32() &&
Ben Murdoch61f157c2016-09-16 13:49:30 +01001362 NodeProperties::GetType(node)->Is(
1363 type_cache_.kSafeIntegerOrMinusZero)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001364 // Multiply reduces to Int32Mul if the inputs are integers,
1365 // the uses are truncating and the result is in the safe
1366 // integer range.
1367 VisitWord32TruncatingBinop(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001368 if (lower()) ChangeToPureOp(node, Int32Op(node));
1369 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001370 }
1371 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001372 // Number x Number => Float64Mul
1373 if (BothInputsAre(node, Type::NumberOrUndefined())) {
1374 VisitFloat64Binop(node);
1375 if (lower()) ChangeToPureOp(node, Float64Op(node));
1376 return;
1377 }
1378 // Checked float64 x float64 => float64
1379 DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode());
1380 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
1381 MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
1382 if (lower()) ChangeToPureOp(node, Float64Op(node));
1383 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001384 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001385 case IrOpcode::kSpeculativeNumberDivide:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001386 case IrOpcode::kNumberDivide: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001387 if (BothInputsAreSigned32(node)) {
1388 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001389 // => signed Int32Div
1390 VisitInt32Binop(node);
1391 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001392 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001393 }
1394 if (truncation.TruncatesToWord32()) {
1395 // => signed Int32Div
1396 VisitWord32TruncatingBinop(node);
1397 if (lower()) DeferReplacement(node, lowering->Int32Div(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001398 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001400 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001402 // => unsigned Uint32Div
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001403 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001404 if (lower()) DeferReplacement(node, lowering->Uint32Div(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001405 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001406 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001407 // Number x Number => Float64Div
1408 if (BothInputsAre(node, Type::NumberOrUndefined())) {
1409 VisitFloat64Binop(node);
1410 if (lower()) ChangeToPureOp(node, Float64Op(node));
1411 return;
1412 }
1413 // Checked float64 x float64 => float64
1414 DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode());
1415 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
1416 MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
1417 if (lower()) ChangeToPureOp(node, Float64Op(node));
1418 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001419 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001420 case IrOpcode::kSpeculativeNumberModulus:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001421 case IrOpcode::kNumberModulus: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 if (BothInputsAreSigned32(node)) {
1423 if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
1424 // => signed Int32Mod
1425 VisitInt32Binop(node);
1426 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001427 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001428 }
1429 if (truncation.TruncatesToWord32()) {
1430 // => signed Int32Mod
1431 VisitWord32TruncatingBinop(node);
1432 if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001433 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001434 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001435 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001436 if (BothInputsAreUnsigned32(node) && truncation.TruncatesToWord32()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001437 // => unsigned Uint32Mod
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001438 VisitWord32TruncatingBinop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001439 if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001440 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001441 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001442 // Number x Number => Float64Mod
1443 if (BothInputsAre(node, Type::NumberOrUndefined())) {
1444 // => Float64Mod
1445 VisitFloat64Binop(node);
1446 if (lower()) ChangeToPureOp(node, Float64Op(node));
1447 return;
1448 }
1449 // Checked float64 x float64 => float64
1450 DCHECK_EQ(IrOpcode::kSpeculativeNumberModulus, node->opcode());
1451 VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
1452 MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
1453 if (lower()) ChangeToPureOp(node, Float64Op(node));
1454 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 case IrOpcode::kNumberBitwiseOr:
1457 case IrOpcode::kNumberBitwiseXor:
1458 case IrOpcode::kNumberBitwiseAnd: {
1459 VisitInt32Binop(node);
1460 if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001461 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001462 }
1463 case IrOpcode::kNumberShiftLeft: {
Ben Murdochda12d292016-06-02 14:46:10 +01001464 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001465 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001466 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001467 if (lower()) {
1468 lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001469 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001470 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001471 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472 case IrOpcode::kNumberShiftRight: {
Ben Murdochda12d292016-06-02 14:46:10 +01001473 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001474 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001475 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001476 if (lower()) {
1477 lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
1478 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001479 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001480 }
1481 case IrOpcode::kNumberShiftRightLogical: {
Ben Murdochda12d292016-06-02 14:46:10 +01001482 Type* rhs_type = GetUpperBound(node->InputAt(1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001483 VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001484 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001485 if (lower()) {
1486 lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
1487 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001488 return;
1489 }
1490 case IrOpcode::kNumberAbs: {
1491 if (InputIs(node, Type::Unsigned32())) {
1492 VisitUnop(node, UseInfo::TruncatingWord32(),
1493 MachineRepresentation::kWord32);
1494 if (lower()) DeferReplacement(node, node->InputAt(0));
1495 } else if (InputIs(node, type_cache_.kSafeSigned32)) {
1496 VisitUnop(node, UseInfo::TruncatingWord32(),
1497 MachineRepresentation::kWord32);
1498 if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
1499 } else if (InputIs(node,
1500 type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
1501 VisitUnop(node, UseInfo::TruncatingFloat64(),
1502 MachineRepresentation::kFloat64);
1503 if (lower()) DeferReplacement(node, node->InputAt(0));
1504 } else {
1505 VisitUnop(node, UseInfo::TruncatingFloat64(),
1506 MachineRepresentation::kFloat64);
1507 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1508 }
1509 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001510 }
Ben Murdochda12d292016-06-02 14:46:10 +01001511 case IrOpcode::kNumberClz32: {
1512 VisitUnop(node, UseInfo::TruncatingWord32(),
1513 MachineRepresentation::kWord32);
1514 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001515 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001516 }
Ben Murdochc5610432016-08-08 18:44:38 +01001517 case IrOpcode::kNumberImul: {
1518 VisitBinop(node, UseInfo::TruncatingWord32(),
1519 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1520 if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001521 return;
Ben Murdochc5610432016-08-08 18:44:38 +01001522 }
Ben Murdochda12d292016-06-02 14:46:10 +01001523 case IrOpcode::kNumberCeil: {
Ben Murdochc5610432016-08-08 18:44:38 +01001524 VisitUnop(node, UseInfo::TruncatingFloat64(),
1525 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001526 if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001527 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001528 }
1529 case IrOpcode::kNumberFloor: {
Ben Murdochc5610432016-08-08 18:44:38 +01001530 VisitUnop(node, UseInfo::TruncatingFloat64(),
1531 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001532 if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001533 return;
1534 }
1535 case IrOpcode::kNumberFround: {
1536 VisitUnop(node, UseInfo::TruncatingFloat64(),
1537 MachineRepresentation::kFloat32);
1538 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1539 return;
1540 }
1541 case IrOpcode::kNumberAtan2: {
1542 VisitBinop(node, UseInfo::TruncatingFloat64(),
1543 MachineRepresentation::kFloat64);
1544 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1545 return;
1546 }
1547 case IrOpcode::kNumberAtan:
1548 case IrOpcode::kNumberAtanh:
1549 case IrOpcode::kNumberCos:
1550 case IrOpcode::kNumberExp:
1551 case IrOpcode::kNumberExpm1:
1552 case IrOpcode::kNumberLog:
1553 case IrOpcode::kNumberLog1p:
1554 case IrOpcode::kNumberLog2:
1555 case IrOpcode::kNumberLog10:
1556 case IrOpcode::kNumberCbrt:
1557 case IrOpcode::kNumberSin:
1558 case IrOpcode::kNumberTan: {
1559 VisitUnop(node, UseInfo::TruncatingFloat64(),
1560 MachineRepresentation::kFloat64);
1561 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1562 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001563 }
1564 case IrOpcode::kNumberRound: {
Ben Murdochc5610432016-08-08 18:44:38 +01001565 VisitUnop(node, UseInfo::TruncatingFloat64(),
1566 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001567 if (lower()) DeferReplacement(node, lowering->Float64Round(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001568 return;
1569 }
1570 case IrOpcode::kNumberSqrt: {
1571 VisitUnop(node, UseInfo::TruncatingFloat64(),
1572 MachineRepresentation::kFloat64);
1573 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
1574 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001575 }
1576 case IrOpcode::kNumberTrunc: {
Ben Murdochc5610432016-08-08 18:44:38 +01001577 VisitUnop(node, UseInfo::TruncatingFloat64(),
1578 MachineRepresentation::kFloat64);
Ben Murdochda12d292016-06-02 14:46:10 +01001579 if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001580 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001581 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001582 case IrOpcode::kNumberToInt32: {
1583 // Just change representation if necessary.
Ben Murdochda12d292016-06-02 14:46:10 +01001584 VisitUnop(node, UseInfo::TruncatingWord32(),
1585 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001586 if (lower()) DeferReplacement(node, node->InputAt(0));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001587 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001589 case IrOpcode::kNumberToUint32: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001590 // Just change representation if necessary.
Ben Murdochda12d292016-06-02 14:46:10 +01001591 VisitUnop(node, UseInfo::TruncatingWord32(),
1592 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001593 if (lower()) DeferReplacement(node, node->InputAt(0));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001594 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001596 case IrOpcode::kReferenceEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001597 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001598 if (lower()) {
1599 NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
1600 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001601 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 }
1603 case IrOpcode::kStringEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001604 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1605 if (lower()) {
1606 // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
Ben Murdochc5610432016-08-08 18:44:38 +01001607 Operator::Properties properties =
Ben Murdoch61f157c2016-09-16 13:49:30 +01001608 Operator::kCommutative | Operator::kEliminatable;
Ben Murdochda12d292016-06-02 14:46:10 +01001609 Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
1610 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1611 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1612 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1613 flags, properties);
1614 node->InsertInput(jsgraph_->zone(), 0,
1615 jsgraph_->HeapConstant(callable.code()));
Ben Murdochc5610432016-08-08 18:44:38 +01001616 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1617 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001618 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1619 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001620 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001621 }
1622 case IrOpcode::kStringLessThan: {
Ben Murdochda12d292016-06-02 14:46:10 +01001623 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1624 if (lower()) {
1625 // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
Ben Murdoch61f157c2016-09-16 13:49:30 +01001626 Operator::Properties properties = Operator::kEliminatable;
Ben Murdochda12d292016-06-02 14:46:10 +01001627 Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
1628 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1629 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1630 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1631 flags, properties);
1632 node->InsertInput(jsgraph_->zone(), 0,
1633 jsgraph_->HeapConstant(callable.code()));
Ben Murdochc5610432016-08-08 18:44:38 +01001634 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1635 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001636 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1637 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001638 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001639 }
1640 case IrOpcode::kStringLessThanOrEqual: {
Ben Murdochda12d292016-06-02 14:46:10 +01001641 VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1642 if (lower()) {
1643 // StringLessThanOrEqual(x, y)
1644 // => Call(StringLessThanOrEqualStub, x, y, no-context)
Ben Murdoch61f157c2016-09-16 13:49:30 +01001645 Operator::Properties properties = Operator::kEliminatable;
Ben Murdochda12d292016-06-02 14:46:10 +01001646 Callable callable =
1647 CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
1648 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1649 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1650 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1651 flags, properties);
1652 node->InsertInput(jsgraph_->zone(), 0,
1653 jsgraph_->HeapConstant(callable.code()));
Ben Murdochc5610432016-08-08 18:44:38 +01001654 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
1655 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001656 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1657 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001658 return;
1659 }
1660 case IrOpcode::kStringFromCharCode: {
1661 VisitUnop(node, UseInfo::TruncatingWord32(),
1662 MachineRepresentation::kTagged);
1663 return;
Ben Murdochda12d292016-06-02 14:46:10 +01001664 }
1665 case IrOpcode::kStringToNumber: {
1666 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1667 if (lower()) {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001668 // StringToNumber(x) => Call(StringToNumber, x, no-context)
1669 Operator::Properties properties = Operator::kEliminatable;
Ben Murdochda12d292016-06-02 14:46:10 +01001670 Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
1671 CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
1672 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
1673 jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
1674 flags, properties);
1675 node->InsertInput(jsgraph_->zone(), 0,
1676 jsgraph_->HeapConstant(callable.code()));
1677 node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
Ben Murdochc5610432016-08-08 18:44:38 +01001678 node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
Ben Murdochda12d292016-06-02 14:46:10 +01001679 NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
1680 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001681 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001682 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001683
1684 case IrOpcode::kCheckBounds: {
1685 VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
1686 UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
1687 return;
1688 }
1689 case IrOpcode::kCheckTaggedPointer: {
1690 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1691 if (lower()) {
1692 if (InputIs(node, Type::TaggedPointer())) {
1693 DeferReplacement(node, node->InputAt(0));
1694 }
1695 }
1696 return;
1697 }
1698 case IrOpcode::kCheckTaggedSigned: {
1699 if (SmiValuesAre32Bits() && truncation.TruncatesToWord32()) {
1700 // TODO(jarin,bmeurer): Add CheckedSignedSmallAsWord32?
1701 VisitUnop(node, UseInfo::CheckedSigned32AsWord32(),
1702 MachineRepresentation::kWord32);
1703 if (lower()) DeferReplacement(node, node->InputAt(0));
1704 } else {
1705 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1706 if (lower()) {
1707 if (InputIs(node, Type::TaggedSigned())) {
1708 DeferReplacement(node, node->InputAt(0));
1709 }
1710 }
1711 }
1712 return;
1713 }
1714
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001715 case IrOpcode::kAllocate: {
Ben Murdochc5610432016-08-08 18:44:38 +01001716 ProcessInput(node, 0, UseInfo::TruncatingWord32());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001717 ProcessRemainingInputs(node, 1);
Ben Murdochda12d292016-06-02 14:46:10 +01001718 SetOutput(node, MachineRepresentation::kTagged);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001719 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001720 }
1721 case IrOpcode::kLoadField: {
1722 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001723 ProcessInput(node, 0, UseInfoForBasePointer(access));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001724 ProcessRemainingInputs(node, 1);
Ben Murdochda12d292016-06-02 14:46:10 +01001725 SetOutput(node, access.machine_type.representation());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001726 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001727 }
1728 case IrOpcode::kStoreField: {
1729 FieldAccess access = FieldAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001730 ProcessInput(node, 0, UseInfoForBasePointer(access));
1731 ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
1732 access.machine_type.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001733 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001734 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochc5610432016-08-08 18:44:38 +01001735 if (lower()) {
1736 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
1737 access.base_is_tagged, access.machine_type.representation(),
1738 access.offset, access.type, node->InputAt(1));
1739 if (write_barrier_kind < access.write_barrier_kind) {
1740 access.write_barrier_kind = write_barrier_kind;
1741 NodeProperties::ChangeOp(
1742 node, jsgraph_->simplified()->StoreField(access));
1743 }
1744 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001745 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001746 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001747 case IrOpcode::kLoadBuffer: {
1748 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001749 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1750 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1751 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001752 ProcessRemainingInputs(node, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001753
Ben Murdochda12d292016-06-02 14:46:10 +01001754 MachineRepresentation output;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 if (truncation.TruncatesUndefinedToZeroOrNaN()) {
1756 if (truncation.TruncatesNaNToZero()) {
1757 // If undefined is truncated to a non-NaN number, we can use
1758 // the load's representation.
Ben Murdochda12d292016-06-02 14:46:10 +01001759 output = access.machine_type().representation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001760 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001761 // If undefined is truncated to a number, but the use can
1762 // observe NaN, we need to output at least the float32
1763 // representation.
1764 if (access.machine_type().representation() ==
1765 MachineRepresentation::kFloat32) {
Ben Murdochda12d292016-06-02 14:46:10 +01001766 output = access.machine_type().representation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001767 } else {
Ben Murdochda12d292016-06-02 14:46:10 +01001768 output = MachineRepresentation::kFloat64;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001769 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001770 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001771 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001772 // If undefined is not truncated away, we need to have the tagged
1773 // representation.
Ben Murdochda12d292016-06-02 14:46:10 +01001774 output = MachineRepresentation::kTagged;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001775 }
Ben Murdochda12d292016-06-02 14:46:10 +01001776 SetOutput(node, output);
1777 if (lower()) lowering->DoLoadBuffer(node, output, changer_);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001778 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001779 }
1780 case IrOpcode::kStoreBuffer: {
1781 BufferAccess access = BufferAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001782 ProcessInput(node, 0, UseInfo::PointerInt()); // buffer
1783 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // offset
1784 ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
1785 ProcessInput(node, 3,
1786 TruncatingUseInfoFromRepresentation(
1787 access.machine_type().representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001788 ProcessRemainingInputs(node, 4);
Ben Murdochda12d292016-06-02 14:46:10 +01001789 SetOutput(node, MachineRepresentation::kNone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001790 if (lower()) lowering->DoStoreBuffer(node);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001791 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001792 }
1793 case IrOpcode::kLoadElement: {
1794 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001795 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1796 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001797 ProcessRemainingInputs(node, 2);
Ben Murdochda12d292016-06-02 14:46:10 +01001798 SetOutput(node, access.machine_type.representation());
Ben Murdoch61f157c2016-09-16 13:49:30 +01001799 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001800 }
1801 case IrOpcode::kStoreElement: {
1802 ElementAccess access = ElementAccessOf(node->op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001803 ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
1804 ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
1805 ProcessInput(node, 2,
1806 TruncatingUseInfoFromRepresentation(
1807 access.machine_type.representation())); // value
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001808 ProcessRemainingInputs(node, 3);
Ben Murdochda12d292016-06-02 14:46:10 +01001809 SetOutput(node, MachineRepresentation::kNone);
Ben Murdochc5610432016-08-08 18:44:38 +01001810 if (lower()) {
1811 WriteBarrierKind write_barrier_kind = WriteBarrierKindFor(
1812 access.base_is_tagged, access.machine_type.representation(),
1813 access.type, node->InputAt(2));
1814 if (write_barrier_kind < access.write_barrier_kind) {
1815 access.write_barrier_kind = write_barrier_kind;
1816 NodeProperties::ChangeOp(
1817 node, jsgraph_->simplified()->StoreElement(access));
1818 }
1819 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001820 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001821 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01001822 case IrOpcode::kPlainPrimitiveToNumber:
1823 if (truncation.TruncatesToWord32()) {
1824 // TODO(jarin): Extend this to Number \/ Oddball
1825 if (InputIs(node, Type::NumberOrUndefined())) {
1826 VisitUnop(node, UseInfo::TruncatingWord32(),
1827 MachineRepresentation::kWord32);
1828 if (lower()) DeferReplacement(node, node->InputAt(0));
1829 } else {
1830 VisitUnop(node, UseInfo::AnyTagged(),
1831 MachineRepresentation::kWord32);
1832 if (lower()) {
1833 NodeProperties::ChangeOp(node,
1834 simplified()->PlainPrimitiveToWord32());
1835 }
1836 }
1837 } else if (truncation.TruncatesToFloat64()) {
1838 // TODO(jarin): Extend this to Number \/ Oddball
1839 if (InputIs(node, Type::NumberOrUndefined())) {
1840 VisitUnop(node, UseInfo::TruncatingFloat64(),
1841 MachineRepresentation::kFloat64);
1842 if (lower()) DeferReplacement(node, node->InputAt(0));
1843 } else {
1844 VisitUnop(node, UseInfo::AnyTagged(),
1845 MachineRepresentation::kFloat64);
1846 if (lower()) {
1847 NodeProperties::ChangeOp(node,
1848 simplified()->PlainPrimitiveToFloat64());
1849 }
1850 }
1851 } else {
1852 VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
1853 }
1854 return;
Ben Murdochc5610432016-08-08 18:44:38 +01001855 case IrOpcode::kObjectIsCallable:
Ben Murdochda12d292016-06-02 14:46:10 +01001856 case IrOpcode::kObjectIsNumber:
1857 case IrOpcode::kObjectIsReceiver:
1858 case IrOpcode::kObjectIsSmi:
Ben Murdochc5610432016-08-08 18:44:38 +01001859 case IrOpcode::kObjectIsString:
Ben Murdochda12d292016-06-02 14:46:10 +01001860 case IrOpcode::kObjectIsUndetectable: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001861 ProcessInput(node, 0, UseInfo::AnyTagged());
Ben Murdochda12d292016-06-02 14:46:10 +01001862 SetOutput(node, MachineRepresentation::kBit);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001863 return;
1864 }
1865 case IrOpcode::kCheckFloat64Hole: {
1866 CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
1867 ProcessInput(node, 0, UseInfo::TruncatingFloat64());
1868 ProcessRemainingInputs(node, 1);
1869 SetOutput(node, MachineRepresentation::kFloat64);
1870 if (truncation.TruncatesToFloat64() &&
1871 mode == CheckFloat64HoleMode::kAllowReturnHole) {
1872 if (lower()) DeferReplacement(node, node->InputAt(0));
1873 }
1874 return;
1875 }
1876 case IrOpcode::kCheckTaggedHole: {
1877 CheckTaggedHoleMode mode = CheckTaggedHoleModeOf(node->op());
1878 if (truncation.TruncatesToWord32() &&
1879 mode == CheckTaggedHoleMode::kConvertHoleToUndefined) {
1880 ProcessInput(node, 0, UseInfo::CheckedSigned32AsWord32());
1881 ProcessRemainingInputs(node, 1);
1882 SetOutput(node, MachineRepresentation::kWord32);
1883 if (lower()) DeferReplacement(node, node->InputAt(0));
1884 } else {
1885 ProcessInput(node, 0, UseInfo::AnyTagged());
1886 ProcessRemainingInputs(node, 1);
1887 SetOutput(node, MachineRepresentation::kTagged);
1888 }
1889 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001890 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001891
1892 //------------------------------------------------------------------
1893 // Machine-level operators.
1894 //------------------------------------------------------------------
1895 case IrOpcode::kLoad: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001896 // TODO(jarin) Eventually, we should get rid of all machine stores
1897 // from the high-level phases, then this becomes UNREACHABLE.
1898 LoadRepresentation rep = LoadRepresentationOf(node->op());
1899 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1900 ProcessInput(node, 1, UseInfo::PointerInt()); // index
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001901 ProcessRemainingInputs(node, 2);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001902 return SetOutput(node, rep.representation());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001903 }
1904 case IrOpcode::kStore: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001905 // TODO(jarin) Eventually, we should get rid of all machine stores
1906 // from the high-level phases, then this becomes UNREACHABLE.
1907 StoreRepresentation rep = StoreRepresentationOf(node->op());
1908 ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
1909 ProcessInput(node, 1, UseInfo::PointerInt()); // index
1910 ProcessInput(node, 2,
1911 TruncatingUseInfoFromRepresentation(rep.representation()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001912 ProcessRemainingInputs(node, 3);
Ben Murdoch61f157c2016-09-16 13:49:30 +01001913 return SetOutput(node, MachineRepresentation::kNone);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001914 }
1915 case IrOpcode::kWord32Shr:
1916 // We output unsigned int32 for shift right because JavaScript.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001917 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001918 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001919 case IrOpcode::kWord32And:
1920 case IrOpcode::kWord32Or:
1921 case IrOpcode::kWord32Xor:
1922 case IrOpcode::kWord32Shl:
1923 case IrOpcode::kWord32Sar:
1924 // We use signed int32 as the output type for these word32 operations,
1925 // though the machine bits are the same for either signed or unsigned,
1926 // because JavaScript considers the result from these operations signed.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001927 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001928 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001929 case IrOpcode::kWord32Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001930 return VisitBinop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001931 MachineRepresentation::kBit);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001932
1933 case IrOpcode::kWord32Clz:
1934 return VisitUnop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01001935 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001936
1937 case IrOpcode::kInt32Add:
1938 case IrOpcode::kInt32Sub:
1939 case IrOpcode::kInt32Mul:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001940 case IrOpcode::kInt32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001941 case IrOpcode::kInt32Div:
1942 case IrOpcode::kInt32Mod:
1943 return VisitInt32Binop(node);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001944 case IrOpcode::kUint32Div:
1945 case IrOpcode::kUint32Mod:
1946 case IrOpcode::kUint32MulHigh:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001947 return VisitUint32Binop(node);
1948 case IrOpcode::kInt32LessThan:
1949 case IrOpcode::kInt32LessThanOrEqual:
1950 return VisitInt32Cmp(node);
1951
1952 case IrOpcode::kUint32LessThan:
1953 case IrOpcode::kUint32LessThanOrEqual:
1954 return VisitUint32Cmp(node);
1955
1956 case IrOpcode::kInt64Add:
1957 case IrOpcode::kInt64Sub:
1958 case IrOpcode::kInt64Mul:
1959 case IrOpcode::kInt64Div:
1960 case IrOpcode::kInt64Mod:
1961 return VisitInt64Binop(node);
1962 case IrOpcode::kInt64LessThan:
1963 case IrOpcode::kInt64LessThanOrEqual:
1964 return VisitInt64Cmp(node);
1965
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001966 case IrOpcode::kUint64LessThan:
1967 return VisitUint64Cmp(node);
1968
1969 case IrOpcode::kUint64Div:
1970 case IrOpcode::kUint64Mod:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001971 return VisitUint64Binop(node);
1972
1973 case IrOpcode::kWord64And:
1974 case IrOpcode::kWord64Or:
1975 case IrOpcode::kWord64Xor:
1976 case IrOpcode::kWord64Shl:
1977 case IrOpcode::kWord64Shr:
1978 case IrOpcode::kWord64Sar:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001979 return VisitBinop(node, UseInfo::TruncatingWord64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001980 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001981 case IrOpcode::kWord64Equal:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001982 return VisitBinop(node, UseInfo::TruncatingWord64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001983 MachineRepresentation::kBit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001984
1985 case IrOpcode::kChangeInt32ToInt64:
Ben Murdochda12d292016-06-02 14:46:10 +01001986 return VisitUnop(node, UseInfo::TruncatingWord32(),
1987 MachineRepresentation::kWord64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001988 case IrOpcode::kChangeUint32ToUint64:
Ben Murdochda12d292016-06-02 14:46:10 +01001989 return VisitUnop(node, UseInfo::TruncatingWord32(),
1990 MachineRepresentation::kWord64);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001991 case IrOpcode::kTruncateFloat64ToFloat32:
Ben Murdochc5610432016-08-08 18:44:38 +01001992 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001993 MachineRepresentation::kFloat32);
Ben Murdochc5610432016-08-08 18:44:38 +01001994 case IrOpcode::kTruncateFloat64ToWord32:
1995 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01001996 MachineRepresentation::kWord32);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001997
1998 case IrOpcode::kChangeInt32ToFloat64:
Ben Murdochda12d292016-06-02 14:46:10 +01001999 return VisitUnop(node, UseInfo::TruncatingWord32(),
2000 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002001 case IrOpcode::kChangeUint32ToFloat64:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002002 return VisitUnop(node, UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01002003 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002004 case IrOpcode::kFloat64Add:
2005 case IrOpcode::kFloat64Sub:
2006 case IrOpcode::kFloat64Mul:
2007 case IrOpcode::kFloat64Div:
2008 case IrOpcode::kFloat64Mod:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002009 case IrOpcode::kFloat64Min:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002010 return VisitFloat64Binop(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002011 case IrOpcode::kFloat64Abs:
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002012 case IrOpcode::kFloat64Sqrt:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002013 case IrOpcode::kFloat64RoundDown:
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002014 case IrOpcode::kFloat64RoundTruncate:
2015 case IrOpcode::kFloat64RoundTiesAway:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002016 case IrOpcode::kFloat64RoundUp:
Ben Murdochc5610432016-08-08 18:44:38 +01002017 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01002018 MachineRepresentation::kFloat64);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002019 case IrOpcode::kFloat64SilenceNaN:
2020 return VisitUnop(node, UseInfo::TruncatingFloat64(),
2021 MachineRepresentation::kFloat64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002022 case IrOpcode::kFloat64Equal:
2023 case IrOpcode::kFloat64LessThan:
2024 case IrOpcode::kFloat64LessThanOrEqual:
2025 return VisitFloat64Cmp(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002026 case IrOpcode::kFloat64ExtractLowWord32:
2027 case IrOpcode::kFloat64ExtractHighWord32:
Ben Murdochc5610432016-08-08 18:44:38 +01002028 return VisitUnop(node, UseInfo::TruncatingFloat64(),
Ben Murdochda12d292016-06-02 14:46:10 +01002029 MachineRepresentation::kWord32);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002030 case IrOpcode::kFloat64InsertLowWord32:
2031 case IrOpcode::kFloat64InsertHighWord32:
Ben Murdochc5610432016-08-08 18:44:38 +01002032 return VisitBinop(node, UseInfo::TruncatingFloat64(),
2033 UseInfo::TruncatingWord32(),
Ben Murdochda12d292016-06-02 14:46:10 +01002034 MachineRepresentation::kFloat64);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002035 case IrOpcode::kNumberSilenceNaN:
2036 VisitUnop(node, UseInfo::TruncatingFloat64(),
2037 MachineRepresentation::kFloat64);
2038 if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
2039 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002040 case IrOpcode::kLoadStackPointer:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002041 case IrOpcode::kLoadFramePointer:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002042 case IrOpcode::kLoadParentFramePointer:
Ben Murdochda12d292016-06-02 14:46:10 +01002043 return VisitLeaf(node, MachineType::PointerRepresentation());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002044 case IrOpcode::kStateValues:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002045 return VisitStateValues(node);
Ben Murdochda12d292016-06-02 14:46:10 +01002046
2047 // The following opcodes are not produced before representation
2048 // inference runs, so we do not have any real test coverage.
2049 // Simply fail here.
2050 case IrOpcode::kChangeFloat64ToInt32:
2051 case IrOpcode::kChangeFloat64ToUint32:
2052 case IrOpcode::kTruncateInt64ToInt32:
Ben Murdoch61f157c2016-09-16 13:49:30 +01002053 case IrOpcode::kChangeFloat32ToFloat64:
2054 case IrOpcode::kCheckedInt32Add:
2055 case IrOpcode::kCheckedInt32Sub:
2056 case IrOpcode::kCheckedUint32ToInt32:
2057 case IrOpcode::kCheckedFloat64ToInt32:
2058 case IrOpcode::kCheckedTaggedToInt32:
2059 case IrOpcode::kCheckedTaggedToFloat64:
2060 case IrOpcode::kPlainPrimitiveToWord32:
2061 case IrOpcode::kPlainPrimitiveToFloat64:
Ben Murdochda12d292016-06-02 14:46:10 +01002062 FATAL("Representation inference: unsupported opcodes.");
Ben Murdoch61f157c2016-09-16 13:49:30 +01002063 break;
Ben Murdochda12d292016-06-02 14:46:10 +01002064
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002065 default:
2066 VisitInputs(node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002067 // Assume the output is tagged.
Ben Murdoch61f157c2016-09-16 13:49:30 +01002068 return SetOutput(node, MachineRepresentation::kTagged);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002069 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01002070 UNREACHABLE();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002071 }
2072
2073 void DeferReplacement(Node* node, Node* replacement) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002074 TRACE("defer replacement #%d:%s with #%d:%s\n", node->id(),
2075 node->op()->mnemonic(), replacement->id(),
2076 replacement->op()->mnemonic());
2077
Ben Murdoch61f157c2016-09-16 13:49:30 +01002078 // Disconnect the node from effect and control chains, if necessary.
2079 if (node->op()->EffectInputCount() > 0) {
2080 DCHECK_LT(0, node->op()->ControlInputCount());
2081 // Disconnect the node from effect and control chains.
2082 Node* control = NodeProperties::GetControlInput(node);
2083 Node* effect = NodeProperties::GetEffectInput(node);
2084 ReplaceEffectControlUses(node, effect, control);
2085 } else {
2086 DCHECK_EQ(0, node->op()->ControlInputCount());
2087 }
2088
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002089 if (replacement->id() < count_ &&
Ben Murdoch61f157c2016-09-16 13:49:30 +01002090 GetUpperBound(node)->Is(GetUpperBound(replacement)) &&
2091 TypeOf(node)->Is(TypeOf(replacement))) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002092 // Replace with a previously existing node eagerly only if the type is the
2093 // same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002094 node->ReplaceUses(replacement);
2095 } else {
2096 // Otherwise, we are replacing a node with a representation change.
2097 // Such a substitution must be done after all lowering is done, because
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002098 // changing the type could confuse the representation change
2099 // insertion for uses of the node.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002100 replacements_.push_back(node);
2101 replacements_.push_back(replacement);
2102 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002103 node->NullAllInputs(); // Node is now dead.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002104 }
2105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002106 void PrintOutputInfo(NodeInfo* info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002107 if (FLAG_trace_representation) {
2108 OFStream os(stdout);
Ben Murdochda12d292016-06-02 14:46:10 +01002109 os << info->representation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002110 }
2111 }
2112
2113 void PrintRepresentation(MachineRepresentation rep) {
2114 if (FLAG_trace_representation) {
2115 OFStream os(stdout);
2116 os << rep;
2117 }
2118 }
2119
2120 void PrintTruncation(Truncation truncation) {
2121 if (FLAG_trace_representation) {
2122 OFStream os(stdout);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002123 os << truncation.description() << std::endl;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002124 }
2125 }
2126
2127 void PrintUseInfo(UseInfo info) {
2128 if (FLAG_trace_representation) {
2129 OFStream os(stdout);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002130 os << info.representation() << ":" << info.truncation().description();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002131 }
2132 }
2133
2134 private:
2135 JSGraph* jsgraph_;
Ben Murdoch61f157c2016-09-16 13:49:30 +01002136 Zone* zone_; // Temporary zone.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002137 size_t const count_; // number of nodes in the graph
2138 ZoneVector<NodeInfo> info_; // node id -> usage information
2139#ifdef DEBUG
2140 ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
2141 // requirements on inputs.
2142#endif // DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002143 NodeVector nodes_; // collected nodes
2144 NodeVector replacements_; // replacements to be done after lowering
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002145 Phase phase_; // current phase of algorithm
2146 RepresentationChanger* changer_; // for inserting representation changes
2147 ZoneQueue<Node*> queue_; // queue for traversing the graph
Ben Murdoch61f157c2016-09-16 13:49:30 +01002148
2149 struct NodeState {
2150 Node* node;
2151 int input_index;
2152 };
2153 ZoneStack<NodeState> typing_stack_; // stack for graph typing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002154 // TODO(danno): RepresentationSelector shouldn't know anything about the
2155 // source positions table, but must for now since there currently is no other
2156 // way to pass down source position information to nodes created during
2157 // lowering. Once this phase becomes a vanilla reducer, it should get source
2158 // position information via the SourcePositionWrapper like all other reducers.
2159 SourcePositionTable* source_positions_;
2160 TypeCache const& type_cache_;
Ben Murdoch61f157c2016-09-16 13:49:30 +01002161 OperationTyper op_typer_; // helper for the feedback typer
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002162
2163 NodeInfo* GetInfo(Node* node) {
2164 DCHECK(node->id() >= 0);
2165 DCHECK(node->id() < count_);
2166 return &info_[node->id()];
2167 }
Ben Murdoch61f157c2016-09-16 13:49:30 +01002168 Zone* zone() { return zone_; }
2169 Zone* graph_zone() { return jsgraph_->zone(); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002170};
2171
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002172SimplifiedLowering::SimplifiedLowering(JSGraph* jsgraph, Zone* zone,
Ben Murdoch61f157c2016-09-16 13:49:30 +01002173 SourcePositionTable* source_positions,
2174 Flags flags)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002175 : jsgraph_(jsgraph),
2176 zone_(zone),
2177 type_cache_(TypeCache::Get()),
Ben Murdoch61f157c2016-09-16 13:49:30 +01002178 flags_(flags),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002179 source_positions_(source_positions) {}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002180
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002181void SimplifiedLowering::LowerAllNodes() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002182 RepresentationChanger changer(jsgraph(), jsgraph()->isolate());
2183 RepresentationSelector selector(jsgraph(), zone_, &changer,
2184 source_positions_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002185 selector.Run(this);
2186}
2187
Ben Murdochc5610432016-08-08 18:44:38 +01002188void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
2189 Node* node, RepresentationSelector* selector) {
2190 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
2191 Node* value = node->InputAt(0);
2192 Node* context = node->InputAt(1);
2193 Node* frame_state = node->InputAt(2);
2194 Node* effect = node->InputAt(3);
2195 Node* control = node->InputAt(4);
2196 Node* throwing;
2197
2198 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
2199 Node* branch0 =
2200 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2201
2202 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2203 Node* etrue0 = effect;
2204 Node* vtrue0;
2205 {
2206 vtrue0 = graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
2207 vtrue0 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue0);
2208 }
2209
2210 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2211 Node* efalse0 = effect;
2212 Node* vfalse0;
2213 {
2214 throwing = vfalse0 = efalse0 =
2215 graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
2216 frame_state, efalse0, if_false0);
2217 if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
2218
2219 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
2220 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2221
2222 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2223 Node* etrue1 = efalse0;
2224 Node* vtrue1;
2225 {
2226 vtrue1 =
2227 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
2228 vtrue1 = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue1);
2229 }
2230
2231 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2232 Node* efalse1 = efalse0;
2233 Node* vfalse1;
2234 {
2235 vfalse1 = efalse1 = graph()->NewNode(
2236 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
2237 efalse1, if_false1);
2238 }
2239
2240 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2241 efalse0 =
2242 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
2243 vfalse0 =
2244 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2245 vtrue1, vfalse1, if_false0);
2246 }
2247
2248 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2249 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
2250 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2251 vtrue0, vfalse0, control);
2252
2253 // Replace effect and control uses appropriately.
2254 for (Edge edge : node->use_edges()) {
2255 if (NodeProperties::IsControlEdge(edge)) {
2256 if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
2257 edge.from()->ReplaceUses(control);
2258 edge.from()->Kill();
2259 } else if (edge.from()->opcode() == IrOpcode::kIfException) {
2260 edge.UpdateTo(throwing);
2261 } else {
2262 UNREACHABLE();
2263 }
2264 } else if (NodeProperties::IsEffectEdge(edge)) {
2265 edge.UpdateTo(effect);
2266 }
2267 }
2268
2269 selector->DeferReplacement(node, value);
2270}
2271
2272void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
2273 Node* node, RepresentationSelector* selector) {
2274 DCHECK_EQ(IrOpcode::kJSToNumber, node->opcode());
2275 Node* value = node->InputAt(0);
2276 Node* context = node->InputAt(1);
2277 Node* frame_state = node->InputAt(2);
2278 Node* effect = node->InputAt(3);
2279 Node* control = node->InputAt(4);
2280 Node* throwing;
2281
2282 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
2283 Node* branch0 =
2284 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
2285
2286 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2287 Node* etrue0 = effect;
2288 Node* vtrue0 =
2289 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), value);
2290
2291 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2292 Node* efalse0 = effect;
2293 Node* vfalse0;
2294 {
2295 throwing = vfalse0 = efalse0 =
2296 graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
2297 frame_state, efalse0, if_false0);
2298 if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
2299
2300 Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
2301 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2302
2303 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2304 Node* etrue1 = efalse0;
2305 Node* vtrue1 =
2306 graph()->NewNode(simplified()->ChangeTaggedSignedToInt32(), vfalse0);
2307
2308 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2309 Node* efalse1 = efalse0;
2310 Node* vfalse1;
2311 {
2312 vfalse1 = efalse1 = graph()->NewNode(
2313 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), efalse0,
2314 efalse1, if_false1);
2315 vfalse1 = graph()->NewNode(machine()->TruncateFloat64ToWord32(), vfalse1);
2316 }
2317
2318 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2319 efalse0 =
2320 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
2321 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2322 vtrue1, vfalse1, if_false0);
2323 }
2324
2325 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2326 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control);
2327 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
2328 vtrue0, vfalse0, control);
2329
2330 // Replace effect and control uses appropriately.
2331 for (Edge edge : node->use_edges()) {
2332 if (NodeProperties::IsControlEdge(edge)) {
2333 if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
2334 edge.from()->ReplaceUses(control);
2335 edge.from()->Kill();
2336 } else if (edge.from()->opcode() == IrOpcode::kIfException) {
2337 edge.UpdateTo(throwing);
2338 } else {
2339 UNREACHABLE();
2340 }
2341 } else if (NodeProperties::IsEffectEdge(edge)) {
2342 edge.UpdateTo(effect);
2343 }
2344 }
2345
2346 selector->DeferReplacement(node, value);
2347}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002349void SimplifiedLowering::DoLoadBuffer(Node* node,
2350 MachineRepresentation output_rep,
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002351 RepresentationChanger* changer) {
2352 DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002353 DCHECK_NE(MachineRepresentation::kNone, output_rep);
2354 MachineType const access_type = BufferAccessOf(node->op()).machine_type();
2355 if (output_rep != access_type.representation()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002356 Node* const buffer = node->InputAt(0);
2357 Node* const offset = node->InputAt(1);
2358 Node* const length = node->InputAt(2);
2359 Node* const effect = node->InputAt(3);
2360 Node* const control = node->InputAt(4);
2361 Node* const index =
2362 machine()->Is64()
2363 ? graph()->NewNode(machine()->ChangeUint32ToUint64(), offset)
2364 : offset;
2365
2366 Node* check = graph()->NewNode(machine()->Uint32LessThan(), offset, length);
2367 Node* branch =
2368 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
2369
2370 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002371 Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
2372 effect, if_true);
Ben Murdochc5610432016-08-08 18:44:38 +01002373 Type* element_type =
2374 Type::Intersect(NodeProperties::GetType(node), Type::Number(), zone());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002375 Node* vtrue = changer->GetRepresentationFor(
Ben Murdoch61f157c2016-09-16 13:49:30 +01002376 etrue, access_type.representation(), element_type, node,
2377 UseInfo(output_rep, Truncation::None()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002378
2379 Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
2380 Node* efalse = effect;
2381 Node* vfalse;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002382 if (output_rep == MachineRepresentation::kTagged) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002383 vfalse = jsgraph()->UndefinedConstant();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002384 } else if (output_rep == MachineRepresentation::kFloat64) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002385 vfalse =
2386 jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002387 } else if (output_rep == MachineRepresentation::kFloat32) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002388 vfalse =
2389 jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
2390 } else {
2391 vfalse = jsgraph()->Int32Constant(0);
2392 }
2393
2394 Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
2395 Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);
2396
2397 // Replace effect uses of {node} with the {ephi}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002398 NodeProperties::ReplaceUses(node, node, ephi);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002399
2400 // Turn the {node} into a Phi.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002401 node->ReplaceInput(0, vtrue);
2402 node->ReplaceInput(1, vfalse);
2403 node->ReplaceInput(2, merge);
2404 node->TrimInputCount(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002405 NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002406 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002407 NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002408 }
2409}
2410
2411
2412void SimplifiedLowering::DoStoreBuffer(Node* node) {
2413 DCHECK_EQ(IrOpcode::kStoreBuffer, node->opcode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002414 MachineRepresentation const rep =
2415 BufferAccessOf(node->op()).machine_type().representation();
2416 NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002417}
2418
Ben Murdochda12d292016-06-02 14:46:10 +01002419Node* SimplifiedLowering::Float64Ceil(Node* const node) {
2420 Node* const one = jsgraph()->Float64Constant(1.0);
2421 Node* const zero = jsgraph()->Float64Constant(0.0);
2422 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
2423 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
2424 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
2425 Node* const input = node->InputAt(0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002426
Ben Murdochda12d292016-06-02 14:46:10 +01002427 // Use fast hardware instruction if available.
2428 if (machine()->Float64RoundUp().IsSupported()) {
2429 return graph()->NewNode(machine()->Float64RoundUp().op(), input);
2430 }
2431
2432 // General case for ceil.
2433 //
2434 // if 0.0 < input then
2435 // if 2^52 <= input then
2436 // input
2437 // else
2438 // let temp1 = (2^52 + input) - 2^52 in
2439 // if temp1 < input then
2440 // temp1 + 1
2441 // else
2442 // temp1
2443 // else
2444 // if input == 0 then
2445 // input
2446 // else
2447 // if input <= -2^52 then
2448 // input
2449 // else
2450 // let temp1 = -0 - input in
2451 // let temp2 = (2^52 + temp1) - 2^52 in
2452 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2453 // -0 - temp3
2454 //
2455 // Note: We do not use the Diamond helper class here, because it really hurts
2456 // readability with nested diamonds.
2457
2458 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
2459 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2460 graph()->start());
2461
2462 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2463 Node* vtrue0;
2464 {
2465 Node* check1 =
2466 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
2467 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2468
2469 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2470 Node* vtrue1 = input;
2471
2472 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2473 Node* vfalse1;
2474 {
2475 Node* temp1 = graph()->NewNode(
2476 machine()->Float64Sub(),
2477 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
2478 vfalse1 = graph()->NewNode(
2479 common()->Select(MachineRepresentation::kFloat64),
2480 graph()->NewNode(machine()->Float64LessThan(), temp1, input),
2481 graph()->NewNode(machine()->Float64Add(), temp1, one), temp1);
2482 }
2483
2484 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2485 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2486 vtrue1, vfalse1, if_true0);
2487 }
2488
2489 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2490 Node* vfalse0;
2491 {
2492 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
2493 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2494 check1, if_false0);
2495
2496 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2497 Node* vtrue1 = input;
2498
2499 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2500 Node* vfalse1;
2501 {
2502 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
2503 input, minus_two_52);
2504 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2505 check2, if_false1);
2506
2507 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2508 Node* vtrue2 = input;
2509
2510 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2511 Node* vfalse2;
2512 {
2513 Node* temp1 =
2514 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
2515 Node* temp2 = graph()->NewNode(
2516 machine()->Float64Sub(),
2517 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
2518 Node* temp3 = graph()->NewNode(
2519 common()->Select(MachineRepresentation::kFloat64),
2520 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
2521 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
2522 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
2523 }
2524
2525 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
2526 vfalse1 =
2527 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2528 vtrue2, vfalse2, if_false1);
2529 }
2530
2531 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2532 vfalse0 =
2533 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2534 vtrue1, vfalse1, if_false0);
2535 }
2536
2537 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2538 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2539 vtrue0, vfalse0, merge0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002540}
2541
Ben Murdochda12d292016-06-02 14:46:10 +01002542Node* SimplifiedLowering::Float64Floor(Node* const node) {
2543 Node* const one = jsgraph()->Float64Constant(1.0);
2544 Node* const zero = jsgraph()->Float64Constant(0.0);
2545 Node* const minus_one = jsgraph()->Float64Constant(-1.0);
2546 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
2547 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
2548 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
2549 Node* const input = node->InputAt(0);
2550
2551 // Use fast hardware instruction if available.
2552 if (machine()->Float64RoundDown().IsSupported()) {
2553 return graph()->NewNode(machine()->Float64RoundDown().op(), input);
2554 }
2555
2556 // General case for floor.
2557 //
2558 // if 0.0 < input then
2559 // if 2^52 <= input then
2560 // input
2561 // else
2562 // let temp1 = (2^52 + input) - 2^52 in
2563 // if input < temp1 then
2564 // temp1 - 1
2565 // else
2566 // temp1
2567 // else
2568 // if input == 0 then
2569 // input
2570 // else
2571 // if input <= -2^52 then
2572 // input
2573 // else
2574 // let temp1 = -0 - input in
2575 // let temp2 = (2^52 + temp1) - 2^52 in
2576 // if temp2 < temp1 then
2577 // -1 - temp2
2578 // else
2579 // -0 - temp2
2580 //
2581 // Note: We do not use the Diamond helper class here, because it really hurts
2582 // readability with nested diamonds.
2583
2584 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
2585 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2586 graph()->start());
2587
2588 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2589 Node* vtrue0;
2590 {
2591 Node* check1 =
2592 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
2593 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2594
2595 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2596 Node* vtrue1 = input;
2597
2598 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2599 Node* vfalse1;
2600 {
2601 Node* temp1 = graph()->NewNode(
2602 machine()->Float64Sub(),
2603 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
2604 vfalse1 = graph()->NewNode(
2605 common()->Select(MachineRepresentation::kFloat64),
2606 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
2607 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
2608 }
2609
2610 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2611 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2612 vtrue1, vfalse1, if_true0);
2613 }
2614
2615 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2616 Node* vfalse0;
2617 {
2618 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
2619 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2620 check1, if_false0);
2621
2622 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2623 Node* vtrue1 = input;
2624
2625 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2626 Node* vfalse1;
2627 {
2628 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
2629 input, minus_two_52);
2630 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2631 check2, if_false1);
2632
2633 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2634 Node* vtrue2 = input;
2635
2636 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2637 Node* vfalse2;
2638 {
2639 Node* temp1 =
2640 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
2641 Node* temp2 = graph()->NewNode(
2642 machine()->Float64Sub(),
2643 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
2644 vfalse2 = graph()->NewNode(
2645 common()->Select(MachineRepresentation::kFloat64),
2646 graph()->NewNode(machine()->Float64LessThan(), temp2, temp1),
2647 graph()->NewNode(machine()->Float64Sub(), minus_one, temp2),
2648 graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2));
2649 }
2650
2651 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
2652 vfalse1 =
2653 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2654 vtrue2, vfalse2, if_false1);
2655 }
2656
2657 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2658 vfalse0 =
2659 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2660 vtrue1, vfalse1, if_false0);
2661 }
2662
2663 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2664 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2665 vtrue0, vfalse0, merge0);
2666}
2667
2668Node* SimplifiedLowering::Float64Round(Node* const node) {
2669 Node* const one = jsgraph()->Float64Constant(1.0);
2670 Node* const one_half = jsgraph()->Float64Constant(0.5);
2671 Node* const input = node->InputAt(0);
2672
2673 // Round up towards Infinity, and adjust if the difference exceeds 0.5.
2674 Node* result = Float64Ceil(node);
2675 return graph()->NewNode(
2676 common()->Select(MachineRepresentation::kFloat64),
2677 graph()->NewNode(
2678 machine()->Float64LessThanOrEqual(),
2679 graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
2680 result, graph()->NewNode(machine()->Float64Sub(), result, one));
2681}
2682
2683Node* SimplifiedLowering::Float64Trunc(Node* const node) {
2684 Node* const one = jsgraph()->Float64Constant(1.0);
2685 Node* const zero = jsgraph()->Float64Constant(0.0);
2686 Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
2687 Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
2688 Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
2689 Node* const input = node->InputAt(0);
2690
2691 // Use fast hardware instruction if available.
2692 if (machine()->Float64RoundTruncate().IsSupported()) {
2693 return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
2694 }
2695
2696 // General case for trunc.
2697 //
2698 // if 0.0 < input then
2699 // if 2^52 <= input then
2700 // input
2701 // else
2702 // let temp1 = (2^52 + input) - 2^52 in
2703 // if input < temp1 then
2704 // temp1 - 1
2705 // else
2706 // temp1
2707 // else
2708 // if input == 0 then
2709 // input
2710 // else
2711 // if input <= -2^52 then
2712 // input
2713 // else
2714 // let temp1 = -0 - input in
2715 // let temp2 = (2^52 + temp1) - 2^52 in
2716 // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
2717 // -0 - temp3
2718 //
2719 // Note: We do not use the Diamond helper class here, because it really hurts
2720 // readability with nested diamonds.
2721
2722 Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
2723 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2724 graph()->start());
2725
2726 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2727 Node* vtrue0;
2728 {
2729 Node* check1 =
2730 graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
2731 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2732
2733 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2734 Node* vtrue1 = input;
2735
2736 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2737 Node* vfalse1;
2738 {
2739 Node* temp1 = graph()->NewNode(
2740 machine()->Float64Sub(),
2741 graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
2742 vfalse1 = graph()->NewNode(
2743 common()->Select(MachineRepresentation::kFloat64),
2744 graph()->NewNode(machine()->Float64LessThan(), input, temp1),
2745 graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
2746 }
2747
2748 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2749 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2750 vtrue1, vfalse1, if_true0);
2751 }
2752
2753 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2754 Node* vfalse0;
2755 {
2756 Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
2757 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2758 check1, if_false0);
2759
2760 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2761 Node* vtrue1 = input;
2762
2763 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2764 Node* vfalse1;
2765 {
2766 Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
2767 input, minus_two_52);
2768 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2769 check2, if_false1);
2770
2771 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2772 Node* vtrue2 = input;
2773
2774 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2775 Node* vfalse2;
2776 {
2777 Node* temp1 =
2778 graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
2779 Node* temp2 = graph()->NewNode(
2780 machine()->Float64Sub(),
2781 graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
2782 Node* temp3 = graph()->NewNode(
2783 common()->Select(MachineRepresentation::kFloat64),
2784 graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
2785 graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
2786 vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
2787 }
2788
2789 if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
2790 vfalse1 =
2791 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2792 vtrue2, vfalse2, if_false1);
2793 }
2794
2795 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
2796 vfalse0 =
2797 graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2798 vtrue1, vfalse1, if_false0);
2799 }
2800
2801 Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
2802 return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
2803 vtrue0, vfalse0, merge0);
2804}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002805
Ben Murdoch61f157c2016-09-16 13:49:30 +01002806Node* SimplifiedLowering::Int32Abs(Node* const node) {
2807 Node* const zero = jsgraph()->Int32Constant(0);
2808 Node* const input = node->InputAt(0);
2809
2810 // if 0 < input then input else 0 - input
2811 return graph()->NewNode(
2812 common()->Select(MachineRepresentation::kWord32, BranchHint::kTrue),
2813 graph()->NewNode(machine()->Int32LessThan(), zero, input), input,
2814 graph()->NewNode(machine()->Int32Sub(), zero, input));
2815}
2816
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002817Node* SimplifiedLowering::Int32Div(Node* const node) {
2818 Int32BinopMatcher m(node);
2819 Node* const zero = jsgraph()->Int32Constant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002820 Node* const minus_one = jsgraph()->Int32Constant(-1);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002821 Node* const lhs = m.left().node();
2822 Node* const rhs = m.right().node();
2823
2824 if (m.right().Is(-1)) {
2825 return graph()->NewNode(machine()->Int32Sub(), zero, lhs);
2826 } else if (m.right().Is(0)) {
2827 return rhs;
2828 } else if (machine()->Int32DivIsSafe() || m.right().HasValue()) {
2829 return graph()->NewNode(machine()->Int32Div(), lhs, rhs, graph()->start());
2830 }
2831
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002832 // General case for signed integer division.
2833 //
2834 // if 0 < rhs then
2835 // lhs / rhs
2836 // else
2837 // if rhs < -1 then
2838 // lhs / rhs
2839 // else if rhs == 0 then
2840 // 0
2841 // else
2842 // 0 - lhs
2843 //
2844 // Note: We do not use the Diamond helper class here, because it really hurts
2845 // readability with nested diamonds.
2846 const Operator* const merge_op = common()->Merge(2);
2847 const Operator* const phi_op =
2848 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002849
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002850 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
2851 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2852 graph()->start());
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002853
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002854 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2855 Node* true0 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true0);
2856
2857 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2858 Node* false0;
2859 {
2860 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
2861 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
2862
2863 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2864 Node* true1 = graph()->NewNode(machine()->Int32Div(), lhs, rhs, if_true1);
2865
2866 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2867 Node* false1;
2868 {
2869 Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
2870 Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_false1);
2871
2872 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2873 Node* true2 = zero;
2874
2875 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2876 Node* false2 = graph()->NewNode(machine()->Int32Sub(), zero, lhs);
2877
2878 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2879 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2880 }
2881
2882 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2883 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2884 }
2885
2886 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2887 return graph()->NewNode(phi_op, true0, false0, merge0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002888}
2889
2890
2891Node* SimplifiedLowering::Int32Mod(Node* const node) {
2892 Int32BinopMatcher m(node);
2893 Node* const zero = jsgraph()->Int32Constant(0);
2894 Node* const minus_one = jsgraph()->Int32Constant(-1);
2895 Node* const lhs = m.left().node();
2896 Node* const rhs = m.right().node();
2897
2898 if (m.right().Is(-1) || m.right().Is(0)) {
2899 return zero;
2900 } else if (m.right().HasValue()) {
2901 return graph()->NewNode(machine()->Int32Mod(), lhs, rhs, graph()->start());
2902 }
2903
2904 // General case for signed integer modulus, with optimization for (unknown)
2905 // power of 2 right hand side.
2906 //
2907 // if 0 < rhs then
2908 // msk = rhs - 1
2909 // if rhs & msk != 0 then
2910 // lhs % rhs
2911 // else
2912 // if lhs < 0 then
2913 // -(-lhs & msk)
2914 // else
2915 // lhs & msk
2916 // else
2917 // if rhs < -1 then
2918 // lhs % rhs
2919 // else
2920 // zero
2921 //
2922 // Note: We do not use the Diamond helper class here, because it really hurts
2923 // readability with nested diamonds.
2924 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002925 const Operator* const phi_op =
2926 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002927
2928 Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
2929 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
2930 graph()->start());
2931
2932 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
2933 Node* true0;
2934 {
2935 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
2936
2937 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
2938 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
2939
2940 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2941 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
2942
2943 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2944 Node* false1;
2945 {
2946 Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
2947 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
2948 check2, if_false1);
2949
2950 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
2951 Node* true2 = graph()->NewNode(
2952 machine()->Int32Sub(), zero,
2953 graph()->NewNode(machine()->Word32And(),
2954 graph()->NewNode(machine()->Int32Sub(), zero, lhs),
2955 msk));
2956
2957 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
2958 Node* false2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
2959
2960 if_false1 = graph()->NewNode(merge_op, if_true2, if_false2);
2961 false1 = graph()->NewNode(phi_op, true2, false2, if_false1);
2962 }
2963
2964 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
2965 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
2966 }
2967
2968 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
2969 Node* false0;
2970 {
2971 Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minus_one);
2972 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
2973 check1, if_false0);
2974
2975 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
2976 Node* true1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
2977
2978 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
2979 Node* false1 = zero;
2980
2981 if_false0 = graph()->NewNode(merge_op, if_true1, if_false1);
2982 false0 = graph()->NewNode(phi_op, true1, false1, if_false0);
2983 }
2984
2985 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
2986 return graph()->NewNode(phi_op, true0, false0, merge0);
2987}
2988
2989
2990Node* SimplifiedLowering::Uint32Div(Node* const node) {
2991 Uint32BinopMatcher m(node);
2992 Node* const zero = jsgraph()->Uint32Constant(0);
2993 Node* const lhs = m.left().node();
2994 Node* const rhs = m.right().node();
2995
2996 if (m.right().Is(0)) {
2997 return zero;
2998 } else if (machine()->Uint32DivIsSafe() || m.right().HasValue()) {
2999 return graph()->NewNode(machine()->Uint32Div(), lhs, rhs, graph()->start());
3000 }
3001
3002 Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
3003 Diamond d(graph(), common(), check, BranchHint::kFalse);
3004 Node* div = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, d.if_false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003005 return d.Phi(MachineRepresentation::kWord32, zero, div);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003006}
3007
3008
3009Node* SimplifiedLowering::Uint32Mod(Node* const node) {
3010 Uint32BinopMatcher m(node);
3011 Node* const minus_one = jsgraph()->Int32Constant(-1);
3012 Node* const zero = jsgraph()->Uint32Constant(0);
3013 Node* const lhs = m.left().node();
3014 Node* const rhs = m.right().node();
3015
3016 if (m.right().Is(0)) {
3017 return zero;
3018 } else if (m.right().HasValue()) {
3019 return graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, graph()->start());
3020 }
3021
3022 // General case for unsigned integer modulus, with optimization for (unknown)
3023 // power of 2 right hand side.
3024 //
3025 // if rhs then
3026 // msk = rhs - 1
3027 // if rhs & msk != 0 then
3028 // lhs % rhs
3029 // else
3030 // lhs & msk
3031 // else
3032 // zero
3033 //
3034 // Note: We do not use the Diamond helper class here, because it really hurts
3035 // readability with nested diamonds.
3036 const Operator* const merge_op = common()->Merge(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003037 const Operator* const phi_op =
3038 common()->Phi(MachineRepresentation::kWord32, 2);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003039
3040 Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), rhs,
3041 graph()->start());
3042
3043 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
3044 Node* true0;
3045 {
3046 Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minus_one);
3047
3048 Node* check1 = graph()->NewNode(machine()->Word32And(), rhs, msk);
3049 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
3050
3051 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
3052 Node* true1 = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, if_true1);
3053
3054 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
3055 Node* false1 = graph()->NewNode(machine()->Word32And(), lhs, msk);
3056
3057 if_true0 = graph()->NewNode(merge_op, if_true1, if_false1);
3058 true0 = graph()->NewNode(phi_op, true1, false1, if_true0);
3059 }
3060
3061 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
3062 Node* false0 = zero;
3063
3064 Node* merge0 = graph()->NewNode(merge_op, if_true0, if_false0);
3065 return graph()->NewNode(phi_op, true0, false0, merge0);
3066}
3067
3068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003069void SimplifiedLowering::DoShift(Node* node, Operator const* op,
3070 Type* rhs_type) {
3071 Node* const rhs = NodeProperties::GetValueInput(node, 1);
3072 if (!rhs_type->Is(type_cache_.kZeroToThirtyOne)) {
3073 node->ReplaceInput(1, graph()->NewNode(machine()->Word32And(), rhs,
3074 jsgraph()->Int32Constant(0x1f)));
3075 }
3076 NodeProperties::ChangeOp(node, op);
3077}
3078
Ben Murdochc5610432016-08-08 18:44:38 +01003079Node* SimplifiedLowering::ToNumberCode() {
3080 if (!to_number_code_.is_set()) {
3081 Callable callable = CodeFactory::ToNumber(isolate());
3082 to_number_code_.set(jsgraph()->HeapConstant(callable.code()));
3083 }
3084 return to_number_code_.get();
3085}
3086
3087Operator const* SimplifiedLowering::ToNumberOperator() {
3088 if (!to_number_operator_.is_set()) {
3089 Callable callable = CodeFactory::ToNumber(isolate());
3090 CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState;
3091 CallDescriptor* desc = Linkage::GetStubCallDescriptor(
3092 isolate(), graph()->zone(), callable.descriptor(), 0, flags,
3093 Operator::kNoProperties);
3094 to_number_operator_.set(common()->Call(desc));
3095 }
3096 return to_number_operator_.get();
3097}
3098
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003099} // namespace compiler
3100} // namespace internal
3101} // namespace v8