1bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org// Copyright 2013 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 4bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/hydrogen-representation-changes.h" 6bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 7bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgnamespace v8 { 8bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgnamespace internal { 9bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 10bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid HRepresentationChangesPhase::InsertRepresentationChangeForUse( 11bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HValue* value, HValue* use_value, int use_index, Representation to) { 12bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Insert the representation change right before its use. For phi-uses we 13bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // insert at the end of the corresponding predecessor. 14bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HInstruction* next = NULL; 15bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (use_value->IsPhi()) { 16bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org next = use_value->block()->predecessors()->at(use_index)->end(); 17bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } else { 18bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org next = HInstruction::cast(use_value); 19bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 20bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // For constants we try to make the representation change at compile 21bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // time. When a representation change is not possible without loss of 22bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // information we treat constants like normal instructions and insert the 23bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // change instructions for them. 24bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HInstruction* new_value = NULL; 25fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org bool is_truncating_to_smi = use_value->CheckFlag(HValue::kTruncatingToSmi); 26fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org bool is_truncating_to_int = use_value->CheckFlag(HValue::kTruncatingToInt32); 27bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (value->IsConstant()) { 28bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HConstant* constant = HConstant::cast(value); 29bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Try to create a new copy of the constant with the new representation. 30fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org if (is_truncating_to_int && to.IsInteger32()) { 31c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org Maybe<HConstant*> res = constant->CopyToTruncatedInt32(graph()->zone()); 32c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org if (res.has_value) new_value = res.value; 33c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org } else { 34c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org new_value = constant->CopyToRepresentation(to, graph()->zone()); 35c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org } 36bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 37bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 38bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (new_value == NULL) { 39c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org new_value = new(graph()->zone()) HChange( 40c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org value, to, is_truncating_to_smi, is_truncating_to_int); 41f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!use_value->operand_position(use_index).IsUnknown()) { 42af9cfcbed5daf6e636e189bce451c6fafdbb127dmachenbach@chromium.org new_value->set_position(use_value->operand_position(use_index)); 4371f9fca5cfb606009211e0631f33b76cc2ddce3cbmeurer@chromium.org } else { 44e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!FLAG_hydrogen_track_positions || 45f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org !graph()->info()->IsOptimizing()); 4671f9fca5cfb606009211e0631f33b76cc2ddce3cbmeurer@chromium.org } 47bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 48bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 49bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org new_value->InsertBefore(next); 50bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org use_value->SetOperandAt(use_index, new_value); 51bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org} 52bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 53bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgstatic bool IsNonDeoptingIntToSmiChange(HChange* change) { 551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Representation from_rep = change->from(); 561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Representation to_rep = change->to(); 571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // Flags indicating Uint32 operations are set in a later Hydrogen phase. 58e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!change->CheckFlag(HValue::kUint32)); 591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return from_rep.IsInteger32() && to_rep.IsSmi() && SmiValuesAre32Bits(); 601845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 611845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 621845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 63bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid HRepresentationChangesPhase::InsertRepresentationChangesForValue( 64bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HValue* value) { 65bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org Representation r = value->representation(); 66bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (r.IsNone()) return; 6750bb868e274f7f873f683d591048376427ffdd72jkummerow@chromium.org if (value->HasNoUses()) { 6850bb868e274f7f873f683d591048376427ffdd72jkummerow@chromium.org if (value->IsForceRepresentation()) value->DeleteAndReplaceWith(NULL); 6950bb868e274f7f873f683d591048376427ffdd72jkummerow@chromium.org return; 7050bb868e274f7f873f683d591048376427ffdd72jkummerow@chromium.org } 71bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 72bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { 73bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HValue* use_value = it.value(); 74bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org int use_index = it.index(); 75bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org Representation req = use_value->RequiredInputRepresentation(use_index); 76bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (req.IsNone() || req.Equals(r)) continue; 771845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 781845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // If this is an HForceRepresentation instruction, and an HChange has been 791845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // inserted above it, examine the input representation of the HChange. If 801845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // that's int32, and this HForceRepresentation use is int32, and int32 to 811845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // smi changes can't cause deoptimisation, set the input of the use to the 821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // input of the HChange. 831845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (value->IsForceRepresentation()) { 841845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org HValue* input = HForceRepresentation::cast(value)->value(); 851845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (input->IsChange()) { 861845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org HChange* change = HChange::cast(input); 871845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (change->from().Equals(req) && IsNonDeoptingIntToSmiChange(change)) { 881845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org use_value->SetOperandAt(use_index, change->value()); 891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org continue; 901845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 911845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 921845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 93bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org InsertRepresentationChangeForUse(value, use_value, use_index, req); 94bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 95bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (value->HasNoUses()) { 96e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(value->IsConstant() || value->IsForceRepresentation()); 97bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org value->DeleteAndReplaceWith(NULL); 981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 991845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // The only purpose of a HForceRepresentation is to represent the value 1001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // after the (possible) HChange instruction. We make it disappear. 1011845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (value->IsForceRepresentation()) { 1021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); 1031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 104bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 105bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org} 106bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 107bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 108bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.orgvoid HRepresentationChangesPhase::Run() { 109bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Compute truncation flag for phis: Initially assume that all 110bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // int32-phis allow truncation and iteratively remove the ones that 111bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // are used in an operation that does not allow a truncating 112bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // conversion. 113662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org ZoneList<HPhi*> int_worklist(8, zone()); 114662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org ZoneList<HPhi*> smi_worklist(8, zone()); 115bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 116bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org const ZoneList<HPhi*>* phi_list(graph()->phi_list()); 117bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (int i = 0; i < phi_list->length(); i++) { 118bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HPhi* phi = phi_list->at(i); 119bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (phi->representation().IsInteger32()) { 120bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org phi->SetFlag(HValue::kTruncatingToInt32); 121fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org } else if (phi->representation().IsSmi()) { 122fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org phi->SetFlag(HValue::kTruncatingToSmi); 123662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org phi->SetFlag(HValue::kTruncatingToInt32); 124bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 125bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 126bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 127bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (int i = 0; i < phi_list->length(); i++) { 128bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HPhi* phi = phi_list->at(i); 129662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org HValue* value = NULL; 130662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org if (phi->representation().IsSmiOrInteger32() && 131662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org !phi->CheckUsesForFlag(HValue::kTruncatingToInt32, &value)) { 132662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org int_worklist.Add(phi, zone()); 133662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org phi->ClearFlag(HValue::kTruncatingToInt32); 134662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org if (FLAG_trace_representation) { 135662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org PrintF("#%d Phi is not truncating Int32 because of #%d %s\n", 136662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org phi->id(), value->id(), value->Mnemonic()); 137662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org } 138662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org } 139662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org 140662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org if (phi->representation().IsSmi() && 141662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org !phi->CheckUsesForFlag(HValue::kTruncatingToSmi, &value)) { 142662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org smi_worklist.Add(phi, zone()); 143662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org phi->ClearFlag(HValue::kTruncatingToSmi); 144662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org if (FLAG_trace_representation) { 145662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org PrintF("#%d Phi is not truncating Smi because of #%d %s\n", 146662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org phi->id(), value->id(), value->Mnemonic()); 147662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org } 148662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org } 149662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org } 150662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org 151662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org while (!int_worklist.is_empty()) { 152662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org HPhi* current = int_worklist.RemoveLast(); 153662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org for (int i = 0; i < current->OperandCount(); ++i) { 154662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org HValue* input = current->OperandAt(i); 155662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org if (input->IsPhi() && 156662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org input->representation().IsSmiOrInteger32() && 157662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org input->CheckFlag(HValue::kTruncatingToInt32)) { 158bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (FLAG_trace_representation) { 159662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org PrintF("#%d Phi is not truncating Int32 because of #%d %s\n", 160662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org input->id(), current->id(), current->Mnemonic()); 161bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 162662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org input->ClearFlag(HValue::kTruncatingToInt32); 163662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org int_worklist.Add(HPhi::cast(input), zone()); 164bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 165bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 166bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 167bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 168662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org while (!smi_worklist.is_empty()) { 169662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org HPhi* current = smi_worklist.RemoveLast(); 170bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (int i = 0; i < current->OperandCount(); ++i) { 171bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HValue* input = current->OperandAt(i); 172bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (input->IsPhi() && 173662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org input->representation().IsSmi() && 174662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org input->CheckFlag(HValue::kTruncatingToSmi)) { 175bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org if (FLAG_trace_representation) { 176662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org PrintF("#%d Phi is not truncating Smi because of #%d %s\n", 177bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org input->id(), current->id(), current->Mnemonic()); 178bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 179fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org input->ClearFlag(HValue::kTruncatingToSmi); 180662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org smi_worklist.Add(HPhi::cast(input), zone()); 181bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 182bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 183bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 184bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 185bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org const ZoneList<HBasicBlock*>* blocks(graph()->blocks()); 186bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (int i = 0; i < blocks->length(); ++i) { 187bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Process phi instructions first. 188bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org const HBasicBlock* block(blocks->at(i)); 189bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org const ZoneList<HPhi*>* phis = block->phis(); 190bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (int j = 0; j < phis->length(); j++) { 191bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org InsertRepresentationChangesForValue(phis->at(j)); 192bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 193bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 194bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org // Process normal instructions. 195bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org for (HInstruction* current = block->first(); current != NULL; ) { 196bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org HInstruction* next = current->next(); 197bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org InsertRepresentationChangesForValue(current); 198bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org current = next; 199bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 200bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org } 201bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org} 202bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org 203bee51999422c0eeaae85ed99b5c0bd4126510ff1danno@chromium.org} } // namespace v8::internal 204