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

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: addressed comments, added tests and flags Created 8 years, 2 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 mint_values_(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 mint_values_->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) {
srdjan 2012/09/28 16:50:26 Add parenthesis
Florian Schneider 2012/10/02 11:10:31 Done.
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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 // [--) 913 // [--)
908 // 914 //
909 // The stack bitmap describes the position i. 915 // The stack bitmap describes the position i.
910 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { 916 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) {
911 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), 917 BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)),
912 pos, 918 pos,
913 pos + 1); 919 pos + 1);
914 } 920 }
915 921
916 for (intptr_t reg = 0; reg < kNumberOfXmmRegisters; reg++) { 922 for (intptr_t reg = 0; reg < kNumberOfXmmRegisters; reg++) {
923 Location::Representation ignored = Location::kDouble;
917 BlockLocation( 924 BlockLocation(
918 Location::XmmRegisterLocation(static_cast<XmmRegister>(reg)), 925 Location::XmmRegisterLocation(static_cast<XmmRegister>(reg), ignored),
919 pos, 926 pos,
920 pos + 1); 927 pos + 1);
921 } 928 }
922 929
923 930
924 #if defined(DEBUG) 931 #if defined(DEBUG)
925 // Verify that temps, inputs and output were specified as fixed 932 // Verify that temps, inputs and output were specified as fixed
926 // locations. Every register is blocked now so attempt to 933 // locations. Every register is blocked now so attempt to
927 // allocate will not succeed. 934 // allocate will not succeed.
928 for (intptr_t j = 0; j < locs->temp_count(); j++) { 935 for (intptr_t j = 0; j < locs->temp_count(); j++) {
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 1383
1377 UsePosition* first_use_after_split = 1384 UsePosition* first_use_after_split =
1378 SplitListOfPositions(&uses_, split_pos, split_at_start); 1385 SplitListOfPositions(&uses_, split_pos, split_at_start);
1379 1386
1380 SafepointPosition* first_safepoint_after_split = 1387 SafepointPosition* first_safepoint_after_split =
1381 SplitListOfPositions(&first_safepoint_, split_pos, split_at_start); 1388 SplitListOfPositions(&first_safepoint_, split_pos, split_at_start);
1382 1389
1383 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? 1390 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ?
1384 first_after_split : last_use_interval_; 1391 first_after_split : last_use_interval_;
1385 next_sibling_ = new LiveRange(vreg(), 1392 next_sibling_ = new LiveRange(vreg(),
1393 representation(),
1386 first_use_after_split, 1394 first_use_after_split,
1387 first_after_split, 1395 first_after_split,
1388 last_use_interval, 1396 last_use_interval,
1389 first_safepoint_after_split, 1397 first_safepoint_after_split,
1390 next_sibling_); 1398 next_sibling_);
1391 1399
1392 TRACE_ALLOC(OS::Print(" split sibling [%"Pd", %"Pd")\n", 1400 TRACE_ALLOC(OS::Print(" split sibling [%"Pd", %"Pd")\n",
1393 next_sibling_->Start(), next_sibling_->End())); 1401 next_sibling_->Start(), next_sibling_->End()));
1394 1402
1395 last_use_interval_ = last_before_split; 1403 last_use_interval_ = last_before_split;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 range->set_spill_slot(Location::StackSlot(idx)); 1498 range->set_spill_slot(Location::StackSlot(idx));
1491 } else { 1499 } else {
1492 // Double spill slots are essentially one (x64) or two (ia32) normal 1500 // Double spill slots are essentially one (x64) or two (ia32) normal
1493 // word size spill slots. We use the index of the slot with the lowest 1501 // word size spill slots. We use the index of the slot with the lowest
1494 // address as an index for the double spill slot. In terms of indexes 1502 // address as an index for the double spill slot. In terms of indexes
1495 // this relation is inverted: so we have to take the highest index. 1503 // this relation is inverted: so we have to take the highest index.
1496 const intptr_t slot_idx = 1504 const intptr_t slot_idx =
1497 idx * kDoubleSpillSlotFactor + (kDoubleSpillSlotFactor - 1); 1505 idx * kDoubleSpillSlotFactor + (kDoubleSpillSlotFactor - 1);
1498 range->set_spill_slot( 1506 range->set_spill_slot(
1499 Location::DoubleStackSlot( 1507 Location::DoubleStackSlot(
1500 cpu_spill_slot_count_ + slot_idx)); 1508 cpu_spill_slot_count_ + slot_idx, range->representation()));
1501 } 1509 }
1502 1510
1503 spilled_.Add(range); 1511 spilled_.Add(range);
1504 } 1512 }
1505 1513
1506 1514
1507 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { 1515 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) {
1508 intptr_t stack_index = range->spill_slot().stack_index(); 1516 intptr_t stack_index = range->spill_slot().stack_index();
1509 ASSERT(stack_index >= 0); 1517 ASSERT(stack_index >= 0);
1510 1518
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 free_until = intersection; 1599 free_until = intersection;
1592 if (free_until == kMaxPosition) break; 1600 if (free_until == kMaxPosition) break;
1593 } 1601 }
1594 } 1602 }
1595 } 1603 }
1596 1604
1597 // All registers are blocked by active ranges. 1605 // All registers are blocked by active ranges.
1598 if (free_until <= unallocated->Start()) return false; 1606 if (free_until <= unallocated->Start()) return false;
1599 1607
1600 TRACE_ALLOC(OS::Print("assigning free register ")); 1608 TRACE_ALLOC(OS::Print("assigning free register "));
1601 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 1609 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
1602 TRACE_ALLOC(OS::Print(" to %"Pd"\n", unallocated->vreg())); 1610 TRACE_ALLOC(OS::Print(" to %"Pd"\n", unallocated->vreg()));
1603 1611
1604 if (free_until != kMaxPosition) { 1612 if (free_until != kMaxPosition) {
1605 // There was an intersection. Split unallocated. 1613 // There was an intersection. Split unallocated.
1606 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until)); 1614 TRACE_ALLOC(OS::Print(" splitting at %"Pd"\n", free_until));
1607 LiveRange* tail = unallocated->SplitAt(free_until); 1615 LiveRange* tail = unallocated->SplitAt(free_until);
1608 AddToUnallocated(tail); 1616 AddToUnallocated(tail);
1609 } 1617 }
1610 1618
1611 registers_[candidate].Add(unallocated); 1619 registers_[candidate].Add(unallocated);
1612 unallocated->set_assigned_location(MakeRegisterLocation(candidate)); 1620 unallocated->set_assigned_location(
1621 MakeRegisterLocation(candidate, unallocated->representation()));
1613 1622
1614 return true; 1623 return true;
1615 } 1624 }
1616 1625
1617 1626
1618 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { 1627 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) {
1619 UsePosition* register_use = 1628 UsePosition* register_use =
1620 unallocated->finger()->FirstRegisterUse(unallocated->Start()); 1629 unallocated->finger()->FirstRegisterUse(unallocated->Start());
1621 if (register_use == NULL) { 1630 if (register_use == NULL) {
1622 Spill(unallocated); 1631 Spill(unallocated);
(...skipping 12 matching lines...) Expand all
1635 } 1644 }
1636 1645
1637 if (free_until < register_use->pos()) { 1646 if (free_until < register_use->pos()) {
1638 // Can't acquire free register. Spill until we really need one. 1647 // Can't acquire free register. Spill until we really need one.
1639 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); 1648 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos()));
1640 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); 1649 SpillBetween(unallocated, unallocated->Start(), register_use->pos());
1641 return; 1650 return;
1642 } 1651 }
1643 1652
1644 TRACE_ALLOC(OS::Print("assigning blocked register ")); 1653 TRACE_ALLOC(OS::Print("assigning blocked register "));
1645 TRACE_ALLOC(MakeRegisterLocation(candidate).Print()); 1654 TRACE_ALLOC(MakeRegisterLocation(candidate, Location::kDouble).Print());
1646 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n", 1655 TRACE_ALLOC(OS::Print(" to live range %"Pd" until %"Pd"\n",
1647 unallocated->vreg(), blocked_at)); 1656 unallocated->vreg(), blocked_at));
1648 1657
1649 if (blocked_at < unallocated->End()) { 1658 if (blocked_at < unallocated->End()) {
1650 // Register is blocked before the end of the live range. Split the range 1659 // Register is blocked before the end of the live range. Split the range
1651 // at latest at blocked_at position. 1660 // at latest at blocked_at position.
1652 LiveRange* tail = SplitBetween(unallocated, 1661 LiveRange* tail = SplitBetween(unallocated,
1653 unallocated->Start(), 1662 unallocated->Start(),
1654 blocked_at + 1); 1663 blocked_at + 1);
1655 AddToUnallocated(tail); 1664 AddToUnallocated(tail);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 } 1750 }
1742 registers_[reg][i] = NULL; 1751 registers_[reg][i] = NULL;
1743 first_evicted = i; 1752 first_evicted = i;
1744 } 1753 }
1745 } 1754 }
1746 1755
1747 // Remove evicted ranges from the array. 1756 // Remove evicted ranges from the array.
1748 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); 1757 if (first_evicted != -1) RemoveEvicted(reg, first_evicted);
1749 1758
1750 registers_[reg].Add(unallocated); 1759 registers_[reg].Add(unallocated);
1751 unallocated->set_assigned_location(MakeRegisterLocation(reg)); 1760 unallocated->set_assigned_location(
1761 MakeRegisterLocation(reg, unallocated->representation()));
1752 } 1762 }
1753 1763
1754 1764
1755 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated, 1765 bool FlowGraphAllocator::EvictIntersection(LiveRange* allocated,
1756 LiveRange* unallocated) { 1766 LiveRange* unallocated) {
1757 UseInterval* first_unallocated = 1767 UseInterval* first_unallocated =
1758 unallocated->finger()->first_pending_use_interval(); 1768 unallocated->finger()->first_pending_use_interval();
1759 const intptr_t intersection = FirstIntersection( 1769 const intptr_t intersection = FirstIntersection(
1760 allocated->finger()->first_pending_use_interval(), 1770 allocated->finger()->first_pending_use_interval(),
1761 first_unallocated); 1771 first_unallocated);
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2132 ASSERT(range->assigned_location().Equals(range->spill_slot())); 2142 ASSERT(range->assigned_location().Equals(range->spill_slot()));
2133 } else { 2143 } else {
2134 AddMoveAt(range->Start() + 1, 2144 AddMoveAt(range->Start() + 1,
2135 range->spill_slot(), 2145 range->spill_slot(),
2136 range->assigned_location()); 2146 range->assigned_location());
2137 } 2147 }
2138 } 2148 }
2139 } 2149 }
2140 2150
2141 2151
2152 void FlowGraphAllocator::CollectRepresentations() {
2153 mint_values_ = new BitVector(flow_graph_.max_virtual_register_number());
2154
2155 for (BlockIterator it = flow_graph_.reverse_postorder_iterator();
2156 !it.Done();
2157 it.Advance()) {
2158 BlockEntryInstr* block = it.Current();
2159 // TODO(fschneider): Support unboxed mint representation for phis.
2160 for (ForwardInstructionIterator instr_it(block);
2161 !instr_it.Done();
2162 instr_it.Advance()) {
2163 Instruction* instr = instr_it.Current();
2164 if (instr->IsDefinition() && instr->representation() == kUnboxedInteger) {
2165 mint_values_->Add(instr->AsDefinition()->ssa_temp_index());
2166 }
2167 }
2168 }
2169 }
2170
2171
2172
2142 void FlowGraphAllocator::AllocateRegisters() { 2173 void FlowGraphAllocator::AllocateRegisters() {
2174 CollectRepresentations();
2175
2143 EliminateEnvironmentUses(); 2176 EliminateEnvironmentUses();
2144 2177
2145 AnalyzeLiveness(); 2178 AnalyzeLiveness();
2146 2179
2147 NumberInstructions(); 2180 NumberInstructions();
2148 2181
2149 DiscoverLoops(); 2182 DiscoverLoops();
2150 2183
2151 BuildLiveRanges(); 2184 BuildLiveRanges();
2152 2185
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", 2238 OS::Print("-- [after ssa allocator] ir [%s] -------------\n",
2206 function.ToFullyQualifiedCString()); 2239 function.ToFullyQualifiedCString());
2207 FlowGraphPrinter printer(flow_graph_, true); 2240 FlowGraphPrinter printer(flow_graph_, true);
2208 printer.PrintBlocks(); 2241 printer.PrintBlocks();
2209 OS::Print("----------------------------------------------\n"); 2242 OS::Print("----------------------------------------------\n");
2210 } 2243 }
2211 } 2244 }
2212 2245
2213 2246
2214 } // namespace dart 2247 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698