[turbofan] Unify BooleanToNumber, StringToNumber and PlainPrimitiveToNumber.
The PlainPrimitiveToNumber operator performs a superset of the operations previously performed by the BooleanToNumber and StringToNumber operators, so we can just use the special lowering rules for PlainPrimitiveToNumber based on the input type and get rid of the specialized operators. R=jarin@chromium.org Review-Url: https://codereview.chromium.org/2139183002 Cr-Commit-Position: refs/heads/master@{#37669}
This commit is contained in:
parent
e92e911814
commit
85969edead
@ -928,14 +928,6 @@ Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
|
||||
// JSToNumber(null) => #0
|
||||
return Replace(jsgraph()->ZeroConstant());
|
||||
}
|
||||
if (input_type->Is(Type::Boolean())) {
|
||||
// JSToNumber(x:boolean) => BooleanToNumber(x)
|
||||
return Replace(graph()->NewNode(simplified()->BooleanToNumber(), input));
|
||||
}
|
||||
if (input_type->Is(Type::String())) {
|
||||
// JSToNumber(x:string) => StringToNumber(x)
|
||||
return Replace(graph()->NewNode(simplified()->StringToNumber(), input));
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,6 @@
|
||||
V(PlainPrimitiveToWord32) \
|
||||
V(PlainPrimitiveToFloat64) \
|
||||
V(BooleanNot) \
|
||||
V(BooleanToNumber) \
|
||||
V(SpeculativeNumberAdd) \
|
||||
V(SpeculativeNumberSubtract) \
|
||||
V(SpeculativeNumberMultiply) \
|
||||
@ -256,7 +255,6 @@
|
||||
V(NumberToUint32) \
|
||||
V(NumberSilenceNaN) \
|
||||
V(StringFromCharCode) \
|
||||
V(StringToNumber) \
|
||||
V(CheckBounds) \
|
||||
V(CheckIf) \
|
||||
V(CheckNumber) \
|
||||
|
@ -1245,24 +1245,6 @@ class RepresentationSelector {
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kBooleanToNumber: {
|
||||
if (lower()) {
|
||||
NodeInfo* input_info = GetInfo(node->InputAt(0));
|
||||
if (input_info->representation() == MachineRepresentation::kBit) {
|
||||
// BooleanToNumber(x: kRepBit) => x
|
||||
DeferReplacement(node, node->InputAt(0));
|
||||
} else {
|
||||
// BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
|
||||
node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
|
||||
NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
|
||||
}
|
||||
} else {
|
||||
// No input representation requirement; adapt during lowering.
|
||||
ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
|
||||
SetOutput(node, MachineRepresentation::kWord32);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kNumberEqual:
|
||||
case IrOpcode::kNumberLessThan:
|
||||
case IrOpcode::kNumberLessThanOrEqual: {
|
||||
@ -1790,24 +1772,6 @@ class RepresentationSelector {
|
||||
MachineRepresentation::kTagged);
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kStringToNumber: {
|
||||
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
|
||||
if (lower()) {
|
||||
// StringToNumber(x) => Call(StringToNumber, x, no-context)
|
||||
Operator::Properties properties = Operator::kEliminatable;
|
||||
Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
|
||||
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
|
||||
flags, properties);
|
||||
node->InsertInput(jsgraph_->zone(), 0,
|
||||
jsgraph_->HeapConstant(callable.code()));
|
||||
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
|
||||
node->AppendInput(jsgraph_->zone(), jsgraph_->graph()->start());
|
||||
NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case IrOpcode::kCheckBounds: {
|
||||
if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) {
|
||||
@ -1995,8 +1959,14 @@ class RepresentationSelector {
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kPlainPrimitiveToNumber:
|
||||
if (truncation.TruncatesToWord32()) {
|
||||
case IrOpcode::kPlainPrimitiveToNumber: {
|
||||
if (InputIs(node, Type::Boolean())) {
|
||||
VisitUnop(node, UseInfo::Bool(), MachineRepresentation::kWord32);
|
||||
if (lower()) DeferReplacement(node, node->InputAt(0));
|
||||
} else if (InputIs(node, Type::String())) {
|
||||
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
|
||||
if (lower()) lowering->DoStringToNumber(node);
|
||||
} else if (truncation.TruncatesToWord32()) {
|
||||
// TODO(jarin): Extend this to Number \/ Oddball
|
||||
if (InputIs(node, Type::NumberOrUndefined())) {
|
||||
VisitUnop(node, UseInfo::TruncatingWord32(),
|
||||
@ -2028,6 +1998,7 @@ class RepresentationSelector {
|
||||
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case IrOpcode::kObjectIsCallable:
|
||||
case IrOpcode::kObjectIsNumber:
|
||||
case IrOpcode::kObjectIsReceiver:
|
||||
@ -3270,6 +3241,19 @@ void SimplifiedLowering::DoShift(Node* node, Operator const* op,
|
||||
NodeProperties::ChangeOp(node, op);
|
||||
}
|
||||
|
||||
void SimplifiedLowering::DoStringToNumber(Node* node) {
|
||||
Operator::Properties properties = Operator::kEliminatable;
|
||||
Callable callable = CodeFactory::StringToNumber(isolate());
|
||||
CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
|
||||
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
|
||||
isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties);
|
||||
node->InsertInput(graph()->zone(), 0,
|
||||
jsgraph()->HeapConstant(callable.code()));
|
||||
node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant());
|
||||
node->AppendInput(graph()->zone(), graph()->start());
|
||||
NodeProperties::ChangeOp(node, common()->Call(desc));
|
||||
}
|
||||
|
||||
Node* SimplifiedLowering::ToNumberCode() {
|
||||
if (!to_number_code_.is_set()) {
|
||||
Callable callable = CodeFactory::ToNumber(isolate());
|
||||
|
@ -42,6 +42,7 @@ class SimplifiedLowering final {
|
||||
RepresentationChanger* changer);
|
||||
void DoStoreBuffer(Node* node);
|
||||
void DoShift(Node* node, Operator const* op, Type* rhs_type);
|
||||
void DoStringToNumber(Node* node);
|
||||
|
||||
private:
|
||||
JSGraph* const jsgraph_;
|
||||
|
@ -230,7 +230,6 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
|
||||
|
||||
#define PURE_OP_LIST(V) \
|
||||
V(BooleanNot, Operator::kNoProperties, 1) \
|
||||
V(BooleanToNumber, Operator::kNoProperties, 1) \
|
||||
V(NumberEqual, Operator::kCommutative, 2) \
|
||||
V(NumberLessThan, Operator::kNoProperties, 2) \
|
||||
V(NumberLessThanOrEqual, Operator::kNoProperties, 2) \
|
||||
@ -280,7 +279,6 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
|
||||
V(NumberToUint32, Operator::kNoProperties, 1) \
|
||||
V(NumberSilenceNaN, Operator::kNoProperties, 1) \
|
||||
V(StringFromCharCode, Operator::kNoProperties, 1) \
|
||||
V(StringToNumber, Operator::kNoProperties, 1) \
|
||||
V(PlainPrimitiveToNumber, Operator::kNoProperties, 1) \
|
||||
V(PlainPrimitiveToWord32, Operator::kNoProperties, 1) \
|
||||
V(PlainPrimitiveToFloat64, Operator::kNoProperties, 1) \
|
||||
|
@ -158,7 +158,6 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
|
||||
explicit SimplifiedOperatorBuilder(Zone* zone);
|
||||
|
||||
const Operator* BooleanNot();
|
||||
const Operator* BooleanToNumber();
|
||||
|
||||
const Operator* NumberEqual();
|
||||
const Operator* NumberLessThan();
|
||||
@ -227,7 +226,6 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
|
||||
const Operator* StringLessThan();
|
||||
const Operator* StringLessThanOrEqual();
|
||||
const Operator* StringFromCharCode();
|
||||
const Operator* StringToNumber();
|
||||
|
||||
const Operator* PlainPrimitiveToNumber();
|
||||
const Operator* PlainPrimitiveToWord32();
|
||||
|
@ -1551,10 +1551,6 @@ Type* Typer::Visitor::TypeJSStackCheck(Node* node) { return Type::Any(); }
|
||||
|
||||
Type* Typer::Visitor::TypeBooleanNot(Node* node) { return Type::Boolean(); }
|
||||
|
||||
Type* Typer::Visitor::TypeBooleanToNumber(Node* node) {
|
||||
return TypeUnaryOp(node, ToNumber);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeNumberEqual(Node* node) { return Type::Boolean(); }
|
||||
|
||||
Type* Typer::Visitor::TypeNumberLessThan(Node* node) { return Type::Boolean(); }
|
||||
@ -1773,10 +1769,6 @@ Type* Typer::Visitor::TypeStringFromCharCode(Node* node) {
|
||||
return TypeUnaryOp(node, StringFromCharCodeTyper);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeStringToNumber(Node* node) {
|
||||
return TypeUnaryOp(node, ToNumber);
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeCheckBounds(Node* node) {
|
||||
// TODO(bmeurer): We could do better here based on the limit.
|
||||
return Type::Unsigned31();
|
||||
|
@ -664,11 +664,6 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckValueInputIs(node, 0, Type::Boolean());
|
||||
CheckUpperIs(node, Type::Boolean());
|
||||
break;
|
||||
case IrOpcode::kBooleanToNumber:
|
||||
// Boolean -> Number
|
||||
CheckValueInputIs(node, 0, Type::Boolean());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kNumberEqual:
|
||||
// (Number, Number) -> Boolean
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
@ -790,13 +785,18 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckUpperIs(node, Type::Unsigned32());
|
||||
break;
|
||||
case IrOpcode::kPlainPrimitiveToNumber:
|
||||
// Type is Number.
|
||||
// PlainPrimitive -> Number
|
||||
CheckValueInputIs(node, 0, Type::PlainPrimitive());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kPlainPrimitiveToWord32:
|
||||
CheckUpperIs(node, Type::Number());
|
||||
// PlainPrimitive -> Integral32
|
||||
CheckValueInputIs(node, 0, Type::PlainPrimitive());
|
||||
CheckUpperIs(node, Type::Integral32());
|
||||
break;
|
||||
case IrOpcode::kPlainPrimitiveToFloat64:
|
||||
// PlainPrimitive -> Number
|
||||
CheckValueInputIs(node, 0, Type::PlainPrimitive());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kStringEqual:
|
||||
@ -812,11 +812,6 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckValueInputIs(node, 0, Type::Number());
|
||||
CheckUpperIs(node, Type::String());
|
||||
break;
|
||||
case IrOpcode::kStringToNumber:
|
||||
// String -> Number
|
||||
CheckValueInputIs(node, 0, Type::String());
|
||||
CheckUpperIs(node, Type::Number());
|
||||
break;
|
||||
case IrOpcode::kReferenceEqual: {
|
||||
// (Unique, Any) -> Boolean and
|
||||
// (Any, Unique) -> Boolean
|
||||
|
@ -612,9 +612,6 @@ TEST(StringComparison) {
|
||||
static void CheckIsConvertedToNumber(Node* val, Node* converted) {
|
||||
if (NodeProperties::GetType(val)->Is(Type::Number())) {
|
||||
CHECK_EQ(val, converted);
|
||||
} else if (NodeProperties::GetType(val)->Is(Type::Boolean())) {
|
||||
CHECK_EQ(IrOpcode::kBooleanToNumber, converted->opcode());
|
||||
CHECK_EQ(val, converted->InputAt(0));
|
||||
} else {
|
||||
if (converted->opcode() == IrOpcode::kNumberConstant) return;
|
||||
CHECK_EQ(IrOpcode::kJSToNumber, converted->opcode());
|
||||
@ -1001,7 +998,8 @@ TEST(OrderCompareEffects) {
|
||||
JSTypedLowering::kNoFlags);
|
||||
CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode());
|
||||
|
||||
Node* i0 = B.CheckConvertedInput(IrOpcode::kStringToNumber, 0, false);
|
||||
Node* i0 =
|
||||
B.CheckConvertedInput(IrOpcode::kPlainPrimitiveToNumber, 0, false);
|
||||
Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);
|
||||
|
||||
// Inputs should be commuted.
|
||||
|
@ -899,63 +899,6 @@ TEST(LowerBooleanNot_tagged_tagged) {
|
||||
CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerBooleanToNumber_bit_int32) {
|
||||
// BooleanToNumber(x: kRepBit) used as MachineType::Int32()
|
||||
TestingGraph t(Type::Boolean());
|
||||
Node* b = t.ExampleWithOutput(MachineType::Bool());
|
||||
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
|
||||
Node* use = t.Use(cnv, MachineType::Int32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CHECK_EQ(b, use->InputAt(0));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerBooleanToNumber_tagged_int32) {
|
||||
// BooleanToNumber(x: kRepTagged) used as MachineType::Int32()
|
||||
TestingGraph t(Type::Boolean());
|
||||
Node* b = t.p0;
|
||||
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
|
||||
Node* use = t.Use(cnv, MachineType::Int32());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
|
||||
CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
|
||||
Node* c = t.jsgraph.TrueConstant();
|
||||
CHECK(c == cnv->InputAt(0) || c == cnv->InputAt(1));
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerBooleanToNumber_bit_tagged) {
|
||||
// BooleanToNumber(x: kRepBit) used as MachineType::AnyTagged()
|
||||
TestingGraph t(Type::Boolean());
|
||||
Node* b = t.ExampleWithOutput(MachineType::Bool());
|
||||
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
|
||||
Node* use = t.Use(cnv, MachineType::AnyTagged());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CHECK_EQ(b, use->InputAt(0)->InputAt(0));
|
||||
CHECK_EQ(IrOpcode::kChangeInt31ToTaggedSigned, use->InputAt(0)->opcode());
|
||||
}
|
||||
|
||||
|
||||
TEST(LowerBooleanToNumber_tagged_tagged) {
|
||||
// BooleanToNumber(x: kRepTagged) used as MachineType::AnyTagged()
|
||||
TestingGraph t(Type::Boolean());
|
||||
Node* b = t.p0;
|
||||
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
|
||||
Node* use = t.Use(cnv, MachineType::AnyTagged());
|
||||
t.Return(use);
|
||||
t.Lower();
|
||||
CHECK_EQ(cnv, use->InputAt(0)->InputAt(0));
|
||||
CHECK_EQ(IrOpcode::kChangeInt31ToTaggedSigned, use->InputAt(0)->opcode());
|
||||
CHECK_EQ(t.machine()->WordEqual()->opcode(), cnv->opcode());
|
||||
CHECK(b == cnv->InputAt(0) || b == cnv->InputAt(1));
|
||||
Node* c = t.jsgraph.TrueConstant();
|
||||
CHECK(c == cnv->InputAt(0) || c == cnv->InputAt(1));
|
||||
}
|
||||
|
||||
static Type* test_types[] = {Type::Signed32(), Type::Unsigned32(),
|
||||
Type::Number()};
|
||||
|
||||
|
@ -38,7 +38,6 @@ const PureOperator kPureOperators[] = {
|
||||
Operator::kPure | properties, input_count \
|
||||
}
|
||||
PURE(BooleanNot, Operator::kNoProperties, 1),
|
||||
PURE(BooleanToNumber, Operator::kNoProperties, 1),
|
||||
PURE(NumberEqual, Operator::kCommutative, 2),
|
||||
PURE(NumberLessThan, Operator::kNoProperties, 2),
|
||||
PURE(NumberLessThanOrEqual, Operator::kNoProperties, 2),
|
||||
|
Loading…
Reference in New Issue
Block a user