 Chromium Code Reviews
 Chromium Code Reviews Issue 10837165:
  Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps …  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 10837165:
  Lattice-based representation inference, powered by left/right specific type feedback for BinaryOps …  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| Index: src/hydrogen-instructions.cc | 
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc | 
| index 72d3aab4944596cd1caf7d09a38f8829ca9d5528..9778aa5fec3d6b5ca4bef05a4bda62e70a2801f5 100644 | 
| --- a/src/hydrogen-instructions.cc | 
| +++ b/src/hydrogen-instructions.cc | 
| @@ -85,6 +85,79 @@ void HValue::AssumeRepresentation(Representation r) { | 
| } | 
| +void HValue::InferRepresentation(HInferRepresentation* hinfer) { | 
| + ASSERT(CheckFlag(kFlexibleRepresentation)); | 
| + Representation new_rep = RepresentationFromInputs(); | 
| + UpdateRepresentation(new_rep, hinfer, "inputs"); | 
| + new_rep = RepresentationFromUses(); | 
| + UpdateRepresentation(new_rep, hinfer, "uses"); | 
| +} | 
| + | 
| + | 
| +Representation HValue::RepresentationFromUses() { | 
| + if (HasNoUses()) return Representation::None(); | 
| + | 
| + // Array of use counts for each representation. | 
| + int use_count[Representation::kNumRepresentations] = { 0 }; | 
| + | 
| + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 
| + HValue* use = it.value(); | 
| + Representation rep = use->observed_input_representation(it.index()); | 
| + if (rep.IsNone()) continue; | 
| + if (FLAG_trace_representation) { | 
| + PrintF("#%d %s is used by #%d %s as %s%s\n", | 
| + id(), Mnemonic(), use->id(), use->Mnemonic(), rep.Mnemonic(), | 
| + (use->CheckFlag(kTruncatingToInt32) ? "-trunc" : "")); | 
| + } | 
| + use_count[rep.kind()] += use->LoopWeight(); | 
| + } | 
| + if (IsPhi()) HPhi::cast(this)->AddIndirectUsesTo(&use_count[0]); | 
| + int tagged_count = use_count[Representation::kTagged]; | 
| + int double_count = use_count[Representation::kDouble]; | 
| + int int32_count = use_count[Representation::kInteger32]; | 
| + | 
| + if (tagged_count > 0) return Representation::Tagged(); | 
| + if (double_count > 0) return Representation::Double(); | 
| + if (int32_count > 0) return Representation::Integer32(); | 
| + | 
| + return Representation::None(); | 
| +} | 
| + | 
| + | 
| +void HValue::UpdateRepresentation(Representation new_rep, | 
| + HInferRepresentation* hinfer, | 
| + const char* reason) { | 
| + Representation r = representation(); | 
| + if (new_rep.is_more_general_than(r)) { | 
| + if (new_rep.IsInteger32() && !IsConvertibleToInteger()) { | 
| 
danno
2012/11/06 11:42:59
Add a comment
 
Jakob Kummerow
2012/11/06 12:44:05
Done.
 | 
| + new_rep = Representation::Tagged(); | 
| + if (FLAG_trace_representation) { | 
| + PrintF("Changing #%d %s representation %s -> %s because it's NCTI" | 
| + " (%s want i)\n", | 
| + id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason); | 
| + } | 
| + } else { | 
| + if (FLAG_trace_representation) { | 
| + PrintF("Changing #%d %s representation %s -> %s based on %s\n", | 
| + id(), Mnemonic(), r.Mnemonic(), new_rep.Mnemonic(), reason); | 
| + } | 
| + } | 
| + ChangeRepresentation(new_rep); | 
| + AddDependantsToWorklist(hinfer); | 
| + } | 
| +} | 
| + | 
| + | 
| +void HValue::AddDependantsToWorklist(HInferRepresentation* hinfer) { | 
| + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 
| + hinfer->AddToWorklist(it.value()); | 
| + } | 
| + for (int i = 0; i < OperandCount(); ++i) { | 
| + hinfer->AddToWorklist(OperandAt(i)); | 
| + } | 
| +} | 
| + | 
| + | 
| static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) { | 
| if (result > kMaxInt) { | 
| *overflow = true; | 
| @@ -301,6 +374,7 @@ HUseListNode* HUseListNode::tail() { | 
| bool HValue::CheckUsesForFlag(Flag f) { | 
| for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 
| + if (it.value()->IsSimulate()) continue; | 
| if (!it.value()->CheckFlag(f)) return false; | 
| } | 
| return true; | 
| @@ -1349,15 +1423,11 @@ void HPhi::InitRealUses(int phi_id) { | 
| for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 
| HValue* value = it.value(); | 
| if (!value->IsPhi()) { | 
| - Representation rep = value->ObservedInputRepresentation(it.index()); | 
| + Representation rep = value->observed_input_representation(it.index()); | 
| non_phi_uses_[rep.kind()] += value->LoopWeight(); | 
| if (FLAG_trace_representation) { | 
| - PrintF("%d %s is used by %d %s as %s\n", | 
| - this->id(), | 
| - this->Mnemonic(), | 
| - value->id(), | 
| - value->Mnemonic(), | 
| - rep.Mnemonic()); | 
| + PrintF("#%d Phi is used by real #%d %s as %s\n", | 
| + id(), value->id(), value->Mnemonic(), rep.Mnemonic()); | 
| } | 
| } | 
| } | 
| @@ -1366,11 +1436,8 @@ void HPhi::InitRealUses(int phi_id) { | 
| void HPhi::AddNonPhiUsesFrom(HPhi* other) { | 
| if (FLAG_trace_representation) { | 
| - PrintF("adding to %d %s uses of %d %s: i%d d%d t%d\n", | 
| - this->id(), | 
| - this->Mnemonic(), | 
| - other->id(), | 
| - other->Mnemonic(), | 
| + PrintF("adding to #%d Phi uses of #%d Phi: i%d d%d t%d\n", | 
| + id(), other->id(), | 
| other->non_phi_uses_[Representation::kInteger32], | 
| other->non_phi_uses_[Representation::kDouble], | 
| other->non_phi_uses_[Representation::kTagged]); | 
| @@ -1389,9 +1456,20 @@ void HPhi::AddIndirectUsesTo(int* dest) { | 
| } | 
| -void HPhi::ResetInteger32Uses() { | 
| - non_phi_uses_[Representation::kInteger32] = 0; | 
| - indirect_uses_[Representation::kInteger32] = 0; | 
| +void HSimulate::MergeInto(HSimulate* other) { | 
| + for (int i = 0; i < values_.length(); ++i) { | 
| + HValue* value = values_[i]; | 
| + if (HasAssignedIndexAt(i)) { | 
| + other->AddAssignedValue(GetAssignedIndexAt(i), value); | 
| + } else { | 
| + if (other->pop_count_ > 0) { | 
| + other->pop_count_--; | 
| + } else { | 
| + other->AddPushedValue(value); | 
| + } | 
| + } | 
| + } | 
| + other->pop_count_ += pop_count(); | 
| } | 
| @@ -1400,7 +1478,7 @@ void HSimulate::PrintDataTo(StringStream* stream) { | 
| if (pop_count_ > 0) stream->Add(" pop %d", pop_count_); | 
| if (values_.length() > 0) { | 
| if (pop_count_ > 0) stream->Add(" /"); | 
| - for (int i = 0; i < values_.length(); ++i) { | 
| + for (int i = values_.length() - 1; i >= 0; --i) { | 
| if (i > 0) stream->Add(","); | 
| if (HasAssignedIndexAt(i)) { | 
| stream->Add(" var[%d] = ", GetAssignedIndexAt(i)); | 
| @@ -1439,7 +1517,6 @@ HConstant::HConstant(Handle<Object> handle, Representation r) | 
| : handle_(handle), | 
| has_int32_value_(false), | 
| has_double_value_(false) { | 
| - set_representation(r); | 
| SetFlag(kUseGVN); | 
| if (handle_->IsNumber()) { | 
| double n = handle_->Number(); | 
| @@ -1448,6 +1525,16 @@ HConstant::HConstant(Handle<Object> handle, Representation r) | 
| double_value_ = n; | 
| has_double_value_ = true; | 
| } | 
| + if (r.IsNone()) { | 
| + if (has_int32_value_) { | 
| + r = Representation::Integer32(); | 
| + } else if (has_double_value_) { | 
| + r = Representation::Double(); | 
| + } else { | 
| + r = Representation::Tagged(); | 
| + } | 
| + } | 
| + set_representation(r); | 
| } | 
| @@ -1546,6 +1633,40 @@ void HBinaryOperation::PrintDataTo(StringStream* stream) { | 
| } | 
| +Representation HBinaryOperation::RepresentationFromInputs() { | 
| + // Determine the worst case of observed input representations and | 
| + // the currently assumed output representation. | 
| + Representation rep = representation(); | 
| + if (observed_output_representation_.is_more_general_than(rep)) { | 
| + rep = observed_output_representation_; | 
| + } | 
| + for (int i = 1; i <= 2; ++i) { | 
| + Representation input_rep = observed_input_representation(i); | 
| + if (input_rep.is_more_general_than(rep)) rep = input_rep; | 
| + } | 
| + // If any of the actual input representation is more general than what we | 
| + // have so far but not Tagged, use that representation instead. | 
| + Representation left_rep = left()->representation(); | 
| + Representation right_rep = right()->representation(); | 
| + | 
| + if (left_rep.is_more_general_than(rep) && | 
| + left()->CheckFlag(kFlexibleRepresentation)) { | 
| + rep = left_rep; | 
| + } | 
| + if (right_rep.is_more_general_than(rep) && | 
| + right()->CheckFlag(kFlexibleRepresentation)) { | 
| + rep = right_rep; | 
| + } | 
| + return rep; | 
| +} | 
| + | 
| + | 
| +void HBinaryOperation::AssumeRepresentation(Representation r) { | 
| + set_observed_input_representation(r, r); | 
| + HValue::AssumeRepresentation(r); | 
| +} | 
| + | 
| + | 
| Range* HBitwise::InferRange(Zone* zone) { | 
| if (op() == Token::BIT_XOR) return HValue::InferRange(zone); | 
| const int32_t kDefaultMask = static_cast<int32_t>(0xffffffff); | 
| @@ -1677,9 +1798,13 @@ void HGoto::PrintDataTo(StringStream* stream) { | 
| } | 
| -void HCompareIDAndBranch::SetInputRepresentation(Representation r) { | 
| - input_representation_ = r; | 
| - if (r.IsDouble()) { | 
| +void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* hinfer) { | 
| + Representation rep = Representation::None(); | 
| + if (observed_input_representation(0).IsInteger32() && | 
| + observed_input_representation(1).IsInteger32()) { | 
| + rep = Representation::Integer32(); | 
| + } else { | 
| + rep = Representation::Double(); | 
| // According to the ES5 spec (11.9.3, 11.8.5), Equality comparisons (==, === | 
| // and !=) have special handling of undefined, e.g. undefined == undefined | 
| // is 'true'. Relational comparisons have a different semantic, first | 
| @@ -1696,9 +1821,8 @@ void HCompareIDAndBranch::SetInputRepresentation(Representation r) { | 
| if (!Token::IsOrderedRelationalCompareOp(token_)) { | 
| SetFlag(kDeoptimizeOnUndefined); | 
| } | 
| - } else { | 
| - ASSERT(r.IsInteger32()); | 
| } | 
| + AssumeRepresentation(rep); | 
| } | 
| @@ -2461,7 +2585,14 @@ void HBitwise::PrintDataTo(StringStream* stream) { | 
| } | 
| -Representation HPhi::InferredRepresentation() { | 
| +void HPhi::InferRepresentation(HInferRepresentation* hinfer) { | 
| + HValue::InferRepresentation(hinfer); | 
| + Representation new_rep = RepresentationFromUseRequirements(); | 
| + UpdateRepresentation(new_rep, hinfer, "use requirements"); | 
| +} | 
| + | 
| + | 
| +Representation HPhi::RepresentationFromInputs() { | 
| bool double_occurred = false; | 
| bool int32_occurred = false; | 
| for (int i = 0; i < OperandCount(); ++i) { | 
| @@ -2470,6 +2601,7 @@ Representation HPhi::InferredRepresentation() { | 
| HPhi* hint_value = HUnknownOSRValue::cast(value)->incoming_value(); | 
| if (hint_value != NULL) { | 
| Representation hint = hint_value->representation(); | 
| + if (hint.IsTagged()) return hint; | 
| if (hint.IsDouble()) double_occurred = true; | 
| if (hint.IsInteger32()) int32_occurred = true; | 
| } | 
| @@ -2488,7 +2620,9 @@ Representation HPhi::InferredRepresentation() { | 
| return Representation::Tagged(); | 
| } | 
| } else { | 
| - return Representation::Tagged(); | 
| + if (value->IsPhi() && !IsConvertibleToInteger()) { | 
| + return Representation::Tagged(); | 
| + } | 
| } | 
| } | 
| } | 
| @@ -2500,6 +2634,36 @@ Representation HPhi::InferredRepresentation() { | 
| return Representation::None(); | 
| } | 
| 
danno
2012/11/06 11:42:59
nit: two lines
 
Jakob Kummerow
2012/11/06 12:44:05
Done.
 | 
| +Representation HPhi::RepresentationFromUseRequirements() { | 
| + Representation all_uses_require = Representation::None(); | 
| + bool all_uses_require_the_same = true; | 
| + for (HUseIterator it(uses()); !it.Done(); it.Advance()) { | 
| + // We check for observed_input_representation elsewhere. | 
| + Representation use_rep = | 
| + it.value()->RequiredInputRepresentation(it.index()); | 
| + // No useful info from this use -> look at the next one. | 
| + if (use_rep.IsNone()) { | 
| + continue; | 
| + } | 
| + if (use_rep.Equals(all_uses_require)) { | 
| + continue; | 
| + } | 
| + // This use's representation contradicts what we've seen so far. | 
| + if (!all_uses_require.IsNone()) { | 
| + ASSERT(!use_rep.Equals(all_uses_require)); | 
| + all_uses_require_the_same = false; | 
| + break; | 
| + } | 
| + // Otherwise, initialize observed representation. | 
| + all_uses_require = use_rep; | 
| + } | 
| + if (all_uses_require_the_same) { | 
| + return all_uses_require; | 
| + } | 
| + | 
| + return Representation::None(); | 
| +} | 
| + | 
| // Node-specific verification code is only included in debug mode. | 
| #ifdef DEBUG |