From 79e095c8d0cf747c97e78d2c0975bb5a8b530578 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Wed, 17 Sep 2014 14:47:25 +0000 Subject: [PATCH] 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 --- src/compiler/js-typed-lowering.cc | 6 ++- src/compiler/opcodes.h | 1 + src/compiler/simplified-lowering.cc | 18 ++++++++ src/compiler/simplified-operator.cc | 1 + src/compiler/simplified-operator.h | 1 + src/compiler/typer.cc | 5 +++ test/cctest/compiler/test-js-typed-lowering.cc | 13 +++--- test/cctest/compiler/test-simplified-lowering.cc | 57 ++++++++++++++++++++++++ 8 files changed, 96 insertions(+), 6 deletions(-) diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index 35283e4..74849af 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -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(); } diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index 722e1be..f295eac 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -131,6 +131,7 @@ // Opcodes for VirtuaMachine-level operators. #define SIMPLIFIED_OP_LIST(V) \ V(BooleanNot) \ + V(BooleanToNumber) \ V(NumberEqual) \ V(NumberLessThan) \ V(NumberLessThanOrEqual) \ diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index d1f2ee3..89c5868 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc @@ -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: { diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index f314d26..75b6e22 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -65,6 +65,7 @@ struct StaticParameterTraits { #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) \ diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 596f7f4..907507c 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -91,6 +91,7 @@ class SimplifiedOperatorBuilder FINAL { explicit SimplifiedOperatorBuilder(Zone* zone); const Operator* BooleanNot(); + const Operator* BooleanToNumber(); const Operator* NumberEqual(); const Operator* NumberLessThan(); diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 1c83fc2..c4af35e 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -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())); } diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc index 4366f18..afb9ed5 100644 --- a/test/cctest/compiler/test-js-typed-lowering.cc +++ b/test/cctest/compiler/test-js-typed-lowering.cc @@ -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); diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc index da75cc4..163fdc8 100644 --- a/test/cctest/compiler/test-simplified-lowering.cc +++ b/test/cctest/compiler/test-simplified-lowering.cc @@ -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()}; -- 2.7.4