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