| Index: src/hydrogen-gvn.cc
|
| diff --git a/src/hydrogen-gvn.cc b/src/hydrogen-gvn.cc
|
| index 3ad93129cd9c981fd9d61784ce1011335a21d4a9..bc836890bb136544c560474c222d7b354c9ddb4a 100644
|
| --- a/src/hydrogen-gvn.cc
|
| +++ b/src/hydrogen-gvn.cc
|
| @@ -364,35 +364,48 @@ void HSideEffectMap::Store(GVNFlagSet flags, HInstruction* instr) {
|
|
|
|
|
| HGlobalValueNumberingPhase::HGlobalValueNumberingPhase(HGraph* graph)
|
| - : HPhase("H_Global value numbering", graph),
|
| - removed_side_effects_(false),
|
| - block_side_effects_(graph->blocks()->length(), zone()),
|
| - loop_side_effects_(graph->blocks()->length(), zone()),
|
| - visited_on_paths_(graph->blocks()->length(), zone()) {
|
| - ASSERT(!AllowHandleAllocation::IsAllowed());
|
| - block_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
|
| - zone());
|
| - loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
|
| + : HPhase("H_Global value numbering", graph),
|
| + removed_side_effects_(false),
|
| + block_side_effects_(graph->blocks()->length(), zone()),
|
| + loop_side_effects_(graph->blocks()->length(), zone()),
|
| + visited_on_paths_(graph->blocks()->length(), zone()) {
|
| + ASSERT(!AllowHandleAllocation::IsAllowed());
|
| + block_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
|
| zone());
|
| - }
|
| + loop_side_effects_.AddBlock(GVNFlagSet(), graph->blocks()->length(),
|
| + zone());
|
| +}
|
| +
|
| +
|
| +void HGlobalValueNumberingPhase::Run() {
|
| + ASSERT(!removed_side_effects_);
|
| + for (int i = FLAG_gvn_iterations; i > 0; --i) {
|
| + // Compute the side effects.
|
| + ComputeBlockSideEffects();
|
| +
|
| + // Perform loop invariant code motion if requested.
|
| + if (FLAG_loop_invariant_code_motion) LoopInvariantCodeMotion();
|
| +
|
| + // Perform the actual value numbering.
|
| + AnalyzeGraph();
|
|
|
| -void HGlobalValueNumberingPhase::Analyze() {
|
| - removed_side_effects_ = false;
|
| - ComputeBlockSideEffects();
|
| - if (FLAG_loop_invariant_code_motion) {
|
| - LoopInvariantCodeMotion();
|
| + // Continue GVN if we removed any side effects.
|
| + if (!removed_side_effects_) break;
|
| + removed_side_effects_ = false;
|
| +
|
| + // Clear all side effects.
|
| + ASSERT_EQ(block_side_effects_.length(), graph()->blocks()->length());
|
| + ASSERT_EQ(loop_side_effects_.length(), graph()->blocks()->length());
|
| + for (int i = 0; i < graph()->blocks()->length(); ++i) {
|
| + block_side_effects_[i].RemoveAll();
|
| + loop_side_effects_[i].RemoveAll();
|
| + }
|
| + visited_on_paths_.Clear();
|
| }
|
| - AnalyzeGraph();
|
| }
|
|
|
|
|
| void HGlobalValueNumberingPhase::ComputeBlockSideEffects() {
|
| - // The Analyze phase of GVN can be called multiple times. Clear loop side
|
| - // effects before computing them to erase the contents from previous Analyze
|
| - // passes.
|
| - for (int i = 0; i < loop_side_effects_.length(); ++i) {
|
| - loop_side_effects_[i].RemoveAll();
|
| - }
|
| for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
|
| // Compute side effects for the block.
|
| HBasicBlock* block = graph()->blocks()->at(i);
|
| @@ -426,7 +439,7 @@ void HGlobalValueNumberingPhase::ComputeBlockSideEffects() {
|
|
|
|
|
| SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) {
|
| - char underlying_buffer[kLastFlag * 128];
|
| + char underlying_buffer[kNumberOfFlags * 128];
|
| Vector<char> buffer(underlying_buffer, sizeof(underlying_buffer));
|
| #if DEBUG
|
| int offset = 0;
|
| @@ -435,7 +448,7 @@ SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) {
|
| buffer[0] = 0;
|
| uint32_t set_depends_on = 0;
|
| uint32_t set_changes = 0;
|
| - for (int bit = 0; bit < kLastFlag; ++bit) {
|
| + for (int bit = 0; bit < kNumberOfFlags; ++bit) {
|
| if (flags.Contains(static_cast<GVNFlag>(bit))) {
|
| if (bit % 2 == 0) {
|
| set_changes++;
|
| @@ -444,15 +457,15 @@ SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) {
|
| }
|
| }
|
| }
|
| - bool positive_changes = set_changes < (kLastFlag / 2);
|
| - bool positive_depends_on = set_depends_on < (kLastFlag / 2);
|
| + bool positive_changes = set_changes < (kNumberOfFlags / 2);
|
| + bool positive_depends_on = set_depends_on < (kNumberOfFlags / 2);
|
| if (set_changes > 0) {
|
| if (positive_changes) {
|
| offset += OS::SNPrintF(buffer + offset, "changes [");
|
| } else {
|
| offset += OS::SNPrintF(buffer + offset, "changes all except [");
|
| }
|
| - for (int bit = 0; bit < kLastFlag; ++bit) {
|
| + for (int bit = 0; bit < kNumberOfFlags; ++bit) {
|
| if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_changes) {
|
| switch (static_cast<GVNFlag>(bit)) {
|
| #define DECLARE_FLAG(type) \
|
| @@ -481,7 +494,7 @@ GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
|
| } else {
|
| offset += OS::SNPrintF(buffer + offset, "depends on all except [");
|
| }
|
| - for (int bit = 0; bit < kLastFlag; ++bit) {
|
| + for (int bit = 0; bit < kNumberOfFlags; ++bit) {
|
| if (flags.Contains(static_cast<GVNFlag>(bit)) == positive_depends_on) {
|
| switch (static_cast<GVNFlag>(bit)) {
|
| #define DECLARE_FLAG(type) \
|
| @@ -522,13 +535,9 @@ void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() {
|
| block->block_id(),
|
| GetGVNFlagsString(side_effects).get());
|
|
|
| - GVNFlagSet accumulated_first_time_depends;
|
| - GVNFlagSet accumulated_first_time_changes;
|
| HBasicBlock* last = block->loop_information()->GetLastBackEdge();
|
| for (int j = block->block_id(); j <= last->block_id(); ++j) {
|
| - ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects,
|
| - &accumulated_first_time_depends,
|
| - &accumulated_first_time_changes);
|
| + ProcessLoopBlock(graph()->blocks()->at(j), block, side_effects);
|
| }
|
| }
|
| }
|
| @@ -538,9 +547,7 @@ void HGlobalValueNumberingPhase::LoopInvariantCodeMotion() {
|
| void HGlobalValueNumberingPhase::ProcessLoopBlock(
|
| HBasicBlock* block,
|
| HBasicBlock* loop_header,
|
| - GVNFlagSet loop_kills,
|
| - GVNFlagSet* first_time_depends,
|
| - GVNFlagSet* first_time_changes) {
|
| + GVNFlagSet loop_kills) {
|
| HBasicBlock* pre_header = loop_header->predecessors()->at(0);
|
| GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
|
| TRACE_GVN_2("Loop invariant motion for B%d %s\n",
|
| @@ -549,7 +556,6 @@ void HGlobalValueNumberingPhase::ProcessLoopBlock(
|
| HInstruction* instr = block->first();
|
| while (instr != NULL) {
|
| HInstruction* next = instr->next();
|
| - bool hoisted = false;
|
| if (instr->CheckFlag(HValue::kUseGVN)) {
|
| TRACE_GVN_4("Checking instruction %d (%s) %s. Loop %s\n",
|
| instr->id(),
|
| @@ -576,26 +582,9 @@ void HGlobalValueNumberingPhase::ProcessLoopBlock(
|
| instr->Unlink();
|
| instr->InsertBefore(pre_header->end());
|
| if (instr->HasSideEffects()) removed_side_effects_ = true;
|
| - hoisted = true;
|
| }
|
| }
|
| }
|
| - if (!hoisted) {
|
| - // If an instruction is not hoisted, we have to account for its side
|
| - // effects when hoisting later HTransitionElementsKind instructions.
|
| - GVNFlagSet previous_depends = *first_time_depends;
|
| - GVNFlagSet previous_changes = *first_time_changes;
|
| - first_time_depends->Add(instr->DependsOnFlags());
|
| - first_time_changes->Add(instr->ChangesFlags());
|
| - if (!(previous_depends == *first_time_depends)) {
|
| - TRACE_GVN_1("Updated first-time accumulated %s\n",
|
| - GetGVNFlagsString(*first_time_depends).get());
|
| - }
|
| - if (!(previous_changes == *first_time_changes)) {
|
| - TRACE_GVN_1("Updated first-time accumulated %s\n",
|
| - GetGVNFlagsString(*first_time_changes).get());
|
| - }
|
| - }
|
| instr = next;
|
| }
|
| }
|
| @@ -791,7 +780,9 @@ void HGlobalValueNumberingPhase::AnalyzeGraph() {
|
| instr->Mnemonic(),
|
| other->id(),
|
| other->Mnemonic());
|
| - instr->HandleSideEffectDominator(changes_flag, other);
|
| + if (instr->HandleSideEffectDominator(changes_flag, other)) {
|
| + removed_side_effects_ = true;
|
| + }
|
| }
|
| }
|
| }
|
|
|