Commit b37e7861 authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Replace MachineSemantic with Type in simplified lowering.

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

Cr-Commit-Position: refs/heads/master@{#33222}
parent b369fefc
......@@ -107,23 +107,22 @@ bool IsWord(MachineRepresentation rep) {
} // namespace
// Changes representation from {output_type} to {use_rep}. The {truncation}
// Changes representation from {output_rep} to {use_rep}. The {truncation}
// parameter is only used for sanity checking - if the changer cannot figure
// out signedness for the word32->float64 conversion, then we check that the
// uses truncate to word32 (so they do not care about signedness).
Node* RepresentationChanger::GetRepresentationFor(Node* node,
MachineType output_type,
MachineRepresentation use_rep,
Truncation truncation) {
if (output_type.representation() == MachineRepresentation::kNone) {
Node* RepresentationChanger::GetRepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type,
MachineRepresentation use_rep, Truncation truncation) {
if (output_rep == MachineRepresentation::kNone) {
// The output representation should be set.
return TypeError(node, output_type, use_rep);
return TypeError(node, output_rep, output_type, use_rep);
}
if (use_rep == output_type.representation()) {
if (use_rep == output_rep) {
// Representations are the same. That's a no-op.
return node;
}
if (IsWord(use_rep) && IsWord(output_type.representation())) {
if (IsWord(use_rep) && IsWord(output_rep)) {
// Both are words less than or equal to 32-bits.
// Since loads of integers from memory implicitly sign or zero extend the
// value to the full machine word size and stores implicitly truncate,
......@@ -132,19 +131,21 @@ Node* RepresentationChanger::GetRepresentationFor(Node* node,
}
switch (use_rep) {
case MachineRepresentation::kTagged:
return GetTaggedRepresentationFor(node, output_type);
return GetTaggedRepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kFloat32:
return GetFloat32RepresentationFor(node, output_type, truncation);
return GetFloat32RepresentationFor(node, output_rep, output_type,
truncation);
case MachineRepresentation::kFloat64:
return GetFloat64RepresentationFor(node, output_type, truncation);
return GetFloat64RepresentationFor(node, output_rep, output_type,
truncation);
case MachineRepresentation::kBit:
return GetBitRepresentationFor(node, output_type);
return GetBitRepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kWord8:
case MachineRepresentation::kWord16:
case MachineRepresentation::kWord32:
return GetWord32RepresentationFor(node, output_type);
return GetWord32RepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kWord64:
return GetWord64RepresentationFor(node, output_type);
return GetWord64RepresentationFor(node, output_rep, output_type);
case MachineRepresentation::kNone:
return node;
}
......@@ -154,24 +155,25 @@ Node* RepresentationChanger::GetRepresentationFor(Node* node,
Node* RepresentationChanger::GetTaggedRepresentationFor(
Node* node, MachineType output_type) {
Node* node, MachineRepresentation output_rep, Type* output_type) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kNumberConstant:
case IrOpcode::kHeapConstant:
return node; // No change necessary.
case IrOpcode::kInt32Constant:
if (output_type.semantic() == MachineSemantic::kUint32) {
uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
return jsgraph()->Constant(static_cast<double>(value));
} else if (output_type.semantic() == MachineSemantic::kInt32) {
if (output_type->Is(Type::Signed32())) {
int32_t value = OpParameter<int32_t>(node);
return jsgraph()->Constant(value);
} else if (output_type.representation() == MachineRepresentation::kBit) {
} else if (output_type->Is(Type::Unsigned32())) {
uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
return jsgraph()->Constant(static_cast<double>(value));
} else if (output_rep == MachineRepresentation::kBit) {
return OpParameter<int32_t>(node) == 0 ? jsgraph()->FalseConstant()
: jsgraph()->TrueConstant();
} else {
return TypeError(node, output_type, MachineRepresentation::kTagged);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTagged);
}
case IrOpcode::kFloat64Constant:
return jsgraph()->Constant(OpParameter<double>(node));
......@@ -182,31 +184,34 @@ Node* RepresentationChanger::GetTaggedRepresentationFor(
}
// Select the correct X -> Tagged operator.
const Operator* op;
if (output_type.representation() == MachineRepresentation::kBit) {
if (output_rep == MachineRepresentation::kBit) {
op = simplified()->ChangeBitToBool();
} else if (IsWord(output_type.representation())) {
if (output_type.semantic() == MachineSemantic::kUint32) {
} else if (IsWord(output_rep)) {
if (output_type->Is(Type::Unsigned32())) {
op = simplified()->ChangeUint32ToTagged();
} else if (output_type.semantic() == MachineSemantic::kInt32) {
} else if (output_type->Is(Type::Signed32())) {
op = simplified()->ChangeInt32ToTagged();
} else {
return TypeError(node, output_type, MachineRepresentation::kTagged);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTagged);
}
} else if (output_type.representation() ==
} else if (output_rep ==
MachineRepresentation::kFloat32) { // float32 -> float64 -> tagged
node = InsertChangeFloat32ToFloat64(node);
op = simplified()->ChangeFloat64ToTagged();
} else if (output_type.representation() == MachineRepresentation::kFloat64) {
} else if (output_rep == MachineRepresentation::kFloat64) {
op = simplified()->ChangeFloat64ToTagged();
} else {
return TypeError(node, output_type, MachineRepresentation::kTagged);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kTagged);
}
return jsgraph()->graph()->NewNode(op, node);
}
Node* RepresentationChanger::GetFloat32RepresentationFor(
Node* node, MachineType output_type, Truncation truncation) {
Node* node, MachineRepresentation output_rep, Type* output_type,
Truncation truncation) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kFloat64Constant:
......@@ -214,7 +219,7 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
return jsgraph()->Float32Constant(
DoubleToFloat32(OpParameter<double>(node)));
case IrOpcode::kInt32Constant:
if (output_type.semantic() == MachineSemantic::kUint32) {
if (output_type->Is(Type::Unsigned32())) {
uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
return jsgraph()->Float32Constant(static_cast<float>(value));
} else {
......@@ -228,47 +233,51 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
}
// Select the correct X -> Float32 operator.
const Operator* op;
if (output_type.representation() == MachineRepresentation::kBit) {
return TypeError(node, output_type, MachineRepresentation::kFloat32);
} else if (IsWord(output_type.representation())) {
if (output_type.semantic() == MachineSemantic::kUint32) {
op = machine()->ChangeUint32ToFloat64();
if (output_rep == MachineRepresentation::kBit) {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kFloat32);
} else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeInt32ToFloat64();
} else {
// Either the output is int32 or the uses only care about the
// low 32 bits (so we can pick int32 safely).
DCHECK(output_type.semantic() == MachineSemantic::kInt32 ||
DCHECK(output_type->Is(Type::Unsigned32()) ||
truncation.TruncatesToWord32());
op = machine()->ChangeInt32ToFloat64();
op = machine()->ChangeUint32ToFloat64();
}
// int32 -> float64 -> float32
node = jsgraph()->graph()->NewNode(op, node);
op = machine()->TruncateFloat64ToFloat32();
} else if (output_type.representation() == MachineRepresentation::kTagged) {
} else if (output_rep == MachineRepresentation::kTagged) {
op = simplified()->ChangeTaggedToFloat64(); // tagged -> float64 -> float32
node = jsgraph()->graph()->NewNode(op, node);
op = machine()->TruncateFloat64ToFloat32();
} else if (output_type.representation() == MachineRepresentation::kFloat64) {
} else if (output_rep == MachineRepresentation::kFloat64) {
op = machine()->TruncateFloat64ToFloat32();
} else {
return TypeError(node, output_type, MachineRepresentation::kFloat32);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kFloat32);
}
return jsgraph()->graph()->NewNode(op, node);
}
Node* RepresentationChanger::GetFloat64RepresentationFor(
Node* node, MachineType output_type, Truncation truncation) {
Node* node, MachineRepresentation output_rep, Type* output_type,
Truncation truncation) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kNumberConstant:
return jsgraph()->Float64Constant(OpParameter<double>(node));
case IrOpcode::kInt32Constant:
if (output_type.semantic() == MachineSemantic::kUint32) {
uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
return jsgraph()->Float64Constant(static_cast<double>(value));
} else {
if (output_type->Is(Type::Signed32())) {
int32_t value = OpParameter<int32_t>(node);
return jsgraph()->Float64Constant(value);
} else {
DCHECK(output_type->Is(Type::Unsigned32()));
uint32_t value = static_cast<uint32_t>(OpParameter<int32_t>(node));
return jsgraph()->Float64Constant(static_cast<double>(value));
}
case IrOpcode::kFloat64Constant:
return node; // No change necessary.
......@@ -279,24 +288,26 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
}
// Select the correct X -> Float64 operator.
const Operator* op;
if (output_type.representation() == MachineRepresentation::kBit) {
return TypeError(node, output_type, MachineRepresentation::kFloat64);
} else if (IsWord(output_type.representation())) {
if (output_type.semantic() == MachineSemantic::kUint32) {
op = machine()->ChangeUint32ToFloat64();
if (output_rep == MachineRepresentation::kBit) {
return TypeError(node, output_rep, output_type,
MachineRepresentation::kFloat64);
} else if (IsWord(output_rep)) {
if (output_type->Is(Type::Signed32())) {
op = machine()->ChangeInt32ToFloat64();
} else {
// Either the output is int32 or the uses only care about the
// low 32 bits (so we can pick int32 safely).
DCHECK(output_type.semantic() == MachineSemantic::kInt32 ||
DCHECK(output_type->Is(Type::Unsigned32()) ||
truncation.TruncatesToWord32());
op = machine()->ChangeInt32ToFloat64();
op = machine()->ChangeUint32ToFloat64();
}
} else if (output_type.representation() == MachineRepresentation::kTagged) {
} else if (output_rep == MachineRepresentation::kTagged) {
op = simplified()->ChangeTaggedToFloat64();
} else if (output_type.representation() == MachineRepresentation::kFloat32) {
} else if (output_rep == MachineRepresentation::kFloat32) {
op = machine()->ChangeFloat32ToFloat64();
} else {
return TypeError(node, output_type, MachineRepresentation::kFloat64);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kFloat64);
}
return jsgraph()->graph()->NewNode(op, node);
}
......@@ -308,7 +319,7 @@ Node* RepresentationChanger::MakeTruncatedInt32Constant(double value) {
Node* RepresentationChanger::GetWord32RepresentationFor(
Node* node, MachineType output_type) {
Node* node, MachineRepresentation output_rep, Type* output_type) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kInt32Constant:
......@@ -325,34 +336,33 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
const Operator* op;
Type* type = NodeProperties::GetType(node);
if (output_type.representation() == MachineRepresentation::kBit) {
if (output_rep == MachineRepresentation::kBit) {
return node; // Sloppy comparison -> word32
} else if (output_type.representation() == MachineRepresentation::kFloat64) {
if (output_type.semantic() == MachineSemantic::kUint32 ||
type->Is(Type::Unsigned32())) {
} else if (output_rep == MachineRepresentation::kFloat64) {
// TODO(jarin) Use only output_type here, once we intersect it with the
// type inferred by the typer.
if (output_type->Is(Type::Unsigned32()) || type->Is(Type::Unsigned32())) {
op = machine()->ChangeFloat64ToUint32();
} else if (output_type.semantic() == MachineSemantic::kInt32 ||
} else if (output_type->Is(Type::Signed32()) ||
type->Is(Type::Signed32())) {
op = machine()->ChangeFloat64ToInt32();
} else {
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
}
} else if (output_type.representation() == MachineRepresentation::kFloat32) {
} else if (output_rep == MachineRepresentation::kFloat32) {
node = InsertChangeFloat32ToFloat64(node); // float32 -> float64 -> int32
if (output_type.semantic() == MachineSemantic::kUint32 ||
type->Is(Type::Unsigned32())) {
if (output_type->Is(Type::Unsigned32()) || type->Is(Type::Unsigned32())) {
op = machine()->ChangeFloat64ToUint32();
} else if (output_type.semantic() == MachineSemantic::kInt32 ||
} else if (output_type->Is(Type::Signed32()) ||
type->Is(Type::Signed32())) {
op = machine()->ChangeFloat64ToInt32();
} else {
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
}
} else if (output_type.representation() == MachineRepresentation::kTagged) {
if (output_type.semantic() == MachineSemantic::kUint32 ||
type->Is(Type::Unsigned32())) {
} else if (output_rep == MachineRepresentation::kTagged) {
if (output_type->Is(Type::Unsigned32()) || type->Is(Type::Unsigned32())) {
op = simplified()->ChangeTaggedToUint32();
} else if (output_type.semantic() == MachineSemantic::kInt32 ||
} else if (output_type->Is(Type::Signed32()) ||
type->Is(Type::Signed32())) {
op = simplified()->ChangeTaggedToInt32();
} else {
......@@ -360,14 +370,15 @@ Node* RepresentationChanger::GetWord32RepresentationFor(
op = machine()->TruncateFloat64ToInt32(TruncationMode::kJavaScript);
}
} else {
return TypeError(node, output_type, MachineRepresentation::kWord32);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kWord32);
}
return jsgraph()->graph()->NewNode(op, node);
}
Node* RepresentationChanger::GetBitRepresentationFor(Node* node,
MachineType output_type) {
Node* RepresentationChanger::GetBitRepresentationFor(
Node* node, MachineRepresentation output_rep, Type* output_type) {
// Eagerly fold representation changes for constants.
switch (node->opcode()) {
case IrOpcode::kHeapConstant: {
......@@ -382,22 +393,24 @@ Node* RepresentationChanger::GetBitRepresentationFor(Node* node,
}
// Select the correct X -> Bit operator.
const Operator* op;
if (output_type.representation() == MachineRepresentation::kTagged) {
if (output_rep == MachineRepresentation::kTagged) {
op = simplified()->ChangeBoolToBit();
} else {
return TypeError(node, output_type, MachineRepresentation::kBit);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kBit);
}
return jsgraph()->graph()->NewNode(op, node);
}
Node* RepresentationChanger::GetWord64RepresentationFor(
Node* node, MachineType output_type) {
if (output_type.representation() == MachineRepresentation::kBit) {
Node* node, MachineRepresentation output_rep, Type* output_type) {
if (output_rep == MachineRepresentation::kBit) {
return node; // Sloppy comparison -> word64
}
// Can't really convert Word64 to anything else. Purported to be internal.
return TypeError(node, output_type, MachineRepresentation::kWord64);
return TypeError(node, output_rep, output_type,
MachineRepresentation::kWord64);
}
......@@ -485,22 +498,16 @@ const Operator* RepresentationChanger::Float64OperatorFor(
}
MachineSemantic RepresentationChanger::TypeFromUpperBound(Type* type) {
CHECK(!type->Is(Type::None()));
if (type->Is(Type::Signed32())) return MachineSemantic::kInt32;
if (type->Is(Type::Unsigned32())) return MachineSemantic::kUint32;
if (type->Is(Type::Number())) return MachineSemantic::kNumber;
if (type->Is(Type::Boolean())) return MachineSemantic::kBool;
return MachineSemantic::kAny;
}
Node* RepresentationChanger::TypeError(Node* node, MachineType output_type,
Node* RepresentationChanger::TypeError(Node* node,
MachineRepresentation output_rep,
Type* output_type,
MachineRepresentation use) {
type_error_ = true;
if (!testing_type_errors_) {
std::ostringstream out_str;
out_str << output_type;
out_str << output_rep << " (";
output_type->PrintTo(out_str, Type::SEMANTIC_DIM);
out_str << ")";
std::ostringstream use_str;
use_str << use;
......
......@@ -86,13 +86,12 @@ class RepresentationChanger final {
// parameter is only used for sanity checking - if the changer cannot figure
// out signedness for the word32->float64 conversion, then we check that the
// uses truncate to word32 (so they do not care about signedness).
Node* GetRepresentationFor(Node* node, MachineType output_type,
MachineRepresentation use_rep,
Node* GetRepresentationFor(Node* node, MachineRepresentation output_rep,
Type* output_type, MachineRepresentation use_rep,
Truncation truncation = Truncation::None());
const Operator* Int32OperatorFor(IrOpcode::Value opcode);
const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
const Operator* Float64OperatorFor(IrOpcode::Value opcode);
MachineSemantic TypeFromUpperBound(Type* type);
MachineType TypeForBasePointer(const FieldAccess& access) {
return access.tag() != 0 ? MachineType::AnyTagged()
......@@ -113,16 +112,22 @@ class RepresentationChanger final {
bool testing_type_errors_; // If {true}, don't abort on a type error.
bool type_error_; // Set when a type error is detected.
Node* GetTaggedRepresentationFor(Node* node, MachineType output_type);
Node* GetFloat32RepresentationFor(Node* node, MachineType output_type,
Truncation truncation);
Node* GetFloat64RepresentationFor(Node* node, MachineType output_type,
Truncation truncation);
Node* GetWord32RepresentationFor(Node* node, MachineType output_type);
Node* GetBitRepresentationFor(Node* node, MachineType output_type);
Node* GetWord64RepresentationFor(Node* node, MachineType output_type);
Node* TypeError(Node* node, MachineType output_type,
MachineRepresentation use);
Node* GetTaggedRepresentationFor(Node* node, MachineRepresentation output_rep,
Type* output_type);
Node* GetFloat32RepresentationFor(Node* node,
MachineRepresentation output_rep,
Type* output_type, Truncation truncation);
Node* GetFloat64RepresentationFor(Node* node,
MachineRepresentation output_rep,
Type* output_type, Truncation truncation);
Node* GetWord32RepresentationFor(Node* node, MachineRepresentation output_rep,
Type* output_type);
Node* GetBitRepresentationFor(Node* node, MachineRepresentation output_rep,
Type* output_type);
Node* GetWord64RepresentationFor(Node* node, MachineRepresentation output_rep,
Type* output_type);
Node* TypeError(Node* node, MachineRepresentation output_rep,
Type* output_type, MachineRepresentation use);
Node* MakeTruncatedInt32Constant(double value);
Node* InsertChangeFloat32ToFloat64(Node* node);
Node* InsertChangeTaggedToFloat64(Node* node);
......
......@@ -162,34 +162,6 @@ UseInfo UseInfoForBasePointer(const ElementAccess& access) {
#ifdef DEBUG
// Helpers for monotonicity checking.
bool MachineTypeIsSubtype(MachineSemantic t1, MachineSemantic t2) {
switch (t1) {
case MachineSemantic::kNone:
return true;
case MachineSemantic::kBool:
return t2 == MachineSemantic::kBool || t2 == MachineSemantic::kNumber ||
t2 == MachineSemantic::kAny;
case MachineSemantic::kInt32:
return t2 == MachineSemantic::kInt32 || t2 == MachineSemantic::kNumber ||
t2 == MachineSemantic::kAny;
case MachineSemantic::kUint32:
return t2 == MachineSemantic::kUint32 || t2 == MachineSemantic::kNumber ||
t2 == MachineSemantic::kAny;
case MachineSemantic::kInt64:
return t2 == MachineSemantic::kInt64;
case MachineSemantic::kUint64:
return t2 == MachineSemantic::kUint64;
case MachineSemantic::kNumber:
return t2 == MachineSemantic::kNumber || t2 == MachineSemantic::kAny;
case MachineSemantic::kAny:
return t2 == MachineSemantic::kAny;
}
UNREACHABLE();
return false;
}
bool MachineRepresentationIsSubtype(MachineRepresentation r1,
MachineRepresentation r2) {
switch (r1) {
......@@ -235,13 +207,6 @@ bool MachineRepresentationIsSubtype(MachineRepresentation r1,
}
bool MachineTypeRepIsSubtype(MachineType m1, MachineType m2) {
return MachineTypeIsSubtype(m1.semantic(), m2.semantic()) &&
MachineRepresentationIsSubtype(m1.representation(),
m2.representation());
}
class InputUseInfos {
public:
explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
......@@ -273,6 +238,71 @@ class InputUseInfos {
class RepresentationSelector {
public:
// Information for each node tracked during the fixpoint.
class NodeOutputInfo {
public:
NodeOutputInfo(MachineRepresentation representation, Type* type)
: type_(type), representation_(representation) {}
NodeOutputInfo()
: type_(Type::None()), representation_(MachineRepresentation::kNone) {}
MachineRepresentation representation() const { return representation_; }
Type* type() const { return type_; }
static NodeOutputInfo None() {
return NodeOutputInfo(MachineRepresentation::kNone, Type::None());
}
static NodeOutputInfo Float32() {
return NodeOutputInfo(MachineRepresentation::kFloat32, Type::Number());
}
static NodeOutputInfo Float64() {
return NodeOutputInfo(MachineRepresentation::kFloat64, Type::Number());
}
static NodeOutputInfo NumberTruncatedToWord32() {
return NodeOutputInfo(MachineRepresentation::kWord32, Type::Number());
}
static NodeOutputInfo Int32() {
return NodeOutputInfo(MachineRepresentation::kWord32, Type::Signed32());
}
static NodeOutputInfo Uint32() {
return NodeOutputInfo(MachineRepresentation::kWord32, Type::Unsigned32());
}
static NodeOutputInfo Bool() {
return NodeOutputInfo(MachineRepresentation::kBit, Type::Boolean());
}
static NodeOutputInfo Int64() {
// TODO(jarin) Fix once we have a real int64 type.
return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
}
static NodeOutputInfo Uint64() {
// TODO(jarin) Fix once we have a real uint64 type.
return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
}
static NodeOutputInfo AnyTagged() {
return NodeOutputInfo(MachineRepresentation::kTagged, Type::Any());
}
static NodeOutputInfo NumberTagged() {
return NodeOutputInfo(MachineRepresentation::kTagged, Type::Number());
}
static NodeOutputInfo Pointer() {
return NodeOutputInfo(MachineType::PointerRepresentation(), Type::Any());
}
private:
Type* type_;
MachineRepresentation representation_;
};
class NodeInfo {
public:
// Adds new use to the node. Returns true if something has changed
......@@ -288,13 +318,17 @@ class RepresentationSelector {
void set_visited() { visited_ = true; }
bool visited() const { return visited_; }
Truncation truncation() const { return truncation_; }
void set_output_type(MachineType type) { output_ = type; }
MachineType output_type() const { return output_; }
void set_output_type(NodeOutputInfo output) { output_ = output; }
Type* output_type() const { return output_.type(); }
MachineRepresentation representation() const {
return output_.representation();
}
private:
bool queued_ = false; // Bookkeeping for the traversal.
bool visited_ = false; // Bookkeeping for the traversal.
MachineType output_ = MachineType::None(); // Output type of the node.
NodeOutputInfo output_; // Output type and representation.
Truncation truncation_ = Truncation::None(); // Information about uses.
};
......@@ -330,7 +364,7 @@ class RepresentationSelector {
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
VisitNode(node, info->truncation(), nullptr);
TRACE(" ==> output ");
PrintInfo(info->output_type());
PrintOutputInfo(info);
TRACE("\n");
}
......@@ -429,36 +463,68 @@ class RepresentationSelector {
}
}
void SetOutput(Node* node, MachineType output) {
void SetOutputFromMachineType(Node* node, MachineType machine_type) {
Type* type = Type::None();
switch (machine_type.semantic()) {
case MachineSemantic::kNone:
type = Type::None();
break;
case MachineSemantic::kBool:
type = Type::Boolean();
break;
case MachineSemantic::kInt32:
type = Type::Signed32();
break;
case MachineSemantic::kUint32:
type = Type::Unsigned32();
break;
case MachineSemantic::kInt64:
// TODO(jarin) Fix once we have proper int64.
type = Type::Internal();
break;
case MachineSemantic::kUint64:
// TODO(jarin) Fix once we have proper uint64.
type = Type::Internal();
break;
case MachineSemantic::kNumber:
type = Type::Number();
break;
case MachineSemantic::kAny:
type = Type::Any();
break;
}
return SetOutput(node, NodeOutputInfo(machine_type.representation(), type));
}
void SetOutput(Node* node, NodeOutputInfo output_info) {
// Every node should have at most one output representation. Note that
// phis can have 0, if they have not been used in a representation-inducing
// instruction.
NodeInfo* info = GetInfo(node);
DCHECK(MachineTypeRepIsSubtype(info->output_type(), output));
if (output != info->output_type()) {
DCHECK(MachineRepresentationIsSubtype(info->representation(),
output_info.representation()));
DCHECK(info->output_type()->Is(output_info.type()));
if (!output_info.type()->Is(info->output_type()) ||
output_info.representation() != info->representation()) {
EnqueueUses(node);
}
info->set_output_type(output);
info->set_output_type(output_info);
}
bool BothInputsAreSigned32(Node* node) {
DCHECK_EQ(2, node->InputCount());
return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Signed32()) ||
(GetInfo(node->InputAt(0))->output_type().semantic() ==
MachineSemantic::kInt32)) &&
GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32())) &&
(NodeProperties::GetType(node->InputAt(1))->Is(Type::Signed32()) ||
(GetInfo(node->InputAt(1))->output_type().semantic() ==
MachineSemantic::kInt32));
GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32()));
}
bool BothInputsAreUnsigned32(Node* node) {
DCHECK_EQ(2, node->InputCount());
return (NodeProperties::GetType(node->InputAt(0))->Is(Type::Unsigned32()) ||
GetInfo(node->InputAt(0))->output_type().semantic() ==
MachineSemantic::kUint32) &&
GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32())) &&
(NodeProperties::GetType(node->InputAt(1))->Is(Type::Unsigned32()) ||
GetInfo(node->InputAt(1))->output_type().semantic() ==
MachineSemantic::kUint32);
GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32()));
}
bool BothInputsAre(Node* node, Type* type) {
......@@ -472,18 +538,20 @@ class RepresentationSelector {
// In the change phase, insert a change before the use if necessary.
if (use.preferred() == MachineRepresentation::kNone)
return; // No input requirement on the use.
MachineType output = GetInfo(input)->output_type();
if (output.representation() != use.preferred()) {
NodeInfo* input_info = GetInfo(input);
MachineRepresentation input_rep = input_info->representation();
if (input_rep != use.preferred()) {
// Output representation doesn't match usage.
TRACE(" change: #%d:%s(@%d #%d:%s) ", node->id(), node->op()->mnemonic(),
index, input->id(), input->op()->mnemonic());
TRACE(" from ");
PrintInfo(output);
PrintOutputInfo(input_info);
TRACE(" to ");
PrintUseInfo(use);
TRACE("\n");
Node* n = changer_->GetRepresentationFor(input, output, use.preferred(),
use.truncation());
Node* n = changer_->GetRepresentationFor(
input, input_info->representation(), input_info->output_type(),
use.preferred(), use.truncation());
node->ReplaceInput(index, n);
}
}
......@@ -528,7 +596,7 @@ class RepresentationSelector {
// Helper for binops of the R x L -> O variety.
void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
MachineType output) {
NodeOutputInfo output) {
DCHECK_EQ(2, node->op()->ValueInputCount());
ProcessInput(node, 0, left_use);
ProcessInput(node, 1, right_use);
......@@ -539,78 +607,77 @@ class RepresentationSelector {
}
// Helper for binops of the I x I -> O variety.
void VisitBinop(Node* node, UseInfo input_use, MachineType output) {
void VisitBinop(Node* node, UseInfo input_use, NodeOutputInfo output) {
VisitBinop(node, input_use, input_use, output);
}
// Helper for unops of the I -> O variety.
void VisitUnop(Node* node, UseInfo input_use, MachineType output) {
void VisitUnop(Node* node, UseInfo input_use, NodeOutputInfo output) {
DCHECK_EQ(1, node->InputCount());
ProcessInput(node, 0, input_use);
SetOutput(node, output);
}
// Helper for leaf nodes.
void VisitLeaf(Node* node, MachineType output) {
void VisitLeaf(Node* node, NodeOutputInfo output) {
DCHECK_EQ(0, node->InputCount());
SetOutput(node, output);
}
// Helpers for specific types of binops.
void VisitFloat64Binop(Node* node) {
VisitBinop(node, UseInfo::Float64(), MachineType::Float64());
VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
}
void VisitInt32Binop(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Int32());
VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
}
void VisitWord32TruncatingBinop(Node* node) {
VisitBinop(
node, UseInfo::TruncatingWord32(),
MachineType(MachineRepresentation::kWord32, MachineSemantic::kNumber));
VisitBinop(node, UseInfo::TruncatingWord32(),
NodeOutputInfo::NumberTruncatedToWord32());
}
void VisitUint32Binop(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Uint32());
VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
}
void VisitInt64Binop(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Int64());
VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Int64());
}
void VisitUint64Binop(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Uint64());
VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Uint64());
}
void VisitFloat64Cmp(Node* node) {
VisitBinop(node, UseInfo::Float64(), MachineType::Bool());
VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
}
void VisitInt32Cmp(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Bool());
VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
}
void VisitUint32Cmp(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(), MachineType::Bool());
VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
}
void VisitInt64Cmp(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Bool());
VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
}
void VisitUint64Cmp(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord64(), MachineType::Bool());
VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
}
// Infer representation for phi-like nodes.
static MachineRepresentation GetRepresentationForPhi(Node* node,
Truncation use) {
// Phis adapt to the output representation their uses demand.
Type* upper = NodeProperties::GetType(node);
if (upper->Is(Type::Signed32()) || upper->Is(Type::Unsigned32())) {
Type* type = NodeProperties::GetType(node);
if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
// We are within 32 bits range => pick kRepWord32.
return MachineRepresentation::kWord32;
} else if (use.TruncatesToWord32()) {
// We only use 32 bits.
return MachineRepresentation::kWord32;
} else if (upper->Is(Type::Boolean())) {
} else if (type->Is(Type::Boolean())) {
// multiple uses => pick kRepBit.
return MachineRepresentation::kBit;
} else if (upper->Is(Type::Number())) {
} else if (type->Is(Type::Number())) {
// multiple uses => pick kRepFloat64.
return MachineRepresentation::kFloat64;
} else if (upper->Is(Type::Internal())) {
} else if (type->Is(Type::Internal())) {
return MachineType::PointerRepresentation();
}
return MachineRepresentation::kTagged;
......@@ -622,10 +689,8 @@ class RepresentationSelector {
ProcessInput(node, 0, UseInfo::Bool());
MachineRepresentation output = GetRepresentationForPhi(node, truncation);
Type* upper = NodeProperties::GetType(node);
MachineType output_type =
MachineType(output, changer_->TypeFromUpperBound(upper));
SetOutput(node, output_type);
Type* type = NodeProperties::GetType(node);
SetOutput(node, NodeOutputInfo(output, type));
if (lower()) {
// Update the select operator.
......@@ -647,10 +712,8 @@ class RepresentationSelector {
SimplifiedLowering* lowering) {
MachineRepresentation output = GetRepresentationForPhi(node, truncation);
Type* upper = NodeProperties::GetType(node);
MachineType output_type =
MachineType(output, changer_->TypeFromUpperBound(upper));
SetOutput(node, output_type);
Type* type = NodeProperties::GetType(node);
SetOutput(node, NodeOutputInfo(output, type));
int values = node->op()->ValueInputCount();
......@@ -687,9 +750,21 @@ class RepresentationSelector {
}
if (sig->return_count() > 0) {
SetOutput(node, desc->GetMachineSignature()->GetReturn());
SetOutputFromMachineType(node, desc->GetMachineSignature()->GetReturn());
} else {
SetOutput(node, MachineType::AnyTagged());
SetOutput(node, NodeOutputInfo::AnyTagged());
}
}
MachineSemantic DeoptValueSemanticOf(Type* type) {
CHECK(!type->Is(Type::None()));
// We only need signedness to do deopt correctly.
if (type->Is(Type::Signed32())) {
return MachineSemantic::kInt32;
} else if (type->Is(Type::Unsigned32())) {
return MachineSemantic::kUint32;
} else {
return MachineSemantic::kAny;
}
}
......@@ -704,13 +779,15 @@ class RepresentationSelector {
new (zone->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(node->InputCount(), zone);
for (int i = 0; i < node->InputCount(); i++) {
MachineType input_type = GetInfo(node->InputAt(i))->output_type();
(*types)[i] = input_type;
NodeInfo* input_info = GetInfo(node->InputAt(i));
(*types)[i] =
MachineType(input_info->representation(),
DeoptValueSemanticOf(input_info->output_type()));
}
NodeProperties::ChangeOp(node,
jsgraph_->common()->TypedStateValues(types));
}
SetOutput(node, MachineType::AnyTagged());
SetOutput(node, NodeOutputInfo::AnyTagged());
}
const Operator* Int32Op(Node* node) {
......@@ -756,29 +833,28 @@ class RepresentationSelector {
//------------------------------------------------------------------
case IrOpcode::kStart:
case IrOpcode::kDead:
return VisitLeaf(node, MachineType::None());
return VisitLeaf(node, NodeOutputInfo::None());
case IrOpcode::kParameter: {
// TODO(titzer): use representation from linkage.
Type* upper = NodeProperties::GetType(node);
Type* type = NodeProperties::GetType(node);
ProcessInput(node, 0, UseInfo::None());
SetOutput(node, MachineType(MachineRepresentation::kTagged,
changer_->TypeFromUpperBound(upper)));
SetOutput(node, NodeOutputInfo(MachineRepresentation::kTagged, type));
return;
}
case IrOpcode::kInt32Constant:
return VisitLeaf(node, MachineType::RepWord32());
return VisitLeaf(node, NodeOutputInfo::Int32());
case IrOpcode::kInt64Constant:
return VisitLeaf(node, MachineType::RepWord64());
return VisitLeaf(node, NodeOutputInfo::Int64());
case IrOpcode::kFloat32Constant:
return VisitLeaf(node, MachineType::RepFloat32());
return VisitLeaf(node, NodeOutputInfo::Float32());
case IrOpcode::kFloat64Constant:
return VisitLeaf(node, MachineType::RepFloat64());
return VisitLeaf(node, NodeOutputInfo::Float64());
case IrOpcode::kExternalConstant:
return VisitLeaf(node, MachineType::Pointer());
return VisitLeaf(node, NodeOutputInfo::Pointer());
case IrOpcode::kNumberConstant:
return VisitLeaf(node, MachineType::RepTagged());
return VisitLeaf(node, NodeOutputInfo::NumberTagged());
case IrOpcode::kHeapConstant:
return VisitLeaf(node, MachineType::RepTagged());
return VisitLeaf(node, NodeOutputInfo::AnyTagged());
case IrOpcode::kBranch:
ProcessInput(node, 0, UseInfo::Bool());
......@@ -807,15 +883,15 @@ class RepresentationSelector {
JS_OP_LIST(DEFINE_JS_CASE)
#undef DEFINE_JS_CASE
VisitInputs(node);
return SetOutput(node, MachineType::RepTagged());
return SetOutput(node, NodeOutputInfo::AnyTagged());
//------------------------------------------------------------------
// Simplified operators.
//------------------------------------------------------------------
case IrOpcode::kBooleanNot: {
if (lower()) {
MachineType input = GetInfo(node->InputAt(0))->output_type();
if (input.representation() == MachineRepresentation::kBit) {
NodeInfo* input_info = GetInfo(node->InputAt(0));
if (input_info->representation() == MachineRepresentation::kBit) {
// BooleanNot(x: kRepBit) => Word32Equal(x, #0)
node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
......@@ -827,14 +903,14 @@ class RepresentationSelector {
} else {
// No input representation requirement; adapt during lowering.
ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
SetOutput(node, MachineType::RepBit());
SetOutput(node, NodeOutputInfo::Bool());
}
break;
}
case IrOpcode::kBooleanToNumber: {
if (lower()) {
MachineType input = GetInfo(node->InputAt(0))->output_type();
if (input.representation() == MachineRepresentation::kBit) {
NodeInfo* input_info = GetInfo(node->InputAt(0));
if (input_info->representation() == MachineRepresentation::kBit) {
// BooleanToNumber(x: kRepBit) => x
DeferReplacement(node, node->InputAt(0));
} else {
......@@ -845,7 +921,7 @@ class RepresentationSelector {
} else {
// No input representation requirement; adapt during lowering.
ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
SetOutput(node, MachineType::Int32());
SetOutput(node, NodeOutputInfo::Int32());
}
break;
}
......@@ -875,7 +951,7 @@ class RepresentationSelector {
if (BothInputsAre(node, type_cache_.kAdditiveSafeInteger) &&
truncation.TruncatesToWord32()) {
// => signed Int32Add/Sub
VisitInt32Binop(node);
VisitWord32TruncatingBinop(node);
if (lower()) NodeProperties::ChangeOp(node, Int32Op(node));
} else {
// => Float64Add/Sub
......@@ -969,36 +1045,36 @@ class RepresentationSelector {
}
case IrOpcode::kNumberShiftLeft: {
VisitBinop(node, UseInfo::TruncatingWord32(),
UseInfo::TruncatingWord32(), MachineType::Int32());
UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shl());
break;
}
case IrOpcode::kNumberShiftRight: {
VisitBinop(node, UseInfo::TruncatingWord32(),
UseInfo::TruncatingWord32(), MachineType::Int32());
UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Sar());
break;
}
case IrOpcode::kNumberShiftRightLogical: {
VisitBinop(node, UseInfo::TruncatingWord32(),
UseInfo::TruncatingWord32(), MachineType::Uint32());
UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
if (lower()) lowering->DoShift(node, lowering->machine()->Word32Shr());
break;
}
case IrOpcode::kNumberToInt32: {
// Just change representation if necessary.
VisitUnop(node, UseInfo::TruncatingWord32(), MachineType::Int32());
VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
if (lower()) DeferReplacement(node, node->InputAt(0));
break;
}
case IrOpcode::kNumberToUint32: {
// Just change representation if necessary.
VisitUnop(node, UseInfo::TruncatingWord32(), MachineType::Uint32());
VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
if (lower()) DeferReplacement(node, node->InputAt(0));
break;
}
case IrOpcode::kNumberIsHoleNaN: {
VisitUnop(node, UseInfo::Float64(), MachineType::Bool());
VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
if (lower()) {
// NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
// #HoleNaNLower32)
......@@ -1013,9 +1089,7 @@ class RepresentationSelector {
break;
}
case IrOpcode::kPlainPrimitiveToNumber: {
VisitUnop(node, UseInfo::AnyTagged(),
MachineType(MachineRepresentation::kTagged,
MachineSemantic::kNumber));
VisitUnop(node, UseInfo::AnyTagged(), NodeOutputInfo::NumberTagged());
if (lower()) {
// PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
Operator::Properties properties = node->op()->properties();
......@@ -1032,38 +1106,38 @@ class RepresentationSelector {
break;
}
case IrOpcode::kReferenceEqual: {
VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
if (lower()) {
NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
}
break;
}
case IrOpcode::kStringEqual: {
VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
if (lower()) lowering->DoStringEqual(node);
break;
}
case IrOpcode::kStringLessThan: {
VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
if (lower()) lowering->DoStringLessThan(node);
break;
}
case IrOpcode::kStringLessThanOrEqual: {
VisitBinop(node, UseInfo::AnyTagged(), MachineType::Bool());
VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
if (lower()) lowering->DoStringLessThanOrEqual(node);
break;
}
case IrOpcode::kAllocate: {
ProcessInput(node, 0, UseInfo::AnyTagged());
ProcessRemainingInputs(node, 1);
SetOutput(node, MachineType::AnyTagged());
SetOutput(node, NodeOutputInfo::AnyTagged());
break;
}
case IrOpcode::kLoadField: {
FieldAccess access = FieldAccessOf(node->op());
ProcessInput(node, 0, UseInfoForBasePointer(access));
ProcessRemainingInputs(node, 1);
SetOutput(node, access.machine_type);
SetOutputFromMachineType(node, access.machine_type);
break;
}
case IrOpcode::kStoreField: {
......@@ -1072,7 +1146,7 @@ class RepresentationSelector {
ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
access.machine_type.representation()));
ProcessRemainingInputs(node, 2);
SetOutput(node, MachineType::None());
SetOutput(node, NodeOutputInfo::None());
break;
}
case IrOpcode::kLoadBuffer: {
......@@ -1082,30 +1156,34 @@ class RepresentationSelector {
ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
ProcessRemainingInputs(node, 3);
MachineType output_type;
NodeOutputInfo output_info;
if (truncation.TruncatesUndefinedToZeroOrNaN()) {
if (truncation.TruncatesNaNToZero()) {
// If undefined is truncated to a non-NaN number, we can use
// the load's representation.
output_type = access.machine_type();
output_info = NodeOutputInfo(access.machine_type().representation(),
NodeProperties::GetType(node));
} else {
// If undefined is truncated to a number, but the use can
// observe NaN, we need to output at least the float32
// representation.
if (access.machine_type().representation() ==
MachineRepresentation::kFloat32) {
output_type = access.machine_type();
output_info =
NodeOutputInfo(access.machine_type().representation(),
NodeProperties::GetType(node));
} else {
output_type = MachineType::Float64();
output_info = NodeOutputInfo::Float64();
}
}
} else {
// If undefined is not truncated away, we need to have the tagged
// representation.
output_type = MachineType::AnyTagged();
output_info = NodeOutputInfo::AnyTagged();
}
SetOutput(node, output_type);
if (lower()) lowering->DoLoadBuffer(node, output_type, changer_);
SetOutput(node, output_info);
if (lower())
lowering->DoLoadBuffer(node, output_info.representation(), changer_);
break;
}
case IrOpcode::kStoreBuffer: {
......@@ -1117,7 +1195,7 @@ class RepresentationSelector {
TruncatingUseInfoFromRepresentation(
access.machine_type().representation())); // value
ProcessRemainingInputs(node, 4);
SetOutput(node, MachineType::None());
SetOutput(node, NodeOutputInfo::None());
if (lower()) lowering->DoStoreBuffer(node);
break;
}
......@@ -1126,7 +1204,7 @@ class RepresentationSelector {
ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
ProcessRemainingInputs(node, 2);
SetOutput(node, access.machine_type);
SetOutputFromMachineType(node, access.machine_type);
break;
}
case IrOpcode::kStoreElement: {
......@@ -1137,18 +1215,18 @@ class RepresentationSelector {
TruncatingUseInfoFromRepresentation(
access.machine_type.representation())); // value
ProcessRemainingInputs(node, 3);
SetOutput(node, MachineType::None());
SetOutput(node, NodeOutputInfo::None());
break;
}
case IrOpcode::kObjectIsNumber: {
ProcessInput(node, 0, UseInfo::AnyTagged());
SetOutput(node, MachineType::Bool());
SetOutput(node, NodeOutputInfo::Bool());
if (lower()) lowering->DoObjectIsNumber(node);
break;
}
case IrOpcode::kObjectIsSmi: {
ProcessInput(node, 0, UseInfo::AnyTagged());
SetOutput(node, MachineType::Bool());
SetOutput(node, NodeOutputInfo::Bool());
if (lower()) lowering->DoObjectIsSmi(node);
break;
}
......@@ -1163,7 +1241,7 @@ class RepresentationSelector {
ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
ProcessInput(node, 1, UseInfo::PointerInt()); // index
ProcessRemainingInputs(node, 2);
SetOutput(node, rep);
SetOutputFromMachineType(node, rep);
break;
}
case IrOpcode::kStore: {
......@@ -1175,13 +1253,13 @@ class RepresentationSelector {
ProcessInput(node, 2,
TruncatingUseInfoFromRepresentation(rep.representation()));
ProcessRemainingInputs(node, 3);
SetOutput(node, MachineType::None());
SetOutput(node, NodeOutputInfo::None());
break;
}
case IrOpcode::kWord32Shr:
// We output unsigned int32 for shift right because JavaScript.
return VisitBinop(node, UseInfo::TruncatingWord32(),
MachineType::Uint32());
NodeOutputInfo::Uint32());
case IrOpcode::kWord32And:
case IrOpcode::kWord32Or:
case IrOpcode::kWord32Xor:
......@@ -1191,14 +1269,14 @@ class RepresentationSelector {
// though the machine bits are the same for either signed or unsigned,
// because JavaScript considers the result from these operations signed.
return VisitBinop(node, UseInfo::TruncatingWord32(),
MachineType::Int32());
NodeOutputInfo::Int32());
case IrOpcode::kWord32Equal:
return VisitBinop(node, UseInfo::TruncatingWord32(),
MachineType::Bool());
NodeOutputInfo::Bool());
case IrOpcode::kWord32Clz:
return VisitUnop(node, UseInfo::TruncatingWord32(),
MachineType::Uint32());
NodeOutputInfo::Uint32());
case IrOpcode::kInt32Add:
case IrOpcode::kInt32Sub:
......@@ -1243,45 +1321,44 @@ class RepresentationSelector {
case IrOpcode::kWord64Shr:
case IrOpcode::kWord64Sar:
return VisitBinop(node, UseInfo::TruncatingWord64(),
MachineType(MachineRepresentation::kWord64,
MachineSemantic::kNone));
NodeOutputInfo::Int64());
case IrOpcode::kWord64Equal:
return VisitBinop(node, UseInfo::TruncatingWord64(),
MachineType::Bool());
NodeOutputInfo::Bool());
case IrOpcode::kChangeInt32ToInt64:
return VisitUnop(node, UseInfo::TruncatingWord32(),
MachineType(MachineRepresentation::kWord64,
MachineSemantic::kInt32));
return VisitUnop(
node, UseInfo::TruncatingWord32(),
NodeOutputInfo(MachineRepresentation::kWord64, Type::Signed32()));
case IrOpcode::kChangeUint32ToUint64:
return VisitUnop(node, UseInfo::TruncatingWord32(),
MachineType(MachineRepresentation::kWord64,
MachineSemantic::kUint32));
return VisitUnop(
node, UseInfo::TruncatingWord32(),
NodeOutputInfo(MachineRepresentation::kWord64, Type::Unsigned32()));
case IrOpcode::kTruncateFloat64ToFloat32:
return VisitUnop(node, UseInfo::Float64(), MachineType::Float32());
return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float32());
case IrOpcode::kTruncateFloat64ToInt32:
return VisitUnop(node, UseInfo::Float64(), MachineType::Int32());
return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
case IrOpcode::kTruncateInt64ToInt32:
// TODO(titzer): Is kTypeInt32 correct here?
return VisitUnop(node, UseInfo::Word64TruncatingToWord32(),
MachineType::Int32());
NodeOutputInfo::Int32());
case IrOpcode::kChangeFloat32ToFloat64:
return VisitUnop(node, UseInfo::Float32(), MachineType::Float64());
return VisitUnop(node, UseInfo::Float32(), NodeOutputInfo::Float64());
case IrOpcode::kChangeInt32ToFloat64:
return VisitUnop(node, UseInfo::TruncatingWord32(),
MachineType(MachineRepresentation::kFloat64,
MachineSemantic::kInt32));
return VisitUnop(
node, UseInfo::TruncatingWord32(),
NodeOutputInfo(MachineRepresentation::kFloat64, Type::Signed32()));
case IrOpcode::kChangeUint32ToFloat64:
return VisitUnop(node, UseInfo::TruncatingWord32(),
MachineType(MachineRepresentation::kFloat64,
MachineSemantic::kUint32));
NodeOutputInfo(MachineRepresentation::kFloat64,
Type::Unsigned32()));
case IrOpcode::kChangeFloat64ToInt32:
return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
MachineType::Int32());
NodeOutputInfo::Int32());
case IrOpcode::kChangeFloat64ToUint32:
return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
MachineType::Uint32());
NodeOutputInfo::Uint32());
case IrOpcode::kFloat64Add:
case IrOpcode::kFloat64Sub:
......@@ -1295,28 +1372,28 @@ class RepresentationSelector {
case IrOpcode::kFloat64RoundDown:
case IrOpcode::kFloat64RoundTruncate:
case IrOpcode::kFloat64RoundTiesAway:
return VisitUnop(node, UseInfo::Float64(), MachineType::Float64());
return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
case IrOpcode::kFloat64Equal:
case IrOpcode::kFloat64LessThan:
case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64Cmp(node);
case IrOpcode::kFloat64ExtractLowWord32:
case IrOpcode::kFloat64ExtractHighWord32:
return VisitUnop(node, UseInfo::Float64(), MachineType::Int32());
return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
case IrOpcode::kFloat64InsertLowWord32:
case IrOpcode::kFloat64InsertHighWord32:
return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
MachineType::Float64());
NodeOutputInfo::Float64());
case IrOpcode::kLoadStackPointer:
case IrOpcode::kLoadFramePointer:
return VisitLeaf(node, MachineType::Pointer());
return VisitLeaf(node, NodeOutputInfo::Pointer());
case IrOpcode::kStateValues:
VisitStateValues(node);
break;
default:
VisitInputs(node);
// Assume the output is tagged.
SetOutput(node, MachineType::AnyTagged());
SetOutput(node, NodeOutputInfo::AnyTagged());
break;
}
}
......@@ -1342,10 +1419,19 @@ class RepresentationSelector {
node->NullAllInputs(); // Node is now dead.
}
void PrintInfo(MachineType info) {
void PrintOutputInfo(NodeInfo* info) {
if (FLAG_trace_representation) {
OFStream os(stdout);
os << info;
os << info->representation() << " (";
info->output_type()->PrintTo(os, Type::SEMANTIC_DIM);
os << ")";
}
}
void PrintRepresentation(MachineRepresentation rep) {
if (FLAG_trace_representation) {
OFStream os(stdout);
os << rep;
}
}
......@@ -1408,12 +1494,13 @@ void SimplifiedLowering::LowerAllNodes() {
}
void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type,
void SimplifiedLowering::DoLoadBuffer(Node* node,
MachineRepresentation output_rep,
RepresentationChanger* changer) {
DCHECK_EQ(IrOpcode::kLoadBuffer, node->opcode());
DCHECK_NE(MachineRepresentation::kNone, output_type.representation());
MachineType const type = BufferAccessOf(node->op()).machine_type();
if (output_type != type) {
DCHECK_NE(MachineRepresentation::kNone, output_rep);
MachineType const access_type = BufferAccessOf(node->op()).machine_type();
if (output_rep != access_type.representation()) {
Node* const buffer = node->InputAt(0);
Node* const offset = node->InputAt(1);
Node* const length = node->InputAt(2);
......@@ -1429,22 +1516,21 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type,
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* etrue =
graph()->NewNode(machine()->Load(type), buffer, index, effect, if_true);
Node* etrue = graph()->NewNode(machine()->Load(access_type), buffer, index,
effect, if_true);
Node* vtrue = changer->GetRepresentationFor(
etrue, type, output_type.representation(), Truncation::None());
etrue, access_type.representation(), NodeProperties::GetType(node),
output_rep, Truncation::None());
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
Node* vfalse;
if (output_type.representation() == MachineRepresentation::kTagged) {
if (output_rep == MachineRepresentation::kTagged) {
vfalse = jsgraph()->UndefinedConstant();
} else if (output_type.representation() ==
MachineRepresentation::kFloat64) {
} else if (output_rep == MachineRepresentation::kFloat64) {
vfalse =
jsgraph()->Float64Constant(std::numeric_limits<double>::quiet_NaN());
} else if (output_type.representation() ==
MachineRepresentation::kFloat32) {
} else if (output_rep == MachineRepresentation::kFloat32) {
vfalse =
jsgraph()->Float32Constant(std::numeric_limits<float>::quiet_NaN());
} else {
......@@ -1462,10 +1548,9 @@ void SimplifiedLowering::DoLoadBuffer(Node* node, MachineType output_type,
node->ReplaceInput(1, vfalse);
node->ReplaceInput(2, merge);
node->TrimInputCount(3);
NodeProperties::ChangeOp(node,
common()->Phi(output_type.representation(), 2));
NodeProperties::ChangeOp(node, common()->Phi(output_rep, 2));
} else {
NodeProperties::ChangeOp(node, machine()->CheckedLoad(type));
NodeProperties::ChangeOp(node, machine()->CheckedLoad(access_type));
}
}
......
......@@ -31,9 +31,9 @@ class SimplifiedLowering final {
void LowerAllNodes();
// TODO(turbofan): The output_type can be removed once the result of the
// TODO(turbofan): The representation can be removed once the result of the
// representation analysis is stored in the node bounds.
void DoLoadBuffer(Node* node, MachineType output_type,
void DoLoadBuffer(Node* node, MachineRepresentation rep,
RepresentationChanger* changer);
void DoStoreBuffer(Node* node);
void DoObjectIsNumber(Node* node);
......
......@@ -83,18 +83,20 @@ class RepresentationChangerTester : public HandleAndZoneScope,
return n;
}
void CheckTypeError(MachineType from, MachineRepresentation to) {
void CheckTypeError(MachineRepresentation from, Type* from_type,
MachineRepresentation to) {
changer()->testing_type_errors_ = true;
changer()->type_error_ = false;
Node* n = Parameter(0);
Node* c = changer()->GetRepresentationFor(n, from, to);
Node* c = changer()->GetRepresentationFor(n, from, from_type, to);
CHECK(changer()->type_error_);
CHECK_EQ(n, c);
}
void CheckNop(MachineType from, MachineRepresentation to) {
void CheckNop(MachineRepresentation from, Type* from_type,
MachineRepresentation to) {
Node* n = Parameter(0);
Node* c = changer()->GetRepresentationFor(n, from, to);
Node* c = changer()->GetRepresentationFor(n, from, from_type, to);
CHECK_EQ(n, c);
}
};
......@@ -112,12 +114,14 @@ TEST(BoolToBit_constant) {
Node* true_node = r.jsgraph()->TrueConstant();
Node* true_bit = r.changer()->GetRepresentationFor(
true_node, MachineType::RepTagged(), MachineRepresentation::kBit);
true_node, MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kBit);
r.CheckInt32Constant(true_bit, 1);
Node* false_node = r.jsgraph()->FalseConstant();
Node* false_bit = r.changer()->GetRepresentationFor(
false_node, MachineType::RepTagged(), MachineRepresentation::kBit);
false_node, MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kBit);
r.CheckInt32Constant(false_bit, 0);
}
......@@ -128,7 +132,8 @@ TEST(BitToBool_constant) {
for (int i = -5; i < 5; i++) {
Node* node = r.jsgraph()->Int32Constant(i);
Node* val = r.changer()->GetRepresentationFor(
node, MachineType::RepBit(), MachineRepresentation::kTagged);
node, MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kTagged);
r.CheckHeapConstant(val, i == 0 ? r.isolate()->heap()->false_value()
: r.isolate()->heap()->true_value());
}
......@@ -142,7 +147,8 @@ TEST(ToTagged_constant) {
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat64(), MachineRepresentation::kTagged);
n, MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
......@@ -151,7 +157,8 @@ TEST(ToTagged_constant) {
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat64(), MachineRepresentation::kTagged);
n, MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
......@@ -160,7 +167,8 @@ TEST(ToTagged_constant) {
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat32(), MachineRepresentation::kTagged);
n, MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
......@@ -169,7 +177,8 @@ TEST(ToTagged_constant) {
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Int32(), MachineRepresentation::kTagged);
n, MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
......@@ -178,7 +187,8 @@ TEST(ToTagged_constant) {
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Uint32(), MachineRepresentation::kTagged);
n, MachineRepresentation::kWord32, Type::Unsigned32(),
MachineRepresentation::kTagged);
r.CheckNumberConstant(c, *i);
}
}
......@@ -192,7 +202,8 @@ TEST(ToFloat64_constant) {
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat64(), MachineRepresentation::kFloat64);
n, MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kFloat64);
CHECK_EQ(n, c);
}
}
......@@ -201,7 +212,8 @@ TEST(ToFloat64_constant) {
FOR_FLOAT64_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepTagged(), MachineRepresentation::kFloat64);
n, MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
......@@ -210,7 +222,8 @@ TEST(ToFloat64_constant) {
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat32(), MachineRepresentation::kFloat64);
n, MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
......@@ -219,7 +232,8 @@ TEST(ToFloat64_constant) {
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Int32(), MachineRepresentation::kFloat64);
n, MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
......@@ -228,7 +242,8 @@ TEST(ToFloat64_constant) {
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Uint32(), MachineRepresentation::kFloat64);
n, MachineRepresentation::kWord32, Type::Unsigned32(),
MachineRepresentation::kFloat64);
r.CheckFloat64Constant(c, *i);
}
}
......@@ -250,7 +265,8 @@ TEST(ToFloat32_constant) {
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat32(), MachineRepresentation::kFloat32);
n, MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kFloat32);
CHECK_EQ(n, c);
}
}
......@@ -259,7 +275,8 @@ TEST(ToFloat32_constant) {
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepTagged(), MachineRepresentation::kFloat32);
n, MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, *i);
}
}
......@@ -268,7 +285,8 @@ TEST(ToFloat32_constant) {
FOR_FLOAT32_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::RepFloat64(), MachineRepresentation::kFloat32);
n, MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, *i);
}
}
......@@ -278,7 +296,8 @@ TEST(ToFloat32_constant) {
if (!IsFloat32Int32(*i)) continue;
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Int32(), MachineRepresentation::kFloat32);
n, MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, static_cast<float>(*i));
}
}
......@@ -288,7 +307,8 @@ TEST(ToFloat32_constant) {
if (!IsFloat32Uint32(*i)) continue;
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Uint32(), MachineRepresentation::kFloat32);
n, MachineRepresentation::kWord32, Type::Unsigned32(),
MachineRepresentation::kFloat32);
r.CheckFloat32Constant(c, static_cast<float>(*i));
}
}
......@@ -302,7 +322,8 @@ TEST(ToInt32_constant) {
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Int32(), MachineRepresentation::kWord32);
n, MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
}
......@@ -312,8 +333,7 @@ TEST(ToInt32_constant) {
if (!IsFloat32Int32(*i)) continue;
Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
Node* c = r.changer()->GetRepresentationFor(
n,
MachineType(MachineRepresentation::kFloat32, MachineSemantic::kInt32),
n, MachineRepresentation::kFloat32, Type::Signed32(),
MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
......@@ -323,8 +343,7 @@ TEST(ToInt32_constant) {
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n,
MachineType(MachineRepresentation::kFloat64, MachineSemantic::kInt32),
n, MachineRepresentation::kFloat64, Type::Signed32(),
MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
......@@ -334,8 +353,7 @@ TEST(ToInt32_constant) {
FOR_INT32_INPUTS(i) {
Node* n = r.jsgraph()->Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n,
MachineType(MachineRepresentation::kTagged, MachineSemantic::kInt32),
n, MachineRepresentation::kTagged, Type::Signed32(),
MachineRepresentation::kWord32);
r.CheckInt32Constant(c, *i);
}
......@@ -350,7 +368,8 @@ TEST(ToUint32_constant) {
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Int32Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType::Uint32(), MachineRepresentation::kWord32);
n, MachineRepresentation::kWord32, Type::Unsigned32(),
MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
}
......@@ -360,8 +379,7 @@ TEST(ToUint32_constant) {
if (!IsFloat32Uint32(*i)) continue;
Node* n = r.jsgraph()->Float32Constant(static_cast<float>(*i));
Node* c = r.changer()->GetRepresentationFor(
n, MachineType(MachineRepresentation::kFloat32,
MachineSemantic::kUint32),
n, MachineRepresentation::kFloat32, Type::Unsigned32(),
MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
......@@ -371,8 +389,7 @@ TEST(ToUint32_constant) {
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Float64Constant(*i);
Node* c = r.changer()->GetRepresentationFor(
n, MachineType(MachineRepresentation::kFloat64,
MachineSemantic::kUint32),
n, MachineRepresentation::kFloat64, Type::Unsigned32(),
MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
......@@ -382,8 +399,7 @@ TEST(ToUint32_constant) {
FOR_UINT32_INPUTS(i) {
Node* n = r.jsgraph()->Constant(static_cast<double>(*i));
Node* c = r.changer()->GetRepresentationFor(
n,
MachineType(MachineRepresentation::kTagged, MachineSemantic::kUint32),
n, MachineRepresentation::kTagged, Type::Unsigned32(),
MachineRepresentation::kWord32);
r.CheckUint32Constant(c, *i);
}
......@@ -391,12 +407,12 @@ TEST(ToUint32_constant) {
}
static void CheckChange(IrOpcode::Value expected, MachineType from,
MachineRepresentation to) {
static void CheckChange(IrOpcode::Value expected, MachineRepresentation from,
Type* from_type, MachineRepresentation to) {
RepresentationChangerTester r;
Node* n = r.Parameter();
Node* c = r.changer()->GetRepresentationFor(n, from, to);
Node* c = r.changer()->GetRepresentationFor(n, from, from_type, to);
CHECK_NE(c, n);
CHECK_EQ(expected, c->opcode());
......@@ -405,12 +421,13 @@ static void CheckChange(IrOpcode::Value expected, MachineType from,
static void CheckTwoChanges(IrOpcode::Value expected2,
IrOpcode::Value expected1, MachineType from,
IrOpcode::Value expected1,
MachineRepresentation from, Type* from_type,
MachineRepresentation to) {
RepresentationChangerTester r;
Node* n = r.Parameter();
Node* c1 = r.changer()->GetRepresentationFor(n, from, to);
Node* c1 = r.changer()->GetRepresentationFor(n, from, from_type, to);
CHECK_NE(c1, n);
CHECK_EQ(expected1, c1->opcode());
......@@ -422,68 +439,65 @@ static void CheckTwoChanges(IrOpcode::Value expected2,
TEST(SingleChanges) {
CheckChange(IrOpcode::kChangeBoolToBit, MachineType::RepTagged(),
MachineRepresentation::kBit);
CheckChange(IrOpcode::kChangeBitToBool, MachineType::RepBit(),
MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeInt32ToTagged, MachineType::Int32(),
MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeUint32ToTagged, MachineType::Uint32(),
MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineType::RepFloat64(),
MachineRepresentation::kTagged);
CheckChange(
IrOpcode::kChangeTaggedToInt32,
MachineType(MachineRepresentation::kTagged, MachineSemantic::kInt32),
MachineRepresentation::kWord32);
CheckChange(
IrOpcode::kChangeTaggedToUint32,
MachineType(MachineRepresentation::kTagged, MachineSemantic::kUint32),
MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineType::RepTagged(),
MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kChangeBoolToBit, MachineRepresentation::kTagged,
Type::None(), MachineRepresentation::kBit);
CheckChange(IrOpcode::kChangeBitToBool, MachineRepresentation::kBit,
Type::None(), MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeInt32ToTagged, MachineRepresentation::kWord32,
Type::Signed32(), MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeUint32ToTagged, MachineRepresentation::kWord32,
Type::Unsigned32(), MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeFloat64ToTagged, MachineRepresentation::kFloat64,
Type::None(), MachineRepresentation::kTagged);
CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
Type::Signed32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
Type::Unsigned32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeTaggedToFloat64, MachineRepresentation::kTagged,
Type::None(), MachineRepresentation::kFloat64);
// Int32,Uint32 <-> Float64 are actually machine conversions.
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineType::Int32(),
MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineType::Uint32(),
MachineRepresentation::kFloat64);
CheckChange(
IrOpcode::kChangeFloat64ToInt32,
MachineType(MachineRepresentation::kFloat64, MachineSemantic::kInt32),
MachineRepresentation::kWord32);
CheckChange(
IrOpcode::kChangeFloat64ToUint32,
MachineType(MachineRepresentation::kFloat64, MachineSemantic::kUint32),
MachineRepresentation::kWord32);
CheckChange(IrOpcode::kTruncateFloat64ToFloat32, MachineType::RepFloat64(),
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
Type::Signed32(), MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kChangeUint32ToFloat64, MachineRepresentation::kWord32,
Type::Unsigned32(), MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
Type::Signed32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeFloat64ToUint32, MachineRepresentation::kFloat64,
Type::Unsigned32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kFloat32);
// Int32,Uint32 <-> Float32 require two changes.
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
IrOpcode::kTruncateFloat64ToFloat32, MachineType::Int32(),
IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeUint32ToFloat64,
IrOpcode::kTruncateFloat64ToFloat32, MachineType::Uint32(),
IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kWord32, Type::Unsigned32(),
MachineRepresentation::kFloat32);
CheckTwoChanges(
IrOpcode::kChangeFloat32ToFloat64, IrOpcode::kChangeFloat64ToInt32,
MachineType(MachineRepresentation::kFloat32, MachineSemantic::kInt32),
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kChangeFloat64ToInt32,
MachineRepresentation::kFloat32, Type::Signed32(),
MachineRepresentation::kWord32);
CheckTwoChanges(
IrOpcode::kChangeFloat32ToFloat64, IrOpcode::kChangeFloat64ToUint32,
MachineType(MachineRepresentation::kFloat32, MachineSemantic::kUint32),
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kChangeFloat64ToUint32,
MachineRepresentation::kFloat32, Type::Unsigned32(),
MachineRepresentation::kWord32);
// Float32 <-> Tagged require two changes.
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kChangeFloat64ToTagged, MachineType::RepFloat32(),
IrOpcode::kChangeFloat64ToTagged,
MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kTagged);
CheckTwoChanges(IrOpcode::kChangeTaggedToFloat64,
IrOpcode::kTruncateFloat64ToFloat32, MachineType::RepTagged(),
IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kFloat32);
}
......@@ -491,28 +505,25 @@ TEST(SingleChanges) {
TEST(SignednessInWord32) {
RepresentationChangerTester r;
CheckChange(
IrOpcode::kChangeTaggedToInt32,
MachineType(MachineRepresentation::kTagged, MachineSemantic::kInt32),
MachineRepresentation::kWord32);
CheckChange(
IrOpcode::kChangeTaggedToUint32,
MachineType(MachineRepresentation::kTagged, MachineSemantic::kUint32),
MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineType::RepWord32(),
MachineRepresentation::kFloat64);
CheckChange(
IrOpcode::kChangeFloat64ToInt32,
MachineType(MachineRepresentation::kFloat64, MachineSemantic::kInt32),
MachineRepresentation::kWord32);
CheckChange(IrOpcode::kTruncateFloat64ToInt32, MachineType::RepFloat64(),
CheckChange(IrOpcode::kChangeTaggedToInt32, MachineRepresentation::kTagged,
Type::Signed32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeTaggedToUint32, MachineRepresentation::kTagged,
Type::Unsigned32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kChangeInt32ToFloat64, MachineRepresentation::kWord32,
Type::None(), MachineRepresentation::kFloat64);
CheckChange(IrOpcode::kChangeFloat64ToInt32, MachineRepresentation::kFloat64,
Type::Signed32(), MachineRepresentation::kWord32);
CheckChange(IrOpcode::kTruncateFloat64ToInt32,
MachineRepresentation::kFloat64, Type::Number(),
MachineRepresentation::kWord32);
CheckTwoChanges(IrOpcode::kChangeInt32ToFloat64,
IrOpcode::kTruncateFloat64ToFloat32, MachineType::RepWord32(),
IrOpcode::kTruncateFloat64ToFloat32,
MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kFloat32);
CheckTwoChanges(IrOpcode::kChangeFloat32ToFloat64,
IrOpcode::kTruncateFloat64ToInt32, MachineType::RepFloat32(),
IrOpcode::kTruncateFloat64ToInt32,
MachineRepresentation::kFloat32, Type::Number(),
MachineRepresentation::kWord32);
}
......@@ -522,31 +533,47 @@ TEST(Nops) {
// X -> X is always a nop for any single representation X.
for (size_t i = 0; i < arraysize(kMachineTypes); i++) {
r.CheckNop(kMachineTypes[i], kMachineTypes[i].representation());
r.CheckNop(kMachineTypes[i].representation(), Type::None(),
kMachineTypes[i].representation());
}
// 32-bit floats.
r.CheckNop(MachineType::RepFloat32(), MachineRepresentation::kFloat32);
r.CheckNop(MachineType::Float32(), MachineRepresentation::kFloat32);
r.CheckNop(MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kFloat32);
r.CheckNop(MachineRepresentation::kFloat32, Type::Number(),
MachineRepresentation::kFloat32);
// 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.
r.CheckNop(MachineType::Int32(), MachineRepresentation::kWord8);
r.CheckNop(MachineType::Int32(), MachineRepresentation::kWord16);
r.CheckNop(MachineType::Int32(), MachineRepresentation::kWord32);
r.CheckNop(MachineType::Int8(), MachineRepresentation::kWord32);
r.CheckNop(MachineType::Int16(), MachineRepresentation::kWord32);
r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kWord8);
r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kWord16);
r.CheckNop(MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kWord32);
r.CheckNop(MachineRepresentation::kWord8, Type::Signed32(),
MachineRepresentation::kWord32);
r.CheckNop(MachineRepresentation::kWord16, Type::Signed32(),
MachineRepresentation::kWord32);
// kRepBit (result of comparison) is implicitly a wordish thing.
r.CheckNop(MachineType::RepBit(), MachineRepresentation::kWord8);
r.CheckNop(MachineType::RepBit(), MachineRepresentation::kWord16);
r.CheckNop(MachineType::RepBit(), MachineRepresentation::kWord32);
r.CheckNop(MachineType::RepBit(), MachineRepresentation::kWord64);
r.CheckNop(MachineType::Bool(), MachineRepresentation::kWord8);
r.CheckNop(MachineType::Bool(), MachineRepresentation::kWord16);
r.CheckNop(MachineType::Bool(), MachineRepresentation::kWord32);
r.CheckNop(MachineType::Bool(), MachineRepresentation::kWord64);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord8);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord16);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord32);
r.CheckNop(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kWord64);
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kWord8);
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kWord16);
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kWord32);
r.CheckNop(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kWord64);
}
......@@ -554,31 +581,48 @@ TEST(TypeErrors) {
RepresentationChangerTester r;
// Wordish cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineType::RepWord8(), MachineRepresentation::kBit);
r.CheckTypeError(MachineType::RepWord16(), MachineRepresentation::kBit);
r.CheckTypeError(MachineType::RepWord32(), MachineRepresentation::kBit);
r.CheckTypeError(MachineType::RepWord64(), MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord8, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord16, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kBit);
// Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineType::RepFloat64(), MachineRepresentation::kBit);
r.CheckTypeError(MachineType::RepBit(), MachineRepresentation::kFloat64);
r.CheckTypeError(MachineType::Bool(), MachineRepresentation::kFloat64);
r.CheckTypeError(MachineRepresentation::kFloat64, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kFloat64);
r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kFloat64);
// Floats cannot be implicitly converted to/from comparison conditions.
r.CheckTypeError(MachineType::RepFloat32(), MachineRepresentation::kBit);
r.CheckTypeError(MachineType::RepBit(), MachineRepresentation::kFloat32);
r.CheckTypeError(MachineType::Bool(), MachineRepresentation::kFloat32);
r.CheckTypeError(MachineRepresentation::kFloat32, Type::None(),
MachineRepresentation::kBit);
r.CheckTypeError(MachineRepresentation::kBit, Type::None(),
MachineRepresentation::kFloat32);
r.CheckTypeError(MachineRepresentation::kBit, Type::Boolean(),
MachineRepresentation::kFloat32);
// Word64 is internal and shouldn't be implicitly converted.
r.CheckTypeError(MachineType::RepWord64(), MachineRepresentation::kTagged);
r.CheckTypeError(MachineType::RepTagged(), MachineRepresentation::kWord64);
r.CheckTypeError(MachineType::TaggedBool(), MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kTagged);
r.CheckTypeError(MachineRepresentation::kTagged, Type::None(),
MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kTagged, Type::Boolean(),
MachineRepresentation::kWord64);
// Word64 / Word32 shouldn't be implicitly converted.
r.CheckTypeError(MachineType::RepWord64(), MachineRepresentation::kWord32);
r.CheckTypeError(MachineType::RepWord32(), MachineRepresentation::kWord64);
r.CheckTypeError(MachineType::Int32(), MachineRepresentation::kWord64);
r.CheckTypeError(MachineType::Uint32(), MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kWord64, Type::None(),
MachineRepresentation::kWord32);
r.CheckTypeError(MachineRepresentation::kWord32, Type::None(),
MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Signed32(),
MachineRepresentation::kWord64);
r.CheckTypeError(MachineRepresentation::kWord32, Type::Unsigned32(),
MachineRepresentation::kWord64);
}
} // namespace compiler
......
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