From 3e94ac952da9a56ec8f7829871d7ae3b12bb8e00 Mon Sep 17 00:00:00 2001 From: "fschneider@chromium.org" Date: Tue, 3 May 2011 08:31:35 +0000 Subject: [PATCH] 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 --- src/hydrogen-instructions.h | 22 ++++++++++++++++++++- src/hydrogen.cc | 38 +++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 0fe4a0ed20..82fdfa70a2 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -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(NumberToInt32(*handle_)))) return true; + return false; + } + virtual bool EmitAtUses() { return !representation().IsDouble(); } virtual void PrintDataTo(StringStream* stream); virtual HType CalculateInferredType(); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 4de8305a24..3b57f9fafa 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -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 . const ZoneList* phi_list = graph_->phi_list(); int phi_count = phi_list->length(); - ScopedVector connected_phis(phi_count); + ZoneList 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* phis = block->phis();