OLD | NEW |
(Empty) | |
| 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 = use_value->CheckFlag(HValue::kTruncatingToInt32); |
| 49 bool allow_undefined_as_nan = |
| 50 use_value->CheckFlag(HValue::kAllowUndefinedAsNaN); |
| 51 if (value->IsConstant()) { |
| 52 HConstant* constant = HConstant::cast(value); |
| 53 // Try to create a new copy of the constant with the new representation. |
| 54 new_value = (is_truncating && to.IsInteger32()) |
| 55 ? constant->CopyToTruncatedInt32(graph()->zone()) |
| 56 : constant->CopyToRepresentation(to, graph()->zone()); |
| 57 } |
| 58 |
| 59 if (new_value == NULL) { |
| 60 new_value = new(graph()->zone()) HChange(value, to, |
| 61 is_truncating, |
| 62 allow_undefined_as_nan); |
| 63 } |
| 64 |
| 65 new_value->InsertBefore(next); |
| 66 use_value->SetOperandAt(use_index, new_value); |
| 67 } |
| 68 |
| 69 |
| 70 void HRepresentationChangesPhase::InsertRepresentationChangesForValue( |
| 71 HValue* value) { |
| 72 Representation r = value->representation(); |
| 73 if (r.IsNone()) return; |
| 74 if (value->HasNoUses()) return; |
| 75 |
| 76 for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { |
| 77 HValue* use_value = it.value(); |
| 78 int use_index = it.index(); |
| 79 Representation req = use_value->RequiredInputRepresentation(use_index); |
| 80 if (req.IsNone() || req.Equals(r)) continue; |
| 81 InsertRepresentationChangeForUse(value, use_value, use_index, req); |
| 82 } |
| 83 if (value->HasNoUses()) { |
| 84 ASSERT(value->IsConstant()); |
| 85 value->DeleteAndReplaceWith(NULL); |
| 86 } |
| 87 |
| 88 // The only purpose of a HForceRepresentation is to represent the value |
| 89 // after the (possible) HChange instruction. We make it disappear. |
| 90 if (value->IsForceRepresentation()) { |
| 91 value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); |
| 92 } |
| 93 } |
| 94 |
| 95 |
| 96 void HRepresentationChangesPhase::Run() { |
| 97 // Compute truncation flag for phis: Initially assume that all |
| 98 // int32-phis allow truncation and iteratively remove the ones that |
| 99 // are used in an operation that does not allow a truncating |
| 100 // conversion. |
| 101 ZoneList<HPhi*> worklist(8, zone()); |
| 102 |
| 103 const ZoneList<HPhi*>* phi_list(graph()->phi_list()); |
| 104 for (int i = 0; i < phi_list->length(); i++) { |
| 105 HPhi* phi = phi_list->at(i); |
| 106 if (phi->representation().IsInteger32()) { |
| 107 phi->SetFlag(HValue::kTruncatingToInt32); |
| 108 } |
| 109 } |
| 110 |
| 111 for (int i = 0; i < phi_list->length(); i++) { |
| 112 HPhi* phi = phi_list->at(i); |
| 113 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
| 114 // If a Phi is used as a non-truncating int32 or as a double, |
| 115 // clear its "truncating" flag. |
| 116 HValue* use = it.value(); |
| 117 Representation input_representation = |
| 118 use->RequiredInputRepresentation(it.index()); |
| 119 if (!input_representation.IsInteger32() || |
| 120 !use->CheckFlag(HValue::kTruncatingToInt32)) { |
| 121 if (FLAG_trace_representation) { |
| 122 PrintF("#%d Phi is not truncating because of #%d %s\n", |
| 123 phi->id(), it.value()->id(), it.value()->Mnemonic()); |
| 124 } |
| 125 phi->ClearFlag(HValue::kTruncatingToInt32); |
| 126 worklist.Add(phi, zone()); |
| 127 break; |
| 128 } |
| 129 } |
| 130 } |
| 131 |
| 132 while (!worklist.is_empty()) { |
| 133 HPhi* current = worklist.RemoveLast(); |
| 134 for (int i = 0; i < current->OperandCount(); ++i) { |
| 135 HValue* input = current->OperandAt(i); |
| 136 if (input->IsPhi() && |
| 137 input->representation().IsInteger32() && |
| 138 input->CheckFlag(HValue::kTruncatingToInt32)) { |
| 139 if (FLAG_trace_representation) { |
| 140 PrintF("#%d Phi is not truncating because of #%d %s\n", |
| 141 input->id(), current->id(), current->Mnemonic()); |
| 142 } |
| 143 input->ClearFlag(HValue::kTruncatingToInt32); |
| 144 worklist.Add(HPhi::cast(input), zone()); |
| 145 } |
| 146 } |
| 147 } |
| 148 |
| 149 const ZoneList<HBasicBlock*>* blocks(graph()->blocks()); |
| 150 for (int i = 0; i < blocks->length(); ++i) { |
| 151 // Process phi instructions first. |
| 152 const HBasicBlock* block(blocks->at(i)); |
| 153 const ZoneList<HPhi*>* phis = block->phis(); |
| 154 for (int j = 0; j < phis->length(); j++) { |
| 155 InsertRepresentationChangesForValue(phis->at(j)); |
| 156 } |
| 157 |
| 158 // Process normal instructions. |
| 159 for (HInstruction* current = block->first(); current != NULL; ) { |
| 160 HInstruction* next = current->next(); |
| 161 InsertRepresentationChangesForValue(current); |
| 162 current = next; |
| 163 } |
| 164 } |
| 165 } |
| 166 |
| 167 } } // namespace v8::internal |
OLD | NEW |