| 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 | 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_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
| 13 | 13 |
| 14 namespace dart { | 14 namespace dart { |
| 15 | 15 |
| 16 DEFINE_FLAG(bool, print_ssa_liveness, false, | 16 DEFINE_FLAG(bool, print_ssa_liveness, false, |
| 17 "Print liveness for ssa variables."); | 17 "Print liveness for ssa variables."); |
| 18 DEFINE_FLAG(bool, trace_ssa_allocator, false, | 18 DEFINE_FLAG(bool, trace_ssa_allocator, false, |
| 19 "Trace register allocation over SSA."); | 19 "Trace register allocation over SSA."); |
| 20 DEFINE_FLAG(bool, print_ssa_liveranges, false, | 20 DEFINE_FLAG(bool, print_ssa_liveranges, false, |
| 21 "Print live ranges after allocation."); | 21 "Print live ranges after allocation."); |
| 22 | 22 |
| 23 #if defined(DEBUG) | 23 #if defined(DEBUG) |
| 24 #define TRACE_ALLOC(m) do { \ | 24 #define TRACE_ALLOC(statement) \ |
| 25 if (FLAG_trace_ssa_allocator) OS::Print m ; \ | 25 do { \ |
| 26 if (FLAG_trace_ssa_allocator) statement; \ |
| 26 } while (0) | 27 } while (0) |
| 27 #else | 28 #else |
| 28 #define TRACE_ALLOC(m) | 29 #define TRACE_ALLOC(statement) |
| 29 #endif | 30 #endif |
| 30 | 31 |
| 31 | 32 |
| 32 static const intptr_t kNoVirtualRegister = -1; | 33 static const intptr_t kNoVirtualRegister = -1; |
| 33 static const intptr_t kTempVirtualRegister = -2; | 34 static const intptr_t kTempVirtualRegister = -2; |
| 34 static const intptr_t kIllegalPosition = -1; | 35 static const intptr_t kIllegalPosition = -1; |
| 35 static const intptr_t kMaxPosition = 0x7FFFFFFF; | 36 static const intptr_t kMaxPosition = 0x7FFFFFFF; |
| 36 | 37 |
| 37 | 38 |
| 38 static intptr_t MinPosition(intptr_t a, intptr_t b) { | 39 static intptr_t MinPosition(intptr_t a, intptr_t b) { |
| (...skipping 1129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1168 } | 1169 } |
| 1169 | 1170 |
| 1170 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? | 1171 UseInterval* last_use_interval = (last_before_split == last_use_interval_) ? |
| 1171 first_after_split : last_use_interval_; | 1172 first_after_split : last_use_interval_; |
| 1172 next_sibling_ = new LiveRange(vreg(), | 1173 next_sibling_ = new LiveRange(vreg(), |
| 1173 first_use_after_split, | 1174 first_use_after_split, |
| 1174 first_after_split, | 1175 first_after_split, |
| 1175 last_use_interval, | 1176 last_use_interval, |
| 1176 next_sibling_); | 1177 next_sibling_); |
| 1177 | 1178 |
| 1178 TRACE_ALLOC((" split sibling [%d, %d)\n", | 1179 TRACE_ALLOC(OS::Print(" split sibling [%d, %d)\n", |
| 1179 next_sibling_->Start(), next_sibling_->End())); | 1180 next_sibling_->Start(), next_sibling_->End())); |
| 1180 | 1181 |
| 1181 last_use_interval_ = last_before_split; | 1182 last_use_interval_ = last_before_split; |
| 1182 last_use_interval_->next_ = NULL; | 1183 last_use_interval_->next_ = NULL; |
| 1183 return next_sibling_; | 1184 return next_sibling_; |
| 1184 } | 1185 } |
| 1185 | 1186 |
| 1186 | 1187 |
| 1187 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, | 1188 LiveRange* FlowGraphAllocator::SplitBetween(LiveRange* range, |
| 1188 intptr_t from, | 1189 intptr_t from, |
| 1189 intptr_t to) { | 1190 intptr_t to) { |
| 1190 TRACE_ALLOC(("split %d [%d, %d) between [%d, %d)\n", | 1191 TRACE_ALLOC(OS::Print("split %d [%d, %d) between [%d, %d)\n", |
| 1191 range->vreg(), range->Start(), range->End(), from, to)); | 1192 range->vreg(), range->Start(), range->End(), from, to)); |
| 1192 | 1193 |
| 1193 intptr_t split_pos = kIllegalPosition; | 1194 intptr_t split_pos = kIllegalPosition; |
| 1194 | 1195 |
| 1195 BlockInfo* split_block = BlockInfoAt(to); | 1196 BlockInfo* split_block = BlockInfoAt(to); |
| 1196 if (from < split_block->entry()->lifetime_position()) { | 1197 if (from < split_block->entry()->lifetime_position()) { |
| 1197 // Interval [from, to) spans multiple blocks. | 1198 // Interval [from, to) spans multiple blocks. |
| 1198 | 1199 |
| 1199 // If last block is inside a loop prefer splitting at outermost loop's | 1200 // If last block is inside a loop prefer splitting at outermost loop's |
| 1200 // header. | 1201 // header. |
| 1201 BlockInfo* loop_header = split_block->loop(); | 1202 BlockInfo* loop_header = split_block->loop(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1218 ASSERT((split_pos != kIllegalPosition) && (from < split_pos)); | 1219 ASSERT((split_pos != kIllegalPosition) && (from < split_pos)); |
| 1219 | 1220 |
| 1220 return range->SplitAt(split_pos); | 1221 return range->SplitAt(split_pos); |
| 1221 } | 1222 } |
| 1222 | 1223 |
| 1223 | 1224 |
| 1224 void FlowGraphAllocator::SpillBetween(LiveRange* range, | 1225 void FlowGraphAllocator::SpillBetween(LiveRange* range, |
| 1225 intptr_t from, | 1226 intptr_t from, |
| 1226 intptr_t to) { | 1227 intptr_t to) { |
| 1227 ASSERT(from < to); | 1228 ASSERT(from < to); |
| 1228 TRACE_ALLOC(("spill %d [%d, %d) between [%d, %d)\n", | 1229 TRACE_ALLOC(OS::Print("spill %d [%d, %d) between [%d, %d)\n", |
| 1229 range->vreg(), range->Start(), range->End(), from, to)); | 1230 range->vreg(), range->Start(), range->End(), from, to)); |
| 1230 LiveRange* tail = range->SplitAt(from); | 1231 LiveRange* tail = range->SplitAt(from); |
| 1231 | 1232 |
| 1232 if (tail->Start() < to) { | 1233 if (tail->Start() < to) { |
| 1233 // There is an intersection of tail and [from, to). | 1234 // There is an intersection of tail and [from, to). |
| 1234 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to); | 1235 LiveRange* tail_tail = SplitBetween(tail, tail->Start(), to); |
| 1235 Spill(tail); | 1236 Spill(tail); |
| 1236 AddToUnallocated(tail_tail); | 1237 AddToUnallocated(tail_tail); |
| 1237 } else { | 1238 } else { |
| 1238 // No intersection between tail and [from, to). | 1239 // No intersection between tail and [from, to). |
| 1239 AddToUnallocated(tail); | 1240 AddToUnallocated(tail); |
| 1240 } | 1241 } |
| 1241 } | 1242 } |
| 1242 | 1243 |
| 1243 | 1244 |
| 1244 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { | 1245 void FlowGraphAllocator::SpillAfter(LiveRange* range, intptr_t from) { |
| 1245 TRACE_ALLOC(("spill %d [%d, %d) after %d\n", | 1246 TRACE_ALLOC(OS::Print("spill %d [%d, %d) after %d\n", |
| 1246 range->vreg(), range->Start(), range->End(), from)); | 1247 range->vreg(), range->Start(), range->End(), from)); |
| 1247 LiveRange* tail = range->SplitAt(from); | 1248 LiveRange* tail = range->SplitAt(from); |
| 1248 Spill(tail); | 1249 Spill(tail); |
| 1249 } | 1250 } |
| 1250 | 1251 |
| 1251 | 1252 |
| 1252 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { | 1253 void FlowGraphAllocator::AllocateSpillSlotFor(LiveRange* range) { |
| 1253 ASSERT(range->spill_slot().IsInvalid()); | 1254 ASSERT(range->spill_slot().IsInvalid()); |
| 1254 | 1255 |
| 1255 intptr_t idx = 0; | 1256 intptr_t idx = 0; |
| 1256 for (; idx < spill_slots_.length(); idx++) { | 1257 for (; idx < spill_slots_.length(); idx++) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 // TODO(vegorov): ensure that phis are hinted on the back edge. | 1312 // TODO(vegorov): ensure that phis are hinted on the back edge. |
| 1312 Location hint = unallocated->finger()->FirstHint(); | 1313 Location hint = unallocated->finger()->FirstHint(); |
| 1313 if (!hint.IsInvalid()) { | 1314 if (!hint.IsInvalid()) { |
| 1314 ASSERT(hint.IsRegister()); | 1315 ASSERT(hint.IsRegister()); |
| 1315 | 1316 |
| 1316 if (!blocked_cpu_regs_[hint.reg()]) { | 1317 if (!blocked_cpu_regs_[hint.reg()]) { |
| 1317 free_until = FirstIntersectionWithAllocated(hint.reg(), unallocated); | 1318 free_until = FirstIntersectionWithAllocated(hint.reg(), unallocated); |
| 1318 candidate = hint.reg(); | 1319 candidate = hint.reg(); |
| 1319 } | 1320 } |
| 1320 | 1321 |
| 1321 TRACE_ALLOC(("found hint %s for %d: free until %d\n", | 1322 TRACE_ALLOC(OS::Print("found hint ")); |
| 1322 hint.Name(), unallocated->vreg(), free_until)); | 1323 TRACE_ALLOC(hint.Print()); |
| 1324 TRACE_ALLOC(OS::Print(" for %d: free until %d\n", |
| 1325 unallocated->vreg(), free_until)); |
| 1323 } | 1326 } |
| 1324 | 1327 |
| 1325 if (free_until != kMaxPosition) { | 1328 if (free_until != kMaxPosition) { |
| 1326 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; ++reg) { | 1329 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; ++reg) { |
| 1327 if (!blocked_cpu_regs_[reg] && cpu_regs_[reg].length() == 0) { | 1330 if (!blocked_cpu_regs_[reg] && cpu_regs_[reg].length() == 0) { |
| 1328 candidate = static_cast<Register>(reg); | 1331 candidate = static_cast<Register>(reg); |
| 1329 free_until = kMaxPosition; | 1332 free_until = kMaxPosition; |
| 1330 break; | 1333 break; |
| 1331 } | 1334 } |
| 1332 } | 1335 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1344 candidate = static_cast<Register>(reg); | 1347 candidate = static_cast<Register>(reg); |
| 1345 free_until = intersection; | 1348 free_until = intersection; |
| 1346 if (free_until == kMaxPosition) break; | 1349 if (free_until == kMaxPosition) break; |
| 1347 } | 1350 } |
| 1348 } | 1351 } |
| 1349 } | 1352 } |
| 1350 | 1353 |
| 1351 // All registers are blocked by active ranges. | 1354 // All registers are blocked by active ranges. |
| 1352 if (free_until <= unallocated->Start()) return false; | 1355 if (free_until <= unallocated->Start()) return false; |
| 1353 | 1356 |
| 1354 TRACE_ALLOC(("assigning free register %s to %d\n", | 1357 TRACE_ALLOC(OS::Print("assigning free register ")); |
| 1355 Location::RegisterLocation(candidate).Name(), | 1358 TRACE_ALLOC(Location::RegisterLocation(candidate).Print()); |
| 1356 unallocated->vreg())); | 1359 TRACE_ALLOC(OS::Print(" to %d\n", unallocated->vreg())); |
| 1357 | 1360 |
| 1358 if (free_until != kMaxPosition) { | 1361 if (free_until != kMaxPosition) { |
| 1359 // There was an intersection. Split unallocated. | 1362 // There was an intersection. Split unallocated. |
| 1360 TRACE_ALLOC((" splitting at %d\n", free_until)); | 1363 TRACE_ALLOC(OS::Print(" splitting at %d\n", free_until)); |
| 1361 LiveRange* tail = unallocated->SplitAt(free_until); | 1364 LiveRange* tail = unallocated->SplitAt(free_until); |
| 1362 AddToUnallocated(tail); | 1365 AddToUnallocated(tail); |
| 1363 } | 1366 } |
| 1364 | 1367 |
| 1365 cpu_regs_[candidate].Add(unallocated); | 1368 cpu_regs_[candidate].Add(unallocated); |
| 1366 unallocated->set_assigned_location(Location::RegisterLocation(candidate)); | 1369 unallocated->set_assigned_location(Location::RegisterLocation(candidate)); |
| 1367 | 1370 |
| 1368 return true; | 1371 return true; |
| 1369 } | 1372 } |
| 1370 | 1373 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1391 } | 1394 } |
| 1392 } | 1395 } |
| 1393 | 1396 |
| 1394 if (free_until < register_use->pos()) { | 1397 if (free_until < register_use->pos()) { |
| 1395 // Can't acquire free register. Spill until we really need one. | 1398 // Can't acquire free register. Spill until we really need one. |
| 1396 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); | 1399 ASSERT(unallocated->Start() < ToInstructionStart(register_use->pos())); |
| 1397 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); | 1400 SpillBetween(unallocated, unallocated->Start(), register_use->pos()); |
| 1398 return; | 1401 return; |
| 1399 } | 1402 } |
| 1400 | 1403 |
| 1401 TRACE_ALLOC(("assigning blocked register %s to live range %d until %d\n", | 1404 TRACE_ALLOC(OS::Print("assigning blocked register ")); |
| 1402 Location::RegisterLocation(candidate).Name(), | 1405 TRACE_ALLOC(Location::RegisterLocation(candidate).Print()); |
| 1403 unallocated->vreg(), | 1406 TRACE_ALLOC(OS::Print(" to live range %d until %d\n", |
| 1404 blocked_at)); | 1407 unallocated->vreg(), blocked_at)); |
| 1405 | 1408 |
| 1406 if (blocked_at < unallocated->End()) { | 1409 if (blocked_at < unallocated->End()) { |
| 1407 LiveRange* tail = SplitBetween(unallocated, | 1410 LiveRange* tail = SplitBetween(unallocated, |
| 1408 unallocated->Start(), | 1411 unallocated->Start(), |
| 1409 blocked_at); | 1412 blocked_at); |
| 1410 AddToUnallocated(tail); | 1413 AddToUnallocated(tail); |
| 1411 } | 1414 } |
| 1412 | 1415 |
| 1413 AssignNonFreeRegister(unallocated, candidate); | 1416 AssignNonFreeRegister(unallocated, candidate); |
| 1414 } | 1417 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1551 } | 1554 } |
| 1552 | 1555 |
| 1553 | 1556 |
| 1554 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { | 1557 void FlowGraphAllocator::ConvertUseTo(UsePosition* use, Location loc) { |
| 1555 ASSERT(use->location_slot() != NULL); | 1558 ASSERT(use->location_slot() != NULL); |
| 1556 Location* slot = use->location_slot(); | 1559 Location* slot = use->location_slot(); |
| 1557 ASSERT(slot->IsUnallocated()); | 1560 ASSERT(slot->IsUnallocated()); |
| 1558 ASSERT((slot->policy() == Location::kRequiresRegister) || | 1561 ASSERT((slot->policy() == Location::kRequiresRegister) || |
| 1559 (slot->policy() == Location::kPrefersRegister) || | 1562 (slot->policy() == Location::kPrefersRegister) || |
| 1560 (slot->policy() == Location::kAny)); | 1563 (slot->policy() == Location::kAny)); |
| 1561 TRACE_ALLOC((" use at %d converted to %s\n", use->pos(), loc.Name())); | 1564 TRACE_ALLOC(OS::Print(" use at %d converted to ", use->pos())); |
| 1565 TRACE_ALLOC(loc.Print()); |
| 1566 TRACE_ALLOC(OS::Print("\n")); |
| 1562 *slot = loc; | 1567 *slot = loc; |
| 1563 } | 1568 } |
| 1564 | 1569 |
| 1565 | 1570 |
| 1566 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { | 1571 void FlowGraphAllocator::ConvertAllUses(LiveRange* range) { |
| 1567 if (range->vreg() == kNoVirtualRegister) return; | 1572 if (range->vreg() == kNoVirtualRegister) return; |
| 1568 TRACE_ALLOC(("range [%d, %d) for v%d has been allocated to %s:\n", | 1573 TRACE_ALLOC(OS::Print("range [%d, %d) for v%d has been allocated to ", |
| 1569 range->Start(), | 1574 range->Start(), range->End(), range->vreg())); |
| 1570 range->End(), | 1575 TRACE_ALLOC(range->assigned_location().Print()); |
| 1571 range->vreg(), | 1576 TRACE_ALLOC(OS::Print(":\n")); |
| 1572 range->assigned_location().Name())); | |
| 1573 ASSERT(!range->assigned_location().IsInvalid()); | 1577 ASSERT(!range->assigned_location().IsInvalid()); |
| 1574 const Location loc = range->assigned_location(); | 1578 const Location loc = range->assigned_location(); |
| 1575 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { | 1579 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { |
| 1576 ConvertUseTo(use, loc); | 1580 ConvertUseTo(use, loc); |
| 1577 } | 1581 } |
| 1578 } | 1582 } |
| 1579 | 1583 |
| 1580 | 1584 |
| 1581 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { | 1585 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { |
| 1582 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 1586 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 if (cpu_regs_[i].length() == 1) { | 1647 if (cpu_regs_[i].length() == 1) { |
| 1644 LiveRange* range = cpu_regs_[i][0]; | 1648 LiveRange* range = cpu_regs_[i][0]; |
| 1645 range->finger()->Initialize(range); | 1649 range->finger()->Initialize(range); |
| 1646 } | 1650 } |
| 1647 } | 1651 } |
| 1648 | 1652 |
| 1649 while (!unallocated_.is_empty()) { | 1653 while (!unallocated_.is_empty()) { |
| 1650 LiveRange* range = unallocated_.Last(); | 1654 LiveRange* range = unallocated_.Last(); |
| 1651 unallocated_.RemoveLast(); | 1655 unallocated_.RemoveLast(); |
| 1652 const intptr_t start = range->Start(); | 1656 const intptr_t start = range->Start(); |
| 1653 TRACE_ALLOC(("Processing live range for vreg %d starting at %d\n", | 1657 TRACE_ALLOC(OS::Print("Processing live range for vreg %d starting at %d\n", |
| 1654 range->vreg(), | 1658 range->vreg(), |
| 1655 start)); | 1659 start)); |
| 1656 | 1660 |
| 1657 // TODO(vegorov): eagerly spill liveranges without register uses. | 1661 // TODO(vegorov): eagerly spill liveranges without register uses. |
| 1658 AdvanceActiveIntervals(start); | 1662 AdvanceActiveIntervals(start); |
| 1659 | 1663 |
| 1660 if (!AllocateFreeRegister(range)) { | 1664 if (!AllocateFreeRegister(range)) { |
| 1661 AllocateAnyRegister(range); | 1665 AllocateAnyRegister(range); |
| 1662 } | 1666 } |
| 1663 } | 1667 } |
| 1664 | 1668 |
| 1665 // All allocation decisions were done. | 1669 // All allocation decisions were done. |
| 1666 ASSERT(unallocated_.is_empty()); | 1670 ASSERT(unallocated_.is_empty()); |
| 1667 | 1671 |
| 1668 // Finish allocation. | 1672 // Finish allocation. |
| 1669 AdvanceActiveIntervals(kMaxPosition); | 1673 AdvanceActiveIntervals(kMaxPosition); |
| 1670 TRACE_ALLOC(("Allocation completed\n")); | 1674 TRACE_ALLOC(OS::Print("Allocation completed\n")); |
| 1671 } | 1675 } |
| 1672 | 1676 |
| 1673 | 1677 |
| 1674 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, | 1678 void FlowGraphAllocator::ConnectSplitSiblings(LiveRange* parent, |
| 1675 BlockEntryInstr* source_block, | 1679 BlockEntryInstr* source_block, |
| 1676 BlockEntryInstr* target_block) { | 1680 BlockEntryInstr* target_block) { |
| 1677 TRACE_ALLOC(("Connect source_block=%d, target_block=%d\n", | 1681 TRACE_ALLOC(OS::Print("Connect source_block=%d, target_block=%d\n", |
| 1678 source_block->block_id(), | 1682 source_block->block_id(), |
| 1679 target_block->block_id())); | 1683 target_block->block_id())); |
| 1680 if (parent->next_sibling() == NULL) { | 1684 if (parent->next_sibling() == NULL) { |
| 1681 // Nothing to connect. The whole range was allocated to the same location. | 1685 // Nothing to connect. The whole range was allocated to the same location. |
| 1682 TRACE_ALLOC(("range %d has no siblings\n", parent->vreg())); | 1686 TRACE_ALLOC(OS::Print("range %d has no siblings\n", parent->vreg())); |
| 1683 return; | 1687 return; |
| 1684 } | 1688 } |
| 1685 | 1689 |
| 1686 const intptr_t source_pos = source_block->end_pos() - 1; | 1690 const intptr_t source_pos = source_block->end_pos() - 1; |
| 1687 ASSERT(IsInstructionEndPosition(source_pos)); | 1691 ASSERT(IsInstructionEndPosition(source_pos)); |
| 1688 | 1692 |
| 1689 const intptr_t target_pos = target_block->start_pos(); | 1693 const intptr_t target_pos = target_block->start_pos(); |
| 1690 | 1694 |
| 1691 Location target; | 1695 Location target; |
| 1692 Location source; | 1696 Location source; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1709 ASSERT(target.IsInvalid()); | 1713 ASSERT(target.IsInvalid()); |
| 1710 target = range->assigned_location(); | 1714 target = range->assigned_location(); |
| 1711 #if defined(DEBUG) | 1715 #if defined(DEBUG) |
| 1712 target_cover = range; | 1716 target_cover = range; |
| 1713 #endif | 1717 #endif |
| 1714 } | 1718 } |
| 1715 | 1719 |
| 1716 range = range->next_sibling(); | 1720 range = range->next_sibling(); |
| 1717 } | 1721 } |
| 1718 | 1722 |
| 1719 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n", | 1723 TRACE_ALLOC(OS::Print("connecting [%d, %d) [", |
| 1720 source_cover->Start(), source_cover->End(), source.Name(), | 1724 source_cover->Start(), source_cover->End())); |
| 1721 target_cover->Start(), target_cover->End(), target.Name())); | 1725 TRACE_ALLOC(source.Print()); |
| 1726 TRACE_ALLOC(OS::Print("] to [%d, %d) [", |
| 1727 target_cover->Start(), target_cover->End())); |
| 1728 TRACE_ALLOC(target.Print()); |
| 1729 TRACE_ALLOC(OS::Print("]\n")); |
| 1722 | 1730 |
| 1723 // Siblings were allocated to the same register. | 1731 // Siblings were allocated to the same register. |
| 1724 if (source.Equals(target)) return; | 1732 if (source.Equals(target)) return; |
| 1725 | 1733 |
| 1726 // Values are eagerly spilled. Spill slot already contains appropriate value. | 1734 // Values are eagerly spilled. Spill slot already contains appropriate value. |
| 1727 if (target.IsStackSlot()) { | 1735 if (target.IsStackSlot()) { |
| 1728 ASSERT(parent->spill_slot().Equals(target)); | 1736 ASSERT(parent->spill_slot().Equals(target)); |
| 1729 return; | 1737 return; |
| 1730 } | 1738 } |
| 1731 | 1739 |
| 1732 Instruction* last = source_block->last_instruction(); | 1740 Instruction* last = source_block->last_instruction(); |
| 1733 if ((last->SuccessorCount() == 1) && !source_block->IsGraphEntry()) { | 1741 if ((last->SuccessorCount() == 1) && !source_block->IsGraphEntry()) { |
| 1734 ASSERT(last->IsGoto()); | 1742 ASSERT(last->IsGoto()); |
| 1735 last->AsGoto()->GetParallelMove()->AddMove(target, source); | 1743 last->AsGoto()->GetParallelMove()->AddMove(target, source); |
| 1736 } else { | 1744 } else { |
| 1737 target_block->GetParallelMove()->AddMove(target, source); | 1745 target_block->GetParallelMove()->AddMove(target, source); |
| 1738 } | 1746 } |
| 1739 } | 1747 } |
| 1740 | 1748 |
| 1741 | 1749 |
| 1742 void FlowGraphAllocator::ResolveControlFlow() { | 1750 void FlowGraphAllocator::ResolveControlFlow() { |
| 1743 // Resolve linear control flow between touching split siblings | 1751 // Resolve linear control flow between touching split siblings |
| 1744 // inside basic blocks. | 1752 // inside basic blocks. |
| 1745 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { | 1753 for (intptr_t vreg = 0; vreg < live_ranges_.length(); vreg++) { |
| 1746 LiveRange* range = live_ranges_[vreg]; | 1754 LiveRange* range = live_ranges_[vreg]; |
| 1747 if (range == NULL) continue; | 1755 if (range == NULL) continue; |
| 1748 | 1756 |
| 1749 while (range->next_sibling() != NULL) { | 1757 while (range->next_sibling() != NULL) { |
| 1750 LiveRange* sibling = range->next_sibling(); | 1758 LiveRange* sibling = range->next_sibling(); |
| 1751 TRACE_ALLOC(("connecting [%d, %d) [%s] to [%d, %d) [%s]\n", | 1759 TRACE_ALLOC(OS::Print("connecting [%d, %d) [", |
| 1752 range->Start(), range->End(), | 1760 range->Start(), range->End())); |
| 1753 range->assigned_location().Name(), | 1761 TRACE_ALLOC(range->assigned_location().Print()); |
| 1754 sibling->Start(), sibling->End(), | 1762 TRACE_ALLOC(OS::Print("] to [%d, %d) [", |
| 1755 sibling->assigned_location().Name())); | 1763 sibling->Start(), sibling->End())); |
| 1764 TRACE_ALLOC(sibling->assigned_location().Print()); |
| 1765 TRACE_ALLOC(OS::Print("]\n")); |
| 1756 if ((range->End() == sibling->Start()) && | 1766 if ((range->End() == sibling->Start()) && |
| 1757 !sibling->assigned_location().IsStackSlot() && | 1767 !sibling->assigned_location().IsStackSlot() && |
| 1758 !range->assigned_location().Equals(sibling->assigned_location()) && | 1768 !range->assigned_location().Equals(sibling->assigned_location()) && |
| 1759 !IsBlockEntry(range->End())) { | 1769 !IsBlockEntry(range->End())) { |
| 1760 AddMoveAt(sibling->Start(), | 1770 AddMoveAt(sibling->Start(), |
| 1761 sibling->assigned_location(), | 1771 sibling->assigned_location(), |
| 1762 range->assigned_location()); | 1772 range->assigned_location()); |
| 1763 } | 1773 } |
| 1764 range = sibling; | 1774 range = sibling; |
| 1765 } | 1775 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1827 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 1837 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 1828 function.ToFullyQualifiedCString()); | 1838 function.ToFullyQualifiedCString()); |
| 1829 FlowGraphPrinter printer(Function::Handle(), block_order_, true); | 1839 FlowGraphPrinter printer(Function::Handle(), block_order_, true); |
| 1830 printer.PrintBlocks(); | 1840 printer.PrintBlocks(); |
| 1831 OS::Print("----------------------------------------------\n"); | 1841 OS::Print("----------------------------------------------\n"); |
| 1832 } | 1842 } |
| 1833 } | 1843 } |
| 1834 | 1844 |
| 1835 | 1845 |
| 1836 } // namespace dart | 1846 } // namespace dart |
| OLD | NEW |