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

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 12871010: Replace scalarlist optimizations and split external array loads into two IL instructions. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_optimizer.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 (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 4
5 #include "vm/flow_graph_allocator.h" 5 #include "vm/flow_graph_allocator.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/il_printer.h" 9 #include "vm/il_printer.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 56
57 57
58 static intptr_t ToInstructionEnd(intptr_t pos) { 58 static intptr_t ToInstructionEnd(intptr_t pos) {
59 return (pos | 1); 59 return (pos | 1);
60 } 60 }
61 61
62 62
63 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph) 63 FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph)
64 : flow_graph_(flow_graph), 64 : flow_graph_(flow_graph),
65 reaching_defs_(flow_graph), 65 reaching_defs_(flow_graph),
66 mint_values_(NULL), 66 value_representations_(flow_graph.max_virtual_register_number()),
67 block_order_(flow_graph.reverse_postorder()), 67 block_order_(flow_graph.reverse_postorder()),
68 postorder_(flow_graph.postorder()), 68 postorder_(flow_graph.postorder()),
69 live_out_(block_order_.length()), 69 live_out_(block_order_.length()),
70 kill_(block_order_.length()), 70 kill_(block_order_.length()),
71 live_in_(block_order_.length()), 71 live_in_(block_order_.length()),
72 vreg_count_(flow_graph.max_virtual_register_number()), 72 vreg_count_(flow_graph.max_virtual_register_number()),
73 live_ranges_(flow_graph.max_virtual_register_number()), 73 live_ranges_(flow_graph.max_virtual_register_number()),
74 cpu_regs_(), 74 cpu_regs_(),
75 fpu_regs_(), 75 fpu_regs_(),
76 blocked_cpu_registers_(), 76 blocked_cpu_registers_(),
77 blocked_fpu_registers_(), 77 blocked_fpu_registers_(),
78 cpu_spill_slot_count_(0) { 78 cpu_spill_slot_count_(0) {
79 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL); 79 for (intptr_t i = 0; i < vreg_count_; i++) live_ranges_.Add(NULL);
80 for (intptr_t i = 0; i < vreg_count_; i++) {
81 value_representations_.Add(kNoRepresentation);
82 }
80 83
81 // All registers are marked as "not blocked" (array initialized to false). 84 // All registers are marked as "not blocked" (array initialized to false).
82 // Mark the unavailable ones as "blocked" (true). 85 // Mark the unavailable ones as "blocked" (true).
83 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) { 86 for (intptr_t i = 0; i < kFirstFreeCpuRegister; i++) {
84 blocked_cpu_registers_[i] = true; 87 blocked_cpu_registers_[i] = true;
85 } 88 }
86 for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) { 89 for (intptr_t i = kLastFreeCpuRegister + 1; i < kNumberOfCpuRegisters; i++) {
87 blocked_cpu_registers_[i] = true; 90 blocked_cpu_registers_[i] = true;
88 } 91 }
89 blocked_cpu_registers_[CTX] = true; 92 blocked_cpu_registers_[CTX] = true;
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 // Shrink the first use interval. It was optimistically expanded to 381 // Shrink the first use interval. It was optimistically expanded to
379 // cover the the block from the start to the last use in the block. 382 // cover the the block from the start to the last use in the block.
380 ASSERT(first_use_interval_->start_ <= pos); 383 ASSERT(first_use_interval_->start_ <= pos);
381 first_use_interval_->start_ = pos; 384 first_use_interval_->start_ = pos;
382 } 385 }
383 } 386 }
384 387
385 388
386 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) { 389 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) {
387 if (live_ranges_[vreg] == NULL) { 390 if (live_ranges_[vreg] == NULL) {
388 Location::Representation rep = 391 Representation rep = value_representations_[vreg];
389 mint_values_->Contains(vreg) ? Location::kMint : Location::kDouble; 392 ASSERT(rep != kNoRepresentation);
390 live_ranges_[vreg] = new LiveRange(vreg, rep); 393 live_ranges_[vreg] = new LiveRange(vreg, rep);
391 } 394 }
392 return live_ranges_[vreg]; 395 return live_ranges_[vreg];
393 } 396 }
394 397
395 398
396 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() { 399 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
397 Location::Representation ignored = Location::kDouble; 400 // Representation does not matter for temps.
401 Representation ignored = kNoRepresentation;
398 LiveRange* range = new LiveRange(kTempVirtualRegister, ignored); 402 LiveRange* range = new LiveRange(kTempVirtualRegister, ignored);
399 #if defined(DEBUG) 403 #if defined(DEBUG)
400 temporaries_.Add(range); 404 temporaries_.Add(range);
401 #endif 405 #endif
402 return range; 406 return range;
403 } 407 }
404 408
405 409
406 void FlowGraphAllocator::BlockRegisterLocation(Location loc, 410 void FlowGraphAllocator::BlockRegisterLocation(Location loc,
407 intptr_t from, 411 intptr_t from,
408 intptr_t to, 412 intptr_t to,
409 bool* blocked_registers, 413 bool* blocked_registers,
410 LiveRange** blocking_ranges) { 414 LiveRange** blocking_ranges) {
411 if (blocked_registers[loc.register_code()]) { 415 if (blocked_registers[loc.register_code()]) {
412 return; 416 return;
413 } 417 }
414 418
415 if (blocking_ranges[loc.register_code()] == NULL) { 419 if (blocking_ranges[loc.register_code()] == NULL) {
416 Location::Representation ignored = Location::kDouble; 420 Representation ignored = kNoRepresentation;
417 LiveRange* range = new LiveRange(kNoVirtualRegister, ignored); 421 LiveRange* range = new LiveRange(kNoVirtualRegister, ignored);
418 blocking_ranges[loc.register_code()] = range; 422 blocking_ranges[loc.register_code()] = range;
419 range->set_assigned_location(loc); 423 range->set_assigned_location(loc);
420 #if defined(DEBUG) 424 #if defined(DEBUG)
421 temporaries_.Add(range); 425 temporaries_.Add(range);
422 #endif 426 #endif
423 } 427 }
424 428
425 blocking_ranges[loc.register_code()]->AddUseInterval(from, to); 429 blocking_ranges[loc.register_code()]->AddUseInterval(from, to);
426 } 430 }
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 // [--) 950 // [--)
947 // 951 //
948 // The stack bitmap describes the position i. 952 // The stack bitmap describes the position i.
949 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 953 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
950 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 954 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
951 pos, 955 pos,
952 pos + 1); 956 pos + 1);
953 } 957 }
954 958
955 for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) { 959 for (intptr_t reg = 0; reg < kNumberOfFpuRegisters; reg++) {
956 Location::Representation ignored = Location::kDouble; 960 Representation ignored = kNoRepresentation;
957 BlockLocation( 961 BlockLocation(
958 Location::FpuRegisterLocation(static_cast<FpuRegister>(reg), ignored), 962 Location::FpuRegisterLocation(static_cast<FpuRegister>(reg), ignored),
959 pos, 963 pos,
960 pos + 1); 964 pos + 1);
961 } 965 }
962 966
963 967
964 #if defined(DEBUG) 968 #if defined(DEBUG)
965 // Verify that temps, inputs and output were specified as fixed 969 // Verify that temps, inputs and output were specified as fixed
966 // locations. Every register is blocked now so attempt to 970 // locations. Every register is blocked now so attempt to
(...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 } 1589 }
1586 range = range->next_sibling(); 1590 range = range->next_sibling();
1587 } 1591 }
1588 } 1592 }
1589 1593
1590 1594
1591 void FlowGraphAllocator::Spill(LiveRange* range) { 1595 void FlowGraphAllocator::Spill(LiveRange* range) {
1592 LiveRange* parent = GetLiveRange(range->vreg()); 1596 LiveRange* parent = GetLiveRange(range->vreg());
1593 if (parent->spill_slot().IsInvalid()) { 1597 if (parent->spill_slot().IsInvalid()) {
1594 AllocateSpillSlotFor(parent); 1598 AllocateSpillSlotFor(parent);
1595 if (register_kind_ == Location::kRegister) { 1599 if (range->representation() == kTagged) {
1596 MarkAsObjectAtSafepoints(parent); 1600 MarkAsObjectAtSafepoints(parent);
1597 } 1601 }
1598 } 1602 }
1599 range->set_assigned_location(parent->spill_slot()); 1603 range->set_assigned_location(parent->spill_slot());
1600 ConvertAllUses(range); 1604 ConvertAllUses(range);
1601 } 1605 }
1602 1606
1603 1607
1604 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated( 1608 intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated(
1605 intptr_t reg, LiveRange* unallocated) { 1609 intptr_t reg, LiveRange* unallocated) {
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) { 1745 if (!reaching_defs_.Get(phi)->Contains(unallocated->vreg())) {
1742 used_on_backedge[reg] = true; 1746 used_on_backedge[reg] = true;
1743 } 1747 }
1744 } 1748 }
1745 } 1749 }
1746 1750
1747 if (used_on_backedge[candidate]) { 1751 if (used_on_backedge[candidate]) {
1748 TRACE_ALLOC(OS::Print( 1752 TRACE_ALLOC(OS::Print(
1749 "considering %s for v%"Pd": has interference on the back edge" 1753 "considering %s for v%"Pd": has interference on the back edge"
1750 " {loop [%"Pd", %"Pd")}\n", 1754 " {loop [%"Pd", %"Pd")}\n",
1751 MakeRegisterLocation(candidate, Location::kDouble).Name(), 1755 MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
1752 unallocated->vreg(), 1756 unallocated->vreg(),
1753 loop_header->entry()->start_pos(), 1757 loop_header->entry()->start_pos(),
1754 loop_header->last_block()->end_pos())); 1758 loop_header->last_block()->end_pos()));
1755 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1759 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1756 if (blocked_registers_[reg] || 1760 if (blocked_registers_[reg] ||
1757 (reg == candidate) || 1761 (reg == candidate) ||
1758 used_on_backedge[reg]) { 1762 used_on_backedge[reg]) {
1759 continue; 1763 continue;
1760 } 1764 }
1761 1765
1762 const intptr_t intersection = 1766 const intptr_t intersection =
1763 FirstIntersectionWithAllocated(reg, unallocated); 1767 FirstIntersectionWithAllocated(reg, unallocated);
1764 if (intersection >= free_until) { 1768 if (intersection >= free_until) {
1765 candidate = reg; 1769 candidate = reg;
1766 free_until = intersection; 1770 free_until = intersection;
1767 TRACE_ALLOC(OS::Print( 1771 TRACE_ALLOC(OS::Print(
1768 "found %s for v%"Pd" with no interference on the back edge\n", 1772 "found %s for v%"Pd" with no interference on the back edge\n",
1769 MakeRegisterLocation(candidate, Location::kDouble).Name(), 1773 MakeRegisterLocation(candidate, kUnboxedDouble).Name(),
1770 candidate)); 1774 candidate));
1771 break; 1775 break;
1772 } 1776 }
1773 } 1777 }
1774 } 1778 }
1775 } 1779 }
1776 1780
1777 ASSERT(0 <= kMaxPosition); 1781 ASSERT(0 <= kMaxPosition);
1778 if (free_until != kMaxPosition) { 1782 if (free_until != kMaxPosition) {
1779 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) { 1783 for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
1780 if (blocked_registers_[reg] || (reg == candidate)) continue; 1784 if (blocked_registers_[reg] || (reg == candidate)) continue;
1781 const intptr_t intersection = 1785 const intptr_t intersection =
1782 FirstIntersectionWithAllocated(reg, unallocated); 1786 FirstIntersectionWithAllocated(reg, unallocated);
1783 if (intersection > free_until) { 1787 if (intersection > free_until) {
1784 candidate = reg; 1788 candidate = reg;
1785 free_until = intersection; 1789 free_until = intersection;
1786 if (free_until == kMaxPosition) break; 1790 if (free_until == kMaxPosition) break;
1787 } 1791 }
1788 } 1792 }
1789 } 1793 }
1790 1794
1791 // All registers are blocked by active ranges. 1795 // All registers are blocked by active ranges.
1792 if (free_until <= unallocated->Start()) return false; 1796 if (free_until <= unallocated->Start()) return false;
1793 1797
1794 TRACE_ALLOC(OS::Print("assigning free register ")); 1798 TRACE_ALLOC(OS::Print("assigning free register "));
1795 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print()); 1799 TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
1796 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg())); 1800 TRACE_ALLOC(OS::Print(" to v%"Pd"\n", unallocated->vreg()));
1797 1801
1798 if (free_until != kMaxPosition) { 1802 if (free_until != kMaxPosition) {
1799 // There was an intersection. Split unallocated. 1803 // There was an intersection. Split unallocated.
1800 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); 1804 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until));
1801 LiveRange* tail = unallocated->SplitAt(free_until); 1805 LiveRange* tail = unallocated->SplitAt(free_until);
1802 AddToUnallocated(tail); 1806 AddToUnallocated(tail);
1803 } 1807 }
1804 1808
1805 registers_[candidate].Add(unallocated); 1809 registers_[candidate].Add(unallocated);
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 (register_use != NULL) ? register_use->pos() 1892 (register_use != NULL) ? register_use->pos()
1889 : unallocated->Start(); 1893 : unallocated->Start();
1890 if (free_until < register_use_pos) { 1894 if (free_until < register_use_pos) {
1891 // Can't acquire free register. Spill until we really need one. 1895 // Can't acquire free register. Spill until we really need one.
1892 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos)); 1896 ASSERT(unallocated->Start() < ToInstructionStart(register_use_pos));
1893 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); 1897 SpillBetween(unallocated, unallocated->Start(), register_use->pos());
1894 return; 1898 return;
1895 } 1899 }
1896 1900
1897 TRACE_ALLOC(OS::Print("assigning blocked register ")); 1901 TRACE_ALLOC(OS::Print("assigning blocked register "));
1898 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print()); 1902 TRACE_ALLOC(MakeRegisterLocation(candidate, kUnboxedDouble).Print());
1899 TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n", 1903 TRACE_ALLOC(OS::Print(" to live range v%"Pd" until %"Pd"\n",
1900 unallocated->vreg(), blocked_at)); 1904 unallocated->vreg(), blocked_at));
1901 1905
1902 if (blocked_at < unallocated->End()) { 1906 if (blocked_at < unallocated->End()) {
1903 // Register is blocked before the end of the live range. Split the range 1907 // Register is blocked before the end of the live range. Split the range
1904 // at latest at blocked_at position. 1908 // at latest at blocked_at position.
1905 LiveRange* tail = SplitBetween(unallocated, 1909 LiveRange* tail = SplitBetween(unallocated,
1906 unallocated->Start(), 1910 unallocated->Start(),
1907 blocked_at + 1); 1911 blocked_at + 1);
1908 AddToUnallocated(tail); 1912 AddToUnallocated(tail);
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after
2390 } else { 2394 } else {
2391 AddMoveAt(range->Start() + 1, 2395 AddMoveAt(range->Start() + 1,
2392 range->spill_slot(), 2396 range->spill_slot(),
2393 range->assigned_location()); 2397 range->assigned_location());
2394 } 2398 }
2395 } 2399 }
2396 } 2400 }
2397 2401
2398 2402
2399 void FlowGraphAllocator::CollectRepresentations() { 2403 void FlowGraphAllocator::CollectRepresentations() {
2400 mint_values_ = new BitVector(flow_graph_.max_virtual_register_number()); 2404 // Parameters.
2405 GraphEntryInstr* graph_entry = flow_graph_.graph_entry();
2406 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); ++i) {
2407 Definition* def = (*graph_entry->initial_definitions())[i];
2408 value_representations_[def->ssa_temp_index()] = def->representation();
2409 }
2401 2410
2402 for (BlockIterator it = flow_graph_.reverse_postorder_iterator(); 2411 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2403 !it.Done(); 2412 !it.Done();
2404 it.Advance()) { 2413 it.Advance()) {
2405 BlockEntryInstr* block = it.Current(); 2414 BlockEntryInstr* block = it.Current();
2406 // TODO(fschneider): Support unboxed mint representation for phis. 2415 // Phis.
2416 if (block->IsJoinEntry()) {
2417 JoinEntryInstr* join = block->AsJoinEntry();
2418 for (PhiIterator it(join); !it.Done(); it.Advance()) {
2419 PhiInstr* phi = it.Current();
2420 if ((phi != NULL) && (phi->ssa_temp_index() >= 0)) {
2421 value_representations_[phi->ssa_temp_index()] = phi->representation();
2422 }
2423 }
2424 }
2425 // Normal instructions.
2407 for (ForwardInstructionIterator instr_it(block); 2426 for (ForwardInstructionIterator instr_it(block);
2408 !instr_it.Done(); 2427 !instr_it.Done();
2409 instr_it.Advance()) { 2428 instr_it.Advance()) {
2410 Definition* defn = instr_it.Current()->AsDefinition(); 2429 Definition* def = instr_it.Current()->AsDefinition();
2411 if ((defn != NULL) && 2430 if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
2412 (defn->ssa_temp_index() >= 0) && 2431 value_representations_[def->ssa_temp_index()] = def->representation();
2413 (defn->representation() == kUnboxedMint)) {
2414 mint_values_->Add(defn->ssa_temp_index());
2415 } 2432 }
2416 } 2433 }
2417 } 2434 }
2418 } 2435 }
2419 2436
2420 2437
2421 void FlowGraphAllocator::AllocateRegisters() { 2438 void FlowGraphAllocator::AllocateRegisters() {
2422 CollectRepresentations(); 2439 CollectRepresentations();
2423 2440
2424 EliminateEnvironments(); 2441 EliminateEnvironments();
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2486 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2503 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2487 function.ToFullyQualifiedCString()); 2504 function.ToFullyQualifiedCString());
2488 FlowGraphPrinter printer(flow_graph_, true); 2505 FlowGraphPrinter printer(flow_graph_, true);
2489 printer.PrintBlocks(); 2506 printer.PrintBlocks();
2490 OS::Print("----------------------------------------------\n"); 2507 OS::Print("----------------------------------------------\n");
2491 } 2508 }
2492 } 2509 }
2493 2510
2494 2511
2495 } // namespace dart 2512 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_allocator.h ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698