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

Side by Side Diff: src/hydrogen.cc

Issue 7036010: Make GVN side effect analysis more precise. (Closed)
Patch Set: Review fixes Created 9 years, 7 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
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698