Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / v8 / src / hydrogen-representation-changes.cc
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 "hydrogen-representation-changes.h"
6
7 namespace v8 {
8 namespace internal {
9
10 void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
11     HValue* value, HValue* use_value, int use_index, Representation to) {
12   // Insert the representation change right before its use. For phi-uses we
13   // insert at the end of the corresponding predecessor.
14   HInstruction* next = NULL;
15   if (use_value->IsPhi()) {
16     next = use_value->block()->predecessors()->at(use_index)->end();
17   } else {
18     next = HInstruction::cast(use_value);
19   }
20   // For constants we try to make the representation change at compile
21   // time. When a representation change is not possible without loss of
22   // information we treat constants like normal instructions and insert the
23   // change instructions for them.
24   HInstruction* new_value = NULL;
25   bool is_truncating_to_smi = use_value->CheckFlag(HValue::kTruncatingToSmi);
26   bool is_truncating_to_int = use_value->CheckFlag(HValue::kTruncatingToInt32);
27   if (value->IsConstant()) {
28     HConstant* constant = HConstant::cast(value);
29     // Try to create a new copy of the constant with the new representation.
30     if (is_truncating_to_int && to.IsInteger32()) {
31       Maybe<HConstant*> res = constant->CopyToTruncatedInt32(graph()->zone());
32       if (res.has_value) new_value = res.value;
33     } else {
34       new_value = constant->CopyToRepresentation(to, graph()->zone());
35     }
36   }
37
38   if (new_value == NULL) {
39     if (((to.IsFloat32x4() || to.IsFloat64x2() || to.IsInt32x4()) &&
40          !value->representation().IsTagged()) ||
41         ((value->representation().IsFloat32x4() ||
42           value->representation().IsFloat64x2() ||
43           value->representation().IsInt32x4()) &&
44          !to.IsTagged())) {
45       new_value = HUnarySIMDOperation::New(graph()->zone(),
46           graph()->entry_block()->last_environment()->context(),
47           value, kSIMD128Change, to);
48     } else {
49       new_value = new(graph()->zone()) HChange(
50           value, to, is_truncating_to_smi, is_truncating_to_int);
51     }
52     if (!use_value->operand_position(use_index).IsUnknown()) {
53       new_value->set_position(use_value->operand_position(use_index));
54     } else {
55       ASSERT(!FLAG_hydrogen_track_positions ||
56              !graph()->info()->IsOptimizing());
57     }
58   }
59
60   new_value->InsertBefore(next);
61   use_value->SetOperandAt(use_index, new_value);
62 }
63
64
65 void HRepresentationChangesPhase::InsertRepresentationChangesForValue(
66     HValue* value) {
67   Representation r = value->representation();
68   if (r.IsNone()) return;
69   if (value->HasNoUses()) {
70     if (value->IsForceRepresentation()) value->DeleteAndReplaceWith(NULL);
71     return;
72   }
73
74   for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
75     HValue* use_value = it.value();
76     int use_index = it.index();
77     Representation req = use_value->RequiredInputRepresentation(use_index);
78     if (req.IsNone() || req.Equals(r)) continue;
79     InsertRepresentationChangeForUse(value, use_value, use_index, req);
80   }
81   if (value->HasNoUses()) {
82     ASSERT(value->IsConstant());
83     value->DeleteAndReplaceWith(NULL);
84   }
85
86   // The only purpose of a HForceRepresentation is to represent the value
87   // after the (possible) HChange instruction.  We make it disappear.
88   if (value->IsForceRepresentation()) {
89     value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
90   }
91 }
92
93
94 void HRepresentationChangesPhase::Run() {
95   // Compute truncation flag for phis: Initially assume that all
96   // int32-phis allow truncation and iteratively remove the ones that
97   // are used in an operation that does not allow a truncating
98   // conversion.
99   ZoneList<HPhi*> int_worklist(8, zone());
100   ZoneList<HPhi*> smi_worklist(8, zone());
101
102   const ZoneList<HPhi*>* phi_list(graph()->phi_list());
103   for (int i = 0; i < phi_list->length(); i++) {
104     HPhi* phi = phi_list->at(i);
105     if (phi->representation().IsInteger32()) {
106       phi->SetFlag(HValue::kTruncatingToInt32);
107     } else if (phi->representation().IsSmi()) {
108       phi->SetFlag(HValue::kTruncatingToSmi);
109       phi->SetFlag(HValue::kTruncatingToInt32);
110     }
111   }
112
113   for (int i = 0; i < phi_list->length(); i++) {
114     HPhi* phi = phi_list->at(i);
115     HValue* value = NULL;
116     if (phi->representation().IsSmiOrInteger32() &&
117         !phi->CheckUsesForFlag(HValue::kTruncatingToInt32, &value)) {
118       int_worklist.Add(phi, zone());
119       phi->ClearFlag(HValue::kTruncatingToInt32);
120       if (FLAG_trace_representation) {
121         PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
122                phi->id(), value->id(), value->Mnemonic());
123       }
124     }
125
126     if (phi->representation().IsSmi() &&
127         !phi->CheckUsesForFlag(HValue::kTruncatingToSmi, &value)) {
128       smi_worklist.Add(phi, zone());
129       phi->ClearFlag(HValue::kTruncatingToSmi);
130       if (FLAG_trace_representation) {
131         PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
132                phi->id(), value->id(), value->Mnemonic());
133       }
134     }
135   }
136
137   while (!int_worklist.is_empty()) {
138     HPhi* current = int_worklist.RemoveLast();
139     for (int i = 0; i < current->OperandCount(); ++i) {
140       HValue* input = current->OperandAt(i);
141       if (input->IsPhi() &&
142           input->representation().IsSmiOrInteger32() &&
143           input->CheckFlag(HValue::kTruncatingToInt32)) {
144         if (FLAG_trace_representation) {
145           PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
146                  input->id(), current->id(), current->Mnemonic());
147         }
148         input->ClearFlag(HValue::kTruncatingToInt32);
149         int_worklist.Add(HPhi::cast(input), zone());
150       }
151     }
152   }
153
154   while (!smi_worklist.is_empty()) {
155     HPhi* current = smi_worklist.RemoveLast();
156     for (int i = 0; i < current->OperandCount(); ++i) {
157       HValue* input = current->OperandAt(i);
158       if (input->IsPhi() &&
159           input->representation().IsSmi() &&
160           input->CheckFlag(HValue::kTruncatingToSmi)) {
161         if (FLAG_trace_representation) {
162           PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
163                  input->id(), current->id(), current->Mnemonic());
164         }
165         input->ClearFlag(HValue::kTruncatingToSmi);
166         smi_worklist.Add(HPhi::cast(input), zone());
167       }
168     }
169   }
170
171   const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
172   for (int i = 0; i < blocks->length(); ++i) {
173     // Process phi instructions first.
174     const HBasicBlock* block(blocks->at(i));
175     const ZoneList<HPhi*>* phis = block->phis();
176     for (int j = 0; j < phis->length(); j++) {
177       InsertRepresentationChangesForValue(phis->at(j));
178     }
179
180     // Process normal instructions.
181     for (HInstruction* current = block->first(); current != NULL; ) {
182       HInstruction* next = current->next();
183       InsertRepresentationChangesForValue(current);
184       current = next;
185     }
186   }
187 }
188
189 } }  // namespace v8::internal