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

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: Rebase 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
« no previous file with comments | « src/compiler/representation-change.h ('k') | src/compiler/simplified-lowering.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 } else if (output_rep == MachineRepresentation::kFloat64) { 291 } else if (output_rep == MachineRepresentation::kFloat64) {
284 op = machine()->TruncateFloat64ToFloat32(); 292 op = machine()->TruncateFloat64ToFloat32();
285 } 293 }
286 if (op == nullptr) { 294 if (op == nullptr) {
287 return TypeError(node, output_rep, output_type, 295 return TypeError(node, output_rep, output_type,
288 MachineRepresentation::kFloat32); 296 MachineRepresentation::kFloat32);
289 } 297 }
290 return jsgraph()->graph()->NewNode(op, node); 298 return jsgraph()->graph()->NewNode(op, node);
291 } 299 }
292 300
293
294 Node* RepresentationChanger::GetFloat64RepresentationFor( 301 Node* RepresentationChanger::GetFloat64RepresentationFor(
295 Node* node, MachineRepresentation output_rep, Type* output_type, 302 Node* node, MachineRepresentation output_rep, Type* output_type,
296 Truncation truncation) { 303 Node* use_node, UseInfo use_info) {
297 // Eagerly fold representation changes for constants. 304 // Eagerly fold representation changes for constants.
298 switch (node->opcode()) { 305 if ((use_info.type_check() == TypeCheckKind::kNone)) {
299 case IrOpcode::kNumberConstant: 306 // TODO(jarin) Handle checked constant conversions.
300 return jsgraph()->Float64Constant(OpParameter<double>(node)); 307 switch (node->opcode()) {
301 case IrOpcode::kInt32Constant: 308 case IrOpcode::kNumberConstant:
302 if (output_type->Is(Type::Signed32())) { 309 return jsgraph()->Float64Constant(OpParameter<double>(node));
303 int32_t value = OpParameter<int32_t>(node); 310 case IrOpcode::kInt32Constant:
304 return jsgraph()->Float64Constant(value); 311 if (output_type->Is(Type::Signed32())) {
305 } else { 312 int32_t value = OpParameter<int32_t>(node);
306 DCHECK(output_type->Is(Type::Unsigned32())); 313 return jsgraph()->Float64Constant(value);
307 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); 314 } else {
308 return jsgraph()->Float64Constant(static_cast<double>(value)); 315 DCHECK(output_type->Is(Type::Unsigned32()));
309 } 316 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
310 case IrOpcode::kFloat64Constant: 317 return jsgraph()->Float64Constant(static_cast<double>(value));
311 return node; // No change necessary. 318 }
312 case IrOpcode::kFloat32Constant: 319 case IrOpcode::kFloat64Constant:
313 return jsgraph()->Float64Constant(OpParameter<float>(node)); 320 return node; // No change necessary.
314 default: 321 case IrOpcode::kFloat32Constant:
315 break; 322 return jsgraph()->Float64Constant(OpParameter<float>(node));
323 default:
324 break;
325 }
316 } 326 }
317 // Select the correct X -> Float64 operator. 327 // Select the correct X -> Float64 operator.
318 const Operator* op = nullptr; 328 const Operator* op = nullptr;
319 if (IsWord(output_rep)) { 329 if (IsWord(output_rep)) {
320 if (output_type->Is(Type::Signed32())) { 330 if (output_type->Is(Type::Signed32())) {
321 op = machine()->ChangeInt32ToFloat64(); 331 op = machine()->ChangeInt32ToFloat64();
322 } else if (output_type->Is(Type::Unsigned32()) || 332 } else if (output_type->Is(Type::Unsigned32()) ||
323 truncation.TruncatesToWord32()) { 333 use_info.truncation().TruncatesToWord32()) {
324 // Either the output is uint32 or the uses only care about the 334 // Either the output is uint32 or the uses only care about the
325 // low 32 bits (so we can pick uint32 safely). 335 // low 32 bits (so we can pick uint32 safely).
326 op = machine()->ChangeUint32ToFloat64(); 336 op = machine()->ChangeUint32ToFloat64();
327 } 337 }
328 } else if (output_rep == MachineRepresentation::kTagged) { 338 } else if (output_rep == MachineRepresentation::kTagged) {
329 if (output_type->Is(Type::Undefined())) { 339 if (output_type->Is(Type::Undefined())) {
330 return jsgraph()->Float64Constant( 340 return jsgraph()->Float64Constant(
331 std::numeric_limits<double>::quiet_NaN()); 341 std::numeric_limits<double>::quiet_NaN());
332 } else if (output_type->Is(Type::TaggedSigned())) { 342 } else if (output_type->Is(Type::TaggedSigned())) {
333 node = InsertChangeTaggedSignedToInt32(node); 343 node = InsertChangeTaggedSignedToInt32(node);
334 op = machine()->ChangeInt32ToFloat64(); 344 op = machine()->ChangeInt32ToFloat64();
335 } else if (output_type->Is(Type::Number())) { 345 } else if (output_type->Is(Type::Number())) {
336 op = simplified()->ChangeTaggedToFloat64(); 346 op = simplified()->ChangeTaggedToFloat64();
337 } else if (output_type->Is(Type::NumberOrUndefined())) { 347 } else if (output_type->Is(Type::NumberOrUndefined())) {
348 // TODO(jarin) Here we should check that truncation is Number.
338 op = simplified()->TruncateTaggedToFloat64(); 349 op = simplified()->TruncateTaggedToFloat64();
350 } else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) {
351 op = simplified()->CheckedTaggedToFloat64();
339 } 352 }
340 } else if (output_rep == MachineRepresentation::kFloat32) { 353 } else if (output_rep == MachineRepresentation::kFloat32) {
341 op = machine()->ChangeFloat32ToFloat64(); 354 op = machine()->ChangeFloat32ToFloat64();
342 } 355 }
343 if (op == nullptr) { 356 if (op == nullptr) {
344 return TypeError(node, output_rep, output_type, 357 return TypeError(node, output_rep, output_type,
345 MachineRepresentation::kFloat64); 358 MachineRepresentation::kFloat64);
346 } 359 }
347 return jsgraph()->graph()->NewNode(op, node); 360 return InsertConversion(node, op, use_node);
348 } 361 }
349 362
350
351 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) { 363 Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
352 return jsgraph()->Int32Constant(DoubleToInt32(value)); 364 return jsgraph()->Int32Constant(DoubleToInt32(value));
353 } 365 }
354 366
355 Node* RepresentationChanger::GetWord32RepresentationFor( 367 Node* RepresentationChanger::GetWord32RepresentationFor(
356 Node* node, MachineRepresentation output_rep, Type* output_type, 368 Node* node, MachineRepresentation output_rep, Type* output_type,
357 Truncation truncation) { 369 Node* use_node, UseInfo use_info) {
358 // Eagerly fold representation changes for constants. 370 // Eagerly fold representation changes for constants.
359 switch (node->opcode()) { 371 // TODO(jarin) Properly fold constants in presence of type check.
360 case IrOpcode::kInt32Constant: 372 if (use_info.type_check() == TypeCheckKind::kNone) {
361 return node; // No change necessary. 373 switch (node->opcode()) {
362 case IrOpcode::kFloat32Constant: 374 case IrOpcode::kInt32Constant:
363 return MakeTruncatedInt32Constant(OpParameter<float>(node)); 375 return node; // No change necessary.
364 case IrOpcode::kNumberConstant: 376 case IrOpcode::kFloat32Constant:
365 case IrOpcode::kFloat64Constant: 377 return MakeTruncatedInt32Constant(OpParameter<float>(node));
366 return MakeTruncatedInt32Constant(OpParameter<double>(node)); 378 case IrOpcode::kNumberConstant:
367 default: 379 case IrOpcode::kFloat64Constant:
368 break; 380 return MakeTruncatedInt32Constant(OpParameter<double>(node));
381 default:
382 break;
383 }
369 } 384 }
385
370 // Select the correct X -> Word32 operator. 386 // Select the correct X -> Word32 operator.
371 const Operator* op = nullptr; 387 const Operator* op = nullptr;
372 if (output_rep == MachineRepresentation::kBit) { 388 if (output_rep == MachineRepresentation::kBit) {
373 return node; // Sloppy comparison -> word32 389 return node; // Sloppy comparison -> word32
374 } else if (output_rep == MachineRepresentation::kFloat64) { 390 } else if (output_rep == MachineRepresentation::kFloat64) {
375 if (output_type->Is(Type::Unsigned32())) { 391 if (output_type->Is(Type::Unsigned32())) {
376 op = machine()->ChangeFloat64ToUint32(); 392 op = machine()->ChangeFloat64ToUint32();
377 } else if (output_type->Is(Type::Signed32())) { 393 } else if (output_type->Is(Type::Signed32())) {
378 op = machine()->ChangeFloat64ToInt32(); 394 op = machine()->ChangeFloat64ToInt32();
379 } else if (truncation.TruncatesToWord32()) { 395 } else if (use_info.truncation().TruncatesToWord32()) {
380 op = machine()->TruncateFloat64ToWord32(); 396 op = machine()->TruncateFloat64ToWord32();
397 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
398 op = simplified()->CheckedFloat64ToInt32();
381 } 399 }
382 } else if (output_rep == MachineRepresentation::kFloat32) { 400 } else if (output_rep == MachineRepresentation::kFloat32) {
383 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32 401 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
384 if (output_type->Is(Type::Unsigned32())) { 402 if (output_type->Is(Type::Unsigned32())) {
385 op = machine()->ChangeFloat64ToUint32(); 403 op = machine()->ChangeFloat64ToUint32();
386 } else if (output_type->Is(Type::Signed32())) { 404 } else if (output_type->Is(Type::Signed32())) {
387 op = machine()->ChangeFloat64ToInt32(); 405 op = machine()->ChangeFloat64ToInt32();
388 } else if (truncation.TruncatesToWord32()) { 406 } else if (use_info.truncation().TruncatesToWord32()) {
389 op = machine()->TruncateFloat64ToWord32(); 407 op = machine()->TruncateFloat64ToWord32();
408 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
409 op = simplified()->CheckedFloat64ToInt32();
390 } 410 }
391 } else if (output_rep == MachineRepresentation::kTagged) { 411 } else if (output_rep == MachineRepresentation::kTagged) {
392 if (output_type->Is(Type::TaggedSigned())) { 412 if (output_type->Is(Type::TaggedSigned())) {
393 op = simplified()->ChangeTaggedSignedToInt32(); 413 op = simplified()->ChangeTaggedSignedToInt32();
394 } else if (output_type->Is(Type::Unsigned32())) { 414 } else if (output_type->Is(Type::Unsigned32())) {
395 op = simplified()->ChangeTaggedToUint32(); 415 op = simplified()->ChangeTaggedToUint32();
396 } else if (output_type->Is(Type::Signed32())) { 416 } else if (output_type->Is(Type::Signed32())) {
397 op = simplified()->ChangeTaggedToInt32(); 417 op = simplified()->ChangeTaggedToInt32();
398 } else if (truncation.TruncatesToWord32()) { 418 } else if (use_info.truncation().TruncatesToWord32()) {
399 op = simplified()->TruncateTaggedToWord32(); 419 op = simplified()->TruncateTaggedToWord32();
420 } else if (use_info.type_check() == TypeCheckKind::kSigned32) {
421 op = simplified()->CheckedTaggedToInt32();
400 } 422 }
423 } else if (output_rep == MachineRepresentation::kWord32) {
424 // Only the checked case should get here, the non-checked case is
425 // handled in GetRepresentationFor.
426 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
427 if (output_type->Is(Type::Signed32())) {
428 return node;
429 } else if (output_type->Is(Type::Unsigned32())) {
430 op = simplified()->CheckedUint32ToInt32();
431 }
432 } else if (output_rep == MachineRepresentation::kWord8 ||
433 output_rep == MachineRepresentation::kWord16) {
434 DCHECK(use_info.representation() == MachineRepresentation::kWord32);
435 DCHECK(use_info.type_check() == TypeCheckKind::kSigned32);
436 return node;
401 } 437 }
438
402 if (op == nullptr) { 439 if (op == nullptr) {
403 return TypeError(node, output_rep, output_type, 440 return TypeError(node, output_rep, output_type,
404 MachineRepresentation::kWord32); 441 MachineRepresentation::kWord32);
405 } 442 }
443 return InsertConversion(node, op, use_node);
444 }
445
446 Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
447 Node* use_node) {
448 if (op->ControlInputCount() > 0) {
449 // If the operator can deoptimize (which means it has control
450 // input), we need to connect it to the effect and control chains
451 // and also provide it with a frame state.
452 Node* effect = NodeProperties::GetEffectInput(use_node);
453 Node* control = NodeProperties::GetControlInput(use_node);
454 Node* frame_state = NodeProperties::GetFrameStateInput(use_node, 0);
455 Node* conversion =
456 jsgraph()->graph()->NewNode(op, node, frame_state, effect, control);
457 NodeProperties::ReplaceControlInput(use_node, control);
458 NodeProperties::ReplaceEffectInput(use_node, effect);
459 return conversion;
460 }
406 return jsgraph()->graph()->NewNode(op, node); 461 return jsgraph()->graph()->NewNode(op, node);
407 } 462 }
408 463
409 464
410 Node* RepresentationChanger::GetBitRepresentationFor( 465 Node* RepresentationChanger::GetBitRepresentationFor(
411 Node* node, MachineRepresentation output_rep, Type* output_type) { 466 Node* node, MachineRepresentation output_rep, Type* output_type) {
412 // Eagerly fold representation changes for constants. 467 // Eagerly fold representation changes for constants.
413 switch (node->opcode()) { 468 switch (node->opcode()) {
414 case IrOpcode::kHeapConstant: { 469 case IrOpcode::kHeapConstant: {
415 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node); 470 Handle<HeapObject> value = OpParameter<Handle<HeapObject>>(node);
416 DCHECK(value.is_identical_to(factory()->true_value()) || 471 DCHECK(value.is_identical_to(factory()->true_value()) ||
417 value.is_identical_to(factory()->false_value())); 472 value.is_identical_to(factory()->false_value()));
418 return jsgraph()->Int32Constant( 473 return jsgraph()->Int32Constant(
419 value.is_identical_to(factory()->true_value()) ? 1 : 0); 474 value.is_identical_to(factory()->true_value()) ? 1 : 0);
420 } 475 }
421 default: 476 default:
422 break; 477 break;
423 } 478 }
424 // Select the correct X -> Bit operator. 479 // Select the correct X -> Bit operator.
425 const Operator* op; 480 const Operator* op;
426 if (output_rep == MachineRepresentation::kTagged) { 481 if (output_rep == MachineRepresentation::kTagged) {
427 op = simplified()->ChangeTaggedToBit(); 482 op = simplified()->ChangeTaggedToBit();
428 } else { 483 } else {
429 return TypeError(node, output_rep, output_type, 484 return TypeError(node, output_rep, output_type,
430 MachineRepresentation::kBit); 485 MachineRepresentation::kBit);
431 } 486 }
432 return jsgraph()->graph()->NewNode(op, node); 487 return jsgraph()->graph()->NewNode(op, node);
433 } 488 }
434 489
435
436 Node* RepresentationChanger::GetWord64RepresentationFor( 490 Node* RepresentationChanger::GetWord64RepresentationFor(
437 Node* node, MachineRepresentation output_rep, Type* output_type) { 491 Node* node, MachineRepresentation output_rep, Type* output_type) {
438 if (output_rep == MachineRepresentation::kBit) { 492 if (output_rep == MachineRepresentation::kBit) {
439 return node; // Sloppy comparison -> word64 493 return node; // Sloppy comparison -> word64
440 } 494 }
441 // Can't really convert Word64 to anything else. Purported to be internal. 495 // Can't really convert Word64 to anything else. Purported to be internal.
442 return TypeError(node, output_rep, output_type, 496 return TypeError(node, output_rep, output_type,
443 MachineRepresentation::kWord64); 497 MachineRepresentation::kWord64);
444 } 498 }
445 499
500 Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
501 Node* node, MachineRepresentation output_rep, Type* output_type,
502 Node* use_node, Truncation truncation, TypeCheckKind check) {
503 // TODO(jarin) Eagerly fold constants (or insert hard deopt if the constant
504 // does not pass the check).
505
506 // If the input is already Signed32 in Word32 representation, we do not
507 // have to do anything. (We could fold this into the big if below, but
508 // it feels nicer to have the shortcut return first).
509 if (output_rep == MachineRepresentation::kWord32 ||
510 output_type->Is(Type::Signed32())) {
511 return node;
512 }
513
514 // Select the correct X -> Word32 operator.
515 const Operator* op = nullptr;
516 if (output_rep == MachineRepresentation::kWord32) {
517 if (output_type->Is(Type::Unsigned32())) {
518 op = simplified()->CheckedUint32ToInt32();
519 }
520 } else if (output_rep == MachineRepresentation::kBit) {
521 return node; // Sloppy comparison -> word32
522 } else if (output_rep == MachineRepresentation::kFloat64) {
523 if (output_type->Is(Type::Unsigned32())) {
524 op = machine()->ChangeFloat64ToUint32();
525 } else if (output_type->Is(Type::Signed32())) {
526 op = machine()->ChangeFloat64ToInt32();
527 } else if (truncation.TruncatesToWord32()) {
528 op = machine()->TruncateFloat64ToWord32();
529 } else if (check == TypeCheckKind::kSigned32) {
530 op = simplified()->CheckedFloat64ToInt32();
531 }
532 } else if (output_rep == MachineRepresentation::kFloat32) {
533 node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
534 if (output_type->Is(Type::Unsigned32())) {
535 op = machine()->ChangeFloat64ToUint32();
536 } else if (output_type->Is(Type::Signed32())) {
537 op = machine()->ChangeFloat64ToInt32();
538 } else if (truncation.TruncatesToWord32()) {
539 op = machine()->TruncateFloat64ToWord32();
540 } else if (check == TypeCheckKind::kSigned32) {
541 op = simplified()->CheckedFloat64ToInt32();
542 }
543 } else if (output_rep == MachineRepresentation::kTagged) {
544 if (output_type->Is(Type::TaggedSigned())) {
545 op = simplified()->ChangeTaggedSignedToInt32();
546 } else if (output_type->Is(Type::Unsigned32())) {
547 op = simplified()->ChangeTaggedToUint32();
548 } else if (output_type->Is(Type::Signed32())) {
549 op = simplified()->ChangeTaggedToInt32();
550 } else if (truncation.TruncatesToWord32()) {
551 op = simplified()->TruncateTaggedToWord32();
552 } else if (check == TypeCheckKind::kSigned32) {
553 op = simplified()->CheckedTaggedToInt32();
554 }
555 }
556 if (op == nullptr) {
557 return TypeError(node, output_rep, output_type,
558 MachineRepresentation::kWord32);
559 }
560 if (op->ControlInputCount() > 0) {
561 // If the operator can deoptimize (which means it has control
562 // input), we need to connect it to the effect and control chains
563 // and also provide it with a frame state.
564 UNIMPLEMENTED();
565 }
566 return jsgraph()->graph()->NewNode(op, node);
567 }
446 568
447 const Operator* RepresentationChanger::Int32OperatorFor( 569 const Operator* RepresentationChanger::Int32OperatorFor(
448 IrOpcode::Value opcode) { 570 IrOpcode::Value opcode) {
449 switch (opcode) { 571 switch (opcode) {
572 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
450 case IrOpcode::kNumberAdd: 573 case IrOpcode::kNumberAdd:
451 return machine()->Int32Add(); 574 return machine()->Int32Add();
575 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
452 case IrOpcode::kNumberSubtract: 576 case IrOpcode::kNumberSubtract:
453 return machine()->Int32Sub(); 577 return machine()->Int32Sub();
454 case IrOpcode::kNumberMultiply: 578 case IrOpcode::kNumberMultiply:
455 return machine()->Int32Mul(); 579 return machine()->Int32Mul();
456 case IrOpcode::kNumberDivide: 580 case IrOpcode::kNumberDivide:
457 return machine()->Int32Div(); 581 return machine()->Int32Div();
458 case IrOpcode::kNumberModulus: 582 case IrOpcode::kNumberModulus:
459 return machine()->Int32Mod(); 583 return machine()->Int32Mod();
460 case IrOpcode::kNumberBitwiseOr: 584 case IrOpcode::kNumberBitwiseOr:
461 return machine()->Word32Or(); 585 return machine()->Word32Or();
462 case IrOpcode::kNumberBitwiseXor: 586 case IrOpcode::kNumberBitwiseXor:
463 return machine()->Word32Xor(); 587 return machine()->Word32Xor();
464 case IrOpcode::kNumberBitwiseAnd: 588 case IrOpcode::kNumberBitwiseAnd:
465 return machine()->Word32And(); 589 return machine()->Word32And();
466 case IrOpcode::kNumberEqual: 590 case IrOpcode::kNumberEqual:
467 return machine()->Word32Equal(); 591 return machine()->Word32Equal();
468 case IrOpcode::kNumberLessThan: 592 case IrOpcode::kNumberLessThan:
469 return machine()->Int32LessThan(); 593 return machine()->Int32LessThan();
470 case IrOpcode::kNumberLessThanOrEqual: 594 case IrOpcode::kNumberLessThanOrEqual:
471 return machine()->Int32LessThanOrEqual(); 595 return machine()->Int32LessThanOrEqual();
472 default: 596 default:
473 UNREACHABLE(); 597 UNREACHABLE();
474 return nullptr; 598 return nullptr;
475 } 599 }
476 } 600 }
477 601
602 const Operator* RepresentationChanger::Int32OverflowOperatorFor(
603 IrOpcode::Value opcode) {
604 switch (opcode) {
605 case IrOpcode::kSpeculativeNumberAdd: // Fall through.
606 return machine()->Int32AddWithOverflow();
607 case IrOpcode::kSpeculativeNumberSubtract: // Fall through.
608 return machine()->Int32SubWithOverflow();
609 default:
610 UNREACHABLE();
611 return nullptr;
612 }
613 }
478 614
479 const Operator* RepresentationChanger::Uint32OperatorFor( 615 const Operator* RepresentationChanger::Uint32OperatorFor(
480 IrOpcode::Value opcode) { 616 IrOpcode::Value opcode) {
481 switch (opcode) { 617 switch (opcode) {
482 case IrOpcode::kNumberAdd: 618 case IrOpcode::kNumberAdd:
483 return machine()->Int32Add(); 619 return machine()->Int32Add();
484 case IrOpcode::kNumberSubtract: 620 case IrOpcode::kNumberSubtract:
485 return machine()->Int32Sub(); 621 return machine()->Int32Sub();
486 case IrOpcode::kNumberMultiply: 622 case IrOpcode::kNumberMultiply:
487 return machine()->Int32Mul(); 623 return machine()->Int32Mul();
(...skipping 14 matching lines...) Expand all
502 default: 638 default:
503 UNREACHABLE(); 639 UNREACHABLE();
504 return nullptr; 640 return nullptr;
505 } 641 }
506 } 642 }
507 643
508 644
509 const Operator* RepresentationChanger::Float64OperatorFor( 645 const Operator* RepresentationChanger::Float64OperatorFor(
510 IrOpcode::Value opcode) { 646 IrOpcode::Value opcode) {
511 switch (opcode) { 647 switch (opcode) {
648 case IrOpcode::kSpeculativeNumberAdd:
512 case IrOpcode::kNumberAdd: 649 case IrOpcode::kNumberAdd:
513 return machine()->Float64Add(); 650 return machine()->Float64Add();
651 case IrOpcode::kSpeculativeNumberSubtract:
514 case IrOpcode::kNumberSubtract: 652 case IrOpcode::kNumberSubtract:
515 return machine()->Float64Sub(); 653 return machine()->Float64Sub();
516 case IrOpcode::kNumberMultiply: 654 case IrOpcode::kNumberMultiply:
517 return machine()->Float64Mul(); 655 return machine()->Float64Mul();
518 case IrOpcode::kNumberDivide: 656 case IrOpcode::kNumberDivide:
519 return machine()->Float64Div(); 657 return machine()->Float64Div();
520 case IrOpcode::kNumberModulus: 658 case IrOpcode::kNumberModulus:
521 return machine()->Float64Mod(); 659 return machine()->Float64Mod();
522 case IrOpcode::kNumberEqual: 660 case IrOpcode::kNumberEqual:
523 return machine()->Float64Equal(); 661 return machine()->Float64Equal();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 } 712 }
575 713
576 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { 714 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) {
577 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), 715 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
578 node); 716 node);
579 } 717 }
580 718
581 } // namespace compiler 719 } // namespace compiler
582 } // namespace internal 720 } // namespace internal
583 } // namespace v8 721 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/representation-change.h ('k') | src/compiler/simplified-lowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698