diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index faf640490b..b05e555e41 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -858,22 +858,20 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, // Shift operations can only deoptimize if we do a logical shift // by 0 and the result cannot be truncated to int32. - bool can_deopt = (op == Token::SHR && constant_value == 0); - if (can_deopt) { - bool can_truncate = true; - for (int i = 0; i < instr->uses()->length(); i++) { - if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { - can_truncate = false; + bool may_deopt = (op == Token::SHR && constant_value == 0); + bool does_deopt = false; + if (may_deopt) { + for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { + if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { + does_deopt = true; break; } } - can_deopt = !can_truncate; } LInstruction* result = - DefineSameAsFirst(new LShiftI(op, left, right, can_deopt)); - if (can_deopt) AssignEnvironment(result); - return result; + DefineSameAsFirst(new LShiftI(op, left, right, does_deopt)); + return does_deopt ? AssignEnvironment(result) : result; } diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index 58e6ff02cd..b50b00b36e 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc @@ -264,31 +264,60 @@ HType HType::TypeFromValue(Handle value) { } -int HValue::LookupOperandIndex(int occurrence_index, HValue* op) { - for (int i = 0; i < OperandCount(); ++i) { - if (OperandAt(i) == op) { - if (occurrence_index == 0) return i; - --occurrence_index; - } - } - return -1; -} - - bool HValue::IsDefinedAfter(HBasicBlock* other) const { return block()->block_id() > other->block_id(); } -bool HValue::UsesMultipleTimes(HValue* op) { - bool seen = false; - for (int i = 0; i < OperandCount(); ++i) { - if (OperandAt(i) == op) { - if (seen) return true; - seen = true; - } +HUseIterator::HUseIterator(HUseListNode* head) : next_(head) { + Advance(); +} + + +void HUseIterator::Advance() { + current_ = next_; + if (current_ != NULL) { + next_ = current_->tail(); + value_ = current_->value(); + index_ = current_->index(); } - return false; +} + + +int HValue::UseCount() const { + int count = 0; + for (HUseIterator it(uses()); !it.Done(); it.Advance()) ++count; + return count; +} + + +HUseListNode* HValue::RemoveUse(HValue* value, int index) { + HUseListNode* previous = NULL; + HUseListNode* current = use_list_; + while (current != NULL) { + if (current->value() == value && current->index() == index) { + if (previous == NULL) { + use_list_ = current->tail(); + } else { + previous->set_tail(current->tail()); + } + break; + } + + previous = current; + current = current->tail(); + } + +#ifdef DEBUG + // Do not reuse use list nodes in debug mode, zap them. + if (current != NULL) { + HUseListNode* temp = + new HUseListNode(current->value(), current->index(), NULL); + current->Zap(); + current = temp; + } +#endif + return current; } @@ -335,64 +364,31 @@ void HValue::SetOperandAt(int index, HValue* value) { } -void HValue::ReplaceAndDelete(HValue* other) { - if (other != NULL) ReplaceValue(other); - Delete(); -} - - -void HValue::ReplaceValue(HValue* other) { - for (int i = 0; i < uses_.length(); ++i) { - HValue* use = uses_[i]; - ASSERT(!use->block()->IsStartBlock()); - InternalReplaceAtUse(use, other); - other->uses_.Add(use); - } - uses_.Rewind(0); -} - - -void HValue::ClearOperands() { - for (int i = 0; i < OperandCount(); ++i) { - SetOperandAt(i, NULL); - } -} - - -void HValue::Delete() { +void HValue::DeleteAndReplaceWith(HValue* other) { + // We replace all uses first, so Delete can assert that there are none. + if (other != NULL) ReplaceAllUsesWith(other); ASSERT(HasNoUses()); ClearOperands(); DeleteFromGraph(); } -void HValue::ReplaceAtUse(HValue* use, HValue* other) { - for (int i = 0; i < use->OperandCount(); ++i) { - if (use->OperandAt(i) == this) { - use->SetOperandAt(i, other); - } +void HValue::ReplaceAllUsesWith(HValue* other) { + while (use_list_ != NULL) { + HUseListNode* list_node = use_list_; + HValue* value = list_node->value(); + ASSERT(!value->block()->IsStartBlock()); + value->InternalSetOperandAt(list_node->index(), other); + use_list_ = list_node->tail(); + list_node->set_tail(other->use_list_); + other->use_list_ = list_node; } } -void HValue::ReplaceFirstAtUse(HValue* use, HValue* other, Representation r) { - for (int i = 0; i < use->OperandCount(); ++i) { - if (use->RequiredInputRepresentation(i).Equals(r) && - use->OperandAt(i) == this) { - use->SetOperandAt(i, other); - return; - } - } -} - - -void HValue::InternalReplaceAtUse(HValue* use, HValue* other) { - for (int i = 0; i < use->OperandCount(); ++i) { - if (use->OperandAt(i) == this) { - // Call internal method that does not update use lists. The caller is - // responsible for doing so. - use->InternalSetOperandAt(i, other); - } +void HValue::ClearOperands() { + for (int i = 0; i < OperandCount(); ++i) { + SetOperandAt(i, NULL); } } @@ -427,9 +423,20 @@ bool HValue::UpdateInferredType() { void HValue::RegisterUse(int index, HValue* new_value) { HValue* old_value = OperandAt(index); if (old_value == new_value) return; - if (old_value != NULL) old_value->uses_.RemoveElement(this); + + HUseListNode* removed = NULL; + if (old_value != NULL) { + removed = old_value->RemoveUse(this, index); + } + if (new_value != NULL) { - new_value->uses_.Add(this); + if (removed == NULL) { + new_value->use_list_ = + new HUseListNode(this, index, new_value->use_list_); + } else { + removed->set_tail(new_value->use_list_); + new_value->use_list_ = removed; + } } } @@ -926,7 +933,7 @@ void HPhi::PrintTo(StringStream* stream) { stream->Add(" "); } stream->Add(" uses%d_%di_%dd_%dt]", - uses()->length(), + UseCount(), int32_non_phi_uses() + int32_indirect_uses(), double_non_phi_uses() + double_indirect_uses(), tagged_non_phi_uses() + tagged_indirect_uses()); @@ -944,8 +951,8 @@ void HPhi::AddInput(HValue* value) { bool HPhi::HasRealUses() { - for (int i = 0; i < uses()->length(); i++) { - if (!uses()->at(i)->IsPhi()) return true; + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { + if (!it.value()->IsPhi()) return true; } return false; } @@ -978,12 +985,11 @@ void HPhi::DeleteFromGraph() { void HPhi::InitRealUses(int phi_id) { // Initialize real uses. phi_id_ = phi_id; - for (int j = 0; j < uses()->length(); j++) { - HValue* use = uses()->at(j); - if (!use->IsPhi()) { - int index = use->LookupOperandIndex(0, this); - Representation req_rep = use->RequiredInputRepresentation(index); - non_phi_uses_[req_rep.kind()]++; + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { + HValue* value = it.value(); + if (!value->IsPhi()) { + Representation rep = value->RequiredInputRepresentation(it.index()); + ++non_phi_uses_[rep.kind()]; } } } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 561dbc1d0f..8d39b69330 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -403,6 +403,62 @@ class HType { }; +class HUseListNode: public ZoneObject { + public: + HUseListNode(HValue* value, int index, HUseListNode* tail) + : tail_(tail), value_(value), index_(index) { + } + + HUseListNode* tail() const { return tail_; } + HValue* value() const { return value_; } + int index() const { return index_; } + + void set_tail(HUseListNode* list) { tail_ = list; } + +#ifdef DEBUG + void Zap() { + tail_ = reinterpret_cast(1); + value_ = NULL; + index_ = -1; + } +#endif + + private: + HUseListNode* tail_; + HValue* value_; + int index_; +}; + + +// We reuse use list nodes behind the scenes as uses are added and deleted. +// This class is the safe way to iterate uses while deleting them. +class HUseIterator BASE_EMBEDDED { + public: + bool Done() { return current_ == NULL; } + void Advance(); + + HValue* value() { + ASSERT(!Done()); + return value_; + } + + int index() { + ASSERT(!Done()); + return index_; + } + + private: + explicit HUseIterator(HUseListNode* head); + + HUseListNode* current_; + HUseListNode* next_; + HValue* value_; + int index_; + + friend class HValue; +}; + + class HValue: public ZoneObject { public: static const int kNoNumber = -1; @@ -473,6 +529,7 @@ class HValue: public ZoneObject { HValue() : block_(NULL), id_(kNoNumber), type_(HType::Tagged()), + use_list_(NULL), range_(NULL), flags_(0) {} virtual ~HValue() {} @@ -483,7 +540,7 @@ class HValue: public ZoneObject { int id() const { return id_; } void set_id(int id) { id_ = id; } - SmallPointerList* uses() { return &uses_; } + HUseIterator uses() const { return HUseIterator(use_list_); } virtual bool EmitAtUses() { return false; } Representation representation() const { return representation_; } @@ -498,7 +555,7 @@ class HValue: public ZoneObject { HType type() const { return type_; } void set_type(HType type) { - ASSERT(uses_.length() == 0); + ASSERT(HasNoUses()); type_ = type; } @@ -524,16 +581,13 @@ class HValue: public ZoneObject { virtual HValue* OperandAt(int index) = 0; void SetOperandAt(int index, HValue* value); - int LookupOperandIndex(int occurrence_index, HValue* op); - bool UsesMultipleTimes(HValue* op); - - void ReplaceAndDelete(HValue* other); - void ReplaceValue(HValue* other); - void ReplaceAtUse(HValue* use, HValue* other); - void ReplaceFirstAtUse(HValue* use, HValue* other, Representation r); - bool HasNoUses() const { return uses_.is_empty(); } + void DeleteAndReplaceWith(HValue* other); + bool HasNoUses() const { return use_list_ == NULL; } + bool HasMultipleUses() const { + return use_list_ != NULL && use_list_->tail() != NULL; + } + int UseCount() const; void ClearOperands(); - void Delete(); int flags() const { return flags_; } void SetFlag(Flag f) { flags_ |= (1 << f); } @@ -611,7 +665,12 @@ class HValue: public ZoneObject { return ChangesFlagsMask() & ~(1 << kChangesOsrEntries); } - void InternalReplaceAtUse(HValue* use, HValue* other); + // Remove the matching use from the use list if present. Returns the + // removed list node or NULL. + HUseListNode* RemoveUse(HValue* value, int index); + + void ReplaceAllUsesWith(HValue* other); + void RegisterUse(int index, HValue* new_value); HBasicBlock* block_; @@ -622,7 +681,7 @@ class HValue: public ZoneObject { Representation representation_; HType type_; - SmallPointerList uses_; + HUseListNode* use_list_; Range* range_; int flags_; @@ -2257,7 +2316,7 @@ class HCompare: public HBinaryOperation { void SetInputRepresentation(Representation r); virtual bool EmitAtUses() { - return !HasSideEffects() && (uses()->length() <= 1); + return !HasSideEffects() && !HasMultipleUses(); } virtual Representation RequiredInputRepresentation(int index) const { @@ -2299,7 +2358,7 @@ class HCompareJSObjectEq: public HBinaryOperation { } virtual bool EmitAtUses() { - return !HasSideEffects() && (uses()->length() <= 1); + return !HasSideEffects() && !HasMultipleUses(); } virtual Representation RequiredInputRepresentation(int index) const { @@ -2322,7 +2381,7 @@ class HUnaryPredicate: public HUnaryOperation { } virtual bool EmitAtUses() { - return !HasSideEffects() && (uses()->length() <= 1); + return !HasSideEffects() && !HasMultipleUses(); } virtual Representation RequiredInputRepresentation(int index) const { @@ -2382,7 +2441,7 @@ class HIsConstructCall: public HTemplateInstruction<0> { } virtual bool EmitAtUses() { - return !HasSideEffects() && (uses()->length() <= 1); + return !HasSideEffects() && !HasMultipleUses(); } virtual Representation RequiredInputRepresentation(int index) const { @@ -2504,7 +2563,7 @@ class HInstanceOf: public HTemplateInstruction<3> { HValue* right() { return OperandAt(2); } virtual bool EmitAtUses() { - return !HasSideEffects() && (uses()->length() <= 1); + return !HasSideEffects() && !HasMultipleUses(); } virtual Representation RequiredInputRepresentation(int index) const { diff --git a/src/hydrogen.cc b/src/hydrogen.cc index f6c47f31db..20e84033ce 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -644,7 +644,7 @@ void HGraph::Canonicalize() { HInstruction* instr = blocks()->at(i)->first(); while (instr != NULL) { HValue* value = instr->Canonicalize(); - if (value != instr) instr->ReplaceAndDelete(value); + if (value != instr) instr->DeleteAndReplaceWith(value); instr = instr->next(); } } @@ -726,9 +726,9 @@ void HGraph::AssignDominators() { void HGraph::EliminateRedundantPhis() { HPhase phase("Redundant phi elimination", this); - // Worklist of phis that can potentially be eliminated. Initialized - // with all phi nodes. When elimination of a phi node modifies - // another phi node the modified phi node is added to the worklist. + // Worklist of phis that can potentially be eliminated. Initialized with + // all phi nodes. When elimination of a phi node modifies another phi node + // the modified phi node is added to the worklist. ZoneList worklist(blocks_.length()); for (int i = 0; i < blocks_.length(); ++i) { worklist.AddAll(*blocks_[i]->phis()); @@ -742,18 +742,14 @@ void HGraph::EliminateRedundantPhis() { if (block == NULL) continue; // Get replacement value if phi is redundant. - HValue* value = phi->GetRedundantReplacement(); + HValue* replacement = phi->GetRedundantReplacement(); - if (value != NULL) { - // Iterate through uses finding the ones that should be - // replaced. - SmallPointerList* uses = phi->uses(); - while (!uses->is_empty()) { - HValue* use = uses->RemoveLast(); - if (use != NULL) { - phi->ReplaceAtUse(use, value); - if (use->IsPhi()) worklist.Add(HPhi::cast(use)); - } + if (replacement != NULL) { + // Iterate through the uses and replace them all. + for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { + HValue* value = it.value(); + value->SetOperandAt(it.index(), replacement); + if (value->IsPhi()) worklist.Add(HPhi::cast(value)); } block->RemovePhi(phi); } @@ -831,8 +827,8 @@ void HGraph::InferTypes(ZoneList* worklist) { HValue* current = worklist->RemoveLast(); in_worklist.Remove(current->id()); if (current->UpdateInferredType()) { - for (int j = 0; j < current->uses()->length(); j++) { - HValue* use = current->uses()->at(j); + for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) { + HValue* use = it.value(); if (!in_worklist.Contains(use->id())) { in_worklist.Add(use->id()); worklist->Add(use); @@ -1445,7 +1441,7 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { instr->Mnemonic(), other->id(), other->Mnemonic()); - instr->ReplaceAndDelete(other); + instr->DeleteAndReplaceWith(other); } else { map->Add(instr); } @@ -1529,12 +1525,12 @@ void HInferRepresentation::InferBasedOnInputs(HValue* current) { } -void HInferRepresentation::AddDependantsToWorklist(HValue* current) { - for (int i = 0; i < current->uses()->length(); ++i) { - AddToWorklist(current->uses()->at(i)); +void HInferRepresentation::AddDependantsToWorklist(HValue* value) { + for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { + AddToWorklist(it.value()); } - for (int i = 0; i < current->OperandCount(); ++i) { - AddToWorklist(current->OperandAt(i)); + for (int i = 0; i < value->OperandCount(); ++i) { + AddToWorklist(value->OperandAt(i)); } } @@ -1543,37 +1539,30 @@ void HInferRepresentation::AddDependantsToWorklist(HValue* current) { // given as the parameter has a benefit in terms of less necessary type // conversions. If there is a benefit, then the representation of the value is // specialized. -void HInferRepresentation::InferBasedOnUses(HValue* current) { - Representation r = current->representation(); - if (r.IsSpecialization() || current->HasNoUses()) return; - ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); - Representation new_rep = TryChange(current); +void HInferRepresentation::InferBasedOnUses(HValue* value) { + Representation r = value->representation(); + if (r.IsSpecialization() || value->HasNoUses()) return; + ASSERT(value->CheckFlag(HValue::kFlexibleRepresentation)); + Representation new_rep = TryChange(value); if (!new_rep.IsNone()) { - if (!current->representation().Equals(new_rep)) { - current->ChangeRepresentation(new_rep); - AddDependantsToWorklist(current); + if (!value->representation().Equals(new_rep)) { + value->ChangeRepresentation(new_rep); + AddDependantsToWorklist(value); } } } -Representation HInferRepresentation::TryChange(HValue* current) { +Representation HInferRepresentation::TryChange(HValue* value) { // Array of use counts for each representation. - int use_count[Representation::kNumRepresentations]; - for (int i = 0; i < Representation::kNumRepresentations; i++) { - use_count[i] = 0; - } + int use_count[Representation::kNumRepresentations] = { 0 }; - for (int i = 0; i < current->uses()->length(); ++i) { - HValue* use = current->uses()->at(i); - int index = use->LookupOperandIndex(0, current); - Representation req_rep = use->RequiredInputRepresentation(index); - if (req_rep.IsNone()) continue; - if (use->IsPhi()) { - HPhi* phi = HPhi::cast(use); - phi->AddIndirectUsesTo(&use_count[0]); - } - use_count[req_rep.kind()]++; + for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { + HValue* use = it.value(); + Representation rep = use->RequiredInputRepresentation(it.index()); + if (rep.IsNone()) continue; + if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]); + ++use_count[rep.kind()]; } int tagged_count = use_count[Representation::kTagged]; int double_count = use_count[Representation::kDouble]; @@ -1581,7 +1570,7 @@ Representation HInferRepresentation::TryChange(HValue* current) { int non_tagged_count = double_count + int32_count; // If a non-loop phi has tagged uses, don't convert it to untagged. - if (current->IsPhi() && !current->block()->IsLoopHeader()) { + if (value->IsPhi() && !value->block()->IsLoopHeader()) { if (tagged_count > 0) return Representation::None(); } @@ -1602,41 +1591,39 @@ Representation HInferRepresentation::TryChange(HValue* current) { void HInferRepresentation::Analyze() { HPhase phase("Infer representations", graph_); - // (1) Initialize bit vectors and count real uses. Each phi - // gets a bit-vector of length . + // (1) Initialize bit vectors and count real uses. Each phi gets a + // bit-vector of length . const ZoneList* phi_list = graph_->phi_list(); - int num_phis = phi_list->length(); - ScopedVector connected_phis(num_phis); - for (int i = 0; i < num_phis; i++) { + int phi_count = phi_list->length(); + ScopedVector connected_phis(phi_count); + for (int i = 0; i < phi_count; ++i) { phi_list->at(i)->InitRealUses(i); - connected_phis[i] = new(zone()) BitVector(num_phis); + connected_phis[i] = new(zone()) BitVector(phi_count); connected_phis[i]->Add(i); } - // (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. + // (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; - for (int i = 0; i < num_phis; i++) { + for (int i = 0; i < phi_count; ++i) { HPhi* phi = phi_list->at(i); - for (int j = 0; j < phi->uses()->length(); j++) { - HValue* use = phi->uses()->at(j); + for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { + HValue* use = it.value(); if (use->IsPhi()) { - int phi_use = HPhi::cast(use)->phi_id(); - if (connected_phis[i]->UnionIsChanged(*connected_phis[phi_use])) { - change = true; - } + int id = HPhi::cast(use)->phi_id(); + change = change || + connected_phis[i]->UnionIsChanged(*connected_phis[id]); } } } } - // (3) Sum up the non-phi use counts of all connected phis. - // Don't include the non-phi uses of the phi itself. - for (int i = 0; i < num_phis; i++) { + // (3) Sum up the non-phi use counts of all connected phis. Don't include + // the non-phi uses of the phi itself. + for (int i = 0; i < phi_count; ++i) { HPhi* phi = phi_list->at(i); for (BitVector::Iterator it(connected_phis.at(i)); !it.Done(); @@ -1746,17 +1733,16 @@ void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { void HGraph::InsertRepresentationChangeForUse(HValue* value, - HValue* use, + HValue* use_value, + int use_index, Representation to) { // Insert the representation change right before its use. For phi-uses we // insert at the end of the corresponding predecessor. HInstruction* next = NULL; - if (use->IsPhi()) { - int index = 0; - while (use->OperandAt(index) != value) ++index; - next = use->block()->predecessors()->at(index)->end(); + if (use_value->IsPhi()) { + next = use_value->block()->predecessors()->at(use_index)->end(); } else { - next = HInstruction::cast(use); + next = HInstruction::cast(use_value); } // For constants we try to make the representation change at compile @@ -1764,7 +1750,7 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value, // information we treat constants like normal instructions and insert the // change instructions for them. HInstruction* new_value = NULL; - bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); + bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); if (value->IsConstant()) { HConstant* constant = HConstant::cast(value); // Try to create a new copy of the constant with the new representation. @@ -1779,89 +1765,26 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value, } new_value->InsertBefore(next); - value->ReplaceFirstAtUse(use, new_value, to); + use_value->SetOperandAt(use_index, new_value); } -int CompareConversionUses(HValue* a, - HValue* b, - Representation a_rep, - Representation b_rep) { - if (a_rep.kind() > b_rep.kind()) { - // Make sure specializations are separated in the result array. - return 1; - } - // Put truncating conversions before non-truncating conversions. - bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32); - bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32); - if (a_truncate != b_truncate) { - return a_truncate ? -1 : 1; - } - // Sort by increasing block ID. - return a->block()->block_id() - b->block()->block_id(); -} - - -void HGraph::InsertRepresentationChangesForValue( - HValue* current, - ZoneList* to_convert, - ZoneList* to_convert_reps) { - Representation r = current->representation(); +void HGraph::InsertRepresentationChangesForValue(HValue* value) { + Representation r = value->representation(); if (r.IsNone()) return; - if (current->uses()->is_empty()) return; + if (value->HasNoUses()) return; - // Collect the representation changes in a sorted list. This allows - // us to avoid duplicate changes without searching the list. - ASSERT(to_convert->is_empty()); - ASSERT(to_convert_reps->is_empty()); - for (int i = 0; i < current->uses()->length(); ++i) { - HValue* use = current->uses()->at(i); - // The occurrences index means the index within the operand array of "use" - // at which "current" is used. While iterating through the use array we - // also have to iterate over the different occurrence indices. - int occurrence_index = 0; - if (use->UsesMultipleTimes(current)) { - occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); - if (FLAG_trace_representation) { - PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", - current->id(), - use->id(), - occurrence_index); - } - } - int operand_index = use->LookupOperandIndex(occurrence_index, current); - Representation req = use->RequiredInputRepresentation(operand_index); + for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { + HValue* use_value = it.value(); + int use_index = it.index(); + Representation req = use_value->RequiredInputRepresentation(use_index); if (req.IsNone() || req.Equals(r)) continue; - int index = 0; - while (index < to_convert->length() && - CompareConversionUses(to_convert->at(index), - use, - to_convert_reps->at(index), - req) < 0) { - ++index; - } - if (FLAG_trace_representation) { - PrintF("Inserting a representation change to %s of %d for use at %d\n", - req.Mnemonic(), - current->id(), - use->id()); - } - to_convert->InsertAt(index, use); - to_convert_reps->InsertAt(index, req); + InsertRepresentationChangeForUse(value, use_value, use_index, req); } - - for (int i = 0; i < to_convert->length(); ++i) { - HValue* use = to_convert->at(i); - Representation r_to = to_convert_reps->at(i); - InsertRepresentationChangeForUse(current, use, r_to); + if (value->HasNoUses()) { + ASSERT(value->IsConstant()); + value->DeleteAndReplaceWith(NULL); } - - if (current->uses()->is_empty()) { - ASSERT(current->IsConstant()); - current->Delete(); - } - to_convert->Rewind(0); - to_convert_reps->Rewind(0); } @@ -1886,8 +1809,8 @@ void HGraph::InsertRepresentationChanges() { for (int i = 0; i < phi_list()->length(); i++) { HPhi* phi = phi_list()->at(i); if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; - for (int j = 0; j < phi->uses()->length(); j++) { - HValue* use = phi->uses()->at(j); + for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { + HValue* use = it.value(); if (!use->CheckFlag(HValue::kTruncatingToInt32)) { phi->ClearFlag(HValue::kTruncatingToInt32); change = true; @@ -1897,19 +1820,17 @@ void HGraph::InsertRepresentationChanges() { } } - ZoneList value_list(4); - ZoneList rep_list(4); for (int i = 0; i < blocks_.length(); ++i) { // Process phi instructions first. - for (int j = 0; j < blocks_[i]->phis()->length(); j++) { - HPhi* phi = blocks_[i]->phis()->at(j); - InsertRepresentationChangesForValue(phi, &value_list, &rep_list); + const ZoneList* phis = blocks_[i]->phis(); + for (int j = 0; j < phis->length(); j++) { + InsertRepresentationChangesForValue(phis->at(j)); } // Process normal instructions. HInstruction* current = blocks_[i]->first(); while (current != NULL) { - InsertRepresentationChangesForValue(current, &value_list, &rep_list); + InsertRepresentationChangesForValue(current); current = current->next(); } } @@ -5943,7 +5864,7 @@ void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { HInstruction* instruction = current->first(); while (instruction != NULL) { int bci = 0; - int uses = instruction->uses()->length(); + int uses = instruction->UseCount(); trace_.Add("%d %d ", bci, uses); instruction->PrintNameTo(&trace_); trace_.Add(" "); diff --git a/src/hydrogen.h b/src/hydrogen.h index 74c119a2f5..32bf6d476a 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -277,11 +277,10 @@ class HGraph: public ZoneObject { void InsertTypeConversions(HInstruction* instr); void PropagateMinusZeroChecks(HValue* value, BitVector* visited); void InsertRepresentationChangeForUse(HValue* value, - HValue* use, + HValue* use_value, + int use_index, Representation to); - void InsertRepresentationChangesForValue(HValue* current, - ZoneList* value_list, - ZoneList* rep_list); + void InsertRepresentationChangesForValue(HValue* value); void InferTypes(ZoneList* worklist); void InitializeInferredTypes(int from_inclusive, int to_inclusive); void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index aa91a83406..735abe624f 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -852,24 +852,22 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, right = UseFixed(right_value, ecx); } - // Shift operations can only deoptimize if we do a logical shift - // by 0 and the result cannot be truncated to int32. - bool can_deopt = (op == Token::SHR && constant_value == 0); - if (can_deopt) { - bool can_truncate = true; - for (int i = 0; i < instr->uses()->length(); i++) { - if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { - can_truncate = false; + // Shift operations can only deoptimize if we do a logical shift by 0 and + // the result cannot be truncated to int32. + bool may_deopt = (op == Token::SHR && constant_value == 0); + bool does_deopt = false; + if (may_deopt) { + for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { + if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { + does_deopt = true; break; } } - can_deopt = !can_truncate; } - LShiftI* result = new LShiftI(op, left, right, can_deopt); - return can_deopt - ? AssignEnvironment(DefineSameAsFirst(result)) - : DefineSameAsFirst(result); + LInstruction* result = + DefineSameAsFirst(new LShiftI(op, left, right, does_deopt)); + return does_deopt ? AssignEnvironment(result) : result; } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 620bbc94e5..931424ee05 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -851,24 +851,22 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op, right = UseFixed(right_value, rcx); } - // Shift operations can only deoptimize if we do a logical shift - // by 0 and the result cannot be truncated to int32. - bool can_deopt = (op == Token::SHR && constant_value == 0); - if (can_deopt) { - bool can_truncate = true; - for (int i = 0; i < instr->uses()->length(); i++) { - if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) { - can_truncate = false; + // Shift operations can only deoptimize if we do a logical shift by 0 and + // the result cannot be truncated to int32. + bool may_deopt = (op == Token::SHR && constant_value == 0); + bool does_deopt = false; + if (may_deopt) { + for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { + if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { + does_deopt = true; break; } } - can_deopt = !can_truncate; } - LShiftI* result = new LShiftI(op, left, right, can_deopt); - return can_deopt - ? AssignEnvironment(DefineSameAsFirst(result)) - : DefineSameAsFirst(result); + LInstruction* result = + DefineSameAsFirst(new LShiftI(op, left, right, does_deopt)); + return does_deopt ? AssignEnvironment(result) : result; }