From fec1bba85223a3a32182e4874be46b355f6df89e Mon Sep 17 00:00:00 2001 From: bmeurer Date: Thu, 8 Jan 2015 01:48:30 -0800 Subject: [PATCH] [turbofan] Correctify representation changes to bit. 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} --- src/compiler/change-lowering.cc | 32 ++++++++-- src/compiler/change-lowering.h | 5 +- src/compiler/js-graph.cc | 9 +++ src/compiler/js-graph.h | 6 ++ src/compiler/opcodes.h | 4 +- src/compiler/representation-change.h | 70 ++++++++++++++-------- src/compiler/simplified-operator-reducer.cc | 13 ++++ src/compiler/simplified-operator-reducer.h | 2 +- src/compiler/simplified-operator.cc | 4 +- src/compiler/simplified-operator.h | 4 +- src/compiler/typer.cc | 21 +++++-- src/compiler/verifier.cc | 23 ++++--- test/cctest/compiler/test-representation-change.cc | 58 ++++++++++++------ .../compiler/regress-bit-number-constant.js | 1 + .../unittests/compiler/change-lowering-unittest.cc | 23 ++++++- .../simplified-operator-reducer-unittest.cc | 21 +++++++ .../compiler/simplified-operator-unittest.cc | 2 + 17 files changed, 233 insertions(+), 65 deletions(-) diff --git a/src/compiler/change-lowering.cc b/src/compiler/change-lowering.cc index 7ddc751..fd425c2 100644 --- a/src/compiler/change-lowering.cc +++ b/src/compiler/change-lowering.cc @@ -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(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))); } diff --git a/src/compiler/change-lowering.h b/src/compiler/change-lowering.h index 773fd08..0147894 100644 --- a/src/compiler/change-lowering.h +++ b/src/compiler/change-lowering.h @@ -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); diff --git a/src/compiler/js-graph.cc b/src/compiler/js-graph.cc index 7759ba1..c8f6062 100644 --- a/src/compiler/js-graph.cc +++ b/src/compiler/js-graph.cc @@ -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* ptrs[] = { diff --git a/src/compiler/js-graph.h b/src/compiler/js-graph.h index 040a745..2d8d035 100644 --- a/src/compiler/js-graph.h +++ b/src/compiler/js-graph.h @@ -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 one_constant_; SetOncePointer nan_constant_; + SetOncePointer zero_one_range_type_; + CommonNodeCache cache_; Node* ImmovableHeapConstant(Handle value); diff --git a/src/compiler/opcodes.h b/src/compiler/opcodes.h index d229b6d..31f8298 100644 --- a/src/compiler/opcodes.h +++ b/src/compiler/opcodes.h @@ -130,7 +130,7 @@ 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) \ @@ -157,6 +157,8 @@ V(ChangeUint32ToTagged) \ V(ChangeFloat64ToTagged) \ V(ChangeBoolToBit) \ + V(ChangeWord32ToBit) \ + V(ChangeWord64ToBit) \ V(ChangeBitToBool) \ V(LoadField) \ V(LoadBuffer) \ diff --git a/src/compiler/representation-change.h b/src/compiler/representation-change.h index 8720afd..909ca62 100644 --- a/src/compiler/representation-change.h +++ b/src/compiler/representation-change.h @@ -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(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 handle = OpParameter >(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 = OpParameter>(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 diff --git a/src/compiler/simplified-operator-reducer.cc b/src/compiler/simplified-operator-reducer.cc index 9d45e5b..01ad15e 100644 --- a/src/compiler/simplified-operator-reducer.cc +++ b/src/compiler/simplified-operator-reducer.cc @@ -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)); diff --git a/src/compiler/simplified-operator-reducer.h b/src/compiler/simplified-operator-reducer.h index 32a7bcc..76f2cb4 100644 --- a/src/compiler/simplified-operator-reducer.h +++ b/src/compiler/simplified-operator-reducer.h @@ -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); diff --git a/src/compiler/simplified-operator.cc b/src/compiler/simplified-operator.cc index 9d88d12..0018d7c 100644 --- a/src/compiler/simplified-operator.cc +++ b/src/compiler/simplified-operator.cc @@ -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) diff --git a/src/compiler/simplified-operator.h b/src/compiler/simplified-operator.h index 22664fa..cdaa064 100644 --- a/src/compiler/simplified-operator.h +++ b/src/compiler/simplified-operator.h @@ -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(); diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 137829e..1fcfa17 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -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())); } diff --git a/src/compiler/verifier.cc b/src/compiler/verifier.cc index 693b414..5ba8c87 100644 --- a/src/compiler/verifier.cc +++ b/src/compiler/verifier.cc @@ -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; } diff --git a/test/cctest/compiler/test-representation-change.cc b/test/cctest/compiler/test-representation-change.cc index 2dc3029..0496ad8 100644 --- a/test/cctest/compiler/test-representation-change.cc +++ b/test/cctest/compiler/test-representation-change.cc @@ -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. diff --git a/test/mjsunit/compiler/regress-bit-number-constant.js b/test/mjsunit/compiler/regress-bit-number-constant.js index d36fe30..ca4cf11 100644 --- a/test/mjsunit/compiler/regress-bit-number-constant.js +++ b/test/mjsunit/compiler/regress-bit-number-constant.js @@ -15,3 +15,4 @@ var foo = (function Module(stdlib, foreign, heap) { })(stdlib, foreign, buffer).foo; assertFalse(foo(1)); +assertTrue(foo(0)); diff --git a/test/unittests/compiler/change-lowering-unittest.cc b/test/unittests/compiler/change-lowering-unittest.cc index 060b1c1..82e262f 100644 --- a/test/unittests/compiler/change-lowering-unittest.cc +++ b/test/unittests/compiler/change-lowering-unittest.cc @@ -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); diff --git a/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/test/unittests/compiler/simplified-operator-reducer-unittest.cc index e5f46c0..1a5b76a 100644 --- a/test/unittests/compiler/simplified-operator-reducer-unittest.cc +++ b/test/unittests/compiler/simplified-operator-reducer-unittest.cc @@ -298,6 +298,27 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) { // ----------------------------------------------------------------------------- +// ChangeWord32ToBit + + +TEST_F(SimplifiedOperatorReducerTest, ChangeWord32ToBitWithBitType) { + Handle zero = factory()->NewNumber(0); + Handle 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 diff --git a/test/unittests/compiler/simplified-operator-unittest.cc b/test/unittests/compiler/simplified-operator-unittest.cc index bc537fd..f02d3df 100644 --- a/test/unittests/compiler/simplified-operator-unittest.cc +++ b/test/unittests/compiler/simplified-operator-unittest.cc @@ -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) -- 2.7.4