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

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

Issue 10968059: Support for unboxed 64-bit integer bitwise operations and equality on ia32. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: fixed boxing of smis and added one more test Created 8 years, 3 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
OLDNEW
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 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 } 55 }
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 reps_(NULL),
65 block_order_(flow_graph.reverse_postorder()), 66 block_order_(flow_graph.reverse_postorder()),
66 postorder_(flow_graph.postorder()), 67 postorder_(flow_graph.postorder()),
67 live_out_(block_order_.length()), 68 live_out_(block_order_.length()),
68 kill_(block_order_.length()), 69 kill_(block_order_.length()),
69 live_in_(block_order_.length()), 70 live_in_(block_order_.length()),
70 vreg_count_(flow_graph.max_virtual_register_number()), 71 vreg_count_(flow_graph.max_virtual_register_number()),
71 live_ranges_(flow_graph.max_virtual_register_number()), 72 live_ranges_(flow_graph.max_virtual_register_number()),
72 cpu_regs_(), 73 cpu_regs_(),
73 xmm_regs_(), 74 xmm_regs_(),
74 blocked_cpu_registers_(), 75 blocked_cpu_registers_(),
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 // Shrink the first use interval. It was optimistically expanded to 386 // Shrink the first use interval. It was optimistically expanded to
386 // cover the the block from the start to the last use in the block. 387 // cover the the block from the start to the last use in the block.
387 ASSERT(first_use_interval_->start_ <= pos); 388 ASSERT(first_use_interval_->start_ <= pos);
388 first_use_interval_->start_ = pos; 389 first_use_interval_->start_ = pos;
389 } 390 }
390 } 391 }
391 392
392 393
393 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) { 394 LiveRange* FlowGraphAllocator::GetLiveRange(intptr_t vreg) {
394 if (live_ranges_[vreg] == NULL) { 395 if (live_ranges_[vreg] == NULL) {
395 live_ranges_[vreg] = new LiveRange(vreg); 396 Location::Representation rep =
397 reps_->Contains(vreg) ? Location::kMint : Location::kDouble;
398 live_ranges_[vreg] = new LiveRange(vreg, rep);
396 } 399 }
397 return live_ranges_[vreg]; 400 return live_ranges_[vreg];
398 } 401 }
399 402
400 403
401 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() { 404 LiveRange* FlowGraphAllocator::MakeLiveRangeForTemporary() {
402 LiveRange* range = new LiveRange(kTempVirtualRegister); 405 Location::Representation ignored = Location::kDouble;
406 LiveRange* range = new LiveRange(kTempVirtualRegister, ignored);
403 #if defined(DEBUG) 407 #if defined(DEBUG)
404 temporaries_.Add(range); 408 temporaries_.Add(range);
405 #endif 409 #endif
406 return range; 410 return range;
407 } 411 }
408 412
409 413
410 void FlowGraphAllocator::BlockRegisterLocation(Location loc, 414 void FlowGraphAllocator::BlockRegisterLocation(Location loc,
411 intptr_t from, 415 intptr_t from,
412 intptr_t to, 416 intptr_t to,
413 bool* blocked_registers, 417 bool* blocked_registers,
414 LiveRange** blocking_ranges) { 418 LiveRange** blocking_ranges) {
415 if (blocked_registers[loc.register_code()]) { 419 if (blocked_registers[loc.register_code()]) {
416 return; 420 return;
417 } 421 }
418 422
419 if (blocking_ranges[loc.register_code()] == NULL) { 423 if (blocking_ranges[loc.register_code()] == NULL) {
420 LiveRange* range = new LiveRange(kNoVirtualRegister); 424 Location::Representation ignored = Location::kDouble;
425 LiveRange* range = new LiveRange(kNoVirtualRegister, ignored);
421 blocking_ranges[loc.register_code()] = range; 426 blocking_ranges[loc.register_code()] = range;
422 range->set_assigned_location(loc); 427 range->set_assigned_location(loc);
423 #if defined(DEBUG) 428 #if defined(DEBUG)
424 temporaries_.Add(range); 429 temporaries_.Add(range);
425 #endif 430 #endif
426 } 431 }
427 432
428 blocking_ranges[loc.register_code()]->AddUseInterval(from, to); 433 blocking_ranges[loc.register_code()]->AddUseInterval(from, to);
429 } 434 }
430 435
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 static Location::Kind RegisterKindFromPolicy(Location loc) { 579 static Location::Kind RegisterKindFromPolicy(Location loc) {
575 if (loc.policy() == Location::kRequiresXmmRegister) { 580 if (loc.policy() == Location::kRequiresXmmRegister) {
576 return Location::kXmmRegister; 581 return Location::kXmmRegister;
577 } else { 582 } else {
578 return Location::kRegister; 583 return Location::kRegister;
579 } 584 }
580 } 585 }
581 586
582 587
583 static Location::Kind RegisterKindForResult(Instruction* instr) { 588 static Location::Kind RegisterKindForResult(Instruction* instr) {
584 if (instr->representation() == kUnboxedDouble) { 589 if (instr->representation() == kUnboxedDouble ||
590 instr->representation() == kUnboxedInteger) {
585 return Location::kXmmRegister; 591 return Location::kXmmRegister;
586 } else { 592 } else {
587 return Location::kRegister; 593 return Location::kRegister;
588 } 594 }
589 } 595 }
590 596
591 597
592 // 598 //
593 // When describing shape of live ranges in comments below we are going to use 599 // When describing shape of live ranges in comments below we are going to use
594 // the following notation: 600 // the following notation:
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 // [--) 912 // [--)
907 // 913 //
908 // The stack bitmap describes the position i. 914 // The stack bitmap describes the position i.
909 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 915 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
910 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 916 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
911 pos, 917 pos,
912 pos + 1); 918 pos + 1);
913 } 919 }
914 920
915 for (intptr_t reg = 0; reg < kNumberOfXmmRegisters; reg++) { 921 for (intptr_t reg = 0; reg < kNumberOfXmmRegisters; reg++) {
922 Location::Representation ignored = Location::kDouble;
916 BlockLocation( 923 BlockLocation(
917 Location::XmmRegisterLocation(static_cast<XmmRegister>(reg)), 924 Location::XmmRegisterLocation(static_cast<XmmRegister>(reg), ignored),
918 pos, 925 pos,
919 pos + 1); 926 pos + 1);
920 } 927 }
921 928
922 929
923 #if defined(DEBUG) 930 #if defined(DEBUG)
924 // Verify that temps, inputs and output were specified as fixed 931 // Verify that temps, inputs and output were specified as fixed
925 // locations. Every register is blocked now so attempt to 932 // locations. Every register is blocked now so attempt to
926 // allocate will not succeed. 933 // allocate will not succeed.
927 for (intptr_t j = 0; j < locs->temp_count(); j++) { 934 for (intptr_t j = 0; j < locs->temp_count(); j++) {
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 1382
1376 UsePosition* first_use_after_split = 1383 UsePosition* first_use_after_split =
1377 SplitListOfPositions(&uses_, split_pos, split_at_start); 1384 SplitListOfPositions(&uses_, split_pos, split_at_start);
1378 1385
1379 SafepointPosition* first_safepoint_after_split = 1386 SafepointPosition* first_safepoint_after_split =
1380 SplitListOfPositions(&first_safepoint_, split_pos, split_at_start); 1387 SplitListOfPositions(&first_safepoint_, split_pos, split_at_start);
1381 1388
1382 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? 1389 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ?
1383 first_after_split : last_use_interval_; 1390 first_after_split : last_use_interval_;
1384 next_sibling_ = new LiveRange(vreg(), 1391 next_sibling_ = new LiveRange(vreg(),
1392 representation(),
1385 first_use_after_split, 1393 first_use_after_split,
1386 first_after_split, 1394 first_after_split,
1387 last_use_interval, 1395 last_use_interval,
1388 first_safepoint_after_split, 1396 first_safepoint_after_split,
1389 next_sibling_); 1397 next_sibling_);
1390 1398
1391 TRACE_ALLOC(OS::Print(" split sibling [%"Pd", %"Pd")\n", 1399 TRACE_ALLOC(OS::Print(" split sibling [%"Pd", %"Pd")\n",
1392 next_sibling_->Start(), next_sibling_->End())); 1400 next_sibling_->Start(), next_sibling_->End()));
1393 1401
1394 last_use_interval_ = last_before_split; 1402 last_use_interval_ = last_before_split;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1489 range->set_spill_slot(Location::StackSlot(idx)); 1497 range->set_spill_slot(Location::StackSlot(idx));
1490 } else { 1498 } else {
1491 // Double spill slots are essentially one (x64) or two (ia32) normal 1499 // Double spill slots are essentially one (x64) or two (ia32) normal
1492 // word size spill slots. We use the index of the slot with the lowest 1500 // word size spill slots. We use the index of the slot with the lowest
1493 // address as an index for the double spill slot. In terms of indexes 1501 // address as an index for the double spill slot. In terms of indexes
1494 // this relation is inverted: so we have to take the highest index. 1502 // this relation is inverted: so we have to take the highest index.
1495 const intptr_t slot_idx = 1503 const intptr_t slot_idx =
1496 idx * kDoubleSpillSlotFactor + (kDoubleSpillSlotFactor - 1); 1504 idx * kDoubleSpillSlotFactor + (kDoubleSpillSlotFactor - 1);
1497 range->set_spill_slot( 1505 range->set_spill_slot(
1498 Location::DoubleStackSlot( 1506 Location::DoubleStackSlot(
1499 cpu_spill_slot_count_ + slot_idx)); 1507 cpu_spill_slot_count_ + slot_idx, range->representation()));
1500 } 1508 }
1501 1509
1502 spilled_.Add(range); 1510 spilled_.Add(range);
1503 } 1511 }
1504 1512
1505 1513
1506 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { 1514 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) {
1507 intptr_t stack_index = range->spill_slot().stack_index(); 1515 intptr_t stack_index = range->spill_slot().stack_index();
1508 ASSERT(stack_index >= 0); 1516 ASSERT(stack_index >= 0);
1509 1517
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1590 free_until = intersection; 1598 free_until = intersection;
1591 if (free_until == kMaxPosition) break; 1599 if (free_until == kMaxPosition) break;
1592 } 1600 }
1593 } 1601 }
1594 } 1602 }
1595 1603
1596 // All registers are blocked by active ranges. 1604 // All registers are blocked by active ranges.
1597 if (free_until <= unallocated->Start()) return false; 1605 if (free_until <= unallocated->Start()) return false;
1598 1606
1599 TRACE_ALLOC(OS::Print("assigning free register ")); 1607 TRACE_ALLOC(OS::Print("assigning free register "));
1600 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 1608 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
1601 TRACE_ALLOC(OS::Print(" to %"Pd"\n", unallocated->vreg())); 1609 TRACE_ALLOC(OS::Print(" to %"Pd"\n", unallocated->vreg()));
1602 1610
1603 if (free_until != kMaxPosition) { 1611 if (free_until != kMaxPosition) {
1604 // There was an intersection. Split unallocated. 1612 // There was an intersection. Split unallocated.
1605 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); 1613 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until));
1606 LiveRange* tail = unallocated->SplitAt(free_until); 1614 LiveRange* tail = unallocated->SplitAt(free_until);
1607 AddToUnallocated(tail); 1615 AddToUnallocated(tail);
1608 } 1616 }
1609 1617
1610 registers_[candidate].Add(unallocated); 1618 registers_[candidate].Add(unallocated);
1611 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); 1619 unallocated->set_assigned_location(
1620 MakeRegisterLocation(candidate, unallocated->representation()));
1612 1621
1613 return true; 1622 return true;
1614 } 1623 }
1615 1624
1616 1625
1617 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { 1626 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) {
1618 UsePosition* register_use = 1627 UsePosition* register_use =
1619 unallocated->finger()->FirstRegisterUse(unallocated->Start()); 1628 unallocated->finger()->FirstRegisterUse(unallocated->Start());
1620 if (register_use == NULL) { 1629 if (register_use == NULL) {
1621 Spill(unallocated); 1630 Spill(unallocated);
(...skipping 12 matching lines...) Expand all
1634 } 1643 }
1635 1644
1636 if (free_until < register_use->pos()) { 1645 if (free_until < register_use->pos()) {
1637 // Can't acquire free register. Spill until we really need one. 1646 // Can't acquire free register. Spill until we really need one.
1638 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); 1647 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos()));
1639 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); 1648 SpillBetween(unallocated, unallocated->Start(), register_use->pos());
1640 return; 1649 return;
1641 } 1650 }
1642 1651
1643 TRACE_ALLOC(OS::Print("assigning blocked register ")); 1652 TRACE_ALLOC(OS::Print("assigning blocked register "));
1644 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 1653 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
1645 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n", 1654 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n",
1646 unallocated->vreg(), blocked_at)); 1655 unallocated->vreg(), blocked_at));
1647 1656
1648 if (blocked_at < unallocated->End()) { 1657 if (blocked_at < unallocated->End()) {
1649 // Register is blocked before the end of the live range. Split the range 1658 // Register is blocked before the end of the live range. Split the range
1650 // at latest at blocked_at position. 1659 // at latest at blocked_at position.
1651 LiveRange* tail = SplitBetween(unallocated, 1660 LiveRange* tail = SplitBetween(unallocated,
1652 unallocated->Start(), 1661 unallocated->Start(),
1653 blocked_at + 1); 1662 blocked_at + 1);
1654 AddToUnallocated(tail); 1663 AddToUnallocated(tail);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1740 } 1749 }
1741 registers_[reg][i] = NULL; 1750 registers_[reg][i] = NULL;
1742 first_evicted = i; 1751 first_evicted = i;
1743 } 1752 }
1744 } 1753 }
1745 1754
1746 // Remove evicted ranges from the array. 1755 // Remove evicted ranges from the array.
1747 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 1756 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
1748 1757
1749 registers_[reg].Add(unallocated); 1758 registers_[reg].Add(unallocated);
1750 unallocated->set_assigned_location(MakeRegisterLocation(reg)); 1759 unallocated->set_assigned_location(
1760 MakeRegisterLocation(reg, unallocated->representation()));
1751 } 1761 }
1752 1762
1753 1763
1754 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, 1764 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
1755 LiveRange* unallocated) { 1765 LiveRange* unallocated) {
1756 UseInterval* first_unallocated = 1766 UseInterval* first_unallocated =
1757 unallocated->finger()->first_pending_use_interval(); 1767 unallocated->finger()->first_pending_use_interval();
1758 const intptr_t intersection = FirstIntersection( 1768 const intptr_t intersection = FirstIntersection(
1759 allocated->finger()->first_pending_use_interval(), 1769 allocated->finger()->first_pending_use_interval(),
1760 first_unallocated); 1770 first_unallocated);
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 ASSERT(range->assigned_location().Equals(range->spill_slot())); 2141 ASSERT(range->assigned_location().Equals(range->spill_slot()));
2132 } else { 2142 } else {
2133 AddMoveAt(range->Start() + 1, 2143 AddMoveAt(range->Start() + 1,
2134 range->spill_slot(), 2144 range->spill_slot(),
2135 range->assigned_location()); 2145 range->assigned_location());
2136 } 2146 }
2137 } 2147 }
2138 } 2148 }
2139 2149
2140 2150
2151 void FlowGraphAllocator::CollectRepresentations() {
2152 reps_ = new BitVector(flow_graph_.max_virtual_register_number());
2153
2154 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2155 !it.Done();
2156 it.Advance()) {
2157 BlockEntryInstr* block = it.Current();
2158 // TODO(fschneider): Support unboxed mint representation for phis.
2159 for (ForwardInstructionIterator instr_it(block);
2160 !instr_it.Done();
2161 instr_it.Advance()) {
2162 Instruction* instr = instr_it.Current();
2163 if (instr->IsDefinition() && instr->representation() == kUnboxedInteger) {
2164 reps_->Add(instr->AsDefinition()->ssa_temp_index());
2165 }
2166 }
2167 }
2168 }
2169
2170
2171
2141 void FlowGraphAllocator::AllocateRegisters() { 2172 void FlowGraphAllocator::AllocateRegisters() {
2173 CollectRepresentations();
2174
2142 EliminateEnvironmentUses(); 2175 EliminateEnvironmentUses();
2143 2176
2144 AnalyzeLiveness(); 2177 AnalyzeLiveness();
2145 2178
2146 NumberInstructions(); 2179 NumberInstructions();
2147 2180
2148 DiscoverLoops(); 2181 DiscoverLoops();
2149 2182
2150 BuildLiveRanges(); 2183 BuildLiveRanges();
2151 2184
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2204 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2237 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2205 function.ToFullyQualifiedCString()); 2238 function.ToFullyQualifiedCString());
2206 FlowGraphPrinter printer(flow_graph_, true); 2239 FlowGraphPrinter printer(flow_graph_, true);
2207 printer.PrintBlocks(); 2240 printer.PrintBlocks();
2208 OS::Print("----------------------------------------------\n"); 2241 OS::Print("----------------------------------------------\n");
2209 } 2242 }
2210 } 2243 }
2211 2244
2212 2245
2213 } // namespace dart 2246 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698