• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InsertRepresentationChangeForUse(HValue * value,HValue * use_value,int use_index,Representation to)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     new_value = new(graph()->zone()) HChange(
63         value, to, is_truncating_to_smi, is_truncating_to_int);
64     if (use_value->operand_position(use_index) != RelocInfo::kNoPosition) {
65       new_value->set_position(use_value->operand_position(use_index));
66     } else {
67       ASSERT(!FLAG_emit_opt_code_positions || !graph()->info()->IsOptimizing());
68     }
69   }
70 
71   new_value->InsertBefore(next);
72   use_value->SetOperandAt(use_index, new_value);
73 }
74 
75 
InsertRepresentationChangesForValue(HValue * value)76 void HRepresentationChangesPhase::InsertRepresentationChangesForValue(
77     HValue* value) {
78   Representation r = value->representation();
79   if (r.IsNone()) return;
80   if (value->HasNoUses()) return;
81 
82   for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) {
83     HValue* use_value = it.value();
84     int use_index = it.index();
85     Representation req = use_value->RequiredInputRepresentation(use_index);
86     if (req.IsNone() || req.Equals(r)) continue;
87     InsertRepresentationChangeForUse(value, use_value, use_index, req);
88   }
89   if (value->HasNoUses()) {
90     ASSERT(value->IsConstant());
91     value->DeleteAndReplaceWith(NULL);
92   }
93 
94   // The only purpose of a HForceRepresentation is to represent the value
95   // after the (possible) HChange instruction.  We make it disappear.
96   if (value->IsForceRepresentation()) {
97     value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value());
98   }
99 }
100 
101 
Run()102 void HRepresentationChangesPhase::Run() {
103   // Compute truncation flag for phis: Initially assume that all
104   // int32-phis allow truncation and iteratively remove the ones that
105   // are used in an operation that does not allow a truncating
106   // conversion.
107   ZoneList<HPhi*> int_worklist(8, zone());
108   ZoneList<HPhi*> smi_worklist(8, zone());
109 
110   const ZoneList<HPhi*>* phi_list(graph()->phi_list());
111   for (int i = 0; i < phi_list->length(); i++) {
112     HPhi* phi = phi_list->at(i);
113     if (phi->representation().IsInteger32()) {
114       phi->SetFlag(HValue::kTruncatingToInt32);
115     } else if (phi->representation().IsSmi()) {
116       phi->SetFlag(HValue::kTruncatingToSmi);
117       phi->SetFlag(HValue::kTruncatingToInt32);
118     }
119   }
120 
121   for (int i = 0; i < phi_list->length(); i++) {
122     HPhi* phi = phi_list->at(i);
123     HValue* value = NULL;
124     if (phi->representation().IsSmiOrInteger32() &&
125         !phi->CheckUsesForFlag(HValue::kTruncatingToInt32, &value)) {
126       int_worklist.Add(phi, zone());
127       phi->ClearFlag(HValue::kTruncatingToInt32);
128       if (FLAG_trace_representation) {
129         PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
130                phi->id(), value->id(), value->Mnemonic());
131       }
132     }
133 
134     if (phi->representation().IsSmi() &&
135         !phi->CheckUsesForFlag(HValue::kTruncatingToSmi, &value)) {
136       smi_worklist.Add(phi, zone());
137       phi->ClearFlag(HValue::kTruncatingToSmi);
138       if (FLAG_trace_representation) {
139         PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
140                phi->id(), value->id(), value->Mnemonic());
141       }
142     }
143   }
144 
145   while (!int_worklist.is_empty()) {
146     HPhi* current = int_worklist.RemoveLast();
147     for (int i = 0; i < current->OperandCount(); ++i) {
148       HValue* input = current->OperandAt(i);
149       if (input->IsPhi() &&
150           input->representation().IsSmiOrInteger32() &&
151           input->CheckFlag(HValue::kTruncatingToInt32)) {
152         if (FLAG_trace_representation) {
153           PrintF("#%d Phi is not truncating Int32 because of #%d %s\n",
154                  input->id(), current->id(), current->Mnemonic());
155         }
156         input->ClearFlag(HValue::kTruncatingToInt32);
157         int_worklist.Add(HPhi::cast(input), zone());
158       }
159     }
160   }
161 
162   while (!smi_worklist.is_empty()) {
163     HPhi* current = smi_worklist.RemoveLast();
164     for (int i = 0; i < current->OperandCount(); ++i) {
165       HValue* input = current->OperandAt(i);
166       if (input->IsPhi() &&
167           input->representation().IsSmi() &&
168           input->CheckFlag(HValue::kTruncatingToSmi)) {
169         if (FLAG_trace_representation) {
170           PrintF("#%d Phi is not truncating Smi because of #%d %s\n",
171                  input->id(), current->id(), current->Mnemonic());
172         }
173         input->ClearFlag(HValue::kTruncatingToSmi);
174         smi_worklist.Add(HPhi::cast(input), zone());
175       }
176     }
177   }
178 
179   const ZoneList<HBasicBlock*>* blocks(graph()->blocks());
180   for (int i = 0; i < blocks->length(); ++i) {
181     // Process phi instructions first.
182     const HBasicBlock* block(blocks->at(i));
183     const ZoneList<HPhi*>* phis = block->phis();
184     for (int j = 0; j < phis->length(); j++) {
185       InsertRepresentationChangesForValue(phis->at(j));
186     }
187 
188     // Process normal instructions.
189     for (HInstruction* current = block->first(); current != NULL; ) {
190       HInstruction* next = current->next();
191       InsertRepresentationChangesForValue(current);
192       current = next;
193     }
194   }
195 }
196 
197 } }  // namespace v8::internal
198