| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 35981ae6c63958b61d7e2af4be099ce8e089f155..f7a6ce91d0a8d4d9a6edaedc470760aefdf4c764 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1021,13 +1021,13 @@ void TraceGVN(const char* msg, ...) {
|
| }
|
|
|
|
|
| -HValueMap::HValueMap(const HValueMap* other)
|
| +HValueMap::HValueMap(Zone* zone, const HValueMap* other)
|
| : array_size_(other->array_size_),
|
| lists_size_(other->lists_size_),
|
| count_(other->count_),
|
| present_flags_(other->present_flags_),
|
| - array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)),
|
| - lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)),
|
| + array_(zone->NewArray<HValueMapListElement>(other->array_size_)),
|
| + lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)),
|
| free_list_head_(other->free_list_head_) {
|
| memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement));
|
| memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement));
|
| @@ -1240,13 +1240,49 @@ void HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) {
|
| }
|
|
|
|
|
| +// Simple sparse set with O(1) add, contains, and clear.
|
| +class SparseSet {
|
| + public:
|
| + SparseSet(Zone* zone, int capacity)
|
| + : capacity_(capacity),
|
| + length_(0),
|
| + dense_(zone->NewArray<int>(capacity)),
|
| + sparse_(zone->NewArray<int>(capacity)) {}
|
| +
|
| + bool Contains(int n) const {
|
| + ASSERT(0 <= n && n < capacity_);
|
| + int d = sparse_[n];
|
| + return 0 <= d && d < length_ && dense_[d] == n;
|
| + }
|
| +
|
| + bool Add(int n) {
|
| + if (Contains(n)) return false;
|
| + dense_[length_] = n;
|
| + sparse_[n] = length_;
|
| + ++length_;
|
| + return true;
|
| + }
|
| +
|
| + void Clear() { length_ = 0; }
|
| +
|
| + private:
|
| + int capacity_;
|
| + int length_;
|
| + int* dense_;
|
| + int* sparse_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SparseSet);
|
| +};
|
| +
|
| +
|
| class HGlobalValueNumberer BASE_EMBEDDED {
|
| public:
|
| explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
|
| : graph_(graph),
|
| info_(info),
|
| - block_side_effects_(graph_->blocks()->length()),
|
| - loop_side_effects_(graph_->blocks()->length()) {
|
| + block_side_effects_(graph->blocks()->length()),
|
| + loop_side_effects_(graph->blocks()->length()),
|
| + visited_on_paths_(graph->zone(), graph->blocks()->length()) {
|
| ASSERT(info->isolate()->heap()->allow_allocation(false));
|
| block_side_effects_.AddBlock(0, graph_->blocks()->length());
|
| loop_side_effects_.AddBlock(0, graph_->blocks()->length());
|
| @@ -1258,6 +1294,8 @@ class HGlobalValueNumberer BASE_EMBEDDED {
|
| void Analyze();
|
|
|
| private:
|
| + int CollectSideEffectsOnPathsToDominatedBlock(HBasicBlock* dominator,
|
| + HBasicBlock* dominated);
|
| void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
|
| void ComputeBlockSideEffects();
|
| void LoopInvariantCodeMotion();
|
| @@ -1279,6 +1317,10 @@ class HGlobalValueNumberer BASE_EMBEDDED {
|
|
|
| // A map of loop header block IDs to their loop's side effects.
|
| ZoneList<int> loop_side_effects_;
|
| +
|
| + // Used when collecting side effects on paths from dominator to
|
| + // dominated.
|
| + SparseSet visited_on_paths_;
|
| };
|
|
|
|
|
| @@ -1414,8 +1456,27 @@ bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
|
| }
|
|
|
|
|
| +int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
|
| + HBasicBlock* dominator, HBasicBlock* dominated) {
|
| + int side_effects = 0;
|
| + for (int i = 0; i < dominated->predecessors()->length(); ++i) {
|
| + HBasicBlock* block = dominated->predecessors()->at(i);
|
| + if (dominator->block_id() < block->block_id() &&
|
| + block->block_id() < dominated->block_id() &&
|
| + visited_on_paths_.Add(block->block_id())) {
|
| + side_effects |= block_side_effects_[block->block_id()];
|
| + side_effects |= CollectSideEffectsOnPathsToDominatedBlock(
|
| + dominator, block);
|
| + }
|
| + }
|
| + return side_effects;
|
| +}
|
| +
|
| +
|
| void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
| - TraceGVN("Analyzing block B%d\n", block->block_id());
|
| + TraceGVN("Analyzing block B%d%s\n",
|
| + block->block_id(),
|
| + block->IsLoopHeader() ? " (loop header)" : "");
|
|
|
| // If this is a loop header kill everything killed by the loop.
|
| if (block->IsLoopHeader()) {
|
| @@ -1456,23 +1517,18 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
| // No need to copy the map for the last child in the dominator tree.
|
| HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone());
|
|
|
| - // If the dominated block is not a successor to this block we have to
|
| - // kill everything killed on any path between this block and the
|
| - // dominated block. Note we rely on the block ordering.
|
| - bool is_successor = false;
|
| - int predecessor_count = dominated->predecessors()->length();
|
| - for (int j = 0; !is_successor && j < predecessor_count; ++j) {
|
| - is_successor = (dominated->predecessors()->at(j) == block);
|
| + // Kill everything killed on any path between this block and the
|
| + // dominated block.
|
| + // We don't have to traverse these paths if the value map is
|
| + // already empty.
|
| + // If the range of block ids (block_id, dominated_id) is empty
|
| + // there are no such paths.
|
| + if (!successor_map->IsEmpty() &&
|
| + block->block_id() + 1 < dominated->block_id()) {
|
| + visited_on_paths_.Clear();
|
| + successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block,
|
| + dominated));
|
| }
|
| -
|
| - if (!is_successor) {
|
| - int side_effects = 0;
|
| - for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) {
|
| - side_effects |= block_side_effects_[j];
|
| - }
|
| - successor_map->Kill(side_effects);
|
| - }
|
| -
|
| AnalyzeBlock(dominated, successor_map);
|
| }
|
| }
|
|
|