Commit 70b32e4b authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Fix truncation/representation sloppiness wrt. bool/bit.

TEST=cctest,mjsunit,unittests
BUG=v8:3812
LOG=y

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

Cr-Commit-Position: refs/heads/master@{#26051}
parent 316f860a
...@@ -22,13 +22,9 @@ Reduction ChangeLowering::Reduce(Node* node) { ...@@ -22,13 +22,9 @@ Reduction ChangeLowering::Reduce(Node* node) {
Node* control = graph()->start(); Node* control = graph()->start();
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kChangeBitToBool: case IrOpcode::kChangeBitToBool:
return ChangeBitToBool(node->InputAt(0)); return ChangeBitToBool(node->InputAt(0), control);
case IrOpcode::kChangeBoolToBit: case IrOpcode::kChangeBoolToBit:
return ChangeBoolToBit(node->InputAt(0)); return ChangeBoolToBit(node->InputAt(0));
case IrOpcode::kChangeWord32ToBit:
return ChangeWord32ToBit(node->InputAt(0));
case IrOpcode::kChangeWord64ToBit:
return ChangeWord64ToBit(node->InputAt(0));
case IrOpcode::kChangeFloat64ToTagged: case IrOpcode::kChangeFloat64ToTagged:
return ChangeFloat64ToTagged(node->InputAt(0), control); return ChangeFloat64ToTagged(node->InputAt(0), control);
case IrOpcode::kChangeInt32ToTagged: case IrOpcode::kChangeInt32ToTagged:
...@@ -142,35 +138,17 @@ Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) { ...@@ -142,35 +138,17 @@ Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) {
} }
Reduction ChangeLowering::ChangeBitToBool(Node* value) { Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged); MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged);
return Replace(graph()->NewNode(common()->Select(type), value, return Replace(graph()->NewNode(common()->Select(type), val,
jsgraph()->TrueConstant(), jsgraph()->TrueConstant(),
jsgraph()->FalseConstant())); jsgraph()->FalseConstant()));
} }
Reduction ChangeLowering::ChangeBoolToBit(Node* value) { Reduction ChangeLowering::ChangeBoolToBit(Node* val) {
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( return Replace(
graph()->NewNode(machine()->Word32Equal(), graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant()));
graph()->NewNode(machine()->Word64Equal(), value,
jsgraph()->Int64Constant(0)),
jsgraph()->Int32Constant(0)));
} }
......
...@@ -17,7 +17,6 @@ class JSGraph; ...@@ -17,7 +17,6 @@ class JSGraph;
class Linkage; class Linkage;
class MachineOperatorBuilder; class MachineOperatorBuilder;
class ChangeLowering FINAL : public Reducer { class ChangeLowering FINAL : public Reducer {
public: public:
ChangeLowering(JSGraph* jsgraph, Linkage* linkage) ChangeLowering(JSGraph* jsgraph, Linkage* linkage)
...@@ -41,10 +40,8 @@ class ChangeLowering FINAL : public Reducer { ...@@ -41,10 +40,8 @@ class ChangeLowering FINAL : public Reducer {
Node* TestNotSmi(Node* value); Node* TestNotSmi(Node* value);
Node* Uint32LessThanOrEqual(Node* lhs, Node* rhs); Node* Uint32LessThanOrEqual(Node* lhs, Node* rhs);
Reduction ChangeBitToBool(Node* value); Reduction ChangeBitToBool(Node* value, Node* control);
Reduction ChangeBoolToBit(Node* value); Reduction ChangeBoolToBit(Node* value);
Reduction ChangeWord32ToBit(Node* value);
Reduction ChangeWord64ToBit(Node* value);
Reduction ChangeFloat64ToTagged(Node* value, Node* control); Reduction ChangeFloat64ToTagged(Node* value, Node* control);
Reduction ChangeInt32ToTagged(Node* value, Node* control); Reduction ChangeInt32ToTagged(Node* value, Node* control);
Reduction ChangeTaggedToFloat64(Node* value, Node* control); Reduction ChangeTaggedToFloat64(Node* value, Node* control);
......
...@@ -200,15 +200,6 @@ Node* JSGraph::ExternalConstant(ExternalReference reference) { ...@@ -200,15 +200,6 @@ 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) { void JSGraph::GetCachedNodes(NodeVector* nodes) {
cache_.GetCachedNodes(nodes); cache_.GetCachedNodes(nodes);
SetOncePointer<Node>* ptrs[] = { SetOncePointer<Node>* ptrs[] = {
......
...@@ -16,7 +16,6 @@ namespace v8 { ...@@ -16,7 +16,6 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
// Forward declarations.
class Typer; class Typer;
// Implements a facade on a Graph, enhancing the graph with JS-specific // Implements a facade on a Graph, enhancing the graph with JS-specific
...@@ -110,9 +109,6 @@ class JSGraph : public ZoneObject { ...@@ -110,9 +109,6 @@ class JSGraph : public ZoneObject {
// stubs and runtime functions that do not require a context. // stubs and runtime functions that do not require a context.
Node* NoContextConstant() { return ZeroConstant(); } Node* NoContextConstant() { return ZeroConstant(); }
// Cached common types.
Type* ZeroOneRangeType();
JSOperatorBuilder* javascript() { return javascript_; } JSOperatorBuilder* javascript() { return javascript_; }
CommonOperatorBuilder* common() { return common_; } CommonOperatorBuilder* common() { return common_; }
MachineOperatorBuilder* machine() { return machine_; } MachineOperatorBuilder* machine() { return machine_; }
...@@ -140,8 +136,6 @@ class JSGraph : public ZoneObject { ...@@ -140,8 +136,6 @@ class JSGraph : public ZoneObject {
SetOncePointer<Node> one_constant_; SetOncePointer<Node> one_constant_;
SetOncePointer<Node> nan_constant_; SetOncePointer<Node> nan_constant_;
SetOncePointer<Type> zero_one_range_type_;
CommonNodeCache cache_; CommonNodeCache cache_;
Node* ImmovableHeapConstant(Handle<HeapObject> value); Node* ImmovableHeapConstant(Handle<HeapObject> value);
......
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
JS_CONTEXT_OP_LIST(V) \ JS_CONTEXT_OP_LIST(V) \
JS_OTHER_OP_LIST(V) JS_OTHER_OP_LIST(V)
// Opcodes for VirtualMachine-level operators. // Opcodes for VirtuaMachine-level operators.
#define SIMPLIFIED_OP_LIST(V) \ #define SIMPLIFIED_OP_LIST(V) \
V(AnyToBoolean) \ V(AnyToBoolean) \
V(BooleanNot) \ V(BooleanNot) \
...@@ -161,8 +161,6 @@ ...@@ -161,8 +161,6 @@
V(ChangeUint32ToTagged) \ V(ChangeUint32ToTagged) \
V(ChangeFloat64ToTagged) \ V(ChangeFloat64ToTagged) \
V(ChangeBoolToBit) \ V(ChangeBoolToBit) \
V(ChangeWord32ToBit) \
V(ChangeWord64ToBit) \
V(ChangeBitToBool) \ V(ChangeBitToBool) \
V(LoadField) \ V(LoadField) \
V(LoadBuffer) \ V(LoadBuffer) \
......
...@@ -27,9 +27,6 @@ class RepresentationChanger { ...@@ -27,9 +27,6 @@ class RepresentationChanger {
: jsgraph_(jsgraph), : jsgraph_(jsgraph),
simplified_(simplified), simplified_(simplified),
isolate_(isolate), isolate_(isolate),
bit_range_(Type::Range(isolate->factory()->NewNumber(0),
isolate->factory()->NewNumber(1),
jsgraph->zone())),
testing_type_errors_(false), testing_type_errors_(false),
type_error_(false) {} type_error_(false) {}
...@@ -266,7 +263,7 @@ class RepresentationChanger { ...@@ -266,7 +263,7 @@ class RepresentationChanger {
// Select the correct X -> Word32 operator. // Select the correct X -> Word32 operator.
const Operator* op; const Operator* op;
if (output_type & kRepBit) { if (output_type & kRepBit) {
return node; // No change necessary. return node; // Sloppy comparison -> word32
} else if (output_type & kRepFloat64) { } else if (output_type & kRepFloat64) {
if (output_type & kTypeUint32 || use_unsigned) { if (output_type & kTypeUint32 || use_unsigned) {
op = machine()->ChangeFloat64ToUint32(); op = machine()->ChangeFloat64ToUint32();
...@@ -295,48 +292,24 @@ class RepresentationChanger { ...@@ -295,48 +292,24 @@ class RepresentationChanger {
Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) { Node* GetBitRepresentationFor(Node* node, MachineTypeUnion output_type) {
// Eagerly fold representation changes for constants. // Eagerly fold representation changes for constants.
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kInt32Constant: {
int32_t value = OpParameter<int32_t>(node);
if (value == 0 || value == 1) return node;
return jsgraph()->Int32Constant(1); // value != 0
}
case IrOpcode::kNumberConstant: {
double value = OpParameter<double>(node);
if (value == 0 || std::isnan(value)) return jsgraph()->Int32Constant(0);
return jsgraph()->Int32Constant(1); // value != +0.0, -0.0, NaN
}
case IrOpcode::kHeapConstant: { case IrOpcode::kHeapConstant: {
Handle<Object> object = OpParameter<Unique<Object>>(node).handle(); Handle<Object> value = OpParameter<Unique<Object> >(node).handle();
return jsgraph()->Int32Constant(object->BooleanValue() ? 1 : 0); DCHECK(value.is_identical_to(factory()->true_value()) ||
value.is_identical_to(factory()->false_value()));
return jsgraph()->Int32Constant(
value.is_identical_to(factory()->true_value()) ? 1 : 0);
} }
default: default:
break; break;
} }
// Select the correct X -> Bit operator. // Select the correct X -> Bit operator.
const Operator* op; const Operator* op;
if (output_type & rWord) { if (output_type & kRepTagged) {
op = simplified()->ChangeWord32ToBit();
} else if (output_type & kRepWord64) {
op = simplified()->ChangeWord64ToBit();
} else if (output_type & kRepTagged) {
Type* upper = NodeProperties::GetBounds(node).upper;
if (upper->Is(Type::Boolean())) {
op = simplified()->ChangeBoolToBit(); 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 { } else {
return TypeError(node, output_type, kRepBit); return TypeError(node, output_type, kRepBit);
} }
return graph()->NewNode(op, node); return jsgraph()->graph()->NewNode(op, node);
} }
Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) { Node* GetWord64RepresentationFor(Node* node, MachineTypeUnion output_type) {
...@@ -441,7 +414,6 @@ class RepresentationChanger { ...@@ -441,7 +414,6 @@ class RepresentationChanger {
JSGraph* jsgraph_; JSGraph* jsgraph_;
SimplifiedOperatorBuilder* simplified_; SimplifiedOperatorBuilder* simplified_;
Isolate* isolate_; Isolate* isolate_;
Type* bit_range_;
friend class RepresentationChangerTester; // accesses the below fields. friend class RepresentationChangerTester; // accesses the below fields.
...@@ -468,26 +440,20 @@ class RepresentationChanger { ...@@ -468,26 +440,20 @@ class RepresentationChanger {
} }
Node* InsertChangeFloat32ToFloat64(Node* node) { Node* InsertChangeFloat32ToFloat64(Node* node) {
return graph()->NewNode(machine()->ChangeFloat32ToFloat64(), node); return jsgraph()->graph()->NewNode(machine()->ChangeFloat32ToFloat64(),
node);
} }
Node* InsertChangeTaggedToFloat64(Node* node) { Node* InsertChangeTaggedToFloat64(Node* node) {
return graph()->NewNode(simplified()->ChangeTaggedToFloat64(), node); return jsgraph()->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);
} }
Graph* graph() const { return jsgraph()->graph(); }
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
SimplifiedOperatorBuilder* simplified() const { return simplified_; } Factory* factory() const { return isolate()->factory(); }
MachineOperatorBuilder* machine() const { return jsgraph()->machine(); } SimplifiedOperatorBuilder* simplified() { return simplified_; }
MachineOperatorBuilder* machine() { return jsgraph()->machine(); }
}; };
} // namespace compiler } // namespace compiler
......
...@@ -77,9 +77,6 @@ class RepresentationSelector { ...@@ -77,9 +77,6 @@ class RepresentationSelector {
memset(info_, 0, sizeof(NodeInfo) * count_); memset(info_, 0, sizeof(NodeInfo) * count_);
Factory* f = zone->isolate()->factory(); Factory* f = zone->isolate()->factory();
safe_bit_range_ =
Type::Union(Type::Boolean(),
Type::Range(f->NewNumber(0), f->NewNumber(1), zone), zone);
safe_int_additive_range_ = safe_int_additive_range_ =
Type::Range(f->NewNumber(-std::pow(2.0, 52.0)), Type::Range(f->NewNumber(-std::pow(2.0, 52.0)),
f->NewNumber(std::pow(2.0, 52.0)), zone); f->NewNumber(std::pow(2.0, 52.0)), zone);
...@@ -323,7 +320,7 @@ class RepresentationSelector { ...@@ -323,7 +320,7 @@ class RepresentationSelector {
} else { } else {
return kRepFloat64; return kRepFloat64;
} }
} else if (IsSafeBitOperand(node)) { } else if (upper->Is(Type::Boolean())) {
// multiple uses => pick kRepBit. // multiple uses => pick kRepBit.
return kRepBit; return kRepBit;
} else if (upper->Is(Type::Number())) { } else if (upper->Is(Type::Number())) {
...@@ -417,11 +414,6 @@ class RepresentationSelector { ...@@ -417,11 +414,6 @@ class RepresentationSelector {
return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use); return BothInputsAre(node, Type::Signed32()) && !CanObserveNonInt32(use);
} }
bool IsSafeBitOperand(Node* node) {
Type* type = NodeProperties::GetBounds(node).upper;
return type->Is(safe_bit_range_);
}
bool IsSafeIntAdditiveOperand(Node* node) { bool IsSafeIntAdditiveOperand(Node* node) {
Type* type = NodeProperties::GetBounds(node).upper; Type* type = NodeProperties::GetBounds(node).upper;
// TODO(jarin): Unfortunately, bitset types are not subtypes of larger // TODO(jarin): Unfortunately, bitset types are not subtypes of larger
...@@ -530,10 +522,6 @@ class RepresentationSelector { ...@@ -530,10 +522,6 @@ class RepresentationSelector {
// Simplified operators. // Simplified operators.
//------------------------------------------------------------------ //------------------------------------------------------------------
case IrOpcode::kAnyToBoolean: { case IrOpcode::kAnyToBoolean: {
if (IsSafeBitOperand(node->InputAt(0))) {
VisitUnop(node, kRepBit, kRepBit);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else {
VisitUnop(node, kMachAnyTagged, kTypeBool | kRepTagged); VisitUnop(node, kMachAnyTagged, kTypeBool | kRepTagged);
if (lower()) { if (lower()) {
// AnyToBoolean(x) => Call(ToBooleanStub, x, no-context) // AnyToBoolean(x) => Call(ToBooleanStub, x, no-context)
...@@ -548,7 +536,6 @@ class RepresentationSelector { ...@@ -548,7 +536,6 @@ class RepresentationSelector {
jsgraph_->HeapConstant(callable.code())); jsgraph_->HeapConstant(callable.code()));
node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant()); node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
} }
}
break; break;
} }
case IrOpcode::kBooleanNot: { case IrOpcode::kBooleanNot: {
...@@ -1080,7 +1067,6 @@ class RepresentationSelector { ...@@ -1080,7 +1067,6 @@ class RepresentationSelector {
Phase phase_; // current phase of algorithm Phase phase_; // current phase of algorithm
RepresentationChanger* changer_; // for inserting representation changes RepresentationChanger* changer_; // for inserting representation changes
ZoneQueue<Node*> queue_; // queue for traversing the graph ZoneQueue<Node*> queue_; // queue for traversing the graph
Type* safe_bit_range_;
Type* safe_int_additive_range_; Type* safe_int_additive_range_;
NodeInfo* GetInfo(Node* node) { NodeInfo* GetInfo(Node* node) {
......
...@@ -54,8 +54,6 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) { ...@@ -54,8 +54,6 @@ Reduction SimplifiedOperatorReducer::Reduce(Node* node) {
if (m.IsChangeBitToBool()) return Replace(m.node()->InputAt(0)); if (m.IsChangeBitToBool()) return Replace(m.node()->InputAt(0));
break; break;
} }
case IrOpcode::kChangeWord32ToBit:
return ReduceChangeWord32ToBit(node);
case IrOpcode::kChangeFloat64ToTagged: { case IrOpcode::kChangeFloat64ToTagged: {
Float64Matcher m(node->InputAt(0)); Float64Matcher m(node->InputAt(0));
if (m.HasValue()) return ReplaceNumber(m.Value()); if (m.HasValue()) return ReplaceNumber(m.Value());
...@@ -138,17 +136,6 @@ Reduction SimplifiedOperatorReducer::ReduceAnyToBoolean(Node* node) { ...@@ -138,17 +136,6 @@ 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, Reduction SimplifiedOperatorReducer::Change(Node* node, const Operator* op,
Node* a) { Node* a) {
DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op)); DCHECK_EQ(node->InputCount(), OperatorProperties::GetTotalInputCount(op));
......
...@@ -13,6 +13,7 @@ namespace internal { ...@@ -13,6 +13,7 @@ namespace internal {
// Forward declarations. // Forward declarations.
class Factory; class Factory;
class Heap;
namespace compiler { namespace compiler {
...@@ -30,7 +31,6 @@ class SimplifiedOperatorReducer FINAL : public Reducer { ...@@ -30,7 +31,6 @@ class SimplifiedOperatorReducer FINAL : public Reducer {
private: private:
Reduction ReduceAnyToBoolean(Node* node); Reduction ReduceAnyToBoolean(Node* node);
Reduction ReduceChangeWord32ToBit(Node* node);
Reduction Change(Node* node, const Operator* op, Node* a); Reduction Change(Node* node, const Operator* op, Node* a);
Reduction ReplaceFloat64(double value); Reduction ReplaceFloat64(double value);
......
...@@ -182,10 +182,8 @@ const ElementAccess& ElementAccessOf(const Operator* op) { ...@@ -182,10 +182,8 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
V(ChangeInt32ToTagged, Operator::kNoProperties, 1) \ V(ChangeInt32ToTagged, Operator::kNoProperties, 1) \
V(ChangeUint32ToTagged, Operator::kNoProperties, 1) \ V(ChangeUint32ToTagged, Operator::kNoProperties, 1) \
V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \ V(ChangeFloat64ToTagged, Operator::kNoProperties, 1) \
V(ChangeBitToBool, Operator::kNoProperties, 1) \
V(ChangeBoolToBit, Operator::kNoProperties, 1) \ V(ChangeBoolToBit, Operator::kNoProperties, 1) \
V(ChangeWord32ToBit, Operator::kNoProperties, 1) \ V(ChangeBitToBool, Operator::kNoProperties, 1) \
V(ChangeWord64ToBit, Operator::kNoProperties, 1) \
V(ObjectIsSmi, Operator::kNoProperties, 1) \ V(ObjectIsSmi, Operator::kNoProperties, 1) \
V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1) V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
......
...@@ -159,10 +159,8 @@ class SimplifiedOperatorBuilder FINAL { ...@@ -159,10 +159,8 @@ class SimplifiedOperatorBuilder FINAL {
const Operator* ChangeInt32ToTagged(); const Operator* ChangeInt32ToTagged();
const Operator* ChangeUint32ToTagged(); const Operator* ChangeUint32ToTagged();
const Operator* ChangeFloat64ToTagged(); const Operator* ChangeFloat64ToTagged();
const Operator* ChangeBitToBool();
const Operator* ChangeBoolToBit(); const Operator* ChangeBoolToBit();
const Operator* ChangeWord32ToBit(); const Operator* ChangeBitToBool();
const Operator* ChangeWord64ToBit();
const Operator* ObjectIsSmi(); const Operator* ObjectIsSmi();
const Operator* ObjectIsNonNegativeSmi(); const Operator* ObjectIsNonNegativeSmi();
......
...@@ -1611,14 +1611,6 @@ Bounds Typer::Visitor::TypeChangeFloat64ToTagged(Node* node) { ...@@ -1611,14 +1611,6 @@ 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 Typer::Visitor::TypeChangeBoolToBit(Node* node) {
Bounds arg = Operand(node, 0); Bounds arg = Operand(node, 0);
// TODO(neis): DCHECK(arg.upper->Is(Type::Boolean())); // TODO(neis): DCHECK(arg.upper->Is(Type::Boolean()));
...@@ -1628,15 +1620,11 @@ Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) { ...@@ -1628,15 +1620,11 @@ Bounds Typer::Visitor::TypeChangeBoolToBit(Node* node) {
} }
Bounds Typer::Visitor::TypeChangeWord32ToBit(Node* node) { Bounds Typer::Visitor::TypeChangeBitToBool(Node* node) {
return Bounds( Bounds arg = Operand(node, 0);
ChangeRepresentation(Type::Boolean(), Type::UntaggedBit(), zone())); // 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::TypeChangeWord64ToBit(Node* node) {
return Bounds(
ChangeRepresentation(Type::Boolean(), Type::UntaggedBit(), zone()));
} }
......
...@@ -632,15 +632,6 @@ void Verifier::Visitor::Pre(Node* node) { ...@@ -632,15 +632,6 @@ void Verifier::Visitor::Pre(Node* node) {
// CheckUpperIs(node, to)); // CheckUpperIs(node, to));
break; 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: { case IrOpcode::kChangeBoolToBit: {
// Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1 // Boolean /\ TaggedPtr -> Boolean /\ UntaggedInt1
// TODO(neis): Activate once ChangeRepresentation works in typer. // TODO(neis): Activate once ChangeRepresentation works in typer.
...@@ -650,13 +641,13 @@ void Verifier::Visitor::Pre(Node* node) { ...@@ -650,13 +641,13 @@ void Verifier::Visitor::Pre(Node* node) {
// CheckUpperIs(node, to)); // CheckUpperIs(node, to));
break; break;
} }
case IrOpcode::kChangeWord32ToBit: { case IrOpcode::kChangeBitToBool: {
// TODO(rossberg): Check. // Boolean /\ UntaggedInt1 -> Boolean /\ TaggedPtr
CheckValueInputIs(node, 0, Type::Integral32()); // TODO(neis): Activate once ChangeRepresentation works in typer.
break; // Type* from = Type::Intersect(Type::Boolean(), Type::UntaggedInt1());
} // Type* to = Type::Intersect(Type::Boolean(), Type::TaggedPtr());
case IrOpcode::kChangeWord64ToBit: { // CheckValueInputIs(node, 0, from));
// TODO(rossberg): Check. // CheckUpperIs(node, to));
break; break;
} }
......
...@@ -79,14 +79,10 @@ class RepresentationChangerTester : public HandleAndZoneScope, ...@@ -79,14 +79,10 @@ class RepresentationChangerTester : public HandleAndZoneScope,
CHECK_EQ(expected, m.Value()); CHECK_EQ(expected, m.Value());
} }
Node* Parameter(Type* type, int index = 0) { Node* Parameter(int index = 0) {
Node* node = graph()->NewNode(common()->Parameter(index), graph()->start()); return 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) { void CheckTypeError(MachineTypeUnion from, MachineTypeUnion to) {
changer()->testing_type_errors_ = true; changer()->testing_type_errors_ = true;
changer()->type_error_ = false; changer()->type_error_ = false;
...@@ -102,17 +98,16 @@ class RepresentationChangerTester : public HandleAndZoneScope, ...@@ -102,17 +98,16 @@ class RepresentationChangerTester : public HandleAndZoneScope,
CHECK_EQ(n, c); CHECK_EQ(n, c);
} }
}; };
}
} // namespace compiler }
} // namespace internal } // namespace v8::internal::compiler
} // namespace v8
static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64, static const MachineType all_reps[] = {kRepBit, kRepWord32, kRepWord64,
kRepFloat32, kRepFloat64, kRepTagged}; kRepFloat32, kRepFloat64, kRepTagged};
TEST(ToBit_constant) { TEST(BoolToBit_constant) {
RepresentationChangerTester r; RepresentationChangerTester r;
Node* true_node = r.jsgraph()->TrueConstant(); Node* true_node = r.jsgraph()->TrueConstant();
...@@ -124,22 +119,6 @@ TEST(ToBit_constant) { ...@@ -124,22 +119,6 @@ TEST(ToBit_constant) {
Node* false_bit = Node* false_bit =
r.changer()->GetRepresentationFor(false_node, kRepTagged, kRepBit); r.changer()->GetRepresentationFor(false_node, kRepTagged, kRepBit);
r.CheckInt32Constant(false_bit, 0); 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);
}
}
} }
...@@ -391,10 +370,10 @@ TEST(ToUint32_constant) { ...@@ -391,10 +370,10 @@ TEST(ToUint32_constant) {
static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from,
MachineTypeUnion to, Type* from_type = Type::Any()) { MachineTypeUnion to) {
RepresentationChangerTester r; RepresentationChangerTester r;
Node* n = r.Parameter(from_type); Node* n = r.Parameter();
Node* c = r.changer()->GetRepresentationFor(n, from, to); Node* c = r.changer()->GetRepresentationFor(n, from, to);
CHECK_NE(c, n); CHECK_NE(c, n);
...@@ -405,11 +384,10 @@ static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from, ...@@ -405,11 +384,10 @@ static void CheckChange(IrOpcode::Value expected, MachineTypeUnion from,
static void CheckTwoChanges(IrOpcode::Value expected2, static void CheckTwoChanges(IrOpcode::Value expected2,
IrOpcode::Value expected1, MachineTypeUnion from, IrOpcode::Value expected1, MachineTypeUnion from,
MachineTypeUnion to, MachineTypeUnion to) {
Type* from_type = Type::Any()) {
RepresentationChangerTester r; RepresentationChangerTester r;
Node* n = r.Parameter(from_type); Node* n = r.Parameter();
Node* c1 = r.changer()->GetRepresentationFor(n, from, to); Node* c1 = r.changer()->GetRepresentationFor(n, from, to);
CHECK_NE(c1, n); CHECK_NE(c1, n);
...@@ -422,15 +400,7 @@ static void CheckTwoChanges(IrOpcode::Value expected2, ...@@ -422,15 +400,7 @@ static void CheckTwoChanges(IrOpcode::Value expected2,
TEST(SingleChanges) { TEST(SingleChanges) {
CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit, Type::Boolean()); CheckChange(IrOpcode::kChangeBoolToBit, kRepTagged, kRepBit);
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::kChangeBitToBool, kRepBit, kRepTagged);
CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32, CheckChange(IrOpcode::kChangeInt32ToTagged, kRepWord32 | kTypeInt32,
...@@ -534,6 +504,16 @@ TEST(Nops) { ...@@ -534,6 +504,16 @@ TEST(Nops) {
TEST(TypeErrors) { TEST(TypeErrors) {
RepresentationChangerTester r; RepresentationChangerTester r;
// Wordish cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(kRepWord8, kRepBit);
r.CheckTypeError(kRepWord8, kRepBit | kTypeBool);
r.CheckTypeError(kRepWord16, kRepBit);
r.CheckTypeError(kRepWord16, kRepBit | kTypeBool);
r.CheckTypeError(kRepWord32, kRepBit);
r.CheckTypeError(kRepWord32, kRepBit | kTypeBool);
r.CheckTypeError(kRepWord64, kRepBit);
r.CheckTypeError(kRepWord64, kRepBit | kTypeBool);
// Floats cannot be implicitly converted to/from comparison conditions. // Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(kRepFloat64, kRepBit); r.CheckTypeError(kRepFloat64, kRepBit);
r.CheckTypeError(kRepFloat64, kRepBit | kTypeBool); r.CheckTypeError(kRepFloat64, kRepBit | kTypeBool);
......
...@@ -787,31 +787,6 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders { ...@@ -787,31 +787,6 @@ class TestingGraph : public HandleAndZoneScope, public GraphAndBuilders {
}; };
TEST(LowerAnyToBoolean_bit_bit) {
// AnyToBoolean(x: kRepBit) used as kRepBit
HandleAndZoneScope scope;
Factory* f = scope.main_zone()->isolate()->factory();
Handle<Object> zero = f->NewNumber(0);
Handle<Object> one = f->NewNumber(1);
Type* singleton_zero = Type::Constant(zero, scope.main_zone());
Type* singleton_one = Type::Constant(one, scope.main_zone());
Type* zero_one_range = Type::Range(zero, one, scope.main_zone());
static Type* kTypes[] = {
singleton_zero, singleton_one, zero_one_range, Type::Boolean(),
Type::Union(Type::Boolean(), singleton_zero, scope.main_zone()),
Type::Union(Type::Boolean(), singleton_one, scope.main_zone()),
Type::Union(Type::Boolean(), zero_one_range, scope.main_zone())};
for (Type* type : kTypes) {
TestingGraph t(type);
Node* x = t.ExampleWithTypeAndRep(type, kRepBit);
Node* cnv = t.graph()->NewNode(t.simplified()->AnyToBoolean(), x);
Node* use = t.Branch(cnv);
t.Lower();
CHECK_EQ(x, use->InputAt(0));
}
}
#if V8_TURBOFAN_TARGET #if V8_TURBOFAN_TARGET
TEST(LowerAnyToBoolean_tagged_tagged) { TEST(LowerAnyToBoolean_tagged_tagged) {
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var stdlib = this;
var buffer = new ArrayBuffer(64 * 1024);
var foreign = {}
var foo = (function Module(stdlib, foreign, heap) {
"use asm";
function foo(i) {
var x = i ? (i&1) : true;
if (x) return x;
return false;
}
return {foo:foo};
})(stdlib, foreign, buffer).foo;
assertEquals(1, foo(1));
...@@ -15,4 +15,3 @@ var foo = (function Module(stdlib, foreign, heap) { ...@@ -15,4 +15,3 @@ var foo = (function Module(stdlib, foreign, heap) {
})(stdlib, foreign, buffer).foo; })(stdlib, foreign, buffer).foo;
assertFalse(foo(1)); assertFalse(foo(1));
assertTrue(foo(0));
...@@ -132,29 +132,8 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) { ...@@ -132,29 +132,8 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val); Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
Reduction reduction = Reduce(node); Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed()); ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant()));
}
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)));
} }
......
...@@ -123,57 +123,6 @@ static const uint32_t kUint32Values[] = { ...@@ -123,57 +123,6 @@ static const uint32_t kUint32Values[] = {
} // namespace } // namespace
// -----------------------------------------------------------------------------
// Unary operators
namespace {
struct UnaryOperator {
const Operator* (SimplifiedOperatorBuilder::*constructor)();
const char* constructor_name;
};
std::ostream& operator<<(std::ostream& os, const UnaryOperator& unop) {
return os << unop.constructor_name;
}
static const UnaryOperator kUnaryOperators[] = {
{&SimplifiedOperatorBuilder::AnyToBoolean, "AnyToBoolean"},
{&SimplifiedOperatorBuilder::BooleanNot, "BooleanNot"},
{&SimplifiedOperatorBuilder::ChangeBitToBool, "ChangeBitToBool"},
{&SimplifiedOperatorBuilder::ChangeBoolToBit, "ChangeBoolToBit"},
{&SimplifiedOperatorBuilder::ChangeFloat64ToTagged,
"ChangeFloat64ToTagged"},
{&SimplifiedOperatorBuilder::ChangeInt32ToTagged, "ChangeInt32ToTagged"},
{&SimplifiedOperatorBuilder::ChangeTaggedToFloat64,
"ChangeTaggedToFloat64"},
{&SimplifiedOperatorBuilder::ChangeTaggedToInt32, "ChangeTaggedToInt32"},
{&SimplifiedOperatorBuilder::ChangeTaggedToUint32, "ChangeTaggedToUint32"},
{&SimplifiedOperatorBuilder::ChangeUint32ToTagged, "ChangeUint32ToTagged"}};
} // namespace
typedef SimplifiedOperatorReducerTestWithParam<UnaryOperator>
SimplifiedUnaryOperatorTest;
TEST_P(SimplifiedUnaryOperatorTest, Parameter) {
const UnaryOperator& unop = GetParam();
Reduction reduction = Reduce(graph()->NewNode(
(simplified()->*unop.constructor)(), Parameter(Type::Any())));
EXPECT_FALSE(reduction.Changed());
}
INSTANTIATE_TEST_CASE_P(SimplifiedOperatorReducerTest,
SimplifiedUnaryOperatorTest,
::testing::ValuesIn(kUnaryOperators));
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// AnyToBoolean // AnyToBoolean
...@@ -297,27 +246,6 @@ TEST_F(SimplifiedOperatorReducerTest, ChangeBoolToBitWithChangeBitToBool) { ...@@ -297,27 +246,6 @@ 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 // ChangeFloat64ToTagged
......
...@@ -63,8 +63,6 @@ const PureOperator kPureOperators[] = { ...@@ -63,8 +63,6 @@ const PureOperator kPureOperators[] = {
PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1), PURE(ChangeUint32ToTagged, Operator::kNoProperties, 1),
PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1), PURE(ChangeFloat64ToTagged, Operator::kNoProperties, 1),
PURE(ChangeBoolToBit, Operator::kNoProperties, 1), PURE(ChangeBoolToBit, Operator::kNoProperties, 1),
PURE(ChangeWord32ToBit, Operator::kNoProperties, 1),
PURE(ChangeWord64ToBit, Operator::kNoProperties, 1),
PURE(ChangeBitToBool, Operator::kNoProperties, 1), PURE(ChangeBitToBool, Operator::kNoProperties, 1),
PURE(ObjectIsSmi, Operator::kNoProperties, 1), PURE(ObjectIsSmi, Operator::kNoProperties, 1),
PURE(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1) PURE(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment