OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 void TraceGVN(const char* msg, ...) { | 1014 void TraceGVN(const char* msg, ...) { |
1015 if (FLAG_trace_gvn) { | 1015 if (FLAG_trace_gvn) { |
1016 va_list arguments; | 1016 va_list arguments; |
1017 va_start(arguments, msg); | 1017 va_start(arguments, msg); |
1018 OS::VPrint(msg, arguments); | 1018 OS::VPrint(msg, arguments); |
1019 va_end(arguments); | 1019 va_end(arguments); |
1020 } | 1020 } |
1021 } | 1021 } |
1022 | 1022 |
1023 | 1023 |
1024 HValueMap::HValueMap(const HValueMap* other) | 1024 HValueMap::HValueMap(Zone* zone, const HValueMap* other) |
1025 : array_size_(other->array_size_), | 1025 : array_size_(other->array_size_), |
1026 lists_size_(other->lists_size_), | 1026 lists_size_(other->lists_size_), |
1027 count_(other->count_), | 1027 count_(other->count_), |
1028 present_flags_(other->present_flags_), | 1028 present_flags_(other->present_flags_), |
1029 array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)), | 1029 array_(zone->NewArray<HValueMapListElement>(other->array_size_)), |
1030 lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)), | 1030 lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)), |
1031 free_list_head_(other->free_list_head_) { | 1031 free_list_head_(other->free_list_head_) { |
1032 memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement)); | 1032 memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement)); |
1033 memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); | 1033 memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); |
1034 } | 1034 } |
1035 | 1035 |
1036 | 1036 |
1037 void HValueMap::Kill(int flags) { | 1037 void HValueMap::Kill(int flags) { |
1038 int depends_flags = HValue::ConvertChangesToDependsFlags(flags); | 1038 int depends_flags = HValue::ConvertChangesToDependsFlags(flags); |
1039 if ((present_flags_ & depends_flags) == 0) return; | 1039 if ((present_flags_ & depends_flags) == 0) return; |
1040 present_flags_ = 0; | 1040 present_flags_ = 0; |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1233 while (instr != NULL) { | 1233 while (instr != NULL) { |
1234 if (instr->IsGoto()) { | 1234 if (instr->IsGoto()) { |
1235 HGoto::cast(instr)->set_include_stack_check(false); | 1235 HGoto::cast(instr)->set_include_stack_check(false); |
1236 return; | 1236 return; |
1237 } | 1237 } |
1238 instr = instr->next(); | 1238 instr = instr->next(); |
1239 } | 1239 } |
1240 } | 1240 } |
1241 | 1241 |
1242 | 1242 |
| 1243 // Simple sparse set with O(1) add, contains, and clear. |
| 1244 class SparseSet { |
| 1245 public: |
| 1246 SparseSet(Zone* zone, int capacity) |
| 1247 : capacity_(capacity), |
| 1248 length_(0), |
| 1249 dense_(zone->NewArray<int>(capacity)), |
| 1250 sparse_(zone->NewArray<int>(capacity)) {} |
| 1251 |
| 1252 bool Contains(int n) const { |
| 1253 ASSERT(0 <= n && n < capacity_); |
| 1254 int d = sparse_[n]; |
| 1255 return 0 <= d && d < length_ && dense_[d] == n; |
| 1256 } |
| 1257 |
| 1258 bool Add(int n) { |
| 1259 if (Contains(n)) return false; |
| 1260 dense_[length_] = n; |
| 1261 sparse_[n] = length_; |
| 1262 ++length_; |
| 1263 return true; |
| 1264 } |
| 1265 |
| 1266 void Clear() { length_ = 0; } |
| 1267 |
| 1268 private: |
| 1269 int capacity_; |
| 1270 int length_; |
| 1271 int* dense_; |
| 1272 int* sparse_; |
| 1273 |
| 1274 DISALLOW_COPY_AND_ASSIGN(SparseSet); |
| 1275 }; |
| 1276 |
| 1277 |
1243 class HGlobalValueNumberer BASE_EMBEDDED { | 1278 class HGlobalValueNumberer BASE_EMBEDDED { |
1244 public: | 1279 public: |
1245 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) | 1280 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) |
1246 : graph_(graph), | 1281 : graph_(graph), |
1247 info_(info), | 1282 info_(info), |
1248 block_side_effects_(graph_->blocks()->length()), | 1283 block_side_effects_(graph->blocks()->length()), |
1249 loop_side_effects_(graph_->blocks()->length()) { | 1284 loop_side_effects_(graph->blocks()->length()), |
| 1285 visited_on_paths_(graph->zone(), graph->blocks()->length()) { |
1250 ASSERT(info->isolate()->heap()->allow_allocation(false)); | 1286 ASSERT(info->isolate()->heap()->allow_allocation(false)); |
1251 block_side_effects_.AddBlock(0, graph_->blocks()->length()); | 1287 block_side_effects_.AddBlock(0, graph_->blocks()->length()); |
1252 loop_side_effects_.AddBlock(0, graph_->blocks()->length()); | 1288 loop_side_effects_.AddBlock(0, graph_->blocks()->length()); |
1253 } | 1289 } |
1254 ~HGlobalValueNumberer() { | 1290 ~HGlobalValueNumberer() { |
1255 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); | 1291 ASSERT(!info_->isolate()->heap()->allow_allocation(true)); |
1256 } | 1292 } |
1257 | 1293 |
1258 void Analyze(); | 1294 void Analyze(); |
1259 | 1295 |
1260 private: | 1296 private: |
| 1297 int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator, |
| 1298 HBasicBlock* dominated); |
1261 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); | 1299 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); |
1262 void ComputeBlockSideEffects(); | 1300 void ComputeBlockSideEffects(); |
1263 void LoopInvariantCodeMotion(); | 1301 void LoopInvariantCodeMotion(); |
1264 void ProcessLoopBlock(HBasicBlock* block, | 1302 void ProcessLoopBlock(HBasicBlock* block, |
1265 HBasicBlock* before_loop, | 1303 HBasicBlock* before_loop, |
1266 int loop_kills); | 1304 int loop_kills); |
1267 bool AllowCodeMotion(); | 1305 bool AllowCodeMotion(); |
1268 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); | 1306 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
1269 | 1307 |
1270 HGraph* graph() { return graph_; } | 1308 HGraph* graph() { return graph_; } |
1271 CompilationInfo* info() { return info_; } | 1309 CompilationInfo* info() { return info_; } |
1272 Zone* zone() { return graph_->zone(); } | 1310 Zone* zone() { return graph_->zone(); } |
1273 | 1311 |
1274 HGraph* graph_; | 1312 HGraph* graph_; |
1275 CompilationInfo* info_; | 1313 CompilationInfo* info_; |
1276 | 1314 |
1277 // A map of block IDs to their side effects. | 1315 // A map of block IDs to their side effects. |
1278 ZoneList<int> block_side_effects_; | 1316 ZoneList<int> block_side_effects_; |
1279 | 1317 |
1280 // A map of loop header block IDs to their loop's side effects. | 1318 // A map of loop header block IDs to their loop's side effects. |
1281 ZoneList<int> loop_side_effects_; | 1319 ZoneList<int> loop_side_effects_; |
| 1320 |
| 1321 // Used when collecting side effects on paths from dominator to |
| 1322 // dominated. |
| 1323 SparseSet visited_on_paths_; |
1282 }; | 1324 }; |
1283 | 1325 |
1284 | 1326 |
1285 void HGlobalValueNumberer::Analyze() { | 1327 void HGlobalValueNumberer::Analyze() { |
1286 ComputeBlockSideEffects(); | 1328 ComputeBlockSideEffects(); |
1287 if (FLAG_loop_invariant_code_motion) { | 1329 if (FLAG_loop_invariant_code_motion) { |
1288 LoopInvariantCodeMotion(); | 1330 LoopInvariantCodeMotion(); |
1289 } | 1331 } |
1290 HValueMap* map = new(zone()) HValueMap(); | 1332 HValueMap* map = new(zone()) HValueMap(); |
1291 AnalyzeBlock(graph_->blocks()->at(0), map); | 1333 AnalyzeBlock(graph_->blocks()->at(0), map); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 if (!found) { | 1449 if (!found) { |
1408 result = false; | 1450 result = false; |
1409 break; | 1451 break; |
1410 } | 1452 } |
1411 } | 1453 } |
1412 } | 1454 } |
1413 return result; | 1455 return result; |
1414 } | 1456 } |
1415 | 1457 |
1416 | 1458 |
| 1459 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( |
| 1460 HBasicBlock* dominator, HBasicBlock* dominated) { |
| 1461 int side_effects = 0; |
| 1462 for (int i = 0; i < dominated->predecessors()->length(); ++i) { |
| 1463 HBasicBlock* block = dominated->predecessors()->at(i); |
| 1464 if (dominator->block_id() < block->block_id() && |
| 1465 block->block_id() < dominated->block_id() && |
| 1466 visited_on_paths_.Add(block->block_id())) { |
| 1467 side_effects |= block_side_effects_[block->block_id()]; |
| 1468 side_effects |= CollectSideEffectsOnPathsToDominatedBlock( |
| 1469 dominator, block); |
| 1470 } |
| 1471 } |
| 1472 return side_effects; |
| 1473 } |
| 1474 |
| 1475 |
1417 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { | 1476 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { |
1418 TraceGVN("Analyzing block B%d\n", block->block_id()); | 1477 TraceGVN("Analyzing block B%d%s\n", |
| 1478 block->block_id(), |
| 1479 block->IsLoopHeader() ? " (loop header)" : ""); |
1419 | 1480 |
1420 // If this is a loop header kill everything killed by the loop. | 1481 // If this is a loop header kill everything killed by the loop. |
1421 if (block->IsLoopHeader()) { | 1482 if (block->IsLoopHeader()) { |
1422 map->Kill(loop_side_effects_[block->block_id()]); | 1483 map->Kill(loop_side_effects_[block->block_id()]); |
1423 } | 1484 } |
1424 | 1485 |
1425 // Go through all instructions of the current block. | 1486 // Go through all instructions of the current block. |
1426 HInstruction* instr = block->first(); | 1487 HInstruction* instr = block->first(); |
1427 while (instr != NULL) { | 1488 while (instr != NULL) { |
1428 HInstruction* next = instr->next(); | 1489 HInstruction* next = instr->next(); |
(...skipping 20 matching lines...) Expand all Loading... |
1449 instr = next; | 1510 instr = next; |
1450 } | 1511 } |
1451 | 1512 |
1452 // Recursively continue analysis for all immediately dominated blocks. | 1513 // Recursively continue analysis for all immediately dominated blocks. |
1453 int length = block->dominated_blocks()->length(); | 1514 int length = block->dominated_blocks()->length(); |
1454 for (int i = 0; i < length; ++i) { | 1515 for (int i = 0; i < length; ++i) { |
1455 HBasicBlock* dominated = block->dominated_blocks()->at(i); | 1516 HBasicBlock* dominated = block->dominated_blocks()->at(i); |
1456 // No need to copy the map for the last child in the dominator tree. | 1517 // No need to copy the map for the last child in the dominator tree. |
1457 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); | 1518 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); |
1458 | 1519 |
1459 // If the dominated block is not a successor to this block we have to | 1520 // Kill everything killed on any path between this block and the |
1460 // kill everything killed on any path between this block and the | 1521 // dominated block. |
1461 // dominated block. Note we rely on the block ordering. | 1522 // We don't have to traverse these paths if the value map is |
1462 bool is_successor = false; | 1523 // already empty. |
1463 int predecessor_count = dominated->predecessors()->length(); | 1524 // If the range of block ids (block_id, dominated_id) is empty |
1464 for (int j = 0; !is_successor && j < predecessor_count; ++j) { | 1525 // there are no such paths. |
1465 is_successor = (dominated->predecessors()->at(j) == block); | 1526 if (!successor_map->IsEmpty() && |
| 1527 block->block_id() + 1 < dominated->block_id()) { |
| 1528 visited_on_paths_.Clear(); |
| 1529 successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block, |
| 1530 dominated)); |
1466 } | 1531 } |
1467 | |
1468 if (!is_successor) { | |
1469 int side_effects = 0; | |
1470 for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) { | |
1471 side_effects |= block_side_effects_[j]; | |
1472 } | |
1473 successor_map->Kill(side_effects); | |
1474 } | |
1475 | |
1476 AnalyzeBlock(dominated, successor_map); | 1532 AnalyzeBlock(dominated, successor_map); |
1477 } | 1533 } |
1478 } | 1534 } |
1479 | 1535 |
1480 | 1536 |
1481 class HInferRepresentation BASE_EMBEDDED { | 1537 class HInferRepresentation BASE_EMBEDDED { |
1482 public: | 1538 public: |
1483 explicit HInferRepresentation(HGraph* graph) | 1539 explicit HInferRepresentation(HGraph* graph) |
1484 : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {} | 1540 : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {} |
1485 | 1541 |
(...skipping 4658 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6144 } | 6200 } |
6145 } | 6201 } |
6146 | 6202 |
6147 #ifdef DEBUG | 6203 #ifdef DEBUG |
6148 if (graph_ != NULL) graph_->Verify(); | 6204 if (graph_ != NULL) graph_->Verify(); |
6149 if (allocator_ != NULL) allocator_->Verify(); | 6205 if (allocator_ != NULL) allocator_->Verify(); |
6150 #endif | 6206 #endif |
6151 } | 6207 } |
6152 | 6208 |
6153 } } // namespace v8::internal | 6209 } } // namespace v8::internal |
OLD | NEW |