diff --git a/src/hydrogen-representation-changes.cc b/src/hydrogen-representation-changes.cc new file mode 100644 index 0000000000..e8f0140f66 --- /dev/null +++ b/src/hydrogen-representation-changes.cc @@ -0,0 +1,167 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "hydrogen-representation-changes.h" + +namespace v8 { +namespace internal { + +void HRepresentationChangesPhase::InsertRepresentationChangeForUse( + HValue* value, HValue* use_value, int use_index, Representation to) { + // Insert the representation change right before its use. For phi-uses we + // insert at the end of the corresponding predecessor. + HInstruction* next = NULL; + if (use_value->IsPhi()) { + next = use_value->block()->predecessors()->at(use_index)->end(); + } else { + next = HInstruction::cast(use_value); + } + // For constants we try to make the representation change at compile + // time. When a representation change is not possible without loss of + // information we treat constants like normal instructions and insert the + // change instructions for them. + HInstruction* new_value = NULL; + bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); + bool allow_undefined_as_nan = + use_value->CheckFlag(HValue::kAllowUndefinedAsNaN); + if (value->IsConstant()) { + HConstant* constant = HConstant::cast(value); + // Try to create a new copy of the constant with the new representation. + new_value = (is_truncating && to.IsInteger32()) + ? constant->CopyToTruncatedInt32(graph()->zone()) + : constant->CopyToRepresentation(to, graph()->zone()); + } + + if (new_value == NULL) { + new_value = new(graph()->zone()) HChange(value, to, + is_truncating, + allow_undefined_as_nan); + } + + new_value->InsertBefore(next); + use_value->SetOperandAt(use_index, new_value); +} + + +void HRepresentationChangesPhase::InsertRepresentationChangesForValue( + HValue* value) { + Representation r = value->representation(); + if (r.IsNone()) return; + if (value->HasNoUses()) return; + + for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { + HValue* use_value = it.value(); + int use_index = it.index(); + Representation req = use_value->RequiredInputRepresentation(use_index); + if (req.IsNone() || req.Equals(r)) continue; + InsertRepresentationChangeForUse(value, use_value, use_index, req); + } + if (value->HasNoUses()) { + ASSERT(value->IsConstant()); + value->DeleteAndReplaceWith(NULL); + } + + // The only purpose of a HForceRepresentation is to represent the value + // after the (possible) HChange instruction. We make it disappear. + if (value->IsForceRepresentation()) { + value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); + } +} + + +void HRepresentationChangesPhase::Run() { + // Compute truncation flag for phis: Initially assume that all + // int32-phis allow truncation and iteratively remove the ones that + // are used in an operation that does not allow a truncating + // conversion. + ZoneList worklist(8, zone()); + + const ZoneList* phi_list(graph()->phi_list()); + for (int i = 0; i < phi_list->length(); i++) { + HPhi* phi = phi_list->at(i); + if (phi->representation().IsInteger32()) { + phi->SetFlag(HValue::kTruncatingToInt32); + } + } + + for (int i = 0; i < phi_list->length(); i++) { + HPhi* phi = phi_list->at(i); + for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { + // If a Phi is used as a non-truncating int32 or as a double, + // clear its "truncating" flag. + HValue* use = it.value(); + Representation input_representation = + use->RequiredInputRepresentation(it.index()); + if (!input_representation.IsInteger32() || + !use->CheckFlag(HValue::kTruncatingToInt32)) { + if (FLAG_trace_representation) { + PrintF("#%d Phi is not truncating because of #%d %s\n", + phi->id(), it.value()->id(), it.value()->Mnemonic()); + } + phi->ClearFlag(HValue::kTruncatingToInt32); + worklist.Add(phi, zone()); + break; + } + } + } + + while (!worklist.is_empty()) { + HPhi* current = worklist.RemoveLast(); + for (int i = 0; i < current->OperandCount(); ++i) { + HValue* input = current->OperandAt(i); + if (input->IsPhi() && + input->representation().IsInteger32() && + input->CheckFlag(HValue::kTruncatingToInt32)) { + if (FLAG_trace_representation) { + PrintF("#%d Phi is not truncating because of #%d %s\n", + input->id(), current->id(), current->Mnemonic()); + } + input->ClearFlag(HValue::kTruncatingToInt32); + worklist.Add(HPhi::cast(input), zone()); + } + } + } + + const ZoneList* blocks(graph()->blocks()); + for (int i = 0; i < blocks->length(); ++i) { + // Process phi instructions first. + const HBasicBlock* block(blocks->at(i)); + const ZoneList* phis = block->phis(); + for (int j = 0; j < phis->length(); j++) { + InsertRepresentationChangesForValue(phis->at(j)); + } + + // Process normal instructions. + for (HInstruction* current = block->first(); current != NULL; ) { + HInstruction* next = current->next(); + InsertRepresentationChangesForValue(current); + current = next; + } + } +} + +} } // namespace v8::internal diff --git a/src/hydrogen-representation-changes.h b/src/hydrogen-representation-changes.h new file mode 100644 index 0000000000..77e899b60b --- /dev/null +++ b/src/hydrogen-representation-changes.h @@ -0,0 +1,55 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef V8_HYDROGEN_REPRESENTATION_CHANGES_H_ +#define V8_HYDROGEN_REPRESENTATION_CHANGES_H_ + +#include "hydrogen.h" + +namespace v8 { +namespace internal { + + +class HRepresentationChangesPhase : public HPhase { + public: + explicit HRepresentationChangesPhase(HGraph* graph) + : HPhase("H_Representation changes", graph) { } + + void Run(); + + private: + void InsertRepresentationChangeForUse(HValue* value, + HValue* use_value, + int use_index, + Representation to); + void InsertRepresentationChangesForValue(HValue* value); +}; + + +} } // namespace v8::internal + +#endif // V8_HYDROGEN_REPRESENTATION_CHANGES_H_ diff --git a/src/hydrogen.cc b/src/hydrogen.cc index a8cc2850c8..8da0e82183 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -43,6 +43,7 @@ #include "hydrogen-osr.h" #include "hydrogen-range-analysis.h" #include "hydrogen-redundant-phi.h" +#include "hydrogen-representation-changes.h" #include "hydrogen-sce.h" #include "hydrogen-uint32-analysis.h" #include "lithium-allocator.h" @@ -2668,141 +2669,6 @@ void HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { } -void HGraph::InsertRepresentationChangeForUse(HValue* value, - HValue* use_value, - int use_index, - Representation to) { - // Insert the representation change right before its use. For phi-uses we - // insert at the end of the corresponding predecessor. - HInstruction* next = NULL; - if (use_value->IsPhi()) { - next = use_value->block()->predecessors()->at(use_index)->end(); - } else { - next = HInstruction::cast(use_value); - } - // For constants we try to make the representation change at compile - // time. When a representation change is not possible without loss of - // information we treat constants like normal instructions and insert the - // change instructions for them. - HInstruction* new_value = NULL; - bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); - bool allow_undefined_as_nan = - use_value->CheckFlag(HValue::kAllowUndefinedAsNaN); - if (value->IsConstant()) { - HConstant* constant = HConstant::cast(value); - // Try to create a new copy of the constant with the new representation. - new_value = (is_truncating && to.IsInteger32()) - ? constant->CopyToTruncatedInt32(zone()) - : constant->CopyToRepresentation(to, zone()); - } - - if (new_value == NULL) { - new_value = new(zone()) HChange(value, to, - is_truncating, allow_undefined_as_nan); - } - - new_value->InsertBefore(next); - use_value->SetOperandAt(use_index, new_value); -} - - -void HGraph::InsertRepresentationChangesForValue(HValue* value) { - Representation r = value->representation(); - if (r.IsNone()) return; - if (value->HasNoUses()) return; - - for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { - HValue* use_value = it.value(); - int use_index = it.index(); - Representation req = use_value->RequiredInputRepresentation(use_index); - if (req.IsNone() || req.Equals(r)) continue; - InsertRepresentationChangeForUse(value, use_value, use_index, req); - } - if (value->HasNoUses()) { - ASSERT(value->IsConstant()); - value->DeleteAndReplaceWith(NULL); - } - - // The only purpose of a HForceRepresentation is to represent the value - // after the (possible) HChange instruction. We make it disappear. - if (value->IsForceRepresentation()) { - value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); - } -} - - -void HGraph::InsertRepresentationChanges() { - HPhase phase("H_Representation changes", this); - - // Compute truncation flag for phis: Initially assume that all - // int32-phis allow truncation and iteratively remove the ones that - // are used in an operation that does not allow a truncating - // conversion. - ZoneList worklist(8, zone()); - - for (int i = 0; i < phi_list()->length(); i++) { - HPhi* phi = phi_list()->at(i); - if (phi->representation().IsInteger32()) { - phi->SetFlag(HValue::kTruncatingToInt32); - } - } - - for (int i = 0; i < phi_list()->length(); i++) { - HPhi* phi = phi_list()->at(i); - for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { - // If a Phi is used as a non-truncating int32 or as a double, - // clear its "truncating" flag. - HValue* use = it.value(); - Representation input_representation = - use->RequiredInputRepresentation(it.index()); - if (!input_representation.IsInteger32() || - !use->CheckFlag(HValue::kTruncatingToInt32)) { - if (FLAG_trace_representation) { - PrintF("#%d Phi is not truncating because of #%d %s\n", - phi->id(), it.value()->id(), it.value()->Mnemonic()); - } - phi->ClearFlag(HValue::kTruncatingToInt32); - worklist.Add(phi, zone()); - break; - } - } - } - - while (!worklist.is_empty()) { - HPhi* current = worklist.RemoveLast(); - for (int i = 0; i < current->OperandCount(); ++i) { - HValue* input = current->OperandAt(i); - if (input->IsPhi() && - input->representation().IsInteger32() && - input->CheckFlag(HValue::kTruncatingToInt32)) { - if (FLAG_trace_representation) { - PrintF("#%d Phi is not truncating because of #%d %s\n", - input->id(), current->id(), current->Mnemonic()); - } - input->ClearFlag(HValue::kTruncatingToInt32); - worklist.Add(HPhi::cast(input), zone()); - } - } - } - - for (int i = 0; i < blocks_.length(); ++i) { - // Process phi instructions first. - const ZoneList* phis = blocks_[i]->phis(); - for (int j = 0; j < phis->length(); j++) { - InsertRepresentationChangesForValue(phis->at(j)); - } - - // Process normal instructions. - HInstruction* current = blocks_[i]->first(); - while (current != NULL) { - HInstruction* next = current->next(); - InsertRepresentationChangesForValue(current); - current = next; - } - } -} - - void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return; phi->ClearFlag(HValue::kAllowUndefinedAsNaN); @@ -3334,7 +3200,7 @@ bool HGraph::Optimize(SmartArrayPointer* bailout_reason) { MergeRemovableSimulates(); MarkDeoptimizeOnUndefined(); - InsertRepresentationChanges(); + Run(); Run(); diff --git a/src/hydrogen.h b/src/hydrogen.h index 354e2808b7..40396bf0cd 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -293,7 +293,6 @@ class HGraph: public ZoneObject { void FinalizeUniqueValueIds(); void InsertTypeConversions(); void MergeRemovableSimulates(); - void InsertRepresentationChanges(); void MarkDeoptimizeOnUndefined(); void ComputeMinusZeroChecks(); bool ProcessArgumentsObject(); @@ -452,11 +451,6 @@ class HGraph: public ZoneObject { void InsertTypeConversions(HInstruction* instr); void PropagateMinusZeroChecks(HValue* value, BitVector* visited); void RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi); - void InsertRepresentationChangeForUse(HValue* value, - HValue* use_value, - int use_index, - Representation to); - void InsertRepresentationChangesForValue(HValue* value); void CheckForBackEdge(HBasicBlock* block, HBasicBlock* successor); void SetupInformativeDefinitionsInBlock(HBasicBlock* block); void SetupInformativeDefinitionsRecursively(HBasicBlock* block); diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index a59b649dae..c52b3a3f40 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp @@ -357,6 +357,8 @@ '../../src/hydrogen-range-analysis.h', '../../src/hydrogen-redundant-phi.cc', '../../src/hydrogen-redundant-phi.h', + '../../src/hydrogen-representation-changes.cc', + '../../src/hydrogen-representation-changes.h', '../../src/hydrogen-sce.cc', '../../src/hydrogen-sce.h', '../../src/hydrogen-uint32-analysis.cc',