--- /dev/null
+// 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
--- /dev/null
+// 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_
#include "double.h"
#include "factory.h"
-#include "hydrogen.h"
+#include "hydrogen-infer-representation.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/lithium-ia32.h"
}
-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");
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)) {
}
-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());
}
}
-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();
}
-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");
}
-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");
}
-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);
}
-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");
// Forward declarations.
class HBasicBlock;
class HEnvironment;
-class HInferRepresentation;
+class HInferRepresentationPhase;
class HInstruction;
class HLoopInformation;
class HValue;
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
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) { }
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();
}
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()) {
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); }
}
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()) {
observed_input_representation_[1] = right;
}
- virtual void InferRepresentation(HInferRepresentation* h_infer);
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
virtual Representation RequiredInputRepresentation(int index) {
return representation();
return RequiredInputRepresentation(index);
}
- virtual void InferRepresentation(HInferRepresentation* h_infer);
+ virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
virtual Representation RepresentationFromInputs() {
Representation left_rep = left()->representation();
#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"
}
-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());
}
}
- 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.
};
-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 {
'../../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',