OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // Class for intrinsifying functions. | 4 // Class for intrinsifying functions. |
5 | 5 |
6 #include "vm/assembler.h" | 6 #include "vm/assembler.h" |
7 #include "vm/intrinsifier.h" | 7 #include "vm/intrinsifier.h" |
8 #include "vm/flags.h" | 8 #include "vm/flags.h" |
9 #include "vm/object.h" | 9 #include "vm/object.h" |
10 #include "vm/symbols.h" | 10 #include "vm/symbols.h" |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 switch (function.recognized_kind()) { | 204 switch (function.recognized_kind()) { |
205 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE) | 205 CORE_INTEGER_LIB_INTRINSIC_LIST(EMIT_CASE) |
206 default: | 206 default: |
207 break; | 207 break; |
208 } | 208 } |
209 } | 209 } |
210 #undef EMIT_INTRINSIC | 210 #undef EMIT_INTRINSIC |
211 } | 211 } |
212 | 212 |
213 | 213 |
| 214 static intptr_t CidForRepresentation(Representation rep) { |
| 215 switch (rep) { |
| 216 case kUnboxedDouble: |
| 217 return kDoubleCid; |
| 218 case kUnboxedFloat32x4: |
| 219 return kFloat32x4Cid; |
| 220 default: |
| 221 UNREACHABLE(); |
| 222 return kIllegalCid; |
| 223 } |
| 224 } |
| 225 |
| 226 |
214 class BlockBuilder : public ValueObject { | 227 class BlockBuilder : public ValueObject { |
215 public: | 228 public: |
216 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) | 229 BlockBuilder(FlowGraph* flow_graph, TargetEntryInstr* entry) |
217 : flow_graph_(flow_graph), entry_(entry), current_(entry) { } | 230 : flow_graph_(flow_graph), entry_(entry), current_(entry) { } |
218 | 231 |
219 Definition* AddToInitialDefinitions(Definition* def) { | 232 Definition* AddToInitialDefinitions(Definition* def) { |
220 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); | 233 def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index()); |
221 flow_graph_->AddToInitialDefinitions(def); | 234 flow_graph_->AddToInitialDefinitions(def); |
222 return def; | 235 return def; |
223 } | 236 } |
(...skipping 25 matching lines...) Expand all Loading... |
249 | 262 |
250 intptr_t TokenPos() { | 263 intptr_t TokenPos() { |
251 return flow_graph_->function().token_pos(); | 264 return flow_graph_->function().token_pos(); |
252 } | 265 } |
253 | 266 |
254 Definition* AddNullDefinition() { | 267 Definition* AddNullDefinition() { |
255 return AddDefinition( | 268 return AddDefinition( |
256 new ConstantInstr(Object::ZoneHandle(Object::null()))); | 269 new ConstantInstr(Object::ZoneHandle(Object::null()))); |
257 } | 270 } |
258 | 271 |
| 272 Definition* AddUnboxInstr(Representation rep, Value* value) { |
| 273 Definition* unboxed_value = AddDefinition( |
| 274 UnboxInstr::Create(rep, value, Isolate::kNoDeoptId)); |
| 275 // Manually adjust reaching type because there is no type propagation |
| 276 // when building intrinsics. |
| 277 unboxed_value->AsUnbox()->value()->SetReachingType(ZoneCompileType::Wrap( |
| 278 CompileType::FromCid(CidForRepresentation(rep)))); |
| 279 return unboxed_value; |
| 280 } |
| 281 |
259 private: | 282 private: |
260 FlowGraph* flow_graph_; | 283 FlowGraph* flow_graph_; |
261 BlockEntryInstr* entry_; | 284 BlockEntryInstr* entry_; |
262 Instruction* current_; | 285 Instruction* current_; |
263 }; | 286 }; |
264 | 287 |
265 | 288 |
266 static void PrepareIndexedOp(BlockBuilder* builder, | 289 static void PrepareIndexedOp(BlockBuilder* builder, |
267 Definition* array, | 290 Definition* array, |
268 Definition* index, | 291 Definition* index, |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 String::Handle(flow_graph->function().name()), | 466 String::Handle(flow_graph->function().name()), |
444 Object::empty_array(), // Dummy args. descr. | 467 Object::empty_array(), // Dummy args. descr. |
445 Isolate::kNoDeoptId, | 468 Isolate::kNoDeoptId, |
446 1)); | 469 1)); |
447 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); | 470 value_check.AddReceiverCheck(kDoubleCid, flow_graph->function()); |
448 builder.AddInstruction( | 471 builder.AddInstruction( |
449 new CheckClassInstr(new Value(value), | 472 new CheckClassInstr(new Value(value), |
450 Isolate::kNoDeoptId, | 473 Isolate::kNoDeoptId, |
451 value_check, | 474 value_check, |
452 builder.TokenPos())); | 475 builder.TokenPos())); |
453 Definition* double_value = builder.AddDefinition( | 476 Definition* double_value = |
454 UnboxInstr::Create(kUnboxedDouble, | 477 builder.AddUnboxInstr(kUnboxedDouble, new Value(value)); |
455 new Value(value), | |
456 Isolate::kNoDeoptId)); | |
457 // Manually adjust reaching type because there is no type propagation | |
458 // when building intrinsics. | |
459 double_value->AsUnbox()->value()->SetReachingType( | |
460 ZoneCompileType::Wrap(CompileType::FromCid(kDoubleCid))); | |
461 | 478 |
462 builder.AddInstruction( | 479 builder.AddInstruction( |
463 new StoreIndexedInstr(new Value(array), | 480 new StoreIndexedInstr(new Value(array), |
464 new Value(index), | 481 new Value(index), |
465 new Value(double_value), | 482 new Value(double_value), |
466 kNoStoreBarrier, | 483 kNoStoreBarrier, |
467 8, // index scale | 484 8, // index scale |
468 kTypedDataFloat64ArrayCid, | 485 kTypedDataFloat64ArrayCid, |
469 Isolate::kNoDeoptId, | 486 Isolate::kNoDeoptId, |
470 builder.TokenPos())); | 487 builder.TokenPos())); |
(...skipping 23 matching lines...) Expand all Loading... |
494 kTypedDataFloat64ArrayCid, | 511 kTypedDataFloat64ArrayCid, |
495 Isolate::kNoDeoptId, | 512 Isolate::kNoDeoptId, |
496 builder.TokenPos())); | 513 builder.TokenPos())); |
497 Definition* result = builder.AddDefinition( | 514 Definition* result = builder.AddDefinition( |
498 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); | 515 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_value))); |
499 builder.AddIntrinsicReturn(new Value(result)); | 516 builder.AddIntrinsicReturn(new Value(result)); |
500 return true; | 517 return true; |
501 } | 518 } |
502 | 519 |
503 | 520 |
| 521 static bool BuildBinaryFloat32x4Op(FlowGraph* flow_graph, Token::Kind kind) { |
| 522 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; |
| 523 |
| 524 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 525 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 526 BlockBuilder builder(flow_graph, normal_entry); |
| 527 |
| 528 Definition* right = builder.AddParameter(1); |
| 529 Definition* left = builder.AddParameter(2); |
| 530 |
| 531 const ICData& value_check = ICData::ZoneHandle(ICData::New( |
| 532 flow_graph->function(), |
| 533 String::Handle(flow_graph->function().name()), |
| 534 Object::empty_array(), // Dummy args. descr. |
| 535 Isolate::kNoDeoptId, |
| 536 1)); |
| 537 value_check.AddReceiverCheck(kFloat32x4Cid, flow_graph->function()); |
| 538 // Check argument. Receiver (left) is known to be a Float32x4. |
| 539 builder.AddInstruction( |
| 540 new CheckClassInstr(new Value(right), |
| 541 Isolate::kNoDeoptId, |
| 542 value_check, |
| 543 builder.TokenPos())); |
| 544 Definition* left_simd = |
| 545 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(left)); |
| 546 |
| 547 Definition* right_simd = |
| 548 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(right)); |
| 549 |
| 550 Definition* unboxed_result = builder.AddDefinition( |
| 551 new BinaryFloat32x4OpInstr(kind, |
| 552 new Value(left_simd), |
| 553 new Value(right_simd), |
| 554 Isolate::kNoDeoptId)); |
| 555 Definition* result = builder.AddDefinition( |
| 556 BoxInstr::Create(kUnboxedFloat32x4, new Value(unboxed_result))); |
| 557 builder.AddIntrinsicReturn(new Value(result)); |
| 558 return true; |
| 559 } |
| 560 |
| 561 |
| 562 bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) { |
| 563 return BuildBinaryFloat32x4Op(flow_graph, Token::kMUL); |
| 564 } |
| 565 |
| 566 |
| 567 bool Intrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) { |
| 568 return BuildBinaryFloat32x4Op(flow_graph, Token::kSUB); |
| 569 } |
| 570 |
| 571 |
| 572 bool Intrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) { |
| 573 return BuildBinaryFloat32x4Op(flow_graph, Token::kADD); |
| 574 } |
| 575 |
| 576 |
| 577 static bool BuildFloat32x4Shuffle(FlowGraph* flow_graph, |
| 578 MethodRecognizer::Kind kind) { |
| 579 if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false; |
| 580 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
| 581 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
| 582 BlockBuilder builder(flow_graph, normal_entry); |
| 583 |
| 584 Definition* receiver = builder.AddParameter(1); |
| 585 |
| 586 Definition* unboxed_receiver = |
| 587 builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver)); |
| 588 |
| 589 Definition* unboxed_result = builder.AddDefinition( |
| 590 new Simd32x4ShuffleInstr(kind, |
| 591 new Value(unboxed_receiver), |
| 592 0, |
| 593 Isolate::kNoDeoptId)); |
| 594 |
| 595 Definition* result = builder.AddDefinition( |
| 596 BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result))); |
| 597 builder.AddIntrinsicReturn(new Value(result)); |
| 598 return true; |
| 599 } |
| 600 |
| 601 |
| 602 bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) { |
| 603 return BuildFloat32x4Shuffle(flow_graph, |
| 604 MethodRecognizer::kFloat32x4ShuffleX); |
| 605 } |
| 606 |
| 607 |
| 608 bool Intrinsifier::Build_Float32x4ShuffleY(FlowGraph* flow_graph) { |
| 609 return BuildFloat32x4Shuffle(flow_graph, |
| 610 MethodRecognizer::kFloat32x4ShuffleY); |
| 611 } |
| 612 |
| 613 |
| 614 bool Intrinsifier::Build_Float32x4ShuffleZ(FlowGraph* flow_graph) { |
| 615 return BuildFloat32x4Shuffle(flow_graph, |
| 616 MethodRecognizer::kFloat32x4ShuffleZ); |
| 617 } |
| 618 |
| 619 |
| 620 bool Intrinsifier::Build_Float32x4ShuffleW(FlowGraph* flow_graph) { |
| 621 return BuildFloat32x4Shuffle(flow_graph, |
| 622 MethodRecognizer::kFloat32x4ShuffleW); |
| 623 } |
| 624 |
| 625 |
504 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) { | 626 static bool BuildLoadField(FlowGraph* flow_graph, intptr_t offset) { |
505 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); | 627 GraphEntryInstr* graph_entry = flow_graph->graph_entry(); |
506 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); | 628 TargetEntryInstr* normal_entry = graph_entry->normal_entry(); |
507 BlockBuilder builder(flow_graph, normal_entry); | 629 BlockBuilder builder(flow_graph, normal_entry); |
508 | 630 |
509 Definition* array = builder.AddParameter(1); | 631 Definition* array = builder.AddParameter(1); |
510 | 632 |
511 Definition* length = builder.AddDefinition( | 633 Definition* length = builder.AddDefinition( |
512 new LoadFieldInstr(new Value(array), | 634 new LoadFieldInstr(new Value(array), |
513 offset, | 635 offset, |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 new Value(growable_array), | 804 new Value(growable_array), |
683 new Value(length), | 805 new Value(length), |
684 kNoStoreBarrier, | 806 kNoStoreBarrier, |
685 builder.TokenPos())); | 807 builder.TokenPos())); |
686 Definition* null_def = builder.AddNullDefinition(); | 808 Definition* null_def = builder.AddNullDefinition(); |
687 builder.AddIntrinsicReturn(new Value(null_def)); | 809 builder.AddIntrinsicReturn(new Value(null_def)); |
688 return true; | 810 return true; |
689 } | 811 } |
690 | 812 |
691 } // namespace dart | 813 } // namespace dart |
OLD | NEW |