| 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" |
| (...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const { | 853 Instruction* FlowGraphAllocator::InstructionAt(intptr_t pos) const { |
| 854 return instructions_[pos / 2]; | 854 return instructions_[pos / 2]; |
| 855 } | 855 } |
| 856 | 856 |
| 857 | 857 |
| 858 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const { | 858 bool FlowGraphAllocator::IsBlockEntry(intptr_t pos) const { |
| 859 return InstructionAt(pos)->IsBlockEntry(); | 859 return InstructionAt(pos)->IsBlockEntry(); |
| 860 } | 860 } |
| 861 | 861 |
| 862 | 862 |
| 863 static UsePosition* FirstUseAfter(UsePosition* use, intptr_t after) { | 863 void AllocationFinger::Initialize(LiveRange* range) { |
| 864 while ((use != NULL) && (use->pos() < after)) { | 864 first_pending_use_interval_ = range->first_use_interval(); |
| 865 use = use->next(); | 865 first_register_use_ = range->first_use(); |
| 866 } | 866 first_register_beneficial_use_ = range->first_use(); |
| 867 return use; | 867 first_hinted_use_ = range->first_use(); |
| 868 } | 868 } |
| 869 | 869 |
| 870 | 870 |
| 871 bool AllocationFinger::Advance(const intptr_t start) { |
| 872 UseInterval* a = first_pending_use_interval_; |
| 873 while (a != NULL && a->end() <= start) a = a->next(); |
| 874 first_pending_use_interval_ = a; |
| 875 if (first_pending_use_interval_ == NULL) { |
| 876 return true; |
| 877 } |
| 878 return false; |
| 879 } |
| 880 |
| 881 |
| 871 Location AllocationFinger::FirstHint() { | 882 Location AllocationFinger::FirstHint() { |
| 872 UsePosition* use = first_hinted_use_; | 883 UsePosition* use = first_hinted_use_; |
| 873 | 884 |
| 874 while (use != NULL) { | 885 while (use != NULL) { |
| 875 if (use->HasHint()) return use->hint(); | 886 if (use->HasHint()) return use->hint(); |
| 876 use = use->next(); | 887 use = use->next(); |
| 877 } | 888 } |
| 878 | 889 |
| 879 return Location::NoLocation(); | 890 return Location::NoLocation(); |
| 880 } | 891 } |
| 881 | 892 |
| 882 | 893 |
| 894 static UsePosition* FirstUseAfter(UsePosition* use, intptr_t after) { |
| 895 while ((use != NULL) && (use->pos() < after)) { |
| 896 use = use->next(); |
| 897 } |
| 898 return use; |
| 899 } |
| 900 |
| 901 |
| 883 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { | 902 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { |
| 884 for (UsePosition* use = FirstUseAfter(first_register_use_, after); | 903 for (UsePosition* use = FirstUseAfter(first_register_use_, after); |
| 885 use != NULL; | 904 use != NULL; |
| 886 use = use->next()) { | 905 use = use->next()) { |
| 887 Location* loc = use->location_slot(); | 906 Location* loc = use->location_slot(); |
| 888 if ((loc != NULL) && | 907 if ((loc != NULL) && |
| 889 loc->IsUnallocated() && | 908 loc->IsUnallocated() && |
| 890 (loc->policy() == Location::kRequiresRegister)) { | 909 (loc->policy() == Location::kRequiresRegister)) { |
| 891 first_register_use_ = use; | 910 first_register_use_ = use; |
| 892 return use; | 911 return use; |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 | 1180 |
| 1162 cpu_regs_[candidate].Add(unallocated); | 1181 cpu_regs_[candidate].Add(unallocated); |
| 1163 unallocated->set_assigned_location(Location::RegisterLocation(candidate)); | 1182 unallocated->set_assigned_location(Location::RegisterLocation(candidate)); |
| 1164 | 1183 |
| 1165 return true; | 1184 return true; |
| 1166 } | 1185 } |
| 1167 | 1186 |
| 1168 | 1187 |
| 1169 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { | 1188 void FlowGraphAllocator::AllocateAnyRegister(LiveRange* unallocated) { |
| 1170 UsePosition* register_use = | 1189 UsePosition* register_use = |
| 1171 unallocated->finger()->FirstRegisterUse(unallocated->Start()); | 1190 unallocated->finger()->FirstRegisterUse(unallocated->Start()); |
| 1172 if (register_use == NULL) { | 1191 if (register_use == NULL) { |
| 1173 Spill(unallocated); | 1192 Spill(unallocated); |
| 1174 return; | 1193 return; |
| 1175 } | 1194 } |
| 1176 | 1195 |
| 1177 Register candidate = kNoRegister; | 1196 Register candidate = kNoRegister; |
| 1178 intptr_t free_until = 0; | 1197 intptr_t free_until = 0; |
| 1179 intptr_t blocked_at = kMaxPosition; | 1198 intptr_t blocked_at = kMaxPosition; |
| 1180 | 1199 |
| 1181 for (int reg = 0; reg < kNumberOfCpuRegisters; ++reg) { | 1200 for (int reg = 0; reg < kNumberOfCpuRegisters; ++reg) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1211 intptr_t* cur_free_until, | 1230 intptr_t* cur_free_until, |
| 1212 intptr_t* cur_blocked_at) { | 1231 intptr_t* cur_blocked_at) { |
| 1213 intptr_t free_until = kMaxPosition; | 1232 intptr_t free_until = kMaxPosition; |
| 1214 intptr_t blocked_at = kMaxPosition; | 1233 intptr_t blocked_at = kMaxPosition; |
| 1215 const intptr_t start = unallocated->Start(); | 1234 const intptr_t start = unallocated->Start(); |
| 1216 | 1235 |
| 1217 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { | 1236 for (intptr_t i = 0; i < cpu_regs_[reg].length(); i++) { |
| 1218 LiveRange* allocated = cpu_regs_[reg][i]; | 1237 LiveRange* allocated = cpu_regs_[reg][i]; |
| 1219 | 1238 |
| 1220 UseInterval* first_pending_use_interval = | 1239 UseInterval* first_pending_use_interval = |
| 1221 allocated->finger()->first_pending_use_interval(); | 1240 allocated->finger()->first_pending_use_interval(); |
| 1222 if (first_pending_use_interval->Contains(start)) { | 1241 if (first_pending_use_interval->Contains(start)) { |
| 1223 // This is an active interval. | 1242 // This is an active interval. |
| 1224 if (allocated->vreg() <= 0) { | 1243 if (allocated->vreg() <= 0) { |
| 1225 // This register blocked by an interval that | 1244 // This register blocked by an interval that |
| 1226 // can't be spilled. | 1245 // can't be spilled. |
| 1227 return false; | 1246 return false; |
| 1228 } | 1247 } |
| 1229 | 1248 |
| 1230 const UsePosition* use = | 1249 const UsePosition* use = |
| 1231 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start()); | 1250 allocated->finger()->FirstRegisterBeneficialUse(unallocated->Start()); |
| 1232 | 1251 |
| 1233 if ((use != NULL) && ((use->pos() - start) <= 1)) { | 1252 if ((use != NULL) && ((use->pos() - start) <= 1)) { |
| 1234 // This register is blocked by interval that is used | 1253 // This register is blocked by interval that is used |
| 1235 // as register in the current instruction and can't | 1254 // as register in the current instruction and can't |
| 1236 // be spilled. | 1255 // be spilled. |
| 1237 return false; | 1256 return false; |
| 1238 } | 1257 } |
| 1239 | 1258 |
| 1240 const intptr_t use_pos = (use != NULL) ? use->pos() | 1259 const intptr_t use_pos = (use != NULL) ? use->pos() |
| 1241 : allocated->End(); | 1260 : allocated->End(); |
| 1242 | 1261 |
| 1243 if (use_pos < free_until) free_until = use_pos; | 1262 if (use_pos < free_until) free_until = use_pos; |
| 1244 } else { | 1263 } else { |
| 1245 // This is inactive interval. | 1264 // This is inactive interval. |
| 1246 const intptr_t intersection = FirstIntersection( | 1265 const intptr_t intersection = FirstIntersection( |
| 1247 first_pending_use_interval, unallocated->first_use_interval()); | 1266 first_pending_use_interval, unallocated->first_use_interval()); |
| 1248 if (intersection != kMaxPosition) { | 1267 if (intersection != kMaxPosition) { |
| 1249 if (intersection < free_until) free_until = intersection; | 1268 if (intersection < free_until) free_until = intersection; |
| 1250 if (allocated->vreg() == kNoVirtualRegister) blocked_at = intersection; | 1269 if (allocated->vreg() == kNoVirtualRegister) blocked_at = intersection; |
| 1251 } | 1270 } |
| 1252 } | 1271 } |
| 1253 | 1272 |
| 1254 if (free_until <= *cur_free_until) { | 1273 if (free_until <= *cur_free_until) { |
| 1255 return false; | 1274 return false; |
| 1256 } | 1275 } |
| 1257 } | 1276 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1277 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, | 1296 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, |
| 1278 Register reg) { | 1297 Register reg) { |
| 1279 TRACE_ALLOC(("assigning blocked register %s to live range %d\n", | 1298 TRACE_ALLOC(("assigning blocked register %s to live range %d\n", |
| 1280 Location::RegisterLocation(reg).Name(), | 1299 Location::RegisterLocation(reg).Name(), |
| 1281 unallocated->vreg())); | 1300 unallocated->vreg())); |
| 1282 | 1301 |
| 1283 intptr_t first_evicted = -1; | 1302 intptr_t first_evicted = -1; |
| 1284 for (intptr_t i = cpu_regs_[reg].length() - 1; i >= 0; i--) { | 1303 for (intptr_t i = cpu_regs_[reg].length() - 1; i >= 0; i--) { |
| 1285 LiveRange* allocated = cpu_regs_[reg][i]; | 1304 LiveRange* allocated = cpu_regs_[reg][i]; |
| 1286 if (allocated->vreg() < 0) continue; // Can't be evicted. | 1305 if (allocated->vreg() < 0) continue; // Can't be evicted. |
| 1287 if (EvictIntersection(allocated, | 1306 if (EvictIntersection(allocated, unallocated)) { |
| 1288 unallocated)) { | |
| 1289 cpu_regs_[reg][i] = NULL; | 1307 cpu_regs_[reg][i] = NULL; |
| 1290 first_evicted = i; | 1308 first_evicted = i; |
| 1291 } | 1309 } |
| 1292 } | 1310 } |
| 1293 | 1311 |
| 1294 // Remove evicted ranges from the array. | 1312 // Remove evicted ranges from the array. |
| 1295 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 1313 if (first_evicted != -1) RemoveEvicted(reg, first_evicted); |
| 1296 | 1314 |
| 1297 cpu_regs_[reg].Add(unallocated); | 1315 cpu_regs_[reg].Add(unallocated); |
| 1298 unallocated->set_assigned_location(Location::RegisterLocation(reg)); | 1316 unallocated->set_assigned_location(Location::RegisterLocation(reg)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 range->vreg(), | 1373 range->vreg(), |
| 1356 range->assigned_location().Name())); | 1374 range->assigned_location().Name())); |
| 1357 ASSERT(!range->assigned_location().IsInvalid()); | 1375 ASSERT(!range->assigned_location().IsInvalid()); |
| 1358 const Location loc = range->assigned_location(); | 1376 const Location loc = range->assigned_location(); |
| 1359 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { | 1377 for (UsePosition* use = range->first_use(); use != NULL; use = use->next()) { |
| 1360 ConvertUseTo(use, loc); | 1378 ConvertUseTo(use, loc); |
| 1361 } | 1379 } |
| 1362 } | 1380 } |
| 1363 | 1381 |
| 1364 | 1382 |
| 1365 bool AllocationFinger::Advance(const intptr_t start) { | |
| 1366 UseInterval* a = first_pending_use_interval_; | |
| 1367 while (a != NULL && a->end() <= start) a = a->next(); | |
| 1368 first_pending_use_interval_ = a; | |
| 1369 if (first_pending_use_interval_ == NULL) { | |
| 1370 return true; | |
| 1371 } | |
| 1372 return false; | |
| 1373 } | |
| 1374 | |
| 1375 | |
| 1376 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { | 1383 void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) { |
| 1377 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 1384 for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { |
| 1378 if (cpu_regs_[reg].is_empty()) continue; | 1385 if (cpu_regs_[reg].is_empty()) continue; |
| 1379 | 1386 |
| 1380 intptr_t first_evicted = -1; | 1387 intptr_t first_evicted = -1; |
| 1381 for (intptr_t i = cpu_regs_[reg].length() - 1; i >= 0; i--) { | 1388 for (intptr_t i = cpu_regs_[reg].length() - 1; i >= 0; i--) { |
| 1382 LiveRange* range = cpu_regs_[reg][i]; | 1389 LiveRange* range = cpu_regs_[reg][i]; |
| 1383 if (range->finger()->Advance(start)) { | 1390 if (range->finger()->Advance(start)) { |
| 1384 ConvertAllUses(range); | 1391 ConvertAllUses(range); |
| 1385 cpu_regs_[reg][i] = NULL; | 1392 cpu_regs_[reg][i] = NULL; |
| 1386 first_evicted = i; | 1393 first_evicted = i; |
| 1387 } | 1394 } |
| 1388 } | 1395 } |
| 1389 | 1396 |
| 1390 if (first_evicted != -1) { | 1397 if (first_evicted != -1) { |
| 1391 RemoveEvicted(static_cast<Register>(reg), first_evicted); | 1398 RemoveEvicted(static_cast<Register>(reg), first_evicted); |
| 1392 } | 1399 } |
| 1393 } | 1400 } |
| 1394 } | 1401 } |
| 1395 | 1402 |
| 1396 | 1403 |
| 1397 void AllocationFinger::Initialize(LiveRange* range) { | |
| 1398 first_pending_use_interval_ = range->first_use_interval(); | |
| 1399 first_register_use_ = range->first_use(); | |
| 1400 first_register_beneficial_use_ = range->first_use(); | |
| 1401 first_hinted_use_ = range->first_use(); | |
| 1402 } | |
| 1403 | |
| 1404 | |
| 1405 static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) { | 1404 static inline bool ShouldBeAllocatedBefore(LiveRange* a, LiveRange* b) { |
| 1406 return a->Start() <= b->Start(); | 1405 return a->Start() <= b->Start(); |
| 1407 } | 1406 } |
| 1408 | 1407 |
| 1409 | 1408 |
| 1410 void FlowGraphAllocator::AddToUnallocated(LiveRange* range) { | 1409 void FlowGraphAllocator::AddToUnallocated(LiveRange* range) { |
| 1411 range->finger()->Initialize(range); | 1410 range->finger()->Initialize(range); |
| 1412 | 1411 |
| 1413 if (unallocated_.is_empty()) { | 1412 if (unallocated_.is_empty()) { |
| 1414 unallocated_.Add(range); | 1413 unallocated_.Add(range); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 | 1594 |
| 1596 if (FLAG_trace_ssa_allocator) { | 1595 if (FLAG_trace_ssa_allocator) { |
| 1597 OS::Print("-- ir after allocation -------------------------\n"); | 1596 OS::Print("-- ir after allocation -------------------------\n"); |
| 1598 FlowGraphPrinter printer(Function::Handle(), block_order_, true); | 1597 FlowGraphPrinter printer(Function::Handle(), block_order_, true); |
| 1599 printer.PrintBlocks(); | 1598 printer.PrintBlocks(); |
| 1600 } | 1599 } |
| 1601 } | 1600 } |
| 1602 | 1601 |
| 1603 | 1602 |
| 1604 } // namespace dart | 1603 } // namespace dart |
| OLD | NEW |