| 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 |