LCOV - code coverage report
Current view: top level - src/crankshaft - hydrogen-representation-changes.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 76 87 87.4 %
Date: 2017-04-26 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/crankshaft/hydrogen-representation-changes.h"
       6             : #include "src/objects-inl.h"
       7             : 
       8             : namespace v8 {
       9             : namespace internal {
      10             : 
      11     1981604 : void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
      12     2070922 :     HValue* value, HValue* use_value, int use_index, Representation to) {
      13             :   // Insert the representation change right before its use. For phi-uses we
      14             :   // insert at the end of the corresponding predecessor.
      15             :   HInstruction* next = NULL;
      16     1981608 :   if (use_value->IsPhi()) {
      17       89314 :     next = use_value->block()->predecessors()->at(use_index)->end();
      18             :   } else {
      19             :     next = HInstruction::cast(use_value);
      20             :   }
      21             :   // For constants we try to make the representation change at compile
      22             :   // time. When a representation change is not possible without loss of
      23             :   // information we treat constants like normal instructions and insert the
      24             :   // change instructions for them.
      25             :   HInstruction* new_value = NULL;
      26             :   bool is_truncating_to_smi = use_value->CheckFlag(HValue::kTruncatingToSmi);
      27             :   bool is_truncating_to_int = use_value->CheckFlag(HValue::kTruncatingToInt32);
      28             :   bool is_truncating_to_number =
      29             :       use_value->CheckFlag(HValue::kTruncatingToNumber);
      30     1981606 :   if (value->IsConstant()) {
      31             :     HConstant* constant = HConstant::cast(value);
      32             :     // Try to create a new copy of the constant with the new representation.
      33     1484262 :     if (is_truncating_to_int && to.IsInteger32()) {
      34     1982686 :       Maybe<HConstant*> res = constant->CopyToTruncatedInt32(graph()->zone());
      35        3902 :       if (res.IsJust()) new_value = res.FromJust();
      36             :     } else {
      37     1469677 :       new_value = constant->CopyToRepresentation(to, graph()->zone());
      38             :     }
      39             :   }
      40             : 
      41     1981606 :   if (new_value == NULL) {
      42      509107 :     new_value = new (graph()->zone())
      43             :         HChange(value, to, is_truncating_to_smi, is_truncating_to_int,
      44     1018215 :                 is_truncating_to_number);
      45             :   }
      46             : 
      47     1981604 :   new_value->InsertBefore(next);
      48     1981605 :   use_value->SetOperandAt(use_index, new_value);
      49     1981603 : }
      50             : 
      51             : 
      52             : static bool IsNonDeoptingIntToSmiChange(HChange* change) {
      53             :   Representation from_rep = change->from();
      54             :   Representation to_rep = change->to();
      55             :   // Flags indicating Uint32 operations are set in a later Hydrogen phase.
      56             :   DCHECK(!change->CheckFlag(HValue::kUint32));
      57        2037 :   return from_rep.IsInteger32() && to_rep.IsSmi() && SmiValuesAre32Bits();
      58             : }
      59             : 
      60             : 
      61    30333519 : void HRepresentationChangesPhase::InsertRepresentationChangesForValue(
      62    27370113 :     HValue* value) {
      63             :   Representation r = value->representation();
      64    30333519 :   if (r.IsNone()) {
      65             : #ifdef DEBUG
      66             :     for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
      67             :       HValue* use_value = it.value();
      68             :       int use_index = it.index();
      69             :       Representation req = use_value->RequiredInputRepresentation(use_index);
      70             :       DCHECK(req.IsNone());
      71             :     }
      72             : #endif
      73             :     return;
      74             :   }
      75    15268994 :   if (value->HasNoUses()) {
      76     3167836 :     if (value->IsForceRepresentation()) value->DeleteAndReplaceWith(NULL);
      77             :     return;
      78             :   }
      79             : 
      80    23536055 :   for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
      81    23536095 :     HValue* use_value = it.value();
      82    23536095 :     int use_index = it.index();
      83    23536095 :     Representation req = use_value->RequiredInputRepresentation(use_index);
      84    23536057 :     if (req.IsNone() || req.Equals(r)) continue;
      85             : 
      86             :     // If this is an HForceRepresentation instruction, and an HChange has been
      87             :     // inserted above it, examine the input representation of the HChange. If
      88             :     // that's int32, and this HForceRepresentation use is int32, and int32 to
      89             :     // smi changes can't cause deoptimisation, set the input of the use to the
      90             :     // input of the HChange.
      91     1982075 :     if (value->IsForceRepresentation()) {
      92             :       HValue* input = HForceRepresentation::cast(value)->value();
      93       16107 :       if (input->IsChange()) {
      94             :         HChange* change = HChange::cast(input);
      95       11474 :         if (change->from().Equals(req) && IsNonDeoptingIntToSmiChange(change)) {
      96         469 :           use_value->SetOperandAt(use_index, change->value());
      97         469 :           continue;
      98             :         }
      99             :       }
     100             :     }
     101     1981606 :     InsertRepresentationChangeForUse(value, use_value, use_index, req);
     102             :   }
     103    12101119 :   if (value->HasNoUses()) {
     104             :     DCHECK(value->IsConstant() || value->IsForceRepresentation());
     105     1309184 :     value->DeleteAndReplaceWith(NULL);
     106             :   } else {
     107             :     // The only purpose of a HForceRepresentation is to represent the value
     108             :     // after the (possible) HChange instruction.  We make it disappear.
     109    10791937 :     if (value->IsForceRepresentation()) {
     110       61156 :       value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
     111             :     }
     112             :   }
     113             : }
     114             : 
     115             : 
     116      283729 : void HRepresentationChangesPhase::Run() {
     117             :   // Compute truncation flag for phis:
     118             :   //
     119             :   // - Initially assume that all phis allow truncation to number and iteratively
     120             :   //   remove the ones that are used in an operation that not do an implicit
     121             :   //   ToNumber conversion.
     122             :   // - Also assume that all Integer32 phis allow ToInt32 truncation and all
     123             :   //   Smi phis allow truncation to Smi.
     124             :   //
     125      283729 :   ZoneList<HPhi*> number_worklist(8, zone());
     126      283730 :   ZoneList<HPhi*> int_worklist(8, zone());
     127      283730 :   ZoneList<HPhi*> smi_worklist(8, zone());
     128             : 
     129      567458 :   const ZoneList<HPhi*>* phi_list(graph()->phi_list());
     130     1201112 :   for (int i = 0; i < phi_list->length(); i++) {
     131     1517938 :     HPhi* phi = phi_list->at(i);
     132      316826 :     if (phi->representation().IsInteger32()) {
     133             :       phi->SetFlag(HValue::kTruncatingToInt32);
     134      264319 :     } else if (phi->representation().IsSmi()) {
     135             :       phi->SetFlag(HValue::kTruncatingToSmi);
     136             :       phi->SetFlag(HValue::kTruncatingToInt32);
     137             :     }
     138             :     phi->SetFlag(HValue::kTruncatingToNumber);
     139             :   }
     140             : 
     141      917382 :   for (int i = 0; i < phi_list->length(); i++) {
     142      316826 :     HPhi* phi = phi_list->at(i);
     143      316826 :     HValue* value = NULL;
     144             : 
     145      950478 :     if (phi->CheckFlag(HValue::kTruncatingToNumber) &&
     146      316826 :         !phi->CheckUsesForFlag(HValue::kTruncatingToNumber, &value)) {
     147             :       number_worklist.Add(phi, zone());
     148             :       phi->ClearFlag(HValue::kTruncatingToNumber);
     149             :       phi->ClearFlag(HValue::kTruncatingToInt32);
     150             :       phi->ClearFlag(HValue::kTruncatingToSmi);
     151      210168 :       if (FLAG_trace_representation) {
     152             :         PrintF("#%d Phi is not truncating Number because of #%d %s\n",
     153           0 :                phi->id(), value->id(), value->Mnemonic());
     154             :       }
     155      118259 :     } else if (phi->representation().IsSmiOrInteger32() &&
     156       11601 :                !phi->CheckUsesForFlag(HValue::kTruncatingToInt32, &value)) {
     157             :       int_worklist.Add(phi, zone());
     158             :       phi->ClearFlag(HValue::kTruncatingToInt32);
     159             :       phi->ClearFlag(HValue::kTruncatingToSmi);
     160        5036 :       if (FLAG_trace_representation) {
     161             :         PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
     162           0 :                phi->id(), value->id(), value->Mnemonic());
     163             :       }
     164      101782 :     } else if (phi->representation().IsSmi() &&
     165         160 :                !phi->CheckUsesForFlag(HValue::kTruncatingToSmi, &value)) {
     166             :       smi_worklist.Add(phi, zone());
     167             :       phi->ClearFlag(HValue::kTruncatingToSmi);
     168           0 :       if (FLAG_trace_representation) {
     169             :         PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
     170           0 :                phi->id(), value->id(), value->Mnemonic());
     171             :       }
     172             :     }
     173             :   }
     174             : 
     175      547738 :   while (!number_worklist.is_empty()) {
     176             :     HPhi* current = number_worklist.RemoveLast();
     177      887379 :     for (int i = current->OperandCount() - 1; i >= 0; --i) {
     178      229835 :       HValue* input = current->OperandAt(i);
     179      853206 :       if (input->IsPhi() && input->CheckFlag(HValue::kTruncatingToNumber)) {
     180       53842 :         if (FLAG_trace_representation) {
     181             :           PrintF("#%d Phi is not truncating Number because of #%d %s\n",
     182           0 :                  input->id(), current->id(), current->Mnemonic());
     183             :         }
     184             :         input->ClearFlag(HValue::kTruncatingToNumber);
     185             :         input->ClearFlag(HValue::kTruncatingToInt32);
     186             :         input->ClearFlag(HValue::kTruncatingToSmi);
     187             :         number_worklist.Add(HPhi::cast(input), zone());
     188             :       }
     189             :     }
     190             :   }
     191             : 
     192      288794 :   while (!int_worklist.is_empty()) {
     193             :     HPhi* current = int_worklist.RemoveLast();
     194       30404 :     for (int i = 0; i < current->OperandCount(); ++i) {
     195         375 :       HValue* input = current->OperandAt(i);
     196       10511 :       if (input->IsPhi() &&
     197       10511 :           input->representation().IsSmiOrInteger32() &&
     198             :           input->CheckFlag(HValue::kTruncatingToInt32)) {
     199          31 :         if (FLAG_trace_representation) {
     200             :           PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
     201           0 :                  input->id(), current->id(), current->Mnemonic());
     202             :         }
     203             :         input->ClearFlag(HValue::kTruncatingToInt32);
     204             :         int_worklist.Add(HPhi::cast(input), zone());
     205             :       }
     206             :     }
     207             :   }
     208             : 
     209      283728 :   while (!smi_worklist.is_empty()) {
     210             :     HPhi* current = smi_worklist.RemoveLast();
     211           2 :     for (int i = 0; i < current->OperandCount(); ++i) {
     212           0 :       HValue* input = current->OperandAt(i);
     213           0 :       if (input->IsPhi() &&
     214           0 :           input->representation().IsSmi() &&
     215             :           input->CheckFlag(HValue::kTruncatingToSmi)) {
     216           0 :         if (FLAG_trace_representation) {
     217             :           PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
     218           0 :                  input->id(), current->id(), current->Mnemonic());
     219             :         }
     220             :         input->ClearFlag(HValue::kTruncatingToSmi);
     221             :         smi_worklist.Add(HPhi::cast(input), zone());
     222             :       }
     223             :     }
     224             :   }
     225             : 
     226             :   const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
     227     9590744 :   for (int i = 0; i < blocks->length(); ++i) {
     228             :     // Process phi instructions first.
     229    13818661 :     const HBasicBlock* block(blocks->at(i));
     230             :     const ZoneList<HPhi*>* phis = block->phis();
     231     9656928 :     for (int j = 0; j < phis->length(); j++) {
     232     5145281 :       InsertRepresentationChangesForValue(phis->at(j));
     233             :     }
     234             : 
     235             :     // Process normal instructions.
     236    39040052 :     for (HInstruction* current = block->first(); current != NULL; ) {
     237             :       HInstruction* next = current->next();
     238    30016761 :       InsertRepresentationChangesForValue(current);
     239             :       current = next;
     240             :     }
     241             :   }
     242      283730 : }
     243             : 
     244             : }  // namespace internal
     245             : }  // namespace v8

Generated by: LCOV version 1.10