| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index f9d41910f31edb9f1bbbda6ac22ec0ce5935d1c0..583a825fe3c2732a714d7ccbe7382fa6d4b18911 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1321,6 +1321,38 @@ void HValueMap::Insert(HValue* value) {
|
| }
|
|
|
|
|
| +HSideEffectMap::HSideEffectMap() : count_(0) {
|
| + memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize);
|
| +}
|
| +
|
| +
|
| +HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) {
|
| + memcpy(data_, other->data_, kNumberOfTrackedSideEffects * kPointerSize);
|
| +}
|
| +
|
| +
|
| +void HSideEffectMap::Kill(GVNFlagSet flags) {
|
| + for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
|
| + GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
|
| + if (flags.Contains(changes_flag)) {
|
| + if (data_[i] != NULL) count_--;
|
| + data_[i] = NULL;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +void HSideEffectMap::Store(GVNFlagSet flags, HInstruction* instr) {
|
| + for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
|
| + GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
|
| + if (flags.Contains(changes_flag)) {
|
| + if (data_[i] == NULL) count_++;
|
| + data_[i] = instr;
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| class HStackCheckEliminator BASE_EMBEDDED {
|
| public:
|
| explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
|
| @@ -1427,7 +1459,9 @@ class HGlobalValueNumberer BASE_EMBEDDED {
|
| GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
|
| HBasicBlock* dominator,
|
| HBasicBlock* dominated);
|
| - void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
|
| + void AnalyzeBlock(HBasicBlock* block,
|
| + HValueMap* map,
|
| + HSideEffectMap* dominators);
|
| void ComputeBlockSideEffects();
|
| void LoopInvariantCodeMotion();
|
| void ProcessLoopBlock(HBasicBlock* block,
|
| @@ -1465,7 +1499,8 @@ bool HGlobalValueNumberer::Analyze() {
|
| LoopInvariantCodeMotion();
|
| }
|
| HValueMap* map = new(zone()) HValueMap();
|
| - AnalyzeBlock(graph_->entry_block(), map);
|
| + HSideEffectMap side_effect_dominators;
|
| + AnalyzeBlock(graph_->entry_block(), map, &side_effect_dominators);
|
| return removed_side_effects_;
|
| }
|
|
|
| @@ -1660,7 +1695,9 @@ GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
|
| }
|
|
|
|
|
| -void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
| +void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block,
|
| + HValueMap* map,
|
| + HSideEffectMap* dominators) {
|
| TraceGVN("Analyzing block B%d%s\n",
|
| block->block_id(),
|
| block->IsLoopHeader() ? " (loop header)" : "");
|
| @@ -1677,7 +1714,9 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
| 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);
|
| TraceGVN("Instruction %d kills\n", instr->id());
|
| }
|
| if (instr->CheckFlag(HValue::kUseGVN)) {
|
| @@ -1696,6 +1735,23 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
| 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)) {
|
| + TraceGVN("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;
|
| }
|
|
|
| @@ -1705,20 +1761,22 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
|
| 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 is
|
| - // already empty.
|
| - // If the range of block ids (block_id, dominated_id) is empty
|
| - // there are no such paths.
|
| - if (!successor_map->IsEmpty() &&
|
| + // 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();
|
| - successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block,
|
| - dominated));
|
| + 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);
|
| + AnalyzeBlock(dominated, successor_map, &successor_dominators);
|
| }
|
| }
|
|
|
|
|