[turbofan] Correctify representation changes to bit.
authorbmeurer <bmeurer@chromium.org>
Thu, 8 Jan 2015 09:48:30 +0000 (01:48 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 8 Jan 2015 09:48:41 +0000 (09:48 +0000)
TEST=cctest/test-representation-change,unittests,mjsunit/compiler/regress-bit-number-constant
R=jarin@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#25987}

17 files changed:
src/compiler/change-lowering.cc
src/compiler/change-lowering.h
src/compiler/js-graph.cc
src/compiler/js-graph.h
src/compiler/opcodes.h
src/compiler/representation-change.h
src/compiler/simplified-operator-reducer.cc
src/compiler/simplified-operator-reducer.h
src/compiler/simplified-operator.cc
src/compiler/simplified-operator.h
src/compiler/typer.cc
src/compiler/verifier.cc
test/cctest/compiler/test-representation-change.cc
test/mjsunit/compiler/regress-bit-number-constant.js
test/unittests/compiler/change-lowering-unittest.cc
test/unittests/compiler/simplified-operator-reducer-unittest.cc
test/unittests/compiler/simplified-operator-unittest.cc

index 7ddc751..fd425c2 100644 (file)
@@ -22,9 +22,13 @@ Reduction ChangeLowering::Reduce(Node* node) {
   Node* control = graph()->start();
   switch (node->opcode()) {
     case IrOpcode::kChangeBitToBool:
-      return ChangeBitToBool(node->InputAt(0), control);
+      return ChangeBitToBool(node->InputAt(0));
     case IrOpcode::kChangeBoolToBit:
       return ChangeBoolToBit(node->InputAt(0));
+    case IrOpcode::kChangeWord32ToBit:
+      return ChangeWord32ToBit(node->InputAt(0));
+    case IrOpcode::kChangeWord64ToBit:
+      return ChangeWord64ToBit(node->InputAt(0));
     case IrOpcode::kChangeFloat64ToTagged:
       return ChangeFloat64ToTagged(node->InputAt(0), control);
     case IrOpcode::kChangeInt32ToTagged:
@@ -138,17 +142,35 @@ Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) {
 }
 
 
-Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
+Reduction ChangeLowering::ChangeBitToBool(Node* value) {
   MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged);
-  return Replace(graph()->NewNode(common()->Select(type), val,
+  return Replace(graph()->NewNode(common()->Select(type), value,
                                   jsgraph()->TrueConstant(),
                                   jsgraph()->FalseConstant()));
 }
 
 
-Reduction ChangeLowering::ChangeBoolToBit(Node* val) {
+Reduction ChangeLowering::ChangeBoolToBit(Node* value) {
+  return Replace(graph()->NewNode(machine()->WordEqual(), value,
+                                  jsgraph()->TrueConstant()));
+}
+
+
+Reduction ChangeLowering::ChangeWord32ToBit(Node* value) {
+  return Replace(
+      graph()->NewNode(machine()->Word32Equal(),
+                       graph()->NewNode(machine()->Word32Equal(), value,
+                                        jsgraph()->Int32Constant(0)),
+                       jsgraph()->Int32Constant(0)));
+}
+
+
+Reduction ChangeLowering::ChangeWord64ToBit(Node* value) {
   return Replace(
-      graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant()));
+      graph()->NewNode(machine()->Word32Equal(),
+                       graph()->NewNode(machine()->Word64Equal(), value,
+                                        jsgraph()->Int64Constant(0)),
+                       jsgraph()->Int32Constant(0)));
 }
 
 
index 773fd08..0147894 100644 (file)
@@ -17,6 +17,7 @@ class JSGraph;
 class Linkage;
 class MachineOperatorBuilder;
 
+
 class ChangeLowering FINAL : public Reducer {
  public:
   ChangeLowering(JSGraph* jsgraph, Linkage* linkage)
@@ -40,8 +41,10 @@ class ChangeLowering FINAL : public Reducer {
   Node* TestNotSmi(Node* value);
   Node* Uint32LessThanOrEqual(Node* lhs, Node* rhs);
 
-  Reduction ChangeBitToBool(Node* value, Node* control);
+  Reduction ChangeBitToBool(Node* value);
   Reduction ChangeBoolToBit(Node* value);
+  Reduction ChangeWord32ToBit(Node* value);
+  Reduction ChangeWord64ToBit(Node* value);
   Reduction ChangeFloat64ToTagged(Node* value, Node* control);
   Reduction ChangeInt32ToTagged(Node* value, Node* control);
   Reduction ChangeTaggedToFloat64(Node* value, Node* control);
index 7759ba1..c8f6062 100644 (file)
@@ -200,6 +200,15 @@ Node* JSGraph::ExternalConstant(ExternalReference reference) {
 }
 
 
+Type* JSGraph::ZeroOneRangeType() {
+  if (!zero_one_range_type_.is_set()) {
+    zero_one_range_type_.set(
+        Type::Range(factory()->NewNumber(0), factory()->NewNumber(1), zone()));
+  }
+  return zero_one_range_type_.get();
+}
+
+
 void JSGraph::GetCachedNodes(NodeVector* nodes) {
   cache_.GetCachedNodes(nodes);
   SetOncePointer<Node>* ptrs[] = {
index 040a745..2d8d035 100644 (file)
@@ -16,6 +16,7 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
+// Forward declarations.
 class Typer;
 
 // Implements a facade on a Graph, enhancing the graph with JS-specific
@@ -109,6 +110,9 @@ class JSGraph : public ZoneObject {
   // stubs and runtime functions that do not require a context.
   Node* NoContextConstant() { return ZeroConstant(); }
 
+  // Cached common types.
+  Type* ZeroOneRangeType();
+
   JSOperatorBuilder* javascript() { return javascript_; }
   CommonOperatorBuilder* common() { return common_; }
   MachineOperatorBuilder* machine() { return machine_; }
@@ -136,6 +140,8 @@ class JSGraph : public ZoneObject {
   SetOncePointer<Node> one_constant_;
   SetOncePointer<Node> nan_constant_;
 
+  SetOncePointer<Type> zero_one_range_type_;
+
   CommonNodeCache cache_;
 
   Node* ImmovableHeapConstant(Handle<HeapObject> value);
index d229b6d..31f8298 100644 (file)
   JS_CONTEXT_OP_LIST(V)   \
   JS_OTHER_OP_LIST(V)
 
-// Opcodes for VirtuaMachine-level operators.
+// Opcodes for VirtualMachine-level operators.
 #define SIMPLIFIED_OP_LIST(V) \
   V(AnyToBoolean)             \
   V(BooleanNot)               \
   V(ChangeUint32ToTagged)     \
   V(ChangeFloat64ToTagged)    \
   V(ChangeBoolToBit)          \
+  V(ChangeWord32ToBit)        \
+  V(ChangeWord64ToBit)        \
   V(ChangeBitToBool)          \
   V(LoadField)                \
   V(LoadBuffer)               \
index 8720afd..909ca62 100644 (file)
@@ -27,12 +27,14 @@ class RepresentationChanger {
       : jsgraph_(jsgraph),
         simplified_(simplified),
         isolate_(isolate),
+        bit_range_(Type::Range(isolate->factory()->NewNumber(0),
+                               isolate->factory()->NewNumber(1),
+                               jsgraph->zone())),
         testing_type_errors_(false),
         type_error_(false) {}
 
   // TODO(titzer): should Word64 also be implicitly convertable to others?
-  static const MachineTypeUnion rWord =
-      kRepBit | kRepWord8 | kRepWord16 | kRepWord32;
+  static const MachineTypeUnion rWord = kRepWord8 | kRepWord16 | kRepWord32;
 
   Node* GetRepresentationFor(Node* node, MachineTypeUnion output_type,
                              MachineTypeUnion use_type) {
@@ -262,8 +264,10 @@ class RepresentationChanger {
         break;
     }
     // Select the correct X -> Word32 operator.
-    const Operator* op = NULL;
-    if (output_type & kRepFloat64) {
+    const Operator* op;
+    if (output_type & kRepBit) {
+      return node;  // No change necessary.
+    } else if (output_type & kRepFloat64) {
       if (output_type & kTypeUint32 || use_unsigned) {
         op = machine()->ChangeFloat64ToUint32();
       } else {
@@ -298,17 +302,12 @@ class RepresentationChanger {
       }
       case IrOpcode::kNumberConstant: {
         double value = OpParameter<double>(node);
-        if (std::isnan(value) || value == 0.0) {
-          return jsgraph()->Int32Constant(0);
-        }
-        return jsgraph()->Int32Constant(1);
+        if (value == 0 || std::isnan(value)) return jsgraph()->Int32Constant(0);
+        return jsgraph()->Int32Constant(1);  // value != +0.0, -0.0, NaN
       }
       case IrOpcode::kHeapConstant: {
-        Handle<Object> handle = OpParameter<Unique<Object> >(node).handle();
-        DCHECK(*handle == isolate()->heap()->true_value() ||
-               *handle == isolate()->heap()->false_value());
-        return jsgraph()->Int32Constant(
-            *handle == isolate()->heap()->true_value() ? 1 : 0);
+        Handle<Object> object = OpParameter<Unique<Object>>(node).handle();
+        return jsgraph()->Int32Constant(object->BooleanValue() ? 1 : 0);
       }
       default:
         break;
@@ -316,15 +315,28 @@ class RepresentationChanger {
     // Select the correct X -> Bit operator.
     const Operator* op;
     if (output_type & rWord) {
-      return node;  // No change necessary.
+      op = simplified()->ChangeWord32ToBit();
     } else if (output_type & kRepWord64) {
-      return node;  // TODO(titzer): No change necessary, on 64-bit.
+      op = simplified()->ChangeWord64ToBit();
     } else if (output_type & kRepTagged) {
-      op = simplified()->ChangeBoolToBit();
+      Type* upper = NodeProperties::GetBounds(node).upper;
+      if (upper->Is(Type::Boolean())) {
+        op = simplified()->ChangeBoolToBit();
+      } else if (upper->Is(Type::Signed32())) {
+        // Tagged -> Int32 -> Bit
+        node = InsertChangeTaggedToInt32(node);
+        op = simplified()->ChangeWord32ToBit();
+      } else if (upper->Is(Type::Unsigned32())) {
+        // Tagged -> Uint32 -> Bit
+        node = InsertChangeTaggedToUint32(node);
+        op = simplified()->ChangeWord32ToBit();
+      } else {
+        return TypeError(node, output_type, kRepBit);
+      }
     } else {
       return TypeError(node, output_type, kRepBit);
     }
-    return jsgraph()->graph()->NewNode(op, node);
+    return graph()->NewNode(op, node);
   }
 
   Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) {
@@ -429,6 +441,7 @@ class RepresentationChanger {
   JSGraph* jsgraph_;
   SimplifiedOperatorBuilder* simplified_;
   Isolate* isolate_;
+  Type* bit_range_;
 
   friend class RepresentationChangerTester;  // accesses the below fields.
 
@@ -455,19 +468,26 @@ class RepresentationChanger {
   }
 
   Node* InsertChangeFloat32ToFloat64(Node* node) {
-    return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(),
-                                       node);
+    return graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node);
   }
 
   Node* InsertChangeTaggedToFloat64(Node* node) {
-    return jsgraph()->graph()->NewNode(simplified()->ChangeTaggedToFloat64(),
-                                       node);
+    return graph()->NewNode(simplified()->ChangeTaggedToFloat64(), node);
+  }
+
+  Node* InsertChangeTaggedToInt32(Node* node) {
+    return graph()->NewNode(simplified()->ChangeTaggedToInt32(), node);
+  }
+
+  Node* InsertChangeTaggedToUint32(Node* node) {
+    return graph()->NewNode(simplified()->ChangeTaggedToUint32(), node);
   }
 
-  JSGraph* jsgraph() { return jsgraph_; }
-  Isolate* isolate() { return isolate_; }
-  SimplifiedOperatorBuilder* simplified() { return simplified_; }
-  MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
+  Graph* graph() const { return jsgraph()->graph(); }
+  JSGraph* jsgraph() const { return jsgraph_; }
+  Isolate* isolate() const { return isolate_; }
+  SimplifiedOperatorBuilder* simplified() const { return simplified_; }
+  MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
 };
 
 }  // namespace compiler
index 9d45e5b..01ad15e 100644 (file)
@@ -54,6 +54,8 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
       if (m.IsChangeBitToBool()) return Replace(m.node()->InputAt(0));
       break;
     }
+    case IrOpcode::kChangeWord32ToBit:
+      return ReduceChangeWord32ToBit(node);
     case IrOpcode::kChangeFloat64ToTagged: {
       Float64Matcher m(node->InputAt(0));
       if (m.HasValue()) return ReplaceNumber(m.Value());
@@ -136,6 +138,17 @@ Reduction SimplifiedOperatorReducer::ReduceAnyToBoolean(Node* node) {
 }
 
 
+Reduction SimplifiedOperatorReducer::ReduceChangeWord32ToBit(Node* node) {
+  Node* const input = NodeProperties::GetValueInput(node, 0);
+  Type* const input_type = NodeProperties::GetBounds(input).upper;
+  if (input_type->Is(jsgraph()->ZeroOneRangeType())) {
+    // ChangeWord32ToBit(x:bit) => x
+    return Replace(input);
+  }
+  return NoChange();
+}
+
+
 Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
                                             Node* a) {
   DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
index 32a7bcc..76f2cb4 100644 (file)
@@ -13,7 +13,6 @@ namespace internal {
 
 // Forward declarations.
 class Factory;
-class Heap;
 
 namespace compiler {
 
@@ -31,6 +30,7 @@ class SimplifiedOperatorReducer FINAL : public Reducer {
 
  private:
   Reduction ReduceAnyToBoolean(Node* node);
+  Reduction ReduceChangeWord32ToBit(Node* node);
 
   Reduction Change(Node* node, const Operator* op, Node* a);
   Reduction ReplaceFloat64(double value);
index 9d88d12..0018d7c 100644 (file)
@@ -181,8 +181,10 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
   V(ChangeInt32ToTagged, Operator::kNoProperties, 1)   \
   V(ChangeUint32ToTagged, Operator::kNoProperties, 1)  \
   V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \
-  V(ChangeBoolToBit, Operator::kNoProperties, 1)       \
   V(ChangeBitToBool, Operator::kNoProperties, 1)       \
+  V(ChangeBoolToBit, Operator::kNoProperties, 1)       \
+  V(ChangeWord32ToBit, Operator::kNoProperties, 1)     \
+  V(ChangeWord64ToBit, Operator::kNoProperties, 1)     \
   V(ObjectIsSmi, Operator::kNoProperties, 1)           \
   V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
 
index 22664fa..cdaa064 100644 (file)
@@ -157,8 +157,10 @@ class SimplifiedOperatorBuilder FINAL {
   const Operator* ChangeInt32ToTagged();
   const Operator* ChangeUint32ToTagged();
   const Operator* ChangeFloat64ToTagged();
-  const Operator* ChangeBoolToBit();
   const Operator* ChangeBitToBool();
+  const Operator* ChangeBoolToBit();
+  const Operator* ChangeWord32ToBit();
+  const Operator* ChangeWord64ToBit();
 
   const Operator* ObjectIsSmi();
   const Operator* ObjectIsNonNegativeSmi();
index 137829e..1fcfa17 100644 (file)
@@ -1596,6 +1596,14 @@ Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) {
 }
 
 
+Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
+  Bounds arg = Operand(node, 0);
+  // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
+  return Bounds(ChangeRepresentation(arg.lower, Type::TaggedPointer(), zone()),
+                ChangeRepresentation(arg.upper, Type::TaggedPointer(), zone()));
+}
+
+
 Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
   Bounds arg = Operand(node, 0);
   // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
@@ -1605,12 +1613,15 @@ Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
 }
 
 
-Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
-  Bounds arg = Operand(node, 0);
-  // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
+Bounds Typer::Visitor::TypeChangeWord32ToBit(Node* node) {
+  return Bounds(
+      ChangeRepresentation(Type::Boolean(), Type::UntaggedBit(), zone()));
+}
+
+
+Bounds Typer::Visitor::TypeChangeWord64ToBit(Node* node) {
   return Bounds(
-      ChangeRepresentation(arg.lower, Type::TaggedPointer(), zone()),
-      ChangeRepresentation(arg.upper, Type::TaggedPointer(), zone()));
+      ChangeRepresentation(Type::Boolean(), Type::UntaggedBit(), zone()));
 }
 
 
index 693b414..5ba8c87 100644 (file)
@@ -612,6 +612,15 @@ void Verifier::Visitor::Pre(Node* node) {
       // CheckUpperIs(node, to));
       break;
     }
+    case IrOpcode::kChangeBitToBool: {
+      // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
+      // TODO(neis): Activate once ChangeRepresentation works in typer.
+      // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
+      // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
+      // CheckValueInputIs(node, 0, from));
+      // CheckUpperIs(node, to));
+      break;
+    }
     case IrOpcode::kChangeBoolToBit: {
       // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
       // TODO(neis): Activate once ChangeRepresentation works in typer.
@@ -621,13 +630,13 @@ void Verifier::Visitor::Pre(Node* node) {
       // CheckUpperIs(node, to));
       break;
     }
-    case IrOpcode::kChangeBitToBool: {
-      // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
-      // TODO(neis): Activate once ChangeRepresentation works in typer.
-      // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
-      // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
-      // CheckValueInputIs(node, 0, from));
-      // CheckUpperIs(node, to));
+    case IrOpcode::kChangeWord32ToBit: {
+      // TODO(rossberg): Check.
+      CheckValueInputIs(node, 0, Type::Integral32());
+      break;
+    }
+    case IrOpcode::kChangeWord64ToBit: {
+      // TODO(rossberg): Check.
       break;
     }
 
index 2dc3029..0496ad8 100644 (file)
@@ -79,10 +79,14 @@ class RepresentationChangerTester : public HandleAndZoneScope,
     CHECK_EQ(expected, m.Value());
   }
 
-  Node* Parameter(int index = 0) {
-    return graph()->NewNode(common()->Parameter(index), graph()->start());
+  Node* Parameter(Type* type, int index = 0) {
+    Node* node = graph()->NewNode(common()->Parameter(index), graph()->start());
+    NodeProperties::SetBounds(node, Bounds(type));
+    return node;
   }
 
+  Node* Parameter(int index = 0) { return Parameter(Type::Any(), index); }
+
   void CheckTypeError(MachineTypeUnion from, MachineTypeUnion to) {
     changer()->testing_type_errors_ = true;
     changer()->type_error_ = false;
@@ -98,16 +102,17 @@ class RepresentationChangerTester : public HandleAndZoneScope,
     CHECK_EQ(n, c);
   }
 };
-}
-}
-}  // namespace v8::internal::compiler
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
 
 
 static const MachineType all_reps[] = {kRepBit,     kRepWord32,  kRepWord64,
                                        kRepFloat32, kRepFloat64, kRepTagged};
 
 
-TEST(BoolToBit_constant) {
+TEST(ToBit_constant) {
   RepresentationChangerTester r;
 
   Node* true_node = r.jsgraph()->TrueConstant();
@@ -119,6 +124,22 @@ TEST(BoolToBit_constant) {
   Node* false_bit =
       r.changer()->GetRepresentationFor(false_node, kRepTagged, kRepBit);
   r.CheckInt32Constant(false_bit, 0);
+
+  {
+    FOR_FLOAT64_INPUTS(i) {
+      Node* node = r.jsgraph()->Constant(*i);
+      Node* bit = r.changer()->GetRepresentationFor(node, kRepTagged, kRepBit);
+      r.CheckInt32Constant(bit, DoubleToBoolean(*i) ? 1 : 0);
+    }
+  }
+
+  {
+    FOR_INT32_INPUTS(i) {
+      Node* node = r.jsgraph()->Int32Constant(*i);
+      Node* bit = r.changer()->GetRepresentationFor(node, kRepWord32, kRepBit);
+      r.CheckInt32Constant(bit, *i == 0 ? 0 : 1);
+    }
+  }
 }
 
 
@@ -370,10 +391,10 @@ TEST(ToUint32_constant) {
 
 
 static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from,
-                        MachineTypeUnion to) {
+                        MachineTypeUnion to, Type* from_type = Type::Any()) {
   RepresentationChangerTester r;
 
-  Node* n = r.Parameter();
+  Node* n = r.Parameter(from_type);
   Node* c = r.changer()->GetRepresentationFor(n, from, to);
 
   CHECK_NE(c, n);
@@ -384,10 +405,11 @@ static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from,
 
 static void CheckTwoChanges(IrOpcode::Value expected2,
                             IrOpcode::Value expected1, MachineTypeUnion from,
-                            MachineTypeUnion to) {
+                            MachineTypeUnion to,
+                            Type* from_type = Type::Any()) {
   RepresentationChangerTester r;
 
-  Node* n = r.Parameter();
+  Node* n = r.Parameter(from_type);
   Node* c1 = r.changer()->GetRepresentationFor(n, from, to);
 
   CHECK_NE(c1, n);
@@ -400,7 +422,15 @@ static void CheckTwoChanges(IrOpcode::Value expected2,
 
 
 TEST(SingleChanges) {
-  CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit);
+  CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit, Type::Boolean());
+  CheckTwoChanges(IrOpcode::kChangeTaggedToInt32, IrOpcode::kChangeWord32ToBit,
+                  kRepTagged, kRepBit, Type::Signed32());
+  CheckTwoChanges(IrOpcode::kChangeTaggedToUint32, IrOpcode::kChangeWord32ToBit,
+                  kRepTagged, kRepBit, Type::Unsigned32());
+  CheckChange(IrOpcode::kChangeWord32ToBit, kRepWord8, kRepBit);
+  CheckChange(IrOpcode::kChangeWord32ToBit, kRepWord16, kRepBit);
+  CheckChange(IrOpcode::kChangeWord32ToBit, kRepWord32, kRepBit);
+  CheckChange(IrOpcode::kChangeWord64ToBit, kRepWord64, kRepBit);
   CheckChange(IrOpcode::kChangeBitToBool, kRepBit, kRepTagged);
 
   CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32,
@@ -480,12 +510,6 @@ TEST(Nops) {
   r.CheckNop(kRepFloat32 | kTypeNumber, kRepFloat32);
   r.CheckNop(kRepFloat32, kRepFloat32 | kTypeNumber);
 
-  // 32-bit or 64-bit words can be used as branch conditions (kRepBit).
-  r.CheckNop(kRepWord32, kRepBit);
-  r.CheckNop(kRepWord32, kRepBit | kTypeBool);
-  r.CheckNop(kRepWord64, kRepBit);
-  r.CheckNop(kRepWord64, kRepBit | kTypeBool);
-
   // 32-bit words can be used as smaller word sizes and vice versa, because
   // loads from memory implicitly sign or zero extend the value to the
   // full machine word size, and stores implicitly truncate.
index d36fe30..ca4cf11 100644 (file)
@@ -15,3 +15,4 @@ var foo = (function Module(stdlib, foreign, heap) {
 })(stdlib, foreign, buffer).foo;
 
 assertFalse(foo(1));
+assertTrue(foo(0));
index 060b1c1..82e262f 100644 (file)
@@ -132,11 +132,32 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
   Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
   Reduction reduction = Reduce(node);
   ASSERT_TRUE(reduction.Changed());
-
   EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant()));
 }
 
 
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeWord32ToBit) {
+  Node* val = Parameter(0);
+  Node* node = graph()->NewNode(simplified()->ChangeWord32ToBit(), val);
+  Reduction reduction = Reduce(node);
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_THAT(reduction.replacement(),
+              IsWord32Equal(IsWord32Equal(val, IsInt32Constant(0)),
+                            IsInt32Constant(0)));
+}
+
+
+TARGET_TEST_P(ChangeLoweringCommonTest, ChangeWord64ToBit) {
+  Node* val = Parameter(0);
+  Node* node = graph()->NewNode(simplified()->ChangeWord64ToBit(), val);
+  Reduction reduction = Reduce(node);
+  ASSERT_TRUE(reduction.Changed());
+  EXPECT_THAT(reduction.replacement(),
+              IsWord32Equal(IsWord64Equal(val, IsInt64Constant(0)),
+                            IsInt32Constant(0)));
+}
+
+
 TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
   Node* val = Parameter(0);
   Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val);
index e5f46c0..1a5b76a 100644 (file)
@@ -298,6 +298,27 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) {
 
 
 // -----------------------------------------------------------------------------
+// ChangeWord32ToBit
+
+
+TEST_F(SimplifiedOperatorReducerTest, ChangeWord32ToBitWithBitType) {
+  Handle<Object> zero = factory()->NewNumber(0);
+  Handle<Object> one = factory()->NewNumber(1);
+  Type* const kBitTypes[] = {
+      Type::Constant(zero, zone()), Type::Constant(one, zone()),
+      Type::Range(zero, zero, zone()), Type::Range(one, one, zone()),
+      Type::Range(zero, one, zone())};
+  TRACED_FOREACH(Type*, type, kBitTypes) {
+    Node* param0 = Parameter(type, 0);
+    Reduction reduction =
+        Reduce(graph()->NewNode(simplified()->ChangeWord32ToBit(), param0));
+    ASSERT_TRUE(reduction.Changed());
+    EXPECT_EQ(param0, reduction.replacement());
+  }
+}
+
+
+// -----------------------------------------------------------------------------
 // ChangeFloat64ToTagged
 
 
index bc537fd..f02d3df 100644 (file)
@@ -62,6 +62,8 @@ const PureOperator kPureOperators[] = {
     PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
     PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
     PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
+    PURE(ChangeWord32ToBit, Operator::kNoProperties, 1),
+    PURE(ChangeWord64ToBit, Operator::kNoProperties, 1),
     PURE(ChangeBitToBool, Operator::kNoProperties, 1),
     PURE(ObjectIsSmi, Operator::kNoProperties, 1),
     PURE(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)