Commit 2fdf33bb authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce dedicated NumberConvertHoleNaN simplified operator.

This is part of the fixes required to make type feedback viable for
TurboFan on Octane.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2065953002
Cr-Commit-Position: refs/heads/master@{#36966}
parent d9e8764f
...@@ -790,9 +790,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -790,9 +790,6 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
this_value = graph()->NewNode(simplified()->TypeGuard(element_type), this_value = graph()->NewNode(simplified()->TypeGuard(element_type),
this_value, this_control); this_value, this_control);
} else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
// Perform the hole check on the result.
Node* check =
graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value);
// Check if we are allowed to return the hole directly. // Check if we are allowed to return the hole directly.
Type* initial_holey_array_type = Type::Class( Type* initial_holey_array_type = Type::Class(
handle(isolate()->get_initial_js_array_map(elements_kind)), handle(isolate()->get_initial_js_array_map(elements_kind)),
...@@ -804,11 +801,12 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess( ...@@ -804,11 +801,12 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
isolate()->initial_object_prototype()); isolate()->initial_object_prototype());
dependencies()->AssumePropertyCell(factory()->array_protector()); dependencies()->AssumePropertyCell(factory()->array_protector());
// Turn the hole into undefined. // Turn the hole into undefined.
this_value = graph()->NewNode( this_value = graph()->NewNode(simplified()->NumberConvertHoleNaN(),
common()->Select(MachineRepresentation::kTagged, this_value);
BranchHint::kFalse),
check, jsgraph()->UndefinedConstant(), this_value);
} else { } else {
// Perform the hole check on the result.
Node* check =
graph()->NewNode(simplified()->NumberIsHoleNaN(), this_value);
// Deoptimize in case of the hole. // Deoptimize in case of the hole.
this_control = this_effect = this_control = this_effect =
graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, graph()->NewNode(common()->DeoptimizeIf(), check, frame_state,
......
...@@ -805,21 +805,6 @@ Reduction JSTypedLowering::ReduceJSToLength(Node* node) { ...@@ -805,21 +805,6 @@ Reduction JSTypedLowering::ReduceJSToLength(Node* node) {
} }
Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) { Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
// Check for ToNumber truncation of signaling NaN to undefined mapping.
if (input->opcode() == IrOpcode::kSelect) {
Node* check = NodeProperties::GetValueInput(input, 0);
Node* vtrue = NodeProperties::GetValueInput(input, 1);
Type* vtrue_type = NodeProperties::GetType(vtrue);
Node* vfalse = NodeProperties::GetValueInput(input, 2);
Type* vfalse_type = NodeProperties::GetType(vfalse);
if (vtrue_type->Is(Type::Undefined()) && vfalse_type->Is(Type::Number())) {
if (check->opcode() == IrOpcode::kNumberIsHoleNaN &&
check->InputAt(0) == vfalse) {
// JSToNumber(Select(NumberIsHoleNaN(x), y:undefined, x:number)) => x
return Replace(vfalse);
}
}
}
// Try constant-folding of JSToNumber with constant inputs. // Try constant-folding of JSToNumber with constant inputs.
Type* input_type = NodeProperties::GetType(input); Type* input_type = NodeProperties::GetType(input);
if (input_type->IsConstant()) { if (input_type->IsConstant()) {
......
...@@ -207,6 +207,7 @@ ...@@ -207,6 +207,7 @@
V(NumberToUint32) \ V(NumberToUint32) \
V(NumberIsHoleNaN) \ V(NumberIsHoleNaN) \
V(NumberSilenceNaN) \ V(NumberSilenceNaN) \
V(NumberConvertHoleNaN) \
V(StringFromCharCode) \ V(StringFromCharCode) \
V(StringToNumber) \ V(StringToNumber) \
V(ChangeTaggedSignedToInt32) \ V(ChangeTaggedSignedToInt32) \
......
...@@ -1449,6 +1449,41 @@ class RepresentationSelector { ...@@ -1449,6 +1449,41 @@ class RepresentationSelector {
} }
return; return;
} }
case IrOpcode::kNumberConvertHoleNaN: {
if (truncation.TruncatesToFloat64()) {
// NumberConvertHoleNaN(x) => x
VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kTagged);
if (lower()) {
// NumberConvertHoleNaN(x) =>
// Select(Word32Equal(Float64ExtractHighWord32(x),
// #HoleNanUpper32),
// #Undefined,
// ChangeFloat64ToTagged(x))
Node* value = node->InputAt(0);
node->ReplaceInput(
0,
jsgraph_->graph()->NewNode(
jsgraph_->machine()->Word32Equal(),
jsgraph_->graph()->NewNode(
jsgraph_->machine()->Float64ExtractHighWord32(), value),
jsgraph_->Int32Constant(kHoleNanUpper32)));
node->AppendInput(jsgraph_->zone(), jsgraph_->UndefinedConstant());
node->AppendInput(
jsgraph_->zone(),
jsgraph_->graph()->NewNode(
jsgraph_->simplified()->ChangeFloat64ToTagged(), value));
NodeProperties::ChangeOp(
node, jsgraph_->common()->Select(MachineRepresentation::kTagged,
BranchHint::kFalse));
}
}
return;
}
case IrOpcode::kReferenceEqual: { case IrOpcode::kReferenceEqual: {
VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
if (lower()) { if (lower()) {
......
...@@ -214,6 +214,7 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) { ...@@ -214,6 +214,7 @@ BinaryOperationHints::Hint BinaryOperationHintOf(const Operator* op) {
V(NumberToUint32, Operator::kNoProperties, 1) \ V(NumberToUint32, Operator::kNoProperties, 1) \
V(NumberIsHoleNaN, Operator::kNoProperties, 1) \ V(NumberIsHoleNaN, Operator::kNoProperties, 1) \
V(NumberSilenceNaN, Operator::kNoProperties, 1) \ V(NumberSilenceNaN, Operator::kNoProperties, 1) \
V(NumberConvertHoleNaN, Operator::kNoProperties, 1) \
V(StringFromCharCode, Operator::kNoProperties, 1) \ V(StringFromCharCode, Operator::kNoProperties, 1) \
V(StringToNumber, Operator::kNoProperties, 1) \ V(StringToNumber, Operator::kNoProperties, 1) \
V(PlainPrimitiveToNumber, Operator::kNoWrite, 1) \ V(PlainPrimitiveToNumber, Operator::kNoWrite, 1) \
......
...@@ -163,6 +163,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject { ...@@ -163,6 +163,7 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* NumberToInt32(); const Operator* NumberToInt32();
const Operator* NumberToUint32(); const Operator* NumberToUint32();
const Operator* NumberIsHoleNaN(); const Operator* NumberIsHoleNaN();
const Operator* NumberConvertHoleNaN();
const Operator* NumberSilenceNaN(); const Operator* NumberSilenceNaN();
......
...@@ -248,6 +248,7 @@ class Typer::Visitor : public Reducer { ...@@ -248,6 +248,7 @@ class Typer::Visitor : public Reducer {
static Type* NumberTrunc(Type*, Typer*); static Type* NumberTrunc(Type*, Typer*);
static Type* NumberToInt32(Type*, Typer*); static Type* NumberToInt32(Type*, Typer*);
static Type* NumberToUint32(Type*, Typer*); static Type* NumberToUint32(Type*, Typer*);
static Type* NumberConvertHoleNaN(Type*, Typer*);
static Type* ObjectIsCallable(Type*, Typer*); static Type* ObjectIsCallable(Type*, Typer*);
static Type* ObjectIsNumber(Type*, Typer*); static Type* ObjectIsNumber(Type*, Typer*);
...@@ -556,6 +557,10 @@ Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) { ...@@ -556,6 +557,10 @@ Type* Typer::Visitor::NumberToUint32(Type* type, Typer* t) {
return Type::Unsigned32(); return Type::Unsigned32();
} }
Type* Typer::Visitor::NumberConvertHoleNaN(Type* type, Typer* t) {
return Type::Union(type, Type::Undefined(), t->zone());
}
// Type checks. // Type checks.
Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) { Type* Typer::Visitor::ObjectIsCallable(Type* type, Typer* t) {
...@@ -1813,6 +1818,10 @@ Type* Typer::Visitor::TypeNumberIsHoleNaN(Node* node) { ...@@ -1813,6 +1818,10 @@ Type* Typer::Visitor::TypeNumberIsHoleNaN(Node* node) {
return Type::Boolean(); return Type::Boolean();
} }
Type* Typer::Visitor::TypeNumberConvertHoleNaN(Node* node) {
return TypeUnaryOp(node, NumberConvertHoleNaN);
}
// static // static
Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) { Type* Typer::Visitor::ReferenceEqualTyper(Type* lhs, Type* rhs, Typer* t) {
if (lhs->IsConstant() && rhs->Is(lhs)) { if (lhs->IsConstant() && rhs->Is(lhs)) {
......
...@@ -770,6 +770,11 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -770,6 +770,11 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Number()); CheckValueInputIs(node, 0, Type::Number());
CheckUpperIs(node, Type::Boolean()); CheckUpperIs(node, Type::Boolean());
break; break;
case IrOpcode::kNumberConvertHoleNaN:
// Number -> Number \/ Undefined
CheckValueInputIs(node, 0, Type::Number());
CheckUpperIs(node, Type::NumberOrUndefined());
break;
case IrOpcode::kPlainPrimitiveToNumber: case IrOpcode::kPlainPrimitiveToNumber:
// Type is Number. // Type is Number.
CheckUpperIs(node, Type::Number()); CheckUpperIs(node, Type::Number());
......
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