Commit cdc7bd61 authored by Jaroslav Sevcik's avatar Jaroslav Sevcik Committed by Commit Bot

[turbofan] Inline SameValue for numbers

Bug: v8:9113
Change-Id: I413d9df34f0bdea9c30db33ad79891218e229341
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1564053Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60776}
parent 97591e39
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "src/compiler/node.h" #include "src/compiler/node.h"
#include "src/compiler/schedule.h" #include "src/compiler/schedule.h"
#include "src/heap/factory-inl.h" #include "src/heap/factory-inl.h"
#include "src/machine-type.h"
#include "src/objects/heap-number.h" #include "src/objects/heap-number.h"
#include "src/objects/oddball.h" #include "src/objects/oddball.h"
#include "src/objects/ordered-hash-table.h" #include "src/objects/ordered-hash-table.h"
...@@ -904,6 +905,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, ...@@ -904,6 +905,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kSameValue: case IrOpcode::kSameValue:
result = LowerSameValue(node); result = LowerSameValue(node);
break; break;
case IrOpcode::kNumberSameValue:
result = LowerNumberSameValue(node);
break;
case IrOpcode::kDeadValue: case IrOpcode::kDeadValue:
result = LowerDeadValue(node); result = LowerDeadValue(node);
break; break;
...@@ -3439,6 +3443,31 @@ Node* EffectControlLinearizer::LowerSameValue(Node* node) { ...@@ -3439,6 +3443,31 @@ Node* EffectControlLinearizer::LowerSameValue(Node* node) {
__ NoContextConstant()); __ NoContextConstant());
} }
Node* EffectControlLinearizer::LowerNumberSameValue(Node* node) {
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
auto is_float64_equal = __ MakeLabel();
auto done = __ MakeLabel(MachineRepresentation::kBit);
__ GotoIf(__ Float64Equal(lhs, rhs), &is_float64_equal);
// Return true iff both {lhs} and {rhs} are NaN.
__ GotoIf(__ Float64Equal(lhs, lhs), &done, __ Int32Constant(0));
__ GotoIf(__ Float64Equal(rhs, rhs), &done, __ Int32Constant(0));
__ Goto(&done, __ Int32Constant(1));
__ Bind(&is_float64_equal);
// Even if the values are float64-equal, we still need to distinguish
// zero and minus zero.
Node* lhs_hi = __ Float64ExtractHighWord32(lhs);
Node* rhs_hi = __ Float64ExtractHighWord32(rhs);
__ Goto(&done, __ Word32Equal(lhs_hi, rhs_hi));
__ Bind(&done);
return done.PhiAt(0);
}
Node* EffectControlLinearizer::LowerDeadValue(Node* node) { Node* EffectControlLinearizer::LowerDeadValue(Node* node) {
Node* input = NodeProperties::GetValueInput(node, 0); Node* input = NodeProperties::GetValueInput(node, 0);
if (input->opcode() != IrOpcode::kUnreachable) { if (input->opcode() != IrOpcode::kUnreachable) {
......
...@@ -146,6 +146,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer { ...@@ -146,6 +146,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerNewConsTwoByteString(Node* node); Node* LowerNewConsTwoByteString(Node* node);
Node* LowerNewConsString(Node* node); Node* LowerNewConsString(Node* node);
Node* LowerSameValue(Node* node); Node* LowerSameValue(Node* node);
Node* LowerNumberSameValue(Node* node);
Node* LowerDeadValue(Node* node); Node* LowerDeadValue(Node* node);
Node* LowerStringConcat(Node* node); Node* LowerStringConcat(Node* node);
Node* LowerStringToNumber(Node* node); Node* LowerStringToNumber(Node* node);
......
...@@ -293,6 +293,7 @@ ...@@ -293,6 +293,7 @@
V(SpeculativeNumberLessThanOrEqual) \ V(SpeculativeNumberLessThanOrEqual) \
V(ReferenceEqual) \ V(ReferenceEqual) \
V(SameValue) \ V(SameValue) \
V(NumberSameValue) \
V(StringEqual) \ V(StringEqual) \
V(StringLessThan) \ V(StringLessThan) \
V(StringLessThanOrEqual) V(StringLessThanOrEqual)
......
...@@ -2582,8 +2582,17 @@ class RepresentationSelector { ...@@ -2582,8 +2582,17 @@ class RepresentationSelector {
} }
case IrOpcode::kSameValue: { case IrOpcode::kSameValue: {
if (truncation.IsUnused()) return VisitUnused(node); if (truncation.IsUnused()) return VisitUnused(node);
if (BothInputsAre(node, Type::Number())) {
VisitBinop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kBit);
if (lower()) {
NodeProperties::ChangeOp(node,
lowering->simplified()->NumberSameValue());
}
} else {
VisitBinop(node, UseInfo::AnyTagged(), VisitBinop(node, UseInfo::AnyTagged(),
MachineRepresentation::kTaggedPointer); MachineRepresentation::kTaggedPointer);
}
return; return;
} }
case IrOpcode::kTypeOf: { case IrOpcode::kTypeOf: {
......
...@@ -736,6 +736,7 @@ bool operator==(CheckMinusZeroParameters const& lhs, ...@@ -736,6 +736,7 @@ bool operator==(CheckMinusZeroParameters const& lhs,
V(ObjectIsInteger, Operator::kNoProperties, 1, 0) \ V(ObjectIsInteger, Operator::kNoProperties, 1, 0) \
V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \ V(ConvertTaggedHoleToUndefined, Operator::kNoProperties, 1, 0) \
V(SameValue, Operator::kCommutative, 2, 0) \ V(SameValue, Operator::kCommutative, 2, 0) \
V(NumberSameValue, Operator::kCommutative, 2, 0) \
V(ReferenceEqual, Operator::kCommutative, 2, 0) \ V(ReferenceEqual, Operator::kCommutative, 2, 0) \
V(StringEqual, Operator::kCommutative, 2, 0) \ V(StringEqual, Operator::kCommutative, 2, 0) \
V(StringLessThan, Operator::kNoProperties, 2, 0) \ V(StringLessThan, Operator::kNoProperties, 2, 0) \
......
...@@ -541,6 +541,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -541,6 +541,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* BooleanNot(); const Operator* BooleanNot();
const Operator* NumberEqual(); const Operator* NumberEqual();
const Operator* NumberSameValue();
const Operator* NumberLessThan(); const Operator* NumberLessThan();
const Operator* NumberLessThanOrEqual(); const Operator* NumberLessThanOrEqual();
const Operator* NumberAdd(); const Operator* NumberAdd();
......
...@@ -1996,6 +1996,8 @@ Type Typer::Visitor::TypeSameValue(Node* node) { ...@@ -1996,6 +1996,8 @@ Type Typer::Visitor::TypeSameValue(Node* node) {
return TypeBinaryOp(node, SameValueTyper); return TypeBinaryOp(node, SameValueTyper);
} }
Type Typer::Visitor::TypeNumberSameValue(Node* node) { UNREACHABLE(); }
Type Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); } Type Typer::Visitor::TypeStringEqual(Node* node) { return Type::Boolean(); }
Type Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); } Type Typer::Visitor::TypeStringLessThan(Node* node) { return Type::Boolean(); }
......
...@@ -1190,7 +1190,12 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) { ...@@ -1190,7 +1190,12 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
CheckValueInputIs(node, 1, Type::Any()); CheckValueInputIs(node, 1, Type::Any());
CheckTypeIs(node, Type::Boolean()); CheckTypeIs(node, Type::Boolean());
break; break;
case IrOpcode::kNumberSameValue:
// (Number, Number) -> Boolean
CheckValueInputIs(node, 0, Type::Number());
CheckValueInputIs(node, 1, Type::Number());
CheckTypeIs(node, Type::Boolean());
break;
case IrOpcode::kObjectIsArrayBufferView: case IrOpcode::kObjectIsArrayBufferView:
case IrOpcode::kObjectIsBigInt: case IrOpcode::kObjectIsBigInt:
case IrOpcode::kObjectIsCallable: case IrOpcode::kObjectIsCallable:
......
...@@ -185,3 +185,33 @@ ...@@ -185,3 +185,33 @@
%OptimizeFunctionOnNextCall(foo); %OptimizeFunctionOnNextCall(foo);
assertFalse(foo()); assertFalse(foo());
})(); })();
(function() {
function foo(a, b) { return Object.is(+a, +b); }
%PrepareFunctionForOptimization(foo);
assertFalse(foo(1, 2));
assertFalse(foo(0, -0));
assertFalse(foo(-0, 0));
assertFalse(foo(-0, 1));
assertFalse(foo(-0, 1));
assertFalse(foo(-Infinity, Infinity));
assertTrue(foo(0, 0));
assertTrue(foo(0.1, 0.1));
assertTrue(foo(Infinity, Infinity));
assertTrue(foo(-0, -0));
assertTrue(foo(NaN, NaN));
assertFalse(foo(Infinity, NaN));
%OptimizeFunctionOnNextCall(foo);
assertFalse(foo(1, 2));
assertFalse(foo(0, -0));
assertFalse(foo(-0, 0));
assertFalse(foo(-0, 1));
assertFalse(foo(-0, 1));
assertFalse(foo(-Infinity, Infinity));
assertTrue(foo(0, 0));
assertTrue(foo(0.1, 0.1));
assertTrue(foo(Infinity, Infinity));
assertTrue(foo(-0, -0));
assertTrue(foo(NaN, NaN));
assertFalse(foo(Infinity, NaN));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment