Introduce simplified BooleanToNumber operator.
authormstarzinger@chromium.org <mstarzinger@chromium.org>
Wed, 17 Sep 2014 14:47:25 +0000 (14:47 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org>
Wed, 17 Sep 2014 14:47:25 +0000 (14:47 +0000)
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
src/compiler/opcodes.h
src/compiler/simplified-lowering.cc
src/compiler/simplified-operator.cc
src/compiler/simplified-operator.h
src/compiler/typer.cc
test/cctest/compiler/test-js-typed-lowering.cc
test/cctest/compiler/test-simplified-lowering.cc

index 35283e4..74849af 100644 (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();
 }
index 722e1be..f295eac 100644 (file)
 // Opcodes for VirtuaMachine-level operators.
 #define SIMPLIFIED_OP_LIST(V) \
   V(BooleanNot)               \
+  V(BooleanToNumber)          \
   V(NumberEqual)              \
   V(NumberLessThan)           \
   V(NumberLessThanOrEqual)    \
index d1f2ee3..89c5868 100644 (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: {
index f314d26..75b6e22 100644 (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) \
index 596f7f4..907507c 100644 (file)
@@ -91,6 +91,7 @@ class SimplifiedOperatorBuilder FINAL {
   explicit SimplifiedOperatorBuilder(Zone* zone);
 
   const Operator* BooleanNot();
+  const Operator* BooleanToNumber();
 
   const Operator* NumberEqual();
   const Operator* NumberLessThan();
index 1c83fc2..c4af35e 100644 (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()));
 }
index 4366f18..afb9ed5 100644 (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);
index da75cc4..163fdc8 100644 (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()};