Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index b9ad8af529d82a9f078d61c0d88af6594b61ac64..0c483a3024ed08b6316308a74bfda76a7c3b9848 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -1359,10 +1359,15 @@ HSideEffectMap::HSideEffectMap() : count_(0) { |
| HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) { |
| - memcpy(data_, other->data_, kNumberOfTrackedSideEffects * kPointerSize); |
| + *this = *other; // Calls operator= |
|
Jakob Kummerow
2012/06/04 16:33:58
nit: full stop at the end of the comment please.
|
| } |
| +HSideEffectMap& HSideEffectMap::operator= (const HSideEffectMap& other) { |
| + memcpy(data_, other.data_, kNumberOfTrackedSideEffects * kPointerSize); |
| + return *this; |
| +} |
| + |
| void HSideEffectMap::Kill(GVNFlagSet flags) { |
| for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
| GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
| @@ -1491,9 +1496,7 @@ class HGlobalValueNumberer BASE_EMBEDDED { |
| GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( |
| HBasicBlock* dominator, |
| HBasicBlock* dominated); |
| - void AnalyzeBlock(HBasicBlock* block, |
| - HValueMap* map, |
| - HSideEffectMap* dominators); |
| + void AnalyzeGraph(); |
| void ComputeBlockSideEffects(); |
| void LoopInvariantCodeMotion(); |
| void ProcessLoopBlock(HBasicBlock* block, |
| @@ -1530,9 +1533,7 @@ bool HGlobalValueNumberer::Analyze() { |
| if (FLAG_loop_invariant_code_motion) { |
| LoopInvariantCodeMotion(); |
| } |
| - HValueMap* map = new(zone()) HValueMap(); |
| - HSideEffectMap side_effect_dominators; |
| - AnalyzeBlock(graph_->entry_block(), map, &side_effect_dominators); |
| + AnalyzeGraph(); |
| return removed_side_effects_; |
| } |
| @@ -1826,89 +1827,210 @@ GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( |
| } |
| -void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, |
| - HValueMap* map, |
| - HSideEffectMap* dominators) { |
| - TRACE_GVN_2("Analyzing block B%d%s\n", |
| - block->block_id(), |
| - block->IsLoopHeader() ? " (loop header)" : ""); |
| +class GvnBasicBlockState: public ZoneObject { |
| + public: |
| + static GvnBasicBlockState* CreateEntry(Zone* zone, |
| + HBasicBlock* entry_block, |
| + HValueMap* entry_map) { |
| + return new(zone) |
| + GvnBasicBlockState(NULL, entry_block, entry_map, NULL, zone); |
| + } |
| + |
| + HBasicBlock* block() { return block_; } |
| + HValueMap* map() { return map_; } |
| + HSideEffectMap* dominators() { return &dominators_; } |
| + |
| + GvnBasicBlockState* next_in_dominator_tree_traversal( |
| + Zone* zone, |
| + HBasicBlock** dominator) { |
| + // This assignment needs to happen before calling next_dominated() because |
| + // that call can reuse "this" if we are at the last dominated block. |
| + *dominator = block(); |
| + GvnBasicBlockState* result = next_dominated(zone); |
| + if (result == NULL) { |
| + GvnBasicBlockState* dominator_state = pop(); |
| + if (dominator_state != NULL) { |
| + // This branch is guaranteed not to return NULL because pop() never |
| + // returns a state where "is_done() == true". |
| + *dominator = dominator_state->block(); |
| + result = dominator_state->next_dominated(zone); |
| + } else { |
| + *dominator = NULL; |
|
Jakob Kummerow
2012/06/04 16:33:58
IIUC, the value of *dominator doesn't matter when
|
| + result = NULL; |
|
Jakob Kummerow
2012/06/04 16:33:58
Unnecessary; result == NULL here anyway.
|
| + } |
| + } |
| + return result; |
| + } |
| - // If this is a loop header kill everything killed by the loop. |
| - if (block->IsLoopHeader()) { |
| - map->Kill(loop_side_effects_[block->block_id()]); |
| + private: |
| + void Initialize(HBasicBlock* block, |
| + HValueMap* map, |
| + HSideEffectMap* dominators, |
| + bool copy_map, |
| + Zone* zone) { |
| + block_ = block; |
| + map_ = copy_map ? map->Copy(zone) : map; |
| + dominated_index_ = -1; |
| + length_ = block->dominated_blocks()->length(); |
| + if (dominators != NULL) { |
| + dominators_ = *dominators; |
| + } |
| + } |
| + bool is_done() { return dominated_index_ >= length_; } |
| + |
| + GvnBasicBlockState(GvnBasicBlockState* previous, |
| + HBasicBlock* block, |
| + HValueMap* map, |
| + HSideEffectMap* dominators, |
| + Zone* zone) |
| + : previous_(previous), next_(NULL) { |
| + Initialize(block, map, dominators, true, zone); |
| + } |
| + |
| + GvnBasicBlockState* next_dominated(Zone* zone) { |
| + dominated_index_++; |
| + if (dominated_index_ == length_ - 1) { |
| + Initialize(block_->dominated_blocks()->at(dominated_index_), |
| + map(), |
| + dominators(), |
| + false, |
| + zone); |
| + return this; |
| + } else if (dominated_index_ < length_) { |
| + return push(zone, |
| + block_->dominated_blocks()->at(dominated_index_), |
| + dominators()); |
| + } else { |
| + return NULL; |
| + } |
| } |
| - // Go through all instructions of the current block. |
| - HInstruction* instr = block->first(); |
| - while (instr != NULL) { |
| - HInstruction* next = instr->next(); |
| - GVNFlagSet flags = instr->ChangesFlags(); |
| - if (!flags.IsEmpty()) { |
| - // Clear all instructions in the map that are affected by side effects. |
| - // Store instruction as the dominating one for tracked side effects. |
| - map->Kill(flags); |
| - dominators->Store(flags, instr); |
| - TRACE_GVN_2("Instruction %d %s\n", instr->id(), |
| - *GetGVNFlagsString(flags)); |
| + GvnBasicBlockState* push(Zone* zone, |
| + HBasicBlock* block, |
| + HSideEffectMap* dominators) { |
| + if (next_ == NULL) { |
| + next_ = |
| + new(zone) GvnBasicBlockState(this, block, map(), dominators, zone); |
| + } else { |
| + next_->Initialize(block, map(), dominators, true, zone); |
| } |
| - if (instr->CheckFlag(HValue::kUseGVN)) { |
| - ASSERT(!instr->HasObservableSideEffects()); |
| - HValue* other = map->Lookup(instr); |
| - if (other != NULL) { |
| - ASSERT(instr->Equals(other) && other->Equals(instr)); |
| - TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", |
| - instr->id(), |
| - instr->Mnemonic(), |
| - other->id(), |
| - other->Mnemonic()); |
| - if (instr->HasSideEffects()) removed_side_effects_ = true; |
| - instr->DeleteAndReplaceWith(other); |
| - } else { |
| - map->Add(instr); |
| - } |
| + return next_; |
| + } |
| + GvnBasicBlockState* pop() { |
| + GvnBasicBlockState* result = previous_; |
| + while (result != NULL && result->is_done()) { |
| + TRACE_GVN_2("Backtracking from block B%d to block b%d\n", |
| + block()->block_id(), |
| + previous_->block()->block_id()) |
| + result = result->previous_; |
| } |
| - if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { |
| - for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
| - HValue* other = dominators->at(i); |
| - GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
| - GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); |
| - if (instr->DependsOnFlags().Contains(depends_on_flag) && |
| - (other != NULL)) { |
| - TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", |
| - i, |
| + return result; |
| + } |
| + |
| + GvnBasicBlockState* previous_; |
| + GvnBasicBlockState* next_; |
| + HBasicBlock* block_; |
| + HValueMap* map_; |
| + HSideEffectMap dominators_; |
| + int dominated_index_; |
| + int length_; |
| +}; |
| + |
| + |
| +void HGlobalValueNumberer::AnalyzeGraph() { |
| + HBasicBlock* entry_block = graph_->entry_block(); |
| + HValueMap* entry_map = new(zone()) HValueMap(); |
| + GvnBasicBlockState* current = |
| + GvnBasicBlockState::CreateEntry(zone(), entry_block, entry_map); |
| + |
| + while (current != NULL) { |
| + HBasicBlock* block = current->block(); |
| + HValueMap* map = current->map(); |
| + HSideEffectMap* dominators = current->dominators(); |
| + |
| + TRACE_GVN_2("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()) { |
| + map->Kill(loop_side_effects_[block->block_id()]); |
| + } |
| + |
| + // Go through all instructions of the current block. |
| + HInstruction* instr = block->first(); |
| + while (instr != NULL) { |
| + HInstruction* next = instr->next(); |
| + GVNFlagSet flags = instr->ChangesFlags(); |
| + if (!flags.IsEmpty()) { |
| + // Clear all instructions in the map that are affected by side effects. |
| + // Store instruction as the dominating one for tracked side effects. |
| + map->Kill(flags); |
| + dominators->Store(flags, instr); |
| + TRACE_GVN_2("Instruction %d %s\n", instr->id(), |
| + *GetGVNFlagsString(flags)); |
| + } |
| + if (instr->CheckFlag(HValue::kUseGVN)) { |
| + ASSERT(!instr->HasObservableSideEffects()); |
| + HValue* other = map->Lookup(instr); |
| + if (other != NULL) { |
| + ASSERT(instr->Equals(other) && other->Equals(instr)); |
| + TRACE_GVN_4("Replacing value %d (%s) with value %d (%s)\n", |
| instr->id(), |
| instr->Mnemonic(), |
| other->id(), |
| other->Mnemonic()); |
| - instr->SetSideEffectDominator(changes_flag, other); |
| + if (instr->HasSideEffects()) removed_side_effects_ = true; |
| + instr->DeleteAndReplaceWith(other); |
| + } else { |
| + map->Add(instr); |
| + } |
| + } |
| + if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) { |
| + for (int i = 0; i < kNumberOfTrackedSideEffects; i++) { |
| + HValue* other = dominators->at(i); |
| + GVNFlag changes_flag = HValue::ChangesFlagFromInt(i); |
| + GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i); |
| + if (instr->DependsOnFlags().Contains(depends_on_flag) && |
| + (other != NULL)) { |
| + TRACE_GVN_5("Side-effect #%d in %d (%s) is dominated by %d (%s)\n", |
| + i, |
| + instr->id(), |
| + instr->Mnemonic(), |
| + other->id(), |
| + other->Mnemonic()); |
| + instr->SetSideEffectDominator(changes_flag, other); |
| + } |
| } |
| } |
| + instr = next; |
| + } |
| + |
| + HBasicBlock *dominator_block; |
|
Jakob Kummerow
2012/06/04 16:33:58
nit: s/ */* /
|
| + GvnBasicBlockState* next = |
| + current->next_in_dominator_tree_traversal(zone(), &dominator_block); |
| + |
| + if (next != NULL) { |
| + HBasicBlock* dominated = next->block(); |
| + // No need to copy the map for the last child in the dominator tree. |
|
Jakob Kummerow
2012/06/04 16:33:58
I think this comment should go inside GvnBasicBloc
|
| + HValueMap* successor_map = next->map(); |
| + HSideEffectMap* successor_dominators = next->dominators(); |
| + |
| + // 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 and the dominators list is already empty. If the range |
| + // of block ids (block_id, dominated_id) is empty there are no such |
| + // paths. |
| + if ((!successor_map->IsEmpty() || !successor_dominators->IsEmpty()) && |
| + dominator_block->block_id() + 1 < dominated->block_id()) { |
| + visited_on_paths_.Clear(); |
| + GVNFlagSet side_effects_on_all_paths = |
| + CollectSideEffectsOnPathsToDominatedBlock(dominator_block, dominated); |
|
Jakob Kummerow
2012/06/04 16:33:58
nit: long line
|
| + successor_map->Kill(side_effects_on_all_paths); |
| + successor_dominators->Kill(side_effects_on_all_paths); |
| + } |
| } |
| - instr = next; |
| - } |
| - |
| - // Recursively continue analysis for all immediately dominated blocks. |
| - int length = block->dominated_blocks()->length(); |
| - for (int i = 0; i < length; ++i) { |
| - HBasicBlock* dominated = block->dominated_blocks()->at(i); |
| - // No need to copy the map for the last child in the dominator tree. |
| - HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); |
| - HSideEffectMap successor_dominators(dominators); |
| - |
| - // 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 and the dominators list is already empty. If the range |
| - // of block ids (block_id, dominated_id) is empty there are no such |
| - // paths. |
| - if ((!successor_map->IsEmpty() || !successor_dominators.IsEmpty()) && |
| - block->block_id() + 1 < dominated->block_id()) { |
| - visited_on_paths_.Clear(); |
| - GVNFlagSet side_effects_on_all_paths = |
| - CollectSideEffectsOnPathsToDominatedBlock(block, dominated); |
| - successor_map->Kill(side_effects_on_all_paths); |
| - successor_dominators.Kill(side_effects_on_all_paths); |
| - } |
| - AnalyzeBlock(dominated, successor_map, &successor_dominators); |
| + current = next; |
| } |
| } |