[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:
bmeurer 2016-07-12 02:12:20 -07:00 committed by Commit bot
parent e92e911814
commit 85969edead
11 changed files with 32 additions and 134 deletions

View File

@ -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();
}

View File

@ -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) \

View File

@ -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());

View File

@ -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_;

View File

@ -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) \

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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.

View File

@ -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()};

View File

@ -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),