OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |