diff options
Diffstat (limited to 'deps/v8/src/compiler/redundancy-elimination.cc')
-rw-r--r-- | deps/v8/src/compiler/redundancy-elimination.cc | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/deps/v8/src/compiler/redundancy-elimination.cc b/deps/v8/src/compiler/redundancy-elimination.cc index 9cfb03c18c..784665cb94 100644 --- a/deps/v8/src/compiler/redundancy-elimination.cc +++ b/deps/v8/src/compiler/redundancy-elimination.cc @@ -4,6 +4,7 @@ #include "src/compiler/redundancy-elimination.h" +#include "src/compiler/js-graph.h" #include "src/compiler/node-properties.h" #include "src/compiler/simplified-operator.h" @@ -11,8 +12,12 @@ namespace v8 { namespace internal { namespace compiler { -RedundancyElimination::RedundancyElimination(Editor* editor, Zone* zone) - : AdvancedReducer(editor), node_checks_(zone), zone_(zone) {} +RedundancyElimination::RedundancyElimination(Editor* editor, JSGraph* jsgraph, + Zone* zone) + : AdvancedReducer(editor), + node_checks_(zone), + jsgraph_(jsgraph), + zone_(zone) {} RedundancyElimination::~RedundancyElimination() = default; @@ -133,8 +138,43 @@ RedundancyElimination::EffectPathChecks::AddCheck(Zone* zone, namespace { +struct Subsumption { + enum class Kind { + kNone, + kImplicit, + kWithConversion, + }; + + static Subsumption None() { return Subsumption(Kind::kNone, nullptr); } + static Subsumption Implicit() { + return Subsumption(Kind::kImplicit, nullptr); + } + static Subsumption WithConversion(const Operator* conversion_op) { + return Subsumption(Kind::kWithConversion, conversion_op); + } + + bool IsNone() const { return kind_ == Kind::kNone; } + bool IsImplicit() const { return kind_ == Kind::kImplicit; } + bool IsWithConversion() const { return kind_ == Kind::kWithConversion; } + const Operator* conversion_operator() const { + DCHECK(IsWithConversion()); + return conversion_op_; + } + + private: + Subsumption(Kind kind, const Operator* conversion_op) + : kind_(kind), conversion_op_(conversion_op) { + DCHECK_EQ(kind_ == Kind::kWithConversion, conversion_op_ != nullptr); + } + + Kind kind_; + const Operator* conversion_op_; +}; + // Does check {a} subsume check {b}? -bool CheckSubsumes(Node const* a, Node const* b) { +Subsumption CheckSubsumes(Node const* a, Node const* b, + MachineOperatorBuilder* machine) { + Subsumption subsumption = Subsumption::Implicit(); if (a->op() != b->op()) { if (a->opcode() == IrOpcode::kCheckInternalizedString && b->opcode() == IrOpcode::kCheckString) { @@ -149,14 +189,24 @@ bool CheckSubsumes(Node const* a, Node const* b) { b->opcode() == IrOpcode::kCheckedTaggedToArrayIndex) { // CheckedTaggedSignedToInt32(node) implies // CheckedTaggedToArrayIndex(node) + if (machine->Is64()) { + // On 64 bit architectures, ArrayIndex is 64 bit. + subsumption = + Subsumption::WithConversion(machine->ChangeInt32ToInt64()); + } } else if (a->opcode() == IrOpcode::kCheckedTaggedToInt32 && b->opcode() == IrOpcode::kCheckedTaggedToArrayIndex) { // CheckedTaggedToInt32(node) implies CheckedTaggedToArrayIndex(node) + if (machine->Is64()) { + // On 64 bit architectures, ArrayIndex is 64 bit. + subsumption = + Subsumption::WithConversion(machine->ChangeInt32ToInt64()); + } } else if (a->opcode() == IrOpcode::kCheckReceiver && b->opcode() == IrOpcode::kCheckReceiverOrNullOrUndefined) { // CheckReceiver(node) implies CheckReceiverOrNullOrUndefined(node) } else if (a->opcode() != b->opcode()) { - return false; + return Subsumption::None(); } else { switch (a->opcode()) { case IrOpcode::kCheckBounds: @@ -189,7 +239,7 @@ bool CheckSubsumes(Node const* a, Node const* b) { const CheckMinusZeroParameters& bp = CheckMinusZeroParametersOf(b->op()); if (ap.mode() != bp.mode()) { - return false; + return Subsumption::None(); } break; } @@ -203,20 +253,20 @@ bool CheckSubsumes(Node const* a, Node const* b) { // for Number, in which case {b} will be subsumed no matter what. if (ap.mode() != bp.mode() && ap.mode() != CheckTaggedInputMode::kNumber) { - return false; + return Subsumption::None(); } break; } default: DCHECK(!IsCheckedWithFeedback(a->op())); - return false; + return Subsumption::None(); } } } for (int i = a->op()->ValueInputCount(); --i >= 0;) { - if (a->InputAt(i) != b->InputAt(i)) return false; + if (a->InputAt(i) != b->InputAt(i)) return Subsumption::None(); } - return true; + return subsumption; } bool TypeSubsumes(Node* node, Node* replacement) { @@ -232,11 +282,19 @@ bool TypeSubsumes(Node* node, Node* replacement) { } // namespace -Node* RedundancyElimination::EffectPathChecks::LookupCheck(Node* node) const { +Node* RedundancyElimination::EffectPathChecks::LookupCheck( + Node* node, JSGraph* jsgraph) const { for (Check const* check = head_; check != nullptr; check = check->next) { - if (CheckSubsumes(check->node, node) && TypeSubsumes(node, check->node)) { + Subsumption subsumption = + CheckSubsumes(check->node, node, jsgraph->machine()); + if (!subsumption.IsNone() && TypeSubsumes(node, check->node)) { DCHECK(!check->node->IsDead()); - return check->node; + Node* result = check->node; + if (subsumption.IsWithConversion()) { + result = jsgraph->graph()->NewNode(subsumption.conversion_operator(), + result); + } + return result; } } return nullptr; @@ -276,7 +334,7 @@ Reduction RedundancyElimination::ReduceCheckNode(Node* node) { // because we will have to recompute anyway once we compute the predecessor. if (checks == nullptr) return NoChange(); // See if we have another check that dominates us. - if (Node* check = checks->LookupCheck(node)) { + if (Node* check = checks->LookupCheck(node, jsgraph_)) { ReplaceWithValue(node, check); return Replace(check); } |