Change heuristics for deciding phi-representation types to use int32 more frequently.

Until now we conservatively chose a double representation if
at least one use occurs in a double operation. This causes performance
degradation in many cases where there are mixes uses (integer and double)

e.g.:

for (int i = 0; i < 10; i++) {
  var t = i / 3.5;
  a[i] = t;
}

where the use in i/3 requires a double, where as the keyed store requires i
as an integer.

For these cases we want to have i as an integer and convert it only before the
double division.

In order to avoid unconditional deoptimization in some rare cases, we check
phis if there is any conversion that will always fail when converting a
heap-number constant to int32.
Review URL: http://codereview.chromium.org/6905166

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7757 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d0fcbb4e
...@@ -555,6 +555,8 @@ class HValue: public ZoneObject { ...@@ -555,6 +555,8 @@ class HValue: public ZoneObject {
representation_ = r; representation_ = r;
} }
virtual bool IsConvertibleToInteger() const { return true; }
HType type() const { return type_; } HType type() const { return type_; }
void set_type(HType type) { void set_type(HType type) {
ASSERT(HasNoUses()); ASSERT(HasNoUses());
...@@ -1923,7 +1925,8 @@ class HPhi: public HValue { ...@@ -1923,7 +1925,8 @@ class HPhi: public HValue {
: inputs_(2), : inputs_(2),
merged_index_(merged_index), merged_index_(merged_index),
phi_id_(-1), phi_id_(-1),
is_live_(false) { is_live_(false),
is_convertible_to_integer_(true) {
for (int i = 0; i < Representation::kNumRepresentations; i++) { for (int i = 0; i < Representation::kNumRepresentations; i++) {
non_phi_uses_[i] = 0; non_phi_uses_[i] = 0;
indirect_uses_[i] = 0; indirect_uses_[i] = 0;
...@@ -2001,6 +2004,14 @@ class HPhi: public HValue { ...@@ -2001,6 +2004,14 @@ class HPhi: public HValue {
} }
virtual Opcode opcode() const { return HValue::kPhi; } virtual Opcode opcode() const { return HValue::kPhi; }
virtual bool IsConvertibleToInteger() const {
return is_convertible_to_integer_;
}
void set_is_convertible_to_integer(bool b) {
is_convertible_to_integer_ = b;
}
protected: protected:
virtual void DeleteFromGraph(); virtual void DeleteFromGraph();
virtual void InternalSetOperandAt(int index, HValue* value) { virtual void InternalSetOperandAt(int index, HValue* value) {
...@@ -2015,6 +2026,7 @@ class HPhi: public HValue { ...@@ -2015,6 +2026,7 @@ class HPhi: public HValue {
int indirect_uses_[Representation::kNumRepresentations]; int indirect_uses_[Representation::kNumRepresentations];
int phi_id_; int phi_id_;
bool is_live_; bool is_live_;
bool is_convertible_to_integer_;
}; };
...@@ -2045,6 +2057,14 @@ class HConstant: public HTemplateInstruction<0> { ...@@ -2045,6 +2057,14 @@ class HConstant: public HTemplateInstruction<0> {
return Representation::None(); return Representation::None();
} }
virtual bool IsConvertibleToInteger() const {
if (handle_->IsSmi()) return true;
if (handle_->IsHeapNumber() &&
(HeapNumber::cast(*handle_)->value() ==
static_cast<double>(NumberToInt32(*handle_)))) return true;
return false;
}
virtual bool EmitAtUses() { return !representation().IsDouble(); } virtual bool EmitAtUses() { return !representation().IsDouble(); }
virtual void PrintDataTo(StringStream* stream); virtual void PrintDataTo(StringStream* stream);
virtual HType CalculateInferredType(); virtual HType CalculateInferredType();
......
...@@ -1574,14 +1574,12 @@ Representation HInferRepresentation::TryChange(HValue* value) { ...@@ -1574,14 +1574,12 @@ Representation HInferRepresentation::TryChange(HValue* value) {
} }
if (non_tagged_count >= tagged_count) { if (non_tagged_count >= tagged_count) {
// More untagged than tagged. if (int32_count > 0) {
if (double_count > 0) { if (!value->IsPhi() || value->IsConvertibleToInteger()) {
// There is at least one usage that is a double => guess that the return Representation::Integer32();
// correct representation is double. }
return Representation::Double();
} else if (int32_count > 0) {
return Representation::Integer32();
} }
if (double_count > 0) return Representation::Double();
} }
return Representation::None(); return Representation::None();
} }
...@@ -1594,11 +1592,12 @@ void HInferRepresentation::Analyze() { ...@@ -1594,11 +1592,12 @@ void HInferRepresentation::Analyze() {
// bit-vector of length <number of phis>. // bit-vector of length <number of phis>.
const ZoneList<HPhi*>* phi_list = graph_->phi_list(); const ZoneList<HPhi*>* phi_list = graph_->phi_list();
int phi_count = phi_list->length(); int phi_count = phi_list->length();
ScopedVector<BitVector*> connected_phis(phi_count); ZoneList<BitVector*> connected_phis(phi_count);
for (int i = 0; i < phi_count; ++i) { for (int i = 0; i < phi_count; ++i) {
phi_list->at(i)->InitRealUses(i); phi_list->at(i)->InitRealUses(i);
connected_phis[i] = new(zone()) BitVector(phi_count); BitVector* connected_set = new(zone()) BitVector(phi_count);
connected_phis[i]->Add(i); connected_set->Add(i);
connected_phis.Add(connected_set);
} }
// (2) Do a fixed point iteration to find the set of connected phis. A // (2) Do a fixed point iteration to find the set of connected phis. A
...@@ -1635,6 +1634,25 @@ void HInferRepresentation::Analyze() { ...@@ -1635,6 +1634,25 @@ void HInferRepresentation::Analyze() {
} }
} }
// (4) Compute phis that definitely can't be converted to integer
// without deoptimization and mark them to avoid unnecessary deoptimization.
change = true;
while (change) {
change = false;
for (int i = 0; i < phi_count; ++i) {
HPhi* phi = phi_list->at(i);
for (int j = 0; j < phi->OperandCount(); ++j) {
if (phi->IsConvertibleToInteger() &&
!phi->OperandAt(j)->IsConvertibleToInteger()) {
phi->set_is_convertible_to_integer(false);
change = true;
break;
}
}
}
}
for (int i = 0; i < graph_->blocks()->length(); ++i) { for (int i = 0; i < graph_->blocks()->length(); ++i) {
HBasicBlock* block = graph_->blocks()->at(i); HBasicBlock* block = graph_->blocks()->at(i);
const ZoneList<HPhi*>* phis = block->phis(); const ZoneList<HPhi*>* phis = block->phis();
......
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