Introduce simplified BooleanToNumber operator.

R=titzer@chromium.org
TEST=cctest/test-simplified-lowering/LowerBooleanToNumber

Review URL: https://codereview.chromium.org/579723004

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24009 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2014-09-17 14:47:25 +00:00
parent 887b77aa83
commit 79e095c8d0
8 changed files with 96 additions and 6 deletions

View File

@ -444,7 +444,11 @@ Reduction JSTypedLowering::ReduceJSToNumberInput(Node* input) {
// JSToNumber(null) => #0
return ReplaceWith(jsgraph()->ZeroConstant());
}
// TODO(turbofan): js-typed-lowering of ToNumber(x:boolean)
if (input_type->Is(Type::Boolean())) {
// JSToNumber(x:boolean) => BooleanToNumber(x)
return ReplaceWith(
graph()->NewNode(simplified()->BooleanToNumber(), input));
}
// TODO(turbofan): js-typed-lowering of ToNumber(x:string)
return NoChange();
}

View File

@ -131,6 +131,7 @@
// Opcodes for VirtuaMachine-level operators.
#define SIMPLIFIED_OP_LIST(V) \
V(BooleanNot) \
V(BooleanToNumber) \
V(NumberEqual) \
V(NumberLessThan) \
V(NumberLessThanOrEqual) \

View File

@ -432,6 +432,24 @@ class RepresentationSelector {
}
break;
}
case IrOpcode::kBooleanToNumber: {
if (lower()) {
MachineTypeUnion input = GetInfo(node->InputAt(0))->output;
if (input & kRepBit) {
// BooleanToNumber(x: kRepBit) => x
DeferReplacement(node, node->InputAt(0));
} else {
// BooleanToNumber(x: kRepTagged) => WordEqual(x, #true)
node->set_op(lowering->machine()->WordEqual());
node->AppendInput(jsgraph_->zone(), jsgraph_->TrueConstant());
}
} else {
// No input representation requirement; adapt during lowering.
ProcessInput(node, 0, kTypeBool);
SetOutput(node, kMachInt32);
}
break;
}
case IrOpcode::kNumberEqual:
case IrOpcode::kNumberLessThan:
case IrOpcode::kNumberLessThanOrEqual: {

View File

@ -65,6 +65,7 @@ struct StaticParameterTraits<ElementAccess> {
#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) \

View File

@ -91,6 +91,7 @@ class SimplifiedOperatorBuilder FINAL {
explicit SimplifiedOperatorBuilder(Zone* zone);
const Operator* BooleanNot();
const Operator* BooleanToNumber();
const Operator* NumberEqual();
const Operator* NumberLessThan();

View File

@ -644,6 +644,11 @@ Bounds Typer::Visitor::TypeBooleanNot(Node* node) {
}
Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
return Bounds(Type::Number(zone()));
}
Bounds Typer::Visitor::TypeNumberEqual(Node* node) {
return Bounds(Type::Boolean(zone()));
}

View File

@ -665,6 +665,9 @@ TEST(StringComparison) {
static void CheckIsConvertedToNumber(Node* val, Node* converted) {
if (NodeProperties::GetBounds(val).upper->Is(Type::Number())) {
CHECK_EQ(val, converted);
} else if (NodeProperties::GetBounds(val).upper->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());
@ -1049,7 +1052,7 @@ TEST(OrderNumberBinopEffects2) {
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
BinopEffectsTester B(ops[j], Type::Number(), Type::Boolean());
BinopEffectsTester B(ops[j], Type::Number(), Type::Symbol());
Node* i0 = B.CheckNoOp(0);
Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);
@ -1062,7 +1065,7 @@ TEST(OrderNumberBinopEffects2) {
}
for (size_t j = 0; j < arraysize(ops); j += 2) {
BinopEffectsTester B(ops[j], Type::Boolean(), Type::Number());
BinopEffectsTester B(ops[j], Type::Symbol(), Type::Number());
Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
Node* i1 = B.CheckNoOp(1);
@ -1085,7 +1088,7 @@ TEST(OrderCompareEffects) {
};
for (size_t j = 0; j < arraysize(ops); j += 2) {
BinopEffectsTester B(ops[j], Type::Boolean(), Type::String());
BinopEffectsTester B(ops[j], Type::Symbol(), Type::String());
CHECK_EQ(ops[j + 1]->opcode(), B.result->op()->opcode());
Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
@ -1100,7 +1103,7 @@ TEST(OrderCompareEffects) {
}
for (size_t j = 0; j < arraysize(ops); j += 2) {
BinopEffectsTester B(ops[j], Type::Number(), Type::Boolean());
BinopEffectsTester B(ops[j], Type::Number(), Type::Symbol());
Node* i0 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 0, true);
Node* i1 = B.result->InputAt(1);
@ -1113,7 +1116,7 @@ TEST(OrderCompareEffects) {
}
for (size_t j = 0; j < arraysize(ops); j += 2) {
BinopEffectsTester B(ops[j], Type::Boolean(), Type::Number());
BinopEffectsTester B(ops[j], Type::Symbol(), Type::Number());
Node* i0 = B.result->InputAt(0);
Node* i1 = B.CheckConvertedInput(IrOpcode::kJSToNumber, 1, true);

View File

@ -810,6 +810,63 @@ TEST(LowerBooleanNot_tagged_tagged) {
}
TEST(LowerBooleanToNumber_bit_int32) {
// BooleanToNumber(x: kRepBit) used as kMachInt32
TestingGraph t(Type::Boolean());
Node* b = t.ExampleWithOutput(kRepBit);
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Node* use = t.Use(cnv, kMachInt32);
t.Return(use);
t.Lower();
CHECK_EQ(b, use->InputAt(0));
}
TEST(LowerBooleanToNumber_tagged_int32) {
// BooleanToNumber(x: kRepTagged) used as kMachInt32
TestingGraph t(Type::Boolean());
Node* b = t.p0;
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Node* use = t.Use(cnv, kMachInt32);
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 kMachAnyTagged
TestingGraph t(Type::Boolean());
Node* b = t.ExampleWithOutput(kRepBit);
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Node* use = t.Use(cnv, kMachAnyTagged);
t.Return(use);
t.Lower();
CHECK_EQ(b, use->InputAt(0)->InputAt(0));
CHECK_EQ(IrOpcode::kChangeInt32ToTagged, use->InputAt(0)->opcode());
}
TEST(LowerBooleanToNumber_tagged_tagged) {
// BooleanToNumber(x: kRepTagged) used as kMachAnyTagged
TestingGraph t(Type::Boolean());
Node* b = t.p0;
Node* cnv = t.graph()->NewNode(t.simplified()->BooleanToNumber(), b);
Node* use = t.Use(cnv, kMachAnyTagged);
t.Return(use);
t.Lower();
CHECK_EQ(cnv, use->InputAt(0)->InputAt(0));
CHECK_EQ(IrOpcode::kChangeInt32ToTagged, 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(), Type::Any()};