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:
parent
887b77aa83
commit
79e095c8d0
@ -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();
|
||||
}
|
||||
|
@ -131,6 +131,7 @@
|
||||
// Opcodes for VirtuaMachine-level operators.
|
||||
#define SIMPLIFIED_OP_LIST(V) \
|
||||
V(BooleanNot) \
|
||||
V(BooleanToNumber) \
|
||||
V(NumberEqual) \
|
||||
V(NumberLessThan) \
|
||||
V(NumberLessThanOrEqual) \
|
||||
|
@ -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: {
|
||||
|
@ -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) \
|
||||
|
@ -91,6 +91,7 @@ class SimplifiedOperatorBuilder FINAL {
|
||||
explicit SimplifiedOperatorBuilder(Zone* zone);
|
||||
|
||||
const Operator* BooleanNot();
|
||||
const Operator* BooleanToNumber();
|
||||
|
||||
const Operator* NumberEqual();
|
||||
const Operator* NumberLessThan();
|
||||
|
@ -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()));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user