Commit f11af230 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Refactor HInferRepresentation into an HPhase and use the phase zone.

Rename HInferRepresentation to HInferRepresentationPhase,
following naming scheme suggested by danno@chromium.org in
https://codereview.chromium.org/17458002

The HInferRepresentationPhase now uses the phase zone for all its
allocations.

Depends on https://codereview.chromium.org/17587008

R=danno@chromium.org
BUG=

Review URL: https://codereview.chromium.org/18054002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15373 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent a46528e8
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "hydrogen-infer-representation.h"
namespace v8 {
namespace internal {
void HInferRepresentationPhase::AddToWorklist(HValue* current) {
if (current->representation().IsTagged()) return;
if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
if (in_worklist_.Contains(current->id())) return;
worklist_.Add(current, zone());
in_worklist_.Add(current->id());
}
void HInferRepresentationPhase::Run() {
// (1) Initialize bit vectors and count real uses. Each phi gets a
// bit-vector of length <number of phis>.
const ZoneList<HPhi*>* phi_list = graph()->phi_list();
int phi_count = phi_list->length();
ZoneList<BitVector*> connected_phis(phi_count, zone());
for (int i = 0; i < phi_count; ++i) {
phi_list->at(i)->InitRealUses(i);
BitVector* connected_set = new(zone()) BitVector(phi_count, zone());
connected_set->Add(i);
connected_phis.Add(connected_set, zone());
}
// (2) Do a fixed point iteration to find the set of connected phis. A
// phi is connected to another phi if its value is used either directly or
// indirectly through a transitive closure of the def-use relation.
bool change = true;
while (change) {
change = false;
// We normally have far more "forward edges" than "backward edges",
// so we terminate faster when we walk backwards.
for (int i = phi_count - 1; i >= 0; --i) {
HPhi* phi = phi_list->at(i);
for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
if (use->IsPhi()) {
int id = HPhi::cast(use)->phi_id();
if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
change = true;
}
}
}
}
// Set truncation flags for groups of connected phis. This is a conservative
// approximation; the flag will be properly re-computed after representations
// have been determined.
if (phi_count > 0) {
BitVector done(phi_count, zone());
for (int i = 0; i < phi_count; ++i) {
if (done.Contains(i)) continue;
// Check if all uses of all connected phis in this group are truncating.
bool all_uses_everywhere_truncating = true;
for (BitVector::Iterator it(connected_phis[i]);
!it.Done();
it.Advance()) {
int index = it.Current();
all_uses_everywhere_truncating &=
phi_list->at(index)->CheckFlag(HInstruction::kTruncatingToInt32);
done.Add(index);
}
if (all_uses_everywhere_truncating) {
continue; // Great, nothing to do.
}
// Clear truncation flag of this group of connected phis.
for (BitVector::Iterator it(connected_phis[i]);
!it.Done();
it.Advance()) {
int index = it.Current();
phi_list->at(index)->ClearFlag(HInstruction::kTruncatingToInt32);
}
}
}
// Simplify constant phi inputs where possible.
// This step uses kTruncatingToInt32 flags of phis.
for (int i = 0; i < phi_count; ++i) {
phi_list->at(i)->SimplifyConstantInputs();
}
// Use the phi reachability information from step 2 to
// sum up the non-phi use counts of all connected phis.
for (int i = 0; i < phi_count; ++i) {
HPhi* phi = phi_list->at(i);
for (BitVector::Iterator it(connected_phis[i]);
!it.Done();
it.Advance()) {
int index = it.Current();
HPhi* it_use = phi_list->at(index);
if (index != i) phi->AddNonPhiUsesFrom(it_use); // Don't count twice.
}
}
// Initialize work list
for (int i = 0; i < graph()->blocks()->length(); ++i) {
HBasicBlock* block = graph()->blocks()->at(i);
const ZoneList<HPhi*>* phis = block->phis();
for (int j = 0; j < phis->length(); ++j) {
AddToWorklist(phis->at(j));
}
HInstruction* current = block->first();
while (current != NULL) {
AddToWorklist(current);
current = current->next();
}
}
// Do a fixed point iteration, trying to improve representations
while (!worklist_.is_empty()) {
HValue* current = worklist_.RemoveLast();
in_worklist_.Remove(current->id());
current->InferRepresentation(this);
}
// Lastly: any instruction that we don't have representation information
// for defaults to Tagged.
for (int i = 0; i < graph()->blocks()->length(); ++i) {
HBasicBlock* block = graph()->blocks()->at(i);
const ZoneList<HPhi*>* phis = block->phis();
for (int j = 0; j < phis->length(); ++j) {
HPhi* phi = phis->at(j);
if (phi->representation().IsNone()) {
phi->ChangeRepresentation(Representation::Tagged());
}
}
for (HInstruction* current = block->first();
current != NULL; current = current->next()) {
if (current->representation().IsNone() &&
current->CheckFlag(HInstruction::kFlexibleRepresentation)) {
if (current->CheckFlag(HInstruction::kCannotBeTagged)) {
current->ChangeRepresentation(Representation::Double());
} else {
current->ChangeRepresentation(Representation::Tagged());
}
}
}
}
}
} } // namespace v8::internal
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_HYDROGEN_INFER_REPRESENTATION_H_
#define V8_HYDROGEN_INFER_REPRESENTATION_H_
#include "hydrogen.h"
namespace v8 {
namespace internal {
class HInferRepresentationPhase : public HPhase {
public:
explicit HInferRepresentationPhase(HGraph* graph)
: HPhase("H_Infer representations", graph),
worklist_(8, zone()),
in_worklist_(graph->GetMaximumValueID(), zone()) { }
void Run();
void AddToWorklist(HValue* current);
private:
ZoneList<HValue*> worklist_;
BitVector in_worklist_;
DISALLOW_COPY_AND_ASSIGN(HInferRepresentationPhase);
};
} } // namespace v8::internal
#endif // V8_HYDROGEN_INFER_REPRESENTATION_H_
......@@ -29,7 +29,7 @@
#include "double.h"
#include "factory.h"
#include "hydrogen.h"
#include "hydrogen-infer-representation.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/lithium-ia32.h"
......@@ -78,7 +78,7 @@ void HValue::AssumeRepresentation(Representation r) {
}
void HValue::InferRepresentation(HInferRepresentation* h_infer) {
void HValue::InferRepresentation(HInferRepresentationPhase* h_infer) {
ASSERT(CheckFlag(kFlexibleRepresentation));
Representation new_rep = RepresentationFromInputs();
UpdateRepresentation(new_rep, h_infer, "inputs");
......@@ -124,7 +124,7 @@ Representation HValue::RepresentationFromUses() {
void HValue::UpdateRepresentation(Representation new_rep,
HInferRepresentation* h_infer,
HInferRepresentationPhase* h_infer,
const char* reason) {
Representation r = representation();
if (new_rep.is_more_general_than(r)) {
......@@ -139,7 +139,7 @@ void HValue::UpdateRepresentation(Representation new_rep,
}
void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
void HValue::AddDependantsToWorklist(HInferRepresentationPhase* h_infer) {
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
h_infer->AddToWorklist(it.value());
}
......@@ -1150,7 +1150,7 @@ void HBoundsCheck::PrintDataTo(StringStream* stream) {
}
void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
void HBoundsCheck::InferRepresentation(HInferRepresentationPhase* h_infer) {
ASSERT(CheckFlag(kFlexibleRepresentation));
HValue* actual_index = index()->ActualValue();
HValue* actual_length = length()->ActualValue();
......@@ -2324,7 +2324,7 @@ void HBinaryOperation::PrintDataTo(StringStream* stream) {
}
void HBinaryOperation::InferRepresentation(HInferRepresentation* h_infer) {
void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) {
ASSERT(CheckFlag(kFlexibleRepresentation));
Representation new_rep = RepresentationFromInputs();
UpdateRepresentation(new_rep, h_infer, "inputs");
......@@ -2387,7 +2387,7 @@ void HBinaryOperation::AssumeRepresentation(Representation r) {
}
void HMathMinMax::InferRepresentation(HInferRepresentation* h_infer) {
void HMathMinMax::InferRepresentation(HInferRepresentationPhase* h_infer) {
ASSERT(CheckFlag(kFlexibleRepresentation));
Representation new_rep = RepresentationFromInputs();
UpdateRepresentation(new_rep, h_infer, "inputs");
......@@ -2566,7 +2566,8 @@ void HGoto::PrintDataTo(StringStream* stream) {
}
void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* h_infer) {
void HCompareIDAndBranch::InferRepresentation(
HInferRepresentationPhase* h_infer) {
Representation left_rep = left()->representation();
Representation right_rep = right()->representation();
Representation observed_left = observed_input_representation(0);
......@@ -3671,7 +3672,7 @@ void HPhi::SimplifyConstantInputs() {
}
void HPhi::InferRepresentation(HInferRepresentation* h_infer) {
void HPhi::InferRepresentation(HInferRepresentationPhase* h_infer) {
ASSERT(CheckFlag(kFlexibleRepresentation));
Representation new_rep = RepresentationFromInputs();
UpdateRepresentation(new_rep, h_infer, "inputs");
......
......@@ -45,7 +45,7 @@ namespace internal {
// Forward declarations.
class HBasicBlock;
class HEnvironment;
class HInferRepresentation;
class HInferRepresentationPhase;
class HInstruction;
class HLoopInformation;
class HValue;
......@@ -1067,7 +1067,7 @@ class HValue: public ZoneObject {
return Representation::None();
}
virtual Representation RequiredInputRepresentation(int index) = 0;
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
// This gives the instruction an opportunity to replace itself with an
// instruction that does the same in some better way. To replace an
......@@ -1159,9 +1159,9 @@ class HValue: public ZoneObject {
Representation RepresentationFromUses();
Representation RepresentationFromUseRequirements();
virtual void UpdateRepresentation(Representation new_rep,
HInferRepresentation* h_infer,
HInferRepresentationPhase* h_infer,
const char* reason);
void AddDependantsToWorklist(HInferRepresentation* h_infer);
void AddDependantsToWorklist(HInferRepresentationPhase* h_infer);
virtual void RepresentationChanged(Representation to) { }
......@@ -3073,7 +3073,7 @@ class HPhi: public HValue {
virtual Representation RepresentationFromInputs();
virtual Range* InferRange(Zone* zone);
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
virtual Representation RequiredInputRepresentation(int index) {
return representation();
}
......@@ -3495,12 +3495,12 @@ class HBinaryOperation: public HTemplateInstruction<3> {
return observed_input_representation_[index - 1];
}
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
virtual Representation RepresentationFromInputs();
virtual void AssumeRepresentation(Representation r);
virtual void UpdateRepresentation(Representation new_rep,
HInferRepresentation* h_infer,
HInferRepresentationPhase* h_infer,
const char* reason) {
// By default, binary operations don't handle Smis.
if (new_rep.IsSmi()) {
......@@ -3712,7 +3712,7 @@ class HBoundsCheck: public HTemplateInstruction<2> {
int scale = 0);
virtual void PrintDataTo(StringStream* stream);
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
HValue* index() { return OperandAt(0); }
HValue* length() { return OperandAt(1); }
......@@ -3809,7 +3809,7 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
}
virtual void UpdateRepresentation(Representation new_rep,
HInferRepresentation* h_infer,
HInferRepresentationPhase* h_infer,
const char* reason) {
// We only generate either int32 or generic tagged bitwise operations.
if (new_rep.IsSmi() || new_rep.IsDouble()) {
......@@ -3944,7 +3944,7 @@ class HCompareIDAndBranch: public HTemplateControlInstruction<2, 2> {
observed_input_representation_[1] = right;
}
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
virtual Representation RequiredInputRepresentation(int index) {
return representation();
......@@ -4561,7 +4561,7 @@ class HMathMinMax: public HArithmeticBinaryOperation {
return RequiredInputRepresentation(index);
}
virtual void InferRepresentation(HInferRepresentation* h_infer);
virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
virtual Representation RepresentationFromInputs() {
Representation left_rep = left()->representation();
......
......@@ -35,6 +35,7 @@
#include "full-codegen.h"
#include "hashmap.h"
#include "hydrogen-environment-liveness.h"
#include "hydrogen-infer-representation.h"
#include "lithium-allocator.h"
#include "parser.h"
#include "scopeinfo.h"
......@@ -2814,149 +2815,6 @@ void HStackCheckEliminator::Process() {
}
void HInferRepresentation::AddToWorklist(HValue* current) {
if (current->representation().IsTagged()) return;
if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return;
if (in_worklist_.Contains(current->id())) return;
worklist_.Add(current, zone());
in_worklist_.Add(current->id());
}
void HInferRepresentation::Analyze() {
HPhase phase("H_Infer representations", graph_);
// (1) Initialize bit vectors and count real uses. Each phi gets a
// bit-vector of length <number of phis>.
const ZoneList<HPhi*>* phi_list = graph_->phi_list();
int phi_count = phi_list->length();
ZoneList<BitVector*> connected_phis(phi_count, graph_->zone());
for (int i = 0; i < phi_count; ++i) {
phi_list->at(i)->InitRealUses(i);
BitVector* connected_set = new(zone()) BitVector(phi_count, graph_->zone());
connected_set->Add(i);
connected_phis.Add(connected_set, zone());
}
// (2) Do a fixed point iteration to find the set of connected phis. A
// phi is connected to another phi if its value is used either directly or
// indirectly through a transitive closure of the def-use relation.
bool change = true;
while (change) {
change = false;
// We normally have far more "forward edges" than "backward edges",
// so we terminate faster when we walk backwards.
for (int i = phi_count - 1; i >= 0; --i) {
HPhi* phi = phi_list->at(i);
for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
if (use->IsPhi()) {
int id = HPhi::cast(use)->phi_id();
if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
change = true;
}
}
}
}
// Set truncation flags for groups of connected phis. This is a conservative
// approximation; the flag will be properly re-computed after representations
// have been determined.
if (phi_count > 0) {
BitVector* done = new(zone()) BitVector(phi_count, graph_->zone());
for (int i = 0; i < phi_count; ++i) {
if (done->Contains(i)) continue;
// Check if all uses of all connected phis in this group are truncating.
bool all_uses_everywhere_truncating = true;
for (BitVector::Iterator it(connected_phis.at(i));
!it.Done();
it.Advance()) {
int index = it.Current();
all_uses_everywhere_truncating &=
phi_list->at(index)->CheckFlag(HInstruction::kTruncatingToInt32);
done->Add(index);
}
if (all_uses_everywhere_truncating) {
continue; // Great, nothing to do.
}
// Clear truncation flag of this group of connected phis.
for (BitVector::Iterator it(connected_phis.at(i));
!it.Done();
it.Advance()) {
int index = it.Current();
phi_list->at(index)->ClearFlag(HInstruction::kTruncatingToInt32);
}
}
}
// Simplify constant phi inputs where possible.
// This step uses kTruncatingToInt32 flags of phis.
for (int i = 0; i < phi_count; ++i) {
phi_list->at(i)->SimplifyConstantInputs();
}
// Use the phi reachability information from step 2 to
// sum up the non-phi use counts of all connected phis.
for (int i = 0; i < phi_count; ++i) {
HPhi* phi = phi_list->at(i);
for (BitVector::Iterator it(connected_phis.at(i));
!it.Done();
it.Advance()) {
int index = it.Current();
HPhi* it_use = phi_list->at(index);
if (index != i) phi->AddNonPhiUsesFrom(it_use); // Don't count twice.
}
}
// Initialize work list
for (int i = 0; i < graph_->blocks()->length(); ++i) {
HBasicBlock* block = graph_->blocks()->at(i);
const ZoneList<HPhi*>* phis = block->phis();
for (int j = 0; j < phis->length(); ++j) {
AddToWorklist(phis->at(j));
}
HInstruction* current = block->first();
while (current != NULL) {
AddToWorklist(current);
current = current->next();
}
}
// Do a fixed point iteration, trying to improve representations
while (!worklist_.is_empty()) {
HValue* current = worklist_.RemoveLast();
in_worklist_.Remove(current->id());
current->InferRepresentation(this);
}
// Lastly: any instruction that we don't have representation information
// for defaults to Tagged.
for (int i = 0; i < graph_->blocks()->length(); ++i) {
HBasicBlock* block = graph_->blocks()->at(i);
const ZoneList<HPhi*>* phis = block->phis();
for (int j = 0; j < phis->length(); ++j) {
HPhi* phi = phis->at(j);
if (phi->representation().IsNone()) {
phi->ChangeRepresentation(Representation::Tagged());
}
}
for (HInstruction* current = block->first();
current != NULL; current = current->next()) {
if (current->representation().IsNone() &&
current->CheckFlag(HInstruction::kFlexibleRepresentation)) {
if (current->CheckFlag(HInstruction::kCannotBeTagged)) {
current->ChangeRepresentation(Representation::Double());
} else {
current->ChangeRepresentation(Representation::Tagged());
}
}
}
}
}
void HGraph::MergeRemovableSimulates() {
HPhase phase("H_Merge removable simulates", this);
ZoneList<HSimulate*> mergelist(2, zone());
......@@ -3986,8 +3844,7 @@ bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) {
}
}
HInferRepresentation rep(this);
rep.Analyze();
Run<HInferRepresentationPhase>();
// Remove HSimulate instructions that have turned out not to be needed
// after all by folding them into the following HSimulate.
......
......@@ -706,25 +706,6 @@ class HEnvironment: public ZoneObject {
};
class HInferRepresentation BASE_EMBEDDED {
public:
explicit HInferRepresentation(HGraph* graph)
: graph_(graph),
worklist_(8, graph->zone()),
in_worklist_(graph->GetMaximumValueID(), graph->zone()) { }
void Analyze();
void AddToWorklist(HValue* current);
private:
Zone* zone() const { return graph_->zone(); }
HGraph* graph_;
ZoneList<HValue*> worklist_;
BitVector in_worklist_;
};
class HOptimizedGraphBuilder;
enum ArgumentsAllowedFlag {
......
......@@ -330,6 +330,8 @@
'../../src/hydrogen.h',
'../../src/hydrogen-gvn.cc',
'../../src/hydrogen-gvn.h',
'../../src/hydrogen-infer-representation.cc',
'../../src/hydrogen-infer-representation.h',
'../../src/ic-inl.h',
'../../src/ic.cc',
'../../src/ic.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment