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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 // Both are words less than or equal to 32-bits. | 135 // Both are words less than or equal to 32-bits. |
136 // Since loads of integers from memory implicitly sign or zero extend the | 136 // Since loads of integers from memory implicitly sign or zero extend the |
137 // value to the full machine word size and stores implicitly truncate, | 137 // value to the full machine word size and stores implicitly truncate, |
138 // no representation change is necessary. | 138 // no representation change is necessary. |
139 return node; | 139 return node; |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 switch (use_info.representation()) { | 143 switch (use_info.representation()) { |
144 case MachineRepresentation::kTaggedSigned: | 144 case MachineRepresentation::kTaggedSigned: |
| 145 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 146 return GetTaggedSignedRepresentationFor(node, output_rep, output_type); |
145 case MachineRepresentation::kTaggedPointer: | 147 case MachineRepresentation::kTaggedPointer: |
| 148 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
| 149 return GetTaggedPointerRepresentationFor(node, output_rep, output_type); |
146 case MachineRepresentation::kTagged: | 150 case MachineRepresentation::kTagged: |
147 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 151 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
148 return GetTaggedRepresentationFor(node, output_rep, output_type); | 152 return GetTaggedRepresentationFor(node, output_rep, output_type); |
149 case MachineRepresentation::kFloat32: | 153 case MachineRepresentation::kFloat32: |
150 DCHECK(use_info.type_check() == TypeCheckKind::kNone); | 154 DCHECK(use_info.type_check() == TypeCheckKind::kNone); |
151 return GetFloat32RepresentationFor(node, output_rep, output_type, | 155 return GetFloat32RepresentationFor(node, output_rep, output_type, |
152 use_info.truncation()); | 156 use_info.truncation()); |
153 case MachineRepresentation::kFloat64: | 157 case MachineRepresentation::kFloat64: |
154 return GetFloat64RepresentationFor(node, output_rep, output_type, | 158 return GetFloat64RepresentationFor(node, output_rep, output_type, |
155 use_node, use_info); | 159 use_node, use_info); |
(...skipping 11 matching lines...) Expand all Loading... |
167 case MachineRepresentation::kSimd128: // Fall through. | 171 case MachineRepresentation::kSimd128: // Fall through. |
168 // TODO(bbudge) Handle conversions between tagged and untagged. | 172 // TODO(bbudge) Handle conversions between tagged and untagged. |
169 break; | 173 break; |
170 case MachineRepresentation::kNone: | 174 case MachineRepresentation::kNone: |
171 return node; | 175 return node; |
172 } | 176 } |
173 UNREACHABLE(); | 177 UNREACHABLE(); |
174 return nullptr; | 178 return nullptr; |
175 } | 179 } |
176 | 180 |
| 181 Node* RepresentationChanger::GetTaggedSignedRepresentationFor( |
| 182 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 183 // Eagerly fold representation changes for constants. |
| 184 switch (node->opcode()) { |
| 185 case IrOpcode::kNumberConstant: { |
| 186 int32_t value = OpParameter<int32_t>(node); |
| 187 if (Smi::IsValid(value)) { |
| 188 return jsgraph()->Constant(value); |
| 189 } |
| 190 return TypeError(node, output_rep, output_type, |
| 191 MachineRepresentation::kTaggedSigned); |
| 192 } |
| 193 case IrOpcode::kHeapConstant: |
| 194 return TypeError(node, output_rep, output_type, |
| 195 MachineRepresentation::kTaggedSigned); |
| 196 case IrOpcode::kInt32Constant: |
| 197 if (output_type->Is(Type::SignedSmall())) { |
| 198 int32_t value = OpParameter<int32_t>(node); |
| 199 return jsgraph()->Constant(value); |
| 200 } else { |
| 201 return TypeError(node, output_rep, output_type, |
| 202 MachineRepresentation::kTaggedSigned); |
| 203 } |
| 204 case IrOpcode::kFloat64Constant: |
| 205 case IrOpcode::kFloat32Constant: |
| 206 return TypeError(node, output_rep, output_type, |
| 207 MachineRepresentation::kTaggedSigned); |
| 208 default: |
| 209 break; |
| 210 } |
| 211 // Select the correct X -> Tagged operator. |
| 212 const Operator* op; |
| 213 if (output_type->Is(Type::None())) { |
| 214 // This is an impossible value; it should not be used at runtime. |
| 215 // We just provide a dummy value here. |
| 216 return jsgraph()->Constant(0); |
| 217 } else if (IsWord(output_rep)) { |
| 218 if (output_type->Is(Type::Signed31())) { |
| 219 op = simplified()->ChangeInt31ToTaggedSigned(); |
| 220 } else if (machine()->Is64() && output_type->Is(Type::Signed32())) { |
| 221 op = simplified()->ChangeInt32ToTagged(); |
| 222 } else { |
| 223 return TypeError(node, output_rep, output_type, |
| 224 MachineRepresentation::kTaggedSigned); |
| 225 } |
| 226 } else { |
| 227 return TypeError(node, output_rep, output_type, |
| 228 MachineRepresentation::kTaggedSigned); |
| 229 } |
| 230 return jsgraph()->graph()->NewNode(op, node); |
| 231 } |
| 232 |
| 233 Node* RepresentationChanger::GetTaggedPointerRepresentationFor( |
| 234 Node* node, MachineRepresentation output_rep, Type* output_type) { |
| 235 // Eagerly fold representation changes for constants. |
| 236 switch (node->opcode()) { |
| 237 case IrOpcode::kHeapConstant: |
| 238 return node; // No change necessary. |
| 239 case IrOpcode::kInt32Constant: |
| 240 if (output_type->Is(Type::Boolean())) { |
| 241 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant() |
| 242 : jsgraph()->TrueConstant(); |
| 243 } else { |
| 244 return TypeError(node, output_rep, output_type, |
| 245 MachineRepresentation::kTaggedPointer); |
| 246 } |
| 247 case IrOpcode::kFloat64Constant: |
| 248 case IrOpcode::kFloat32Constant: |
| 249 return TypeError(node, output_rep, output_type, |
| 250 MachineRepresentation::kTaggedPointer); |
| 251 default: |
| 252 break; |
| 253 } |
| 254 // Select the correct X -> Tagged operator. |
| 255 const Operator* op; |
| 256 if (output_type->Is(Type::None())) { |
| 257 // This is an impossible value; it should not be used at runtime. |
| 258 // We just provide a dummy value here. |
| 259 return jsgraph()->TheHoleConstant(); |
| 260 } else if (IsWord(output_rep)) { |
| 261 // These are all about optimizing to smi types, and we want a pointer. |
| 262 // Let's be very conservative at first here and declare this to be a |
| 263 // type error. |
| 264 return TypeError(node, output_rep, output_type, |
| 265 MachineRepresentation::kTaggedPointer); |
| 266 } else { |
| 267 // TODO(mvstanton): Consider introducing a ChangeFloat64ToTaggedPointer |
| 268 // operator, but for now all kFloat to kTaggedPointer conversions seem |
| 269 // suspicious. Really, if we want a TaggedPointer representation we |
| 270 // should have come from a TaggedPointer type. |
| 271 return TypeError(node, output_rep, output_type, |
| 272 MachineRepresentation::kTaggedPointer); |
| 273 } |
| 274 return jsgraph()->graph()->NewNode(op, node); |
| 275 } |
| 276 |
177 Node* RepresentationChanger::GetTaggedRepresentationFor( | 277 Node* RepresentationChanger::GetTaggedRepresentationFor( |
178 Node* node, MachineRepresentation output_rep, Type* output_type) { | 278 Node* node, MachineRepresentation output_rep, Type* output_type) { |
179 // Eagerly fold representation changes for constants. | 279 // Eagerly fold representation changes for constants. |
180 switch (node->opcode()) { | 280 switch (node->opcode()) { |
181 case IrOpcode::kNumberConstant: | 281 case IrOpcode::kNumberConstant: |
182 case IrOpcode::kHeapConstant: | 282 case IrOpcode::kHeapConstant: |
183 return node; // No change necessary. | 283 return node; // No change necessary. |
184 case IrOpcode::kInt32Constant: | 284 case IrOpcode::kInt32Constant: |
185 if (output_type->Is(Type::Signed32())) { | 285 if (output_type->Is(Type::Signed32())) { |
186 int32_t value = OpParameter<int32_t>(node); | 286 int32_t value = OpParameter<int32_t>(node); |
187 return jsgraph()->Constant(value); | 287 return jsgraph()->Constant(value); |
188 } else if (output_type->Is(Type::Unsigned32())) { | 288 } else if (output_type->Is(Type::Unsigned32())) { |
189 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); | 289 uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node)); |
190 return jsgraph()->Constant(static_cast<double>(value)); | 290 return jsgraph()->Constant(static_cast<double>(value)); |
191 } else if (output_type->Is(Type::Boolean())) { | 291 } else if (output_type->Is(Type::Boolean())) { |
192 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant() | 292 return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant() |
193 : jsgraph()->TrueConstant(); | 293 : jsgraph()->TrueConstant(); |
194 } else { | 294 } else { |
195 return TypeError(node, output_rep, output_type, | 295 return TypeError(node, output_rep, output_type, |
196 MachineRepresentation::kTagged); | 296 MachineRepresentation::kTagged); |
197 } | 297 } |
198 case IrOpcode::kFloat64Constant: | 298 case IrOpcode::kFloat64Constant: |
199 return jsgraph()->Constant(OpParameter<double>(node)); | 299 return jsgraph()->Constant(OpParameter<double>(node)); |
200 case IrOpcode::kFloat32Constant: | 300 case IrOpcode::kFloat32Constant: |
201 return jsgraph()->Constant(OpParameter<float>(node)); | 301 return jsgraph()->Constant(OpParameter<float>(node)); |
202 default: | 302 default: |
203 break; | 303 break; |
204 } | 304 } |
| 305 if (output_rep == MachineRepresentation::kTaggedSigned || |
| 306 output_rep == MachineRepresentation::kTaggedPointer) { |
| 307 // this is a no-op. |
| 308 return node; |
| 309 } |
205 // Select the correct X -> Tagged operator. | 310 // Select the correct X -> Tagged operator. |
206 const Operator* op; | 311 const Operator* op; |
207 if (output_type->Is(Type::None())) { | 312 if (output_type->Is(Type::None())) { |
208 // This is an impossible value; it should not be used at runtime. | 313 // This is an impossible value; it should not be used at runtime. |
209 // We just provide a dummy value here. | 314 // We just provide a dummy value here. |
210 return jsgraph()->TheHoleConstant(); | 315 return jsgraph()->TheHoleConstant(); |
211 } else if (output_rep == MachineRepresentation::kBit) { | 316 } else if (output_rep == MachineRepresentation::kBit) { |
212 if (output_type->Is(Type::Boolean())) { | 317 if (output_type->Is(Type::Boolean())) { |
213 op = simplified()->ChangeBitToTagged(); | 318 op = simplified()->ChangeBitToTagged(); |
214 } else { | 319 } else { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 } else if (output_type->Is(Type::Unsigned32()) || | 401 } else if (output_type->Is(Type::Unsigned32()) || |
297 truncation.IsUsedAsWord32()) { | 402 truncation.IsUsedAsWord32()) { |
298 // Either the output is uint32 or the uses only care about the | 403 // Either the output is uint32 or the uses only care about the |
299 // low 32 bits (so we can pick uint32 safely). | 404 // low 32 bits (so we can pick uint32 safely). |
300 | 405 |
301 // uint32 -> float64 -> float32 | 406 // uint32 -> float64 -> float32 |
302 op = machine()->ChangeUint32ToFloat64(); | 407 op = machine()->ChangeUint32ToFloat64(); |
303 node = jsgraph()->graph()->NewNode(op, node); | 408 node = jsgraph()->graph()->NewNode(op, node); |
304 op = machine()->TruncateFloat64ToFloat32(); | 409 op = machine()->TruncateFloat64ToFloat32(); |
305 } | 410 } |
306 } else if (output_rep == MachineRepresentation::kTagged) { | 411 } else if (output_rep == MachineRepresentation::kTagged || |
| 412 output_rep == MachineRepresentation::kTaggedPointer) { |
307 if (output_type->Is(Type::NumberOrOddball())) { | 413 if (output_type->Is(Type::NumberOrOddball())) { |
308 // tagged -> float64 -> float32 | 414 // tagged -> float64 -> float32 |
309 if (output_type->Is(Type::Number())) { | 415 if (output_type->Is(Type::Number())) { |
310 op = simplified()->ChangeTaggedToFloat64(); | 416 op = simplified()->ChangeTaggedToFloat64(); |
311 } else { | 417 } else { |
312 op = simplified()->TruncateTaggedToFloat64(); | 418 op = simplified()->TruncateTaggedToFloat64(); |
313 } | 419 } |
314 node = jsgraph()->graph()->NewNode(op, node); | 420 node = jsgraph()->graph()->NewNode(op, node); |
315 op = machine()->TruncateFloat64ToFloat32(); | 421 op = machine()->TruncateFloat64ToFloat32(); |
316 } | 422 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 if (output_type->Is(Type::Signed32())) { | 466 if (output_type->Is(Type::Signed32())) { |
361 op = machine()->ChangeInt32ToFloat64(); | 467 op = machine()->ChangeInt32ToFloat64(); |
362 } else if (output_type->Is(Type::Unsigned32()) || | 468 } else if (output_type->Is(Type::Unsigned32()) || |
363 use_info.truncation().IsUsedAsWord32()) { | 469 use_info.truncation().IsUsedAsWord32()) { |
364 // Either the output is uint32 or the uses only care about the | 470 // Either the output is uint32 or the uses only care about the |
365 // low 32 bits (so we can pick uint32 safely). | 471 // low 32 bits (so we can pick uint32 safely). |
366 op = machine()->ChangeUint32ToFloat64(); | 472 op = machine()->ChangeUint32ToFloat64(); |
367 } | 473 } |
368 } else if (output_rep == MachineRepresentation::kBit) { | 474 } else if (output_rep == MachineRepresentation::kBit) { |
369 op = machine()->ChangeUint32ToFloat64(); | 475 op = machine()->ChangeUint32ToFloat64(); |
370 } else if (output_rep == MachineRepresentation::kTagged) { | 476 } else if (output_rep == MachineRepresentation::kTagged || |
| 477 output_rep == MachineRepresentation::kTaggedSigned || |
| 478 output_rep == MachineRepresentation::kTaggedPointer) { |
371 if (output_type->Is(Type::Undefined())) { | 479 if (output_type->Is(Type::Undefined())) { |
372 return jsgraph()->Float64Constant( | 480 return jsgraph()->Float64Constant( |
373 std::numeric_limits<double>::quiet_NaN()); | 481 std::numeric_limits<double>::quiet_NaN()); |
374 } else if (output_type->Is(Type::TaggedSigned())) { | 482 } else if (output_type->Is(Type::TaggedSigned())) { |
375 node = InsertChangeTaggedSignedToInt32(node); | 483 node = InsertChangeTaggedSignedToInt32(node); |
376 op = machine()->ChangeInt32ToFloat64(); | 484 op = machine()->ChangeInt32ToFloat64(); |
377 } else if (output_type->Is(Type::Number())) { | 485 } else if (output_type->Is(Type::Number())) { |
378 op = simplified()->ChangeTaggedToFloat64(); | 486 op = simplified()->ChangeTaggedToFloat64(); |
379 } else if (output_type->Is(Type::NumberOrOddball())) { | 487 } else if (output_type->Is(Type::NumberOrOddball())) { |
380 // TODO(jarin) Here we should check that truncation is Number. | 488 // TODO(jarin) Here we should check that truncation is Number. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 op = machine()->ChangeFloat64ToInt32(); | 571 op = machine()->ChangeFloat64ToInt32(); |
464 } else if (use_info.truncation().IsUsedAsWord32()) { | 572 } else if (use_info.truncation().IsUsedAsWord32()) { |
465 op = machine()->TruncateFloat64ToWord32(); | 573 op = machine()->TruncateFloat64ToWord32(); |
466 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || | 574 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall || |
467 use_info.type_check() == TypeCheckKind::kSigned32) { | 575 use_info.type_check() == TypeCheckKind::kSigned32) { |
468 op = simplified()->CheckedFloat64ToInt32( | 576 op = simplified()->CheckedFloat64ToInt32( |
469 output_type->Maybe(Type::MinusZero()) | 577 output_type->Maybe(Type::MinusZero()) |
470 ? CheckForMinusZeroMode::kCheckForMinusZero | 578 ? CheckForMinusZeroMode::kCheckForMinusZero |
471 : CheckForMinusZeroMode::kDontCheckForMinusZero); | 579 : CheckForMinusZeroMode::kDontCheckForMinusZero); |
472 } | 580 } |
473 } else if (output_rep == MachineRepresentation::kTagged) { | 581 } else if (output_rep == MachineRepresentation::kTaggedSigned) { |
474 if (output_type->Is(Type::TaggedSigned())) { | 582 if (output_type->Is(Type::Signed32())) { |
475 op = simplified()->ChangeTaggedSignedToInt32(); | 583 op = simplified()->ChangeTaggedSignedToInt32(); |
476 } else if (output_type->Is(Type::Unsigned32())) { | 584 } else if (use_info.truncation().IsUsedAsWord32()) { |
| 585 if (use_info.type_check() != TypeCheckKind::kNone) { |
| 586 op = simplified()->CheckedTruncateTaggedToWord32(); |
| 587 } else { |
| 588 op = simplified()->TruncateTaggedToWord32(); |
| 589 } |
| 590 } |
| 591 } else if (output_rep == MachineRepresentation::kTagged || |
| 592 output_rep == MachineRepresentation::kTaggedPointer) { |
| 593 if (output_type->Is(Type::Unsigned32())) { |
477 op = simplified()->ChangeTaggedToUint32(); | 594 op = simplified()->ChangeTaggedToUint32(); |
478 } else if (output_type->Is(Type::Signed32())) { | 595 } else if (output_type->Is(Type::Signed32())) { |
479 op = simplified()->ChangeTaggedToInt32(); | 596 op = simplified()->ChangeTaggedToInt32(); |
480 } else if (use_info.truncation().IsUsedAsWord32()) { | 597 } else if (use_info.truncation().IsUsedAsWord32()) { |
481 if (use_info.type_check() != TypeCheckKind::kNone) { | 598 if (use_info.type_check() != TypeCheckKind::kNone) { |
482 op = simplified()->CheckedTruncateTaggedToWord32(); | 599 op = simplified()->CheckedTruncateTaggedToWord32(); |
483 } else { | 600 } else { |
484 op = simplified()->TruncateTaggedToWord32(); | 601 op = simplified()->TruncateTaggedToWord32(); |
485 } | 602 } |
486 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { | 603 } else if (use_info.type_check() == TypeCheckKind::kSignedSmall) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 } | 665 } |
549 default: | 666 default: |
550 break; | 667 break; |
551 } | 668 } |
552 // Select the correct X -> Bit operator. | 669 // Select the correct X -> Bit operator. |
553 const Operator* op; | 670 const Operator* op; |
554 if (output_type->Is(Type::None())) { | 671 if (output_type->Is(Type::None())) { |
555 // This is an impossible value; it should not be used at runtime. | 672 // This is an impossible value; it should not be used at runtime. |
556 // We just provide a dummy value here. | 673 // We just provide a dummy value here. |
557 return jsgraph()->Int32Constant(0); | 674 return jsgraph()->Int32Constant(0); |
558 } else if (output_rep == MachineRepresentation::kTagged) { | 675 } else if (output_rep == MachineRepresentation::kTagged || |
| 676 output_rep == MachineRepresentation::kTaggedSigned || |
| 677 output_rep == MachineRepresentation::kTaggedPointer) { |
559 op = simplified()->ChangeTaggedToBit(); | 678 op = simplified()->ChangeTaggedToBit(); |
560 } else { | 679 } else { |
561 return TypeError(node, output_rep, output_type, | 680 return TypeError(node, output_rep, output_type, |
562 MachineRepresentation::kBit); | 681 MachineRepresentation::kBit); |
563 } | 682 } |
564 return jsgraph()->graph()->NewNode(op, node); | 683 return jsgraph()->graph()->NewNode(op, node); |
565 } | 684 } |
566 | 685 |
567 Node* RepresentationChanger::GetWord64RepresentationFor( | 686 Node* RepresentationChanger::GetWord64RepresentationFor( |
568 Node* node, MachineRepresentation output_rep, Type* output_type) { | 687 Node* node, MachineRepresentation output_rep, Type* output_type) { |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 } | 940 } |
822 | 941 |
823 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { | 942 Node* RepresentationChanger::InsertChangeTaggedToFloat64(Node* node) { |
824 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), | 943 return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(), |
825 node); | 944 node); |
826 } | 945 } |
827 | 946 |
828 } // namespace compiler | 947 } // namespace compiler |
829 } // namespace internal | 948 } // namespace internal |
830 } // namespace v8 | 949 } // namespace v8 |
OLD | NEW |