Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/compiler/representation-change.cc

Issue 1921563002: [turbofan] Initial version of number type feedback. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add tests for the checks and fix check insertion Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/representation-change.h" 5 #include "src/compiler/representation-change.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 namespace { 98 namespace {
99 99
100 bool IsWord(MachineRepresentation rep) { 100 bool IsWord(MachineRepresentation rep) {
101 return rep == MachineRepresentation::kWord8 || 101 return rep == MachineRepresentation::kWord8 ||
102 rep == MachineRepresentation::kWord16 || 102 rep == MachineRepresentation::kWord16 ||
103 rep == MachineRepresentation::kWord32; 103 rep == MachineRepresentation::kWord32;
104 } 104 }
105 105
106 } // namespace 106 } // namespace
107 107
108
109 // Changes representation from {output_rep} to {use_rep}. The {truncation} 108 // Changes representation from {output_rep} to {use_rep}. The {truncation}
110 // parameter is only used for sanity checking - if the changer cannot figure 109 // parameter is only used for sanity checking - if the changer cannot figure
111 // out signedness for the word32->float64 conversion, then we check that the 110 // out signedness for the word32->float64 conversion, then we check that the
112 // uses truncate to word32 (so they do not care about signedness). 111 // uses truncate to word32 (so they do not care about signedness).
113 Node* RepresentationChanger::GetRepresentationFor( 112 Node* RepresentationChanger::GetRepresentationFor(
114 Node* node, MachineRepresentation output_rep, Type* output_type, 113 Node* node, MachineRepresentation output_rep, Type* output_type,
115 MachineRepresentation use_rep, Truncation truncation) { 114 Node* use_node, UseInfo use_info) {
116 if (output_rep == MachineRepresentation::kNone) { 115 if (output_rep == MachineRepresentation::kNone) {
117 // The output representation should be set. 116 // The output representation should be set.
118 return TypeError(node, output_rep, output_type, use_rep); 117 return TypeError(node, output_rep, output_type, use_info.representation());
119 } 118 }
120 if (use_rep == output_rep) { 119
121 // Representations are the same. That's a no-op. 120 // Handle the no-op shortcuts when no checking is necessary.
122 return node; 121 if (use_info.type_check() == TypeCheckKind::kNone ||
122 output_rep != MachineRepresentation::kWord32) {
123 if (use_info.representation() == output_rep) {
124 // Representations are the same. That's a no-op.
125 return node;
126 }
127 if (IsWord(use_info.representation()) && IsWord(output_rep)) {
128 // Both are words less than or equal to 32-bits.
129 // Since loads of integers from memory implicitly sign or zero extend the
130 // value to the full machine word size and stores implicitly truncate,
131 // no representation change is necessary.
132 return node;
133 }
123 } 134 }
124 if (IsWord(use_rep) && IsWord(output_rep)) { 135
125 // Both are words less than or equal to 32-bits. 136 switch (use_info.representation()) {
126 // Since loads of integers from memory implicitly sign or zero extend the
127 // value to the full machine word size and stores implicitly truncate,
128 // no representation change is necessary.
129 return node;
130 }
131 switch (use_rep) {
132 case MachineRepresentation::kTagged: 137 case MachineRepresentation::kTagged:
138 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
133 return GetTaggedRepresentationFor(node, output_rep, output_type); 139 return GetTaggedRepresentationFor(node, output_rep, output_type);
134 case MachineRepresentation::kFloat32: 140 case MachineRepresentation::kFloat32:
141 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
135 return GetFloat32RepresentationFor(node, output_rep, output_type, 142 return GetFloat32RepresentationFor(node, output_rep, output_type,
136 truncation); 143 use_info.truncation());
137 case MachineRepresentation::kFloat64: 144 case MachineRepresentation::kFloat64:
138 return GetFloat64RepresentationFor(node, output_rep, output_type, 145 return GetFloat64RepresentationFor(node, output_rep, output_type,
139 truncation); 146 use_node, use_info);
140 case MachineRepresentation::kBit: 147 case MachineRepresentation::kBit:
148 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
141 return GetBitRepresentationFor(node, output_rep, output_type); 149 return GetBitRepresentationFor(node, output_rep, output_type);
142 case MachineRepresentation::kWord8: 150 case MachineRepresentation::kWord8:
143 case MachineRepresentation::kWord16: 151 case MachineRepresentation::kWord16:
144 case MachineRepresentation::kWord32: 152 case MachineRepresentation::kWord32:
145 return GetWord32RepresentationFor(node, output_rep, output_type, 153 return GetWord32RepresentationFor(node, output_rep, output_type, use_node,
146 truncation); 154 use_info);
147 case MachineRepresentation::kWord64: 155 case MachineRepresentation::kWord64:
156 DCHECK(use_info.type_check() == TypeCheckKind::kNone);
148 return GetWord64RepresentationFor(node, output_rep, output_type); 157 return GetWord64RepresentationFor(node, output_rep, output_type);
149 case MachineRepresentation::kSimd128: // Fall through. 158 case MachineRepresentation::kSimd128: // Fall through.
150 // TODO(bbudge) Handle conversions between tagged and untagged. 159 // TODO(bbudge) Handle conversions between tagged and untagged.
151 break; 160 break;
152 case MachineRepresentation::kNone: 161 case MachineRepresentation::kNone:
153 return node; 162 return node;
154 } 163 }
155 UNREACHABLE(); 164 UNREACHABLE();
156 return nullptr; 165 return nullptr;
157 } 166 }
158 167
159
160 Node* RepresentationChanger::GetTaggedRepresentationFor( 168 Node* RepresentationChanger::GetTaggedRepresentationFor(
161 Node* node, MachineRepresentation output_rep, Type* output_type) { 169 Node* node, MachineRepresentation output_rep, Type* output_type) {
162 // Eagerly fold representation changes for constants. 170 // Eagerly fold representation changes for constants.
163 switch (node->opcode()) { 171 switch (node->opcode()) {
164 case IrOpcode::kNumberConstant: 172 case IrOpcode::kNumberConstant:
165 case IrOpcode::kHeapConstant: 173 case IrOpcode::kHeapConstant:
166 return node; // No change necessary. 174 return node; // No change necessary.
167 case IrOpcode::kInt32Constant: 175 case IrOpcode::kInt32Constant:
168 if (output_type->Is(Type::Signed32())) { 176 if (output_type->Is(Type::Signed32())) {
169 int32_t value = OpParameter<int32_t>(node); 177 int32_t value = OpParameter<int32_t>(node);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 } else if (output_rep == MachineRepresentation::kFloat64) { 287 } else if (output_rep == MachineRepresentation::kFloat64) {
280 op = machine()->TruncateFloat64ToFloat32(); 288 op = machine()->TruncateFloat64ToFloat32();
281 } 289 }
282 if (op == nullptr) { 290 if (op == nullptr) {
283 return TypeError(node, output_rep, output_type, 291 return TypeError(node, output_rep, output_type,
284 MachineRepresentation::kFloat32); 292 MachineRepresentation::kFloat32);
285 } 293 }
286 return jsgraph()->graph()->NewNode(op, node); 294 return jsgraph()->graph()->NewNode(op, node);
287 } 295 }
288 296
289
290 Node* RepresentationChanger::GetFloat64RepresentationFor( 297 Node* RepresentationChanger::GetFloat64RepresentationFor(
291 Node* node, MachineRepresentation output_rep, Type* output_type, 298 Node* node, MachineRepresentation output_rep, Type* output_type,
292 Truncation truncation) { 299 Node* use_node, UseInfo use_info) {
293 // Eagerly fold representation changes for constants. 300 // Eagerly fold representation changes for constants.
294 switch (node->opcode()) { 301 if ((use_info.type_check() == TypeCheckKind::kNone)) {
295 case IrOpcode::kNumberConstant: 302 // TODO(jarin) Handle checked constant conversions.
296 return jsgraph()->Float64Constant(OpParameter<double>(node)); 303 switch (node->opcode()) {
297 case IrOpcode::kInt32Constant: 304 case IrOpcode::kNumberConstant:
298 if (output_type->Is(Type::Signed32())) { 305 return jsgraph()->Float64Constant(OpParameter<double>(node));
299 int32_t value = OpParameter<int32_t>(node); 306 case IrOpcode::kInt32Constant:
300 return jsgraph()->Float64Constant(value); 307 if (output_type->Is(Type::Signed32())) {
301 } else { 308 int32_t value = OpParameter<int32_t>(node);
302 DCHECK(output_type->Is(Type::Unsigned32())); 309 return jsgraph()->Float64Constant(value);
303 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); 310 } else {
304 return jsgraph()->Float64Constant(static_cast<double>(value)); 311 DCHECK(output_type->Is(Type::Unsigned32()));
305 } 312 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
306 case IrOpcode::kFloat64Constant: 313 return jsgraph()->Float64Constant(static_cast<double>(value));
307 return node; // No change necessary. 314 }
308 case IrOpcode::kFloat32Constant: 315 case IrOpcode::kFloat64Constant:
309 return jsgraph()->Float64Constant(OpParameter<float>(node)); 316 return node; // No change necessary.
310 default: 317 case IrOpcode::kFloat32Constant:
311 break; 318 return jsgraph()->Float64Constant(OpParameter<float>(node));
319 default:
320 break;
321 }
312 } 322 }
313 // Select the correct X -> Float64 operator. 323 // Select the correct X -> Float64 operator.
314 const Operator* op = nullptr; 324 const Operator* op = nullptr;
315 if (IsWord(output_rep)) { 325 if (IsWord(output_rep)) {
316 if (output_type->Is(Type::Signed32())) { 326 if (output_type->Is(Type::Signed32())) {
317 op = machine()->ChangeInt32ToFloat64(); 327 op = machine()->ChangeInt32ToFloat64();
318 } else if (output_type->Is(Type::Unsigned32()) || 328 } else if (output_type->Is(Type::Unsigned32()) ||
319 truncation.TruncatesToWord32()) { 329 use_info.truncation().TruncatesToWord32()) {
320 // Either the output is uint32 or the uses only care about the 330 // Either the output is uint32 or the uses only care about the
321 // low 32 bits (so we can pick uint32 safely). 331 // low 32 bits (so we can pick uint32 safely).
322 op = machine()->ChangeUint32ToFloat64(); 332 op = machine()->ChangeUint32ToFloat64();
323 } 333 }
324 } else if (output_rep == MachineRepresentation::kTagged) { 334 } else if (output_rep == MachineRepresentation::kTagged) {
325 if (output_type->Is(Type::Undefined())) { 335 if (output_type->Is(Type::Undefined())) {
326 return jsgraph()->Float64Constant( 336 return jsgraph()->Float64Constant(
327 std::numeric_limits<double>::quiet_NaN()); 337 std::numeric_limits<double>::quiet_NaN());
328 } else if (output_type->Is(Type::TaggedSigned())) { 338 } else if (output_type->Is(Type::TaggedSigned())) {
329 node = InsertChangeTaggedSignedToInt32(node); 339 node = InsertChangeTaggedSignedToInt32(node);
330 op = machine()->ChangeInt32ToFloat64(); 340 op = machine()->ChangeInt32ToFloat64();
331 } else if (output_type->Is(Type::NumberOrUndefined())) { 341 } else if (output_type->Is(Type::NumberOrUndefined())) {
342 // TODO(jarin) Here we should check that truncation is Number.
332 op = simplified()->ChangeTaggedToFloat64(); 343 op = simplified()->ChangeTaggedToFloat64();
Benedikt Meurer 2016/05/30 18:39:50 This should probably be TruncateTaggedToFloat64
Jarin 2016/05/31 20:28:53 Done in https://codereview.chromium.org/2027593002
344 } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) {
345 op = simplified()->CheckedTaggedToFloat64();
333 } 346 }
334 } else if (output_rep == MachineRepresentation::kFloat32) { 347 } else if (output_rep == MachineRepresentation::kFloat32) {
335 op = machine()->ChangeFloat32ToFloat64(); 348 op = machine()->ChangeFloat32ToFloat64();
336 } 349 }
337 if (op == nullptr) { 350 if (op == nullptr) {
338 return TypeError(node, output_rep, output_type, 351 return TypeError(node, output_rep, output_type,
339 MachineRepresentation::kFloat64); 352 MachineRepresentation::kFloat64);
340 } 353 }
341 return jsgraph()->graph()->NewNode(op, node); 354 return InsertConversion(node, op, use_node);
342 } 355 }
343 356
344
345 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { 357 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
346 return jsgraph()->Int32Constant(DoubleToInt32(value)); 358 return jsgraph()->Int32Constant(DoubleToInt32(value));
347 } 359 }
348 360
349 Node* RepresentationChanger::GetWord32RepresentationFor( 361 Node* RepresentationChanger::GetWord32RepresentationFor(
350 Node* node, MachineRepresentation output_rep, Type* output_type, 362 Node* node, MachineRepresentation output_rep, Type* output_type,
351 Truncation truncation) { 363 Node* use_node, UseInfo use_info) {
352 // Eagerly fold representation changes for constants. 364 // Eagerly fold representation changes for constants.
353 switch (node->opcode()) { 365 // TODO(jarin) Properly fold constants in presence of type check.
354 case IrOpcode::kInt32Constant: 366 if (use_info.type_check() == TypeCheckKind::kNone) {
355 return node; // No change necessary. 367 switch (node->opcode()) {
356 case IrOpcode::kFloat32Constant: 368 case IrOpcode::kInt32Constant:
357 return MakeTruncatedInt32Constant(OpParameter<float>(node)); 369 return node; // No change necessary.
358 case IrOpcode::kNumberConstant: 370 case IrOpcode::kFloat32Constant:
359 case IrOpcode::kFloat64Constant: 371 return MakeTruncatedInt32Constant(OpParameter<float>(node));
360 return MakeTruncatedInt32Constant(OpParameter<double>(node)); 372 case IrOpcode::kNumberConstant:
361 default: 373 case IrOpcode::kFloat64Constant:
362 break; 374 return MakeTruncatedInt32Constant(OpParameter<double>(node));
375 default:
376 break;
377 }
363 } 378 }
379
364 // Select the correct X -> Word32 operator. 380 // Select the correct X -> Word32 operator.
365 const Operator* op = nullptr; 381 const Operator* op = nullptr;
366 if (output_rep == MachineRepresentation::kBit) { 382 if (output_rep == MachineRepresentation::kBit) {
367 return node; // Sloppy comparison -> word32 383 return node; // Sloppy comparison -> word32
368 } else if (output_rep == MachineRepresentation::kFloat64) { 384 } else if (output_rep == MachineRepresentation::kFloat64) {
369 if (output_type->Is(Type::Unsigned32())) { 385 if (output_type->Is(Type::Unsigned32())) {
370 op = machine()->ChangeFloat64ToUint32(); 386 op = machine()->ChangeFloat64ToUint32();
371 } else if (output_type->Is(Type::Signed32())) { 387 } else if (output_type->Is(Type::Signed32())) {
372 op = machine()->ChangeFloat64ToInt32(); 388 op = machine()->ChangeFloat64ToInt32();
373 } else if (truncation.TruncatesToWord32()) { 389 } else if (use_info.truncation().TruncatesToWord32()) {
374 op = machine()->TruncateFloat64ToWord32(); 390 op = machine()->TruncateFloat64ToWord32();
391 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
392 op = simplified()->CheckedFloat64ToInt32();
375 } 393 }
376 } else if (output_rep == MachineRepresentation::kFloat32) { 394 } else if (output_rep == MachineRepresentation::kFloat32) {
377 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 395 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
378 if (output_type->Is(Type::Unsigned32())) { 396 if (output_type->Is(Type::Unsigned32())) {
379 op = machine()->ChangeFloat64ToUint32(); 397 op = machine()->ChangeFloat64ToUint32();
380 } else if (output_type->Is(Type::Signed32())) { 398 } else if (output_type->Is(Type::Signed32())) {
381 op = machine()->ChangeFloat64ToInt32(); 399 op = machine()->ChangeFloat64ToInt32();
382 } else if (truncation.TruncatesToWord32()) { 400 } else if (use_info.truncation().TruncatesToWord32()) {
383 op = machine()->TruncateFloat64ToWord32(); 401 op = machine()->TruncateFloat64ToWord32();
402 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
403 op = simplified()->CheckedFloat64ToInt32();
384 } 404 }
385 } else if (output_rep == MachineRepresentation::kTagged) { 405 } else if (output_rep == MachineRepresentation::kTagged) {
386 if (output_type->Is(Type::TaggedSigned())) { 406 if (output_type->Is(Type::TaggedSigned())) {
387 op = simplified()->ChangeTaggedSignedToInt32(); 407 op = simplified()->ChangeTaggedSignedToInt32();
388 } else if (output_type->Is(Type::Unsigned32())) { 408 } else if (output_type->Is(Type::Unsigned32())) {
389 op = simplified()->ChangeTaggedToUint32(); 409 op = simplified()->ChangeTaggedToUint32();
390 } else if (output_type->Is(Type::Signed32())) { 410 } else if (output_type->Is(Type::Signed32())) {
391 op = simplified()->ChangeTaggedToInt32(); 411 op = simplified()->ChangeTaggedToInt32();
392 } else if (truncation.TruncatesToWord32()) { 412 } else if (use_info.truncation().TruncatesToWord32()) {
393 op = simplified()->TruncateTaggedToWord32(); 413 op = simplified()->TruncateTaggedToWord32();
414 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
415 op = simplified()->CheckedTaggedToInt32();
394 } 416 }
417 } else if (output_rep == MachineRepresentation::kWord32) {
418 // Only the checked case should get here, the non-checked case is
419 // handled in GetRepresentationFor.
420 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
421 if (output_type->Is(Type::Signed32())) {
422 return node;
423 } else if (output_type->Is(Type::Unsigned32())) {
424 op = simplified()->CheckedUint32ToInt32();
425 }
426 } else if (output_rep == MachineRepresentation::kWord8 ||
427 output_rep == MachineRepresentation::kWord16) {
428 DCHECK(use_info.representation() == MachineRepresentation::kWord32);
429 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
430 return node;
395 } 431 }
432
396 if (op == nullptr) { 433 if (op == nullptr) {
397 return TypeError(node, output_rep, output_type, 434 return TypeError(node, output_rep, output_type,
398 MachineRepresentation::kWord32); 435 MachineRepresentation::kWord32);
399 } 436 }
437 return InsertConversion(node, op, use_node);
438 }
439
440 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
441 Node* use_node) {
442 if (op->ControlInputCount() > 0) {
443 // If the operator can deoptimize (which means it has control
444 // input), we need to connect it to the effect and control chains
445 // and also provide it with a frame state.
446 Node* effect = NodeProperties::GetEffectInput(use_node);
447 Node* control = NodeProperties::GetControlInput(use_node);
448 Node* frame_state = NodeProperties::GetFrameStateInput(use_node, 0);
449 Node* conversion =
450 jsgraph()->graph()->NewNode(op, node, frame_state, effect, control);
451 NodeProperties::ReplaceControlInput(use_node, control);
452 NodeProperties::ReplaceEffectInput(use_node, effect);
453 return conversion;
454 }
400 return jsgraph()->graph()->NewNode(op, node); 455 return jsgraph()->graph()->NewNode(op, node);
401 } 456 }
402 457
403 458
404 Node* RepresentationChanger::GetBitRepresentationFor( 459 Node* RepresentationChanger::GetBitRepresentationFor(
405 Node* node, MachineRepresentation output_rep, Type* output_type) { 460 Node* node, MachineRepresentation output_rep, Type* output_type) {
406 // Eagerly fold representation changes for constants. 461 // Eagerly fold representation changes for constants.
407 switch (node->opcode()) { 462 switch (node->opcode()) {
408 case IrOpcode::kHeapConstant: { 463 case IrOpcode::kHeapConstant: {
409 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); 464 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
410 DCHECK(value.is_identical_to(factory()->true_value()) || 465 DCHECK(value.is_identical_to(factory()->true_value()) ||
411 value.is_identical_to(factory()->false_value())); 466 value.is_identical_to(factory()->false_value()));
412 return jsgraph()->Int32Constant( 467 return jsgraph()->Int32Constant(
413 value.is_identical_to(factory()->true_value()) ? 1 : 0); 468 value.is_identical_to(factory()->true_value()) ? 1 : 0);
414 } 469 }
415 default: 470 default:
416 break; 471 break;
417 } 472 }
418 // Select the correct X -> Bit operator. 473 // Select the correct X -> Bit operator.
419 const Operator* op; 474 const Operator* op;
420 if (output_rep == MachineRepresentation::kTagged) { 475 if (output_rep == MachineRepresentation::kTagged) {
421 op = simplified()->ChangeTaggedToBit(); 476 op = simplified()->ChangeTaggedToBit();
422 } else { 477 } else {
423 return TypeError(node, output_rep, output_type, 478 return TypeError(node, output_rep, output_type,
424 MachineRepresentation::kBit); 479 MachineRepresentation::kBit);
425 } 480 }
426 return jsgraph()->graph()->NewNode(op, node); 481 return jsgraph()->graph()->NewNode(op, node);
427 } 482 }
428 483
429
430 Node* RepresentationChanger::GetWord64RepresentationFor( 484 Node* RepresentationChanger::GetWord64RepresentationFor(
431 Node* node, MachineRepresentation output_rep, Type* output_type) { 485 Node* node, MachineRepresentation output_rep, Type* output_type) {
432 if (output_rep == MachineRepresentation::kBit) { 486 if (output_rep == MachineRepresentation::kBit) {
433 return node; // Sloppy comparison -> word64 487 return node; // Sloppy comparison -> word64
434 } 488 }
435 // Can't really convert Word64 to anything else. Purported to be internal. 489 // Can't really convert Word64 to anything else. Purported to be internal.
436 return TypeError(node, output_rep, output_type, 490 return TypeError(node, output_rep, output_type,
437 MachineRepresentation::kWord64); 491 MachineRepresentation::kWord64);
438 } 492 }
439 493
494 Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
495 Node* node, MachineRepresentation output_rep, Type* output_type,
496 Node* use_node, Truncation truncation, TypeCheckKind check) {
497 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant
498 // does not pass the check).
499
500 // If the input is already Signed32 in Word32 representation, we do not
501 // have to do anything. (We could fold this into the big if below, but
502 // it feels nicer to have the shortcut return first).
503 if (output_rep == MachineRepresentation::kWord32 ||
504 output_type->Is(Type::Signed32())) {
505 return node;
506 }
507
508 // Select the correct X -> Word32 operator.
509 const Operator* op = nullptr;
510 if (output_rep == MachineRepresentation::kWord32) {
511 if (output_type->Is(Type::Unsigned32())) {
512 op = simplified()->CheckedUint32ToInt32();
513 }
514 } else if (output_rep == MachineRepresentation::kBit) {
515 return node; // Sloppy comparison -> word32
516 } else if (output_rep == MachineRepresentation::kFloat64) {
517 if (output_type->Is(Type::Unsigned32())) {
518 op = machine()->ChangeFloat64ToUint32();
519 } else if (output_type->Is(Type::Signed32())) {
520 op = machine()->ChangeFloat64ToInt32();
521 } else if (truncation.TruncatesToWord32()) {
522 op = machine()->TruncateFloat64ToWord32();
523 } else if (check == TypeCheckKind::kSigned32) {
524 op = simplified()->CheckedFloat64ToInt32();
525 }
526 } else if (output_rep == MachineRepresentation::kFloat32) {
527 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
528 if (output_type->Is(Type::Unsigned32())) {
529 op = machine()->ChangeFloat64ToUint32();
530 } else if (output_type->Is(Type::Signed32())) {
531 op = machine()->ChangeFloat64ToInt32();
532 } else if (truncation.TruncatesToWord32()) {
533 op = machine()->TruncateFloat64ToWord32();
534 } else if (check == TypeCheckKind::kSigned32) {
535 op = simplified()->CheckedFloat64ToInt32();
536 }
537 } else if (output_rep == MachineRepresentation::kTagged) {
538 if (output_type->Is(Type::TaggedSigned())) {
539 op = simplified()->ChangeTaggedSignedToInt32();
540 } else if (output_type->Is(Type::Unsigned32())) {
541 op = simplified()->ChangeTaggedToUint32();
542 } else if (output_type->Is(Type::Signed32())) {
543 op = simplified()->ChangeTaggedToInt32();
544 } else if (truncation.TruncatesToWord32()) {
545 op = simplified()->TruncateTaggedToWord32();
546 } else if (check == TypeCheckKind::kSigned32) {
547 op = simplified()->CheckedTaggedToInt32();
548 }
549 }
550 if (op == nullptr) {
551 return TypeError(node, output_rep, output_type,
552 MachineRepresentation::kWord32);
553 }
554 if (op->ControlInputCount() > 0) {
555 // If the operator can deoptimize (which means it has control
556 // input), we need to connect it to the effect and control chains
557 // and also provide it with a frame state.
558 UNIMPLEMENTED();
559 }
560 return jsgraph()->graph()->NewNode(op, node);
561 }
440 562
441 const Operator* RepresentationChanger::Int32OperatorFor( 563 const Operator* RepresentationChanger::Int32OperatorFor(
442 IrOpcode::Value opcode) { 564 IrOpcode::Value opcode) {
443 switch (opcode) { 565 switch (opcode) {
566 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
444 case IrOpcode::kNumberAdd: 567 case IrOpcode::kNumberAdd:
445 return machine()->Int32Add(); 568 return machine()->Int32Add();
569 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
446 case IrOpcode::kNumberSubtract: 570 case IrOpcode::kNumberSubtract:
447 return machine()->Int32Sub(); 571 return machine()->Int32Sub();
448 case IrOpcode::kNumberMultiply: 572 case IrOpcode::kNumberMultiply:
449 return machine()->Int32Mul(); 573 return machine()->Int32Mul();
450 case IrOpcode::kNumberDivide: 574 case IrOpcode::kNumberDivide:
451 return machine()->Int32Div(); 575 return machine()->Int32Div();
452 case IrOpcode::kNumberModulus: 576 case IrOpcode::kNumberModulus:
453 return machine()->Int32Mod(); 577 return machine()->Int32Mod();
454 case IrOpcode::kNumberBitwiseOr: 578 case IrOpcode::kNumberBitwiseOr:
455 return machine()->Word32Or(); 579 return machine()->Word32Or();
456 case IrOpcode::kNumberBitwiseXor: 580 case IrOpcode::kNumberBitwiseXor:
457 return machine()->Word32Xor(); 581 return machine()->Word32Xor();
458 case IrOpcode::kNumberBitwiseAnd: 582 case IrOpcode::kNumberBitwiseAnd:
459 return machine()->Word32And(); 583 return machine()->Word32And();
460 case IrOpcode::kNumberEqual: 584 case IrOpcode::kNumberEqual:
461 return machine()->Word32Equal(); 585 return machine()->Word32Equal();
462 case IrOpcode::kNumberLessThan: 586 case IrOpcode::kNumberLessThan:
463 return machine()->Int32LessThan(); 587 return machine()->Int32LessThan();
464 case IrOpcode::kNumberLessThanOrEqual: 588 case IrOpcode::kNumberLessThanOrEqual:
465 return machine()->Int32LessThanOrEqual(); 589 return machine()->Int32LessThanOrEqual();
466 default: 590 default:
467 UNREACHABLE(); 591 UNREACHABLE();
468 return nullptr; 592 return nullptr;
469 } 593 }
470 } 594 }
471 595
596 const Operator* RepresentationChanger::Int32OverflowOperatorFor(
597 IrOpcode::Value opcode) {
598 switch (opcode) {
599 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
600 return machine()->Int32AddWithOverflow();
601 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
602 return machine()->Int32SubWithOverflow();
603 default:
604 UNREACHABLE();
605 return nullptr;
606 }
607 }
472 608
473 const Operator* RepresentationChanger::Uint32OperatorFor( 609 const Operator* RepresentationChanger::Uint32OperatorFor(
474 IrOpcode::Value opcode) { 610 IrOpcode::Value opcode) {
475 switch (opcode) { 611 switch (opcode) {
476 case IrOpcode::kNumberAdd: 612 case IrOpcode::kNumberAdd:
477 return machine()->Int32Add(); 613 return machine()->Int32Add();
478 case IrOpcode::kNumberSubtract: 614 case IrOpcode::kNumberSubtract:
479 return machine()->Int32Sub(); 615 return machine()->Int32Sub();
480 case IrOpcode::kNumberMultiply: 616 case IrOpcode::kNumberMultiply:
481 return machine()->Int32Mul(); 617 return machine()->Int32Mul();
(...skipping 14 matching lines...) Expand all
496 default: 632 default:
497 UNREACHABLE(); 633 UNREACHABLE();
498 return nullptr; 634 return nullptr;
499 } 635 }
500 } 636 }
501 637
502 638
503 const Operator* RepresentationChanger::Float64OperatorFor( 639 const Operator* RepresentationChanger::Float64OperatorFor(
504 IrOpcode::Value opcode) { 640 IrOpcode::Value opcode) {
505 switch (opcode) { 641 switch (opcode) {
642 case IrOpcode::kSpeculativeNumberAdd:
506 case IrOpcode::kNumberAdd: 643 case IrOpcode::kNumberAdd:
507 return machine()->Float64Add(); 644 return machine()->Float64Add();
645 case IrOpcode::kSpeculativeNumberSubtract:
508 case IrOpcode::kNumberSubtract: 646 case IrOpcode::kNumberSubtract:
509 return machine()->Float64Sub(); 647 return machine()->Float64Sub();
510 case IrOpcode::kNumberMultiply: 648 case IrOpcode::kNumberMultiply:
511 return machine()->Float64Mul(); 649 return machine()->Float64Mul();
512 case IrOpcode::kNumberDivide: 650 case IrOpcode::kNumberDivide:
513 return machine()->Float64Div(); 651 return machine()->Float64Div();
514 case IrOpcode::kNumberModulus: 652 case IrOpcode::kNumberModulus:
515 return machine()->Float64Mod(); 653 return machine()->Float64Mod();
516 case IrOpcode::kNumberEqual: 654 case IrOpcode::kNumberEqual:
517 return machine()->Float64Equal(); 655 return machine()->Float64Equal();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 } 706 }
569 707
570 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { 708 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
571 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), 709 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
572 node); 710 node);
573 } 711 }
574 712
575 } // namespace compiler 713 } // namespace compiler
576 } // namespace internal 714 } // namespace internal
577 } // namespace v8 715 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698