Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / v8 / src / hydrogen-representation-changes.cc
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "hydrogen-representation-changes.h"
29
30 namespace v8 {
31 namespace internal {
32
33 void HRepresentationChangesPhase::InsertRepresentationChangeForUse(
34     HValue* value, HValue* use_value, int use_index, Representation to) {
35   // Insert the representation change right before its use. For phi-uses we
36   // insert at the end of the corresponding predecessor.
37   HInstruction* next = NULL;
38   if (use_value->IsPhi()) {
39     next = use_value->block()->predecessors()->at(use_index)->end();
40   } else {
41     next = HInstruction::cast(use_value);
42   }
43   // For constants we try to make the representation change at compile
44   // time. When a representation change is not possible without loss of
45   // information we treat constants like normal instructions and insert the
46   // change instructions for them.
47   HInstruction* new_value = NULL;
48   bool is_truncating_to_smi = use_value->CheckFlag(HValue::kTruncatingToSmi);
49   bool is_truncating_to_int = use_value->CheckFlag(HValue::kTruncatingToInt32);
50   if (value->IsConstant()) {
51     HConstant* constant = HConstant::cast(value);
52     // Try to create a new copy of the constant with the new representation.
53     if (is_truncating_to_int && to.IsInteger32()) {
54       Maybe<HConstant*> res = constant->CopyToTruncatedInt32(graph()->zone());
55       if (res.has_value) new_value = res.value;
56     } else {
57       new_value = constant->CopyToRepresentation(to, graph()->zone());
58     }
59   }
60
61   if (new_value == NULL) {
62     if (((to.IsFloat32x4() || to.IsInt32x4()) &&
63          !value->representation().IsTagged()) ||
64         ((value->representation().IsFloat32x4() ||
65           value->representation().IsInt32x4()) &&
66          !to.IsTagged())) {
67       new_value = HUnarySIMDOperation::New(graph()->zone(),
68           graph()->entry_block()->last_environment()->context(),
69           value, kSIMD128Change, to);
70     } else {
71       new_value = new(graph()->zone()) HChange(
72           value, to, is_truncating_to_smi, is_truncating_to_int);
73     }
74     if (use_value->operand_position(use_index) != RelocInfo::kNoPosition) {
75       new_value->set_position(use_value->operand_position(use_index));
76     } else {
77       ASSERT(!FLAG_emit_opt_code_positions || !graph()->info()->IsOptimizing());
78     }
79   }
80
81   new_value->InsertBefore(next);
82   use_value->SetOperandAt(use_index, new_value);
83 }
84
85
86 void HRepresentationChangesPhase::InsertRepresentationChangesForValue(
87     HValue* value) {
88   Representation r = value->representation();
89   if (r.IsNone()) return;
90   if (value->HasNoUses()) return;
91
92   for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
93     HValue* use_value = it.value();
94     int use_index = it.index();
95     Representation req = use_value->RequiredInputRepresentation(use_index);
96     if (req.IsNone() || req.Equals(r)) continue;
97     InsertRepresentationChangeForUse(value, use_value, use_index, req);
98   }
99   if (value->HasNoUses()) {
100     ASSERT(value->IsConstant());
101     value->DeleteAndReplaceWith(NULL);
102   }
103
104   // The only purpose of a HForceRepresentation is to represent the value
105   // after the (possible) HChange instruction.  We make it disappear.
106   if (value->IsForceRepresentation()) {
107     value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
108   }
109 }
110
111
112 void HRepresentationChangesPhase::Run() {
113   // Compute truncation flag for phis: Initially assume that all
114   // int32-phis allow truncation and iteratively remove the ones that
115   // are used in an operation that does not allow a truncating
116   // conversion.
117   ZoneList<HPhi*> int_worklist(8, zone());
118   ZoneList<HPhi*> smi_worklist(8, zone());
119
120   const ZoneList<HPhi*>* phi_list(graph()->phi_list());
121   for (int i = 0; i < phi_list->length(); i++) {
122     HPhi* phi = phi_list->at(i);
123     if (phi->representation().IsInteger32()) {
124       phi->SetFlag(HValue::kTruncatingToInt32);
125     } else if (phi->representation().IsSmi()) {
126       phi->SetFlag(HValue::kTruncatingToSmi);
127       phi->SetFlag(HValue::kTruncatingToInt32);
128     }
129   }
130
131   for (int i = 0; i < phi_list->length(); i++) {
132     HPhi* phi = phi_list->at(i);
133     HValue* value = NULL;
134     if (phi->representation().IsSmiOrInteger32() &&
135         !phi->CheckUsesForFlag(HValue::kTruncatingToInt32, &value)) {
136       int_worklist.Add(phi, zone());
137       phi->ClearFlag(HValue::kTruncatingToInt32);
138       if (FLAG_trace_representation) {
139         PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
140                phi->id(), value->id(), value->Mnemonic());
141       }
142     }
143
144     if (phi->representation().IsSmi() &&
145         !phi->CheckUsesForFlag(HValue::kTruncatingToSmi, &value)) {
146       smi_worklist.Add(phi, zone());
147       phi->ClearFlag(HValue::kTruncatingToSmi);
148       if (FLAG_trace_representation) {
149         PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
150                phi->id(), value->id(), value->Mnemonic());
151       }
152     }
153   }
154
155   while (!int_worklist.is_empty()) {
156     HPhi* current = int_worklist.RemoveLast();
157     for (int i = 0; i < current->OperandCount(); ++i) {
158       HValue* input = current->OperandAt(i);
159       if (input->IsPhi() &&
160           input->representation().IsSmiOrInteger32() &&
161           input->CheckFlag(HValue::kTruncatingToInt32)) {
162         if (FLAG_trace_representation) {
163           PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
164                  input->id(), current->id(), current->Mnemonic());
165         }
166         input->ClearFlag(HValue::kTruncatingToInt32);
167         int_worklist.Add(HPhi::cast(input), zone());
168       }
169     }
170   }
171
172   while (!smi_worklist.is_empty()) {
173     HPhi* current = smi_worklist.RemoveLast();
174     for (int i = 0; i < current->OperandCount(); ++i) {
175       HValue* input = current->OperandAt(i);
176       if (input->IsPhi() &&
177           input->representation().IsSmi() &&
178           input->CheckFlag(HValue::kTruncatingToSmi)) {
179         if (FLAG_trace_representation) {
180           PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
181                  input->id(), current->id(), current->Mnemonic());
182         }
183         input->ClearFlag(HValue::kTruncatingToSmi);
184         smi_worklist.Add(HPhi::cast(input), zone());
185       }
186     }
187   }
188
189   const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
190   for (int i = 0; i < blocks->length(); ++i) {
191     // Process phi instructions first.
192     const HBasicBlock* block(blocks->at(i));
193     const ZoneList<HPhi*>* phis = block->phis();
194     for (int j = 0; j < phis->length(); j++) {
195       InsertRepresentationChangesForValue(phis->at(j));
196     }
197
198     // Process normal instructions.
199     for (HInstruction* current = block->first(); current != NULL; ) {
200       HInstruction* next = current->next();
201       InsertRepresentationChangesForValue(current);
202       current = next;
203     }
204   }
205 }
206
207 } }  // namespace v8::internal