[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}
This commit is contained in:
parent
e1d957268d
commit
fec1bba852
@ -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()->WordEqual(), val, jsgraph()->TrueConstant()));
|
||||
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()->Word32Equal(),
|
||||
graph()->NewNode(machine()->Word64Equal(), value,
|
||||
jsgraph()->Int64Constant(0)),
|
||||
jsgraph()->Int32Constant(0)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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[] = {
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
JSGraph* jsgraph() { return jsgraph_; }
|
||||
Isolate* isolate() { return isolate_; }
|
||||
SimplifiedOperatorBuilder* simplified() { return simplified_; }
|
||||
MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
|
||||
Node* InsertChangeTaggedToInt32(Node* node) {
|
||||
return graph()->NewNode(simplified()->ChangeTaggedToInt32(), node);
|
||||
}
|
||||
|
||||
Node* InsertChangeTaggedToUint32(Node* node) {
|
||||
return graph()->NewNode(simplified()->ChangeTaggedToUint32(), node);
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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(arg.lower, Type::TaggedPointer(), zone()),
|
||||
ChangeRepresentation(arg.upper, Type::TaggedPointer(), zone()));
|
||||
ChangeRepresentation(Type::Boolean(), Type::UntaggedBit(), zone()));
|
||||
}
|
||||
|
||||
|
||||
Bounds Typer::Visitor::TypeChangeWord64ToBit(Node* node) {
|
||||
return Bounds(
|
||||
ChangeRepresentation(Type::Boolean(), Type::UntaggedBit(), zone()));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -15,3 +15,4 @@ var foo = (function Module(stdlib, foreign, heap) {
|
||||
})(stdlib, foreign, buffer).foo;
|
||||
|
||||
assertFalse(foo(1));
|
||||
assertTrue(foo(0));
|
||||
|
@ -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);
|
||||
|
@ -297,6 +297,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
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user