Commit 76949ba4 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Consume number type hints for strict equality.

This allows us to consume the type hints gathered by the CompareIC
for the strict equality and inequality operators. Similar to abstract
equality We need to distinguish Number and NumberOrOddball feedback,
as strict equality doesn't truncate Oddball to Number.

R=epertoso@chromium.org
BUG=v8:4583

Review-Url: https://codereview.chromium.org/2222993003
Cr-Commit-Position: refs/heads/master@{#38438}
parent f8938e50
...@@ -120,14 +120,14 @@ void JSGenericLowering::ReplaceWithRuntimeCall(Node* node, ...@@ -120,14 +120,14 @@ void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
void JSGenericLowering::LowerJSStrictEqual(Node* node) { void JSGenericLowering::LowerJSStrictEqual(Node* node) {
Callable callable = CodeFactory::StrictEqual(isolate()); Callable callable = CodeFactory::StrictEqual(isolate());
node->AppendInput(zone(), graph()->start()); node->RemoveInput(4); // control
ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags, ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
Operator::kEliminatable); Operator::kEliminatable);
} }
void JSGenericLowering::LowerJSStrictNotEqual(Node* node) { void JSGenericLowering::LowerJSStrictNotEqual(Node* node) {
Callable callable = CodeFactory::StrictNotEqual(isolate()); Callable callable = CodeFactory::StrictNotEqual(isolate());
node->AppendInput(zone(), graph()->start()); node->RemoveInput(4); // control
ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags, ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
Operator::kEliminatable); Operator::kEliminatable);
} }
......
...@@ -579,7 +579,7 @@ const Operator* JSOperatorBuilder::StrictEqual(CompareOperationHints hints) { ...@@ -579,7 +579,7 @@ const Operator* JSOperatorBuilder::StrictEqual(CompareOperationHints hints) {
return new (zone()) Operator1<CompareOperationHints>( //-- return new (zone()) Operator1<CompareOperationHints>( //--
IrOpcode::kJSStrictEqual, Operator::kPure, // opcode IrOpcode::kJSStrictEqual, Operator::kPure, // opcode
"JSStrictEqual", // name "JSStrictEqual", // name
2, 0, 0, 1, 0, 0, // inputs/outputs 2, 1, 1, 1, 1, 0, // inputs/outputs
hints); // parameter hints); // parameter
} }
...@@ -588,7 +588,7 @@ const Operator* JSOperatorBuilder::StrictNotEqual(CompareOperationHints hints) { ...@@ -588,7 +588,7 @@ const Operator* JSOperatorBuilder::StrictNotEqual(CompareOperationHints hints) {
return new (zone()) Operator1<CompareOperationHints>( //-- return new (zone()) Operator1<CompareOperationHints>( //--
IrOpcode::kJSStrictNotEqual, Operator::kPure, // opcode IrOpcode::kJSStrictNotEqual, Operator::kPure, // opcode
"JSStrictNotEqual", // name "JSStrictNotEqual", // name
2, 0, 0, 1, 0, 0, // inputs/outputs 2, 1, 1, 1, 1, 0, // inputs/outputs
hints); // parameter hints); // parameter
} }
......
...@@ -55,9 +55,7 @@ class JSBinopReduction final { ...@@ -55,9 +55,7 @@ class JSBinopReduction final {
bool GetCompareNumberOperationHint(NumberOperationHint* hint) { bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) { if (lowering_->flags() & JSTypedLowering::kDeoptimizationEnabled) {
DCHECK_NE(0, node_->op()->ControlOutputCount());
DCHECK_EQ(1, node_->op()->EffectOutputCount()); DCHECK_EQ(1, node_->op()->EffectOutputCount());
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
CompareOperationHints hints = CompareOperationHintsOf(node_->op()); CompareOperationHints hints = CompareOperationHintsOf(node_->op());
switch (hints.combined()) { switch (hints.combined()) {
case CompareOperationHints::kSignedSmall: case CompareOperationHints::kSignedSmall:
...@@ -175,8 +173,6 @@ class JSBinopReduction final { ...@@ -175,8 +173,6 @@ class JSBinopReduction final {
DCHECK_EQ(1, node_->op()->EffectInputCount()); DCHECK_EQ(1, node_->op()->EffectInputCount());
DCHECK_EQ(1, node_->op()->EffectOutputCount()); DCHECK_EQ(1, node_->op()->EffectOutputCount());
DCHECK_EQ(1, node_->op()->ControlInputCount()); DCHECK_EQ(1, node_->op()->ControlInputCount());
DCHECK_LT(1, node_->op()->ControlOutputCount());
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node_->op()));
DCHECK_EQ(2, node_->op()->ValueInputCount()); DCHECK_EQ(2, node_->op()->ValueInputCount());
// Reconnect the control output to bypass the IfSuccess node and // Reconnect the control output to bypass the IfSuccess node and
...@@ -196,7 +192,9 @@ class JSBinopReduction final { ...@@ -196,7 +192,9 @@ class JSBinopReduction final {
} }
// Remove the frame state and the context. // Remove the frame state and the context.
node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_)); if (OperatorProperties::HasFrameStateInput(node_->op())) {
node_->RemoveInput(NodeProperties::FirstFrameStateIndex(node_));
}
node_->RemoveInput(NodeProperties::FirstContextIndex(node_)); node_->RemoveInput(NodeProperties::FirstContextIndex(node_));
NodeProperties::ChangeOp(node_, op); NodeProperties::ChangeOp(node_, op);
...@@ -694,6 +692,7 @@ Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { ...@@ -694,6 +692,7 @@ Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
if (invert) { if (invert) {
replacement = graph()->NewNode(simplified()->BooleanNot(), replacement); replacement = graph()->NewNode(simplified()->BooleanNot(), replacement);
} }
ReplaceWithValue(node, replacement);
return Replace(replacement); return Replace(replacement);
} }
return NoChange(); return NoChange();
...@@ -701,10 +700,7 @@ Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) { ...@@ -701,10 +700,7 @@ Reduction JSTypedLowering::ReduceJSEqualTypeOf(Node* node, bool invert) {
Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) { Reduction JSTypedLowering::ReduceJSEqual(Node* node, bool invert) {
Reduction const reduction = ReduceJSEqualTypeOf(node, invert); Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
if (reduction.Changed()) { if (reduction.Changed()) return reduction;
ReplaceWithValue(node, reduction.replacement());
return reduction;
}
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
...@@ -769,10 +765,10 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { ...@@ -769,10 +765,10 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
return Replace(replacement); return Replace(replacement);
} }
} }
Reduction const reduction = ReduceJSEqualTypeOf(node, invert); Reduction const reduction = ReduceJSEqualTypeOf(node, invert);
if (reduction.Changed()) { if (reduction.Changed()) return reduction;
return reduction;
}
if (r.OneInputIs(the_hole_type_)) { if (r.OneInputIs(the_hole_type_)) {
return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_), return r.ChangeToPureOperator(simplified()->ReferenceEqual(the_hole_type_),
invert); invert);
...@@ -804,10 +800,17 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) { ...@@ -804,10 +800,17 @@ Reduction JSTypedLowering::ReduceJSStrictEqual(Node* node, bool invert) {
if (r.BothInputsAre(Type::String())) { if (r.BothInputsAre(Type::String())) {
return r.ChangeToPureOperator(simplified()->StringEqual(), invert); return r.ChangeToPureOperator(simplified()->StringEqual(), invert);
} }
if (r.BothInputsAre(Type::Number())) {
NumberOperationHint hint;
if (r.BothInputsAre(Type::Signed32()) ||
r.BothInputsAre(Type::Unsigned32())) {
return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
} else if (r.GetCompareNumberOperationHint(&hint)) {
return r.ChangeToSpeculativeOperator(
simplified()->SpeculativeNumberEqual(hint), invert, Type::Boolean());
} else if (r.BothInputsAre(Type::Number())) {
return r.ChangeToPureOperator(simplified()->NumberEqual(), invert); return r.ChangeToPureOperator(simplified()->NumberEqual(), invert);
} }
// TODO(turbofan): js-typed-lowering of StrictEqual(mixed types)
return NoChange(); return NoChange();
} }
......
...@@ -390,11 +390,13 @@ TEST_F(JSTypedLoweringTest, JSToStringWithBoolean) { ...@@ -390,11 +390,13 @@ TEST_F(JSTypedLoweringTest, JSToStringWithBoolean) {
TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) {
Node* const the_hole = HeapConstant(factory()->the_hole_value()); Node* const the_hole = HeapConstant(factory()->the_hole_value());
Node* const context = UndefinedConstant(); Node* const context = UndefinedConstant();
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FOREACH(Type*, type, kJSTypes) { TRACED_FOREACH(Type*, type, kJSTypes) {
Node* const lhs = Parameter(type); Node* const lhs = Parameter(type);
Reduction r = Reduce(graph()->NewNode( Reduction r = Reduce(graph()->NewNode(
javascript()->StrictEqual(CompareOperationHints::Any()), lhs, the_hole, javascript()->StrictEqual(CompareOperationHints::Any()), lhs, the_hole,
context)); context, effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsFalseConstant()); EXPECT_THAT(r.replacement(), IsFalseConstant());
} }
...@@ -405,9 +407,11 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) { ...@@ -405,9 +407,11 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithUnique) {
Node* const lhs = Parameter(Type::Unique(), 0); Node* const lhs = Parameter(Type::Unique(), 0);
Node* const rhs = Parameter(Type::Unique(), 1); Node* const rhs = Parameter(Type::Unique(), 1);
Node* const context = Parameter(Type::Any(), 2); Node* const context = Parameter(Type::Any(), 2);
Node* const effect = graph()->start();
Node* const control = graph()->start();
Reduction r = Reduce( Reduction r = Reduce(
graph()->NewNode(javascript()->StrictEqual(CompareOperationHints::Any()), graph()->NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
lhs, rhs, context)); lhs, rhs, context, effect, control));
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs)); EXPECT_THAT(r.replacement(), IsReferenceEqual(Type::Unique(), lhs, rhs));
} }
......
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