| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index fecdcf0774a70cbbfbf5bc70976d759619160aaf..fd4eec3ab5ae3674c63aeeb08fd8c419f44e7a8b 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -1552,14 +1552,97 @@ void HGlobalValueNumberer::ComputeBlockSideEffects() {
|
| }
|
|
|
|
|
| +SmartArrayPointer<char> GetGVNFlagsString(GVNFlagSet flags) {
|
| +#if DEBUG
|
| + char buffer[kLastFlag * 128];
|
| + const char* separator = "";
|
| + const char* comma = ", ";
|
| + buffer[0] = 0;
|
| + uint32_t set_depends_on = 0;
|
| + uint32_t set_changes = 0;
|
| + for (int bit = 0; bit < kLastFlag; ++bit) {
|
| + if ((flags.ToIntegral() & (1 << bit)) != 0) {
|
| + if (bit % 2 == 0) {
|
| + set_changes++;
|
| + } else {
|
| + set_depends_on++;
|
| + }
|
| + }
|
| + }
|
| + bool positive_changes = set_changes < (kLastFlag / 2);
|
| + bool positive_depends_on = set_depends_on < (kLastFlag / 2);
|
| + if (set_changes > 0) {
|
| + if (positive_changes) {
|
| + strcat(buffer, "changes [");
|
| + } else {
|
| + strcat(buffer, "changes all except [");
|
| + }
|
| + for (int bit = 0; bit < kLastFlag; ++bit) {
|
| + if (((flags.ToIntegral() & (1 << bit)) != 0) == positive_changes) {
|
| + switch (static_cast<GVNFlag>(bit)) {
|
| +#define DECLARE_FLAG(type) \
|
| + case kChanges##type: \
|
| + strcat(buffer, separator); \
|
| + strcat(buffer, #type); \
|
| + separator = comma; \
|
| + break;
|
| +GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
|
| +GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
|
| +#undef DECLARE_FLAG
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + strcat(buffer, "]");
|
| + }
|
| + if (set_depends_on > 0) {
|
| + separator = "";
|
| + if (set_changes > 0) {
|
| + strcat(buffer, ", ");
|
| + }
|
| + if (positive_depends_on) {
|
| + strcat(buffer, "depends on [");
|
| + } else {
|
| + strcat(buffer, "depends on all except [");
|
| + }
|
| + for (int bit = 0; bit < kLastFlag; ++bit) {
|
| + if (((flags.ToIntegral() & (1 << bit)) != 0) == positive_depends_on) {
|
| + switch (static_cast<GVNFlag>(bit)) {
|
| +#define DECLARE_FLAG(type) \
|
| + case kDependsOn##type: \
|
| + strcat(buffer, separator); \
|
| + strcat(buffer, #type); \
|
| + separator = comma; \
|
| + break;
|
| +GVN_TRACKED_FLAG_LIST(DECLARE_FLAG)
|
| +GVN_UNTRACKED_FLAG_LIST(DECLARE_FLAG)
|
| +#undef DECLARE_FLAG
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + strcat(buffer, "]");
|
| + }
|
| +#else
|
| + char buffer[128];
|
| + snprintf(buffer, 128, "0x%08X", flags.ToIntegral());
|
| +#endif
|
| + char* result = new char[strlen(buffer) + 1];
|
| + strcpy(result, buffer);
|
| + return SmartArrayPointer<char>(result);
|
| +}
|
| +
|
| +
|
| void HGlobalValueNumberer::LoopInvariantCodeMotion() {
|
| for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
|
| HBasicBlock* block = graph_->blocks()->at(i);
|
| if (block->IsLoopHeader()) {
|
| GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
|
| - TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
|
| + TraceGVN("Try loop invariant motion for block B%d %s\n",
|
| block->block_id(),
|
| - side_effects.ToIntegral());
|
| + *GetGVNFlagsString(side_effects));
|
|
|
| GVNFlagSet accumulated_first_time_depends;
|
| GVNFlagSet accumulated_first_time_changes;
|
| @@ -1582,20 +1665,19 @@ void HGlobalValueNumberer::ProcessLoopBlock(
|
| GVNFlagSet* first_time_changes) {
|
| HBasicBlock* pre_header = loop_header->predecessors()->at(0);
|
| GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
|
| - TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
|
| + TraceGVN("Loop invariant motion for B%d %s\n",
|
| block->block_id(),
|
| - depends_flags.ToIntegral());
|
| + *GetGVNFlagsString(depends_flags));
|
| HInstruction* instr = block->first();
|
| while (instr != NULL) {
|
| HInstruction* next = instr->next();
|
| bool hoisted = false;
|
| if (instr->CheckFlag(HValue::kUseGVN)) {
|
| - TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, "
|
| - "loop kills 0x%X\n",
|
| + TraceGVN("Checking instruction %d (%s) %s. Loop %s\n",
|
| instr->id(),
|
| instr->Mnemonic(),
|
| - instr->gvn_flags().ToIntegral(),
|
| - depends_flags.ToIntegral());
|
| + *GetGVNFlagsString(instr->gvn_flags()),
|
| + *GetGVNFlagsString(loop_kills));
|
| bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
|
| if (instr->IsTransitionElementsKind()) {
|
| // It's possible to hoist transitions out of a loop as long as the
|
| @@ -1619,14 +1701,14 @@ void HGlobalValueNumberer::ProcessLoopBlock(
|
| hoist_change_blockers.Add(kChangesArrayElements);
|
| }
|
| TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) "
|
| - "hoist depends blockers 0x%X, hoist change blockers 0x%X, "
|
| - "accumulated depends 0x%X, accumulated changes 0x%X\n",
|
| + "hoist blockers: %s %s; "
|
| + "first-time accumulated: %s %s\n",
|
| instr->id(),
|
| instr->Mnemonic(),
|
| - hoist_depends_blockers.ToIntegral(),
|
| - hoist_change_blockers.ToIntegral(),
|
| - first_time_depends->ToIntegral(),
|
| - first_time_changes->ToIntegral());
|
| + *GetGVNFlagsString(hoist_depends_blockers),
|
| + *GetGVNFlagsString(hoist_change_blockers),
|
| + *GetGVNFlagsString(*first_time_depends),
|
| + *GetGVNFlagsString(*first_time_changes));
|
| // It's possible to hoist transition from the current loop loop only if
|
| // they dominate all of the successor blocks in the same loop and there
|
| // are not any instructions that have Changes/DependsOn that intervene
|
| @@ -1661,8 +1743,18 @@ void HGlobalValueNumberer::ProcessLoopBlock(
|
| 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)) {
|
| + TraceGVN("Updated first-time accumulated %s\n",
|
| + *GetGVNFlagsString(*first_time_depends));
|
| + }
|
| + if (!(previous_changes == *first_time_changes)) {
|
| + TraceGVN("Updated first-time accumulated %s\n",
|
| + *GetGVNFlagsString(*first_time_changes));
|
| + }
|
| }
|
| instr = next;
|
| }
|
|
|