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
This commit is contained in:
fschneider@chromium.org 2011-05-03 08:31:35 +00:00
parent d0fcbb4ece
commit 3e94ac952d
2 changed files with 49 additions and 11 deletions

View File

@ -555,6 +555,8 @@ class HValue: public ZoneObject {
representation_ = r;
}
virtual bool IsConvertibleToInteger() const { return true; }
HType type() const { return type_; }
void set_type(HType type) {
ASSERT(HasNoUses());
@ -1923,7 +1925,8 @@ class HPhi: public HValue {
: inputs_(2),
merged_index_(merged_index),
phi_id_(-1),
is_live_(false) {
is_live_(false),
is_convertible_to_integer_(true) {
for (int i = 0; i < Representation::kNumRepresentations; i++) {
non_phi_uses_[i] = 0;
indirect_uses_[i] = 0;
@ -2001,6 +2004,14 @@ class HPhi: public HValue {
}
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:
virtual void DeleteFromGraph();
virtual void InternalSetOperandAt(int index, HValue* value) {
@ -2015,6 +2026,7 @@ class HPhi: public HValue {
int indirect_uses_[Representation::kNumRepresentations];
int phi_id_;
bool is_live_;
bool is_convertible_to_integer_;
};
@ -2045,6 +2057,14 @@ class HConstant: public HTemplateInstruction<0> {
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 void PrintDataTo(StringStream* stream);
virtual HType CalculateInferredType();

View File

@ -1574,14 +1574,12 @@ Representation HInferRepresentation::TryChange(HValue* value) {
}
if (non_tagged_count >= tagged_count) {
// More untagged than tagged.
if (double_count > 0) {
// There is at least one usage that is a double => guess that the
// correct representation is double.
return Representation::Double();
} else if (int32_count > 0) {
return Representation::Integer32();
if (int32_count > 0) {
if (!value->IsPhi() || value->IsConvertibleToInteger()) {
return Representation::Integer32();
}
}
if (double_count > 0) return Representation::Double();
}
return Representation::None();
}
@ -1594,11 +1592,12 @@ void HInferRepresentation::Analyze() {
// bit-vector of length <number of phis>.
const ZoneList<HPhi*>* phi_list = graph_->phi_list();
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) {
phi_list->at(i)->InitRealUses(i);
connected_phis[i] = new(zone()) BitVector(phi_count);
connected_phis[i]->Add(i);
BitVector* connected_set = new(zone()) BitVector(phi_count);
connected_set->Add(i);
connected_phis.Add(connected_set);
}
// (2) Do a fixed point iteration to find the set of connected phis. A
@ -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) {
HBasicBlock* block = graph_->blocks()->at(i);
const ZoneList<HPhi*>* phis = block->phis();