| 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 |