Commit 04b4df2c authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Extend undefined-to-number truncation to all oddballs.

Extends the truncation and type checks for NumberOrUndefined in
representation selection and truncation analysis to deal with all
oddballs not just undefined. Also extend the type hints to always
report NumberOrOddball. This is necessary for the bitwise and shift
operators where NUMBER feedback actually means NUMBER or ODDBALL.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2149583002
Cr-Commit-Position: refs/heads/master@{#37711}
parent 7ae653f7
...@@ -39,7 +39,7 @@ class JSBinopReduction final { ...@@ -39,7 +39,7 @@ class JSBinopReduction final {
BinaryOperationHints::Hint combined = hints.combined(); BinaryOperationHints::Hint combined = hints.combined();
if (combined == BinaryOperationHints::kSignedSmall || if (combined == BinaryOperationHints::kSignedSmall ||
combined == BinaryOperationHints::kSigned32 || combined == BinaryOperationHints::kSigned32 ||
combined == BinaryOperationHints::kNumberOrUndefined) { combined == BinaryOperationHints::kNumberOrOddball) {
return combined; return combined;
} }
return BinaryOperationHints::kAny; return BinaryOperationHints::kAny;
...@@ -56,7 +56,7 @@ class JSBinopReduction final { ...@@ -56,7 +56,7 @@ class JSBinopReduction final {
CompareOperationHints hints = CompareOperationHintsOf(node_->op()); CompareOperationHints hints = CompareOperationHintsOf(node_->op());
CompareOperationHints::Hint combined = hints.combined(); CompareOperationHints::Hint combined = hints.combined();
if (combined == CompareOperationHints::kSignedSmall || if (combined == CompareOperationHints::kSignedSmall ||
combined == CompareOperationHints::kNumber) { combined == CompareOperationHints::kNumberOrOddball) {
return combined; return combined;
} }
return CompareOperationHints::kAny; return CompareOperationHints::kAny;
...@@ -435,7 +435,7 @@ JSTypedLowering::JSTypedLowering(Editor* editor, ...@@ -435,7 +435,7 @@ JSTypedLowering::JSTypedLowering(Editor* editor,
Reduction JSTypedLowering::ReduceJSAdd(Node* node) { Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
if (feedback == BinaryOperationHints::kNumberOrUndefined && if (feedback == BinaryOperationHints::kNumberOrOddball &&
r.BothInputsAre(Type::PlainPrimitive()) && r.BothInputsAre(Type::PlainPrimitive()) &&
r.NeitherInputCanBe(Type::StringOrReceiver())) { r.NeitherInputCanBe(Type::StringOrReceiver())) {
// JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y)) // JSAdd(x:-string, y:-string) => NumberAdd(ToNumber(x), ToNumber(y))
...@@ -486,7 +486,7 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) { ...@@ -486,7 +486,7 @@ Reduction JSTypedLowering::ReduceJSAdd(Node* node) {
Reduction JSTypedLowering::ReduceJSSubtract(Node* node) { Reduction JSTypedLowering::ReduceJSSubtract(Node* node) {
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
if (feedback == BinaryOperationHints::kNumberOrUndefined && if (feedback == BinaryOperationHints::kNumberOrOddball &&
r.BothInputsAre(Type::PlainPrimitive())) { r.BothInputsAre(Type::PlainPrimitive())) {
// JSSubtract(x:plain-primitive, y:plain-primitive) // JSSubtract(x:plain-primitive, y:plain-primitive)
// => NumberSubtract(ToNumber(x), ToNumber(y)) // => NumberSubtract(ToNumber(x), ToNumber(y))
...@@ -533,7 +533,7 @@ Reduction JSTypedLowering::ReduceJSMultiply(Node* node) { ...@@ -533,7 +533,7 @@ Reduction JSTypedLowering::ReduceJSMultiply(Node* node) {
Reduction JSTypedLowering::ReduceJSDivide(Node* node) { Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
if (feedback == BinaryOperationHints::kNumberOrUndefined && if (feedback == BinaryOperationHints::kNumberOrOddball &&
r.BothInputsAre(Type::PlainPrimitive())) { r.BothInputsAre(Type::PlainPrimitive())) {
// JSDivide(x:plain-primitive, // JSDivide(x:plain-primitive,
// y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y)) // y:plain-primitive) => NumberDivide(ToNumber(x), ToNumber(y))
...@@ -556,7 +556,7 @@ Reduction JSTypedLowering::ReduceJSDivide(Node* node) { ...@@ -556,7 +556,7 @@ Reduction JSTypedLowering::ReduceJSDivide(Node* node) {
Reduction JSTypedLowering::ReduceJSModulus(Node* node) { Reduction JSTypedLowering::ReduceJSModulus(Node* node) {
JSBinopReduction r(this, node); JSBinopReduction r(this, node);
BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback(); BinaryOperationHints::Hint feedback = r.GetNumberBinaryOperationFeedback();
if (feedback == BinaryOperationHints::kNumberOrUndefined && if (feedback == BinaryOperationHints::kNumberOrOddball &&
r.BothInputsAre(Type::PlainPrimitive())) { r.BothInputsAre(Type::PlainPrimitive())) {
// JSModulus(x:plain-primitive, // JSModulus(x:plain-primitive,
// y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y)) // y:plain-primitive) => NumberModulus(ToNumber(x), ToNumber(y))
......
...@@ -63,6 +63,11 @@ Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1, ...@@ -63,6 +63,11 @@ Truncation::TruncationKind Truncation::Generalize(TruncationKind rep1,
LessGeneral(rep2, TruncationKind::kFloat64)) { LessGeneral(rep2, TruncationKind::kFloat64)) {
return TruncationKind::kFloat64; return TruncationKind::kFloat64;
} }
// Handle the generalization of any-representable values.
if (LessGeneral(rep1, TruncationKind::kAny) &&
LessGeneral(rep2, TruncationKind::kAny)) {
return TruncationKind::kAny;
}
// All other combinations are illegal. // All other combinations are illegal.
FATAL("Tried to combine incompatible truncations"); FATAL("Tried to combine incompatible truncations");
return TruncationKind::kNone; return TruncationKind::kNone;
...@@ -278,7 +283,7 @@ Node* RepresentationChanger::GetFloat32RepresentationFor( ...@@ -278,7 +283,7 @@ Node* RepresentationChanger::GetFloat32RepresentationFor(
op = machine()->TruncateFloat64ToFloat32(); op = machine()->TruncateFloat64ToFloat32();
} }
} else if (output_rep == MachineRepresentation::kTagged) { } else if (output_rep == MachineRepresentation::kTagged) {
if (output_type->Is(Type::NumberOrUndefined())) { if (output_type->Is(Type::NumberOrOddball())) {
// tagged -> float64 -> float32 // tagged -> float64 -> float32
if (output_type->Is(Type::Number())) { if (output_type->Is(Type::Number())) {
op = simplified()->ChangeTaggedToFloat64(); op = simplified()->ChangeTaggedToFloat64();
...@@ -344,10 +349,10 @@ Node* RepresentationChanger::GetFloat64RepresentationFor( ...@@ -344,10 +349,10 @@ Node* RepresentationChanger::GetFloat64RepresentationFor(
op = machine()->ChangeInt32ToFloat64(); op = machine()->ChangeInt32ToFloat64();
} else if (output_type->Is(Type::Number())) { } else if (output_type->Is(Type::Number())) {
op = simplified()->ChangeTaggedToFloat64(); op = simplified()->ChangeTaggedToFloat64();
} else if (output_type->Is(Type::NumberOrUndefined())) { } else if (output_type->Is(Type::NumberOrOddball())) {
// TODO(jarin) Here we should check that truncation is Number. // TODO(jarin) Here we should check that truncation is Number.
op = simplified()->TruncateTaggedToFloat64(); op = simplified()->TruncateTaggedToFloat64();
} else if (use_info.type_check() == TypeCheckKind::kNumberOrUndefined) { } else if (use_info.type_check() == TypeCheckKind::kNumberOrOddball) {
op = simplified()->CheckedTaggedToFloat64(); op = simplified()->CheckedTaggedToFloat64();
} }
} else if (output_rep == MachineRepresentation::kFloat32) { } else if (output_rep == MachineRepresentation::kFloat32) {
......
...@@ -73,12 +73,7 @@ class Truncation final { ...@@ -73,12 +73,7 @@ class Truncation final {
static bool LessGeneral(TruncationKind rep1, TruncationKind rep2); static bool LessGeneral(TruncationKind rep1, TruncationKind rep2);
}; };
enum class TypeCheckKind : uint8_t { enum class TypeCheckKind : uint8_t { kNone, kSigned32, kNumberOrOddball };
kNone,
kSigned32,
kNumberOrUndefined,
kNumber
};
inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) { inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
switch (type_check) { switch (type_check) {
...@@ -86,10 +81,8 @@ inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) { ...@@ -86,10 +81,8 @@ inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
return os << "None"; return os << "None";
case TypeCheckKind::kSigned32: case TypeCheckKind::kSigned32:
return os << "Signed32"; return os << "Signed32";
case TypeCheckKind::kNumberOrUndefined: case TypeCheckKind::kNumberOrOddball:
return os << "NumberOrUndefined"; return os << "NumberOrOddball";
case TypeCheckKind::kNumber:
return os << "Number";
} }
UNREACHABLE(); UNREACHABLE();
return os; return os;
...@@ -141,9 +134,9 @@ class UseInfo { ...@@ -141,9 +134,9 @@ class UseInfo {
return UseInfo(MachineRepresentation::kWord32, Truncation::Any(), return UseInfo(MachineRepresentation::kWord32, Truncation::Any(),
TypeCheckKind::kSigned32); TypeCheckKind::kSigned32);
} }
static UseInfo CheckedNumberOrUndefinedAsFloat64() { static UseInfo CheckedNumberOrOddballAsFloat64() {
return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(), return UseInfo(MachineRepresentation::kFloat64, Truncation::Any(),
TypeCheckKind::kNumberOrUndefined); TypeCheckKind::kNumberOrOddball);
} }
// Undetermined representation. // Undetermined representation.
......
...@@ -1130,7 +1130,7 @@ class RepresentationSelector { ...@@ -1130,7 +1130,7 @@ class RepresentationSelector {
} }
// default case => Float64Add/Sub // default case => Float64Add/Sub
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number()); MachineRepresentation::kFloat64, Type::Number());
if (lower()) { if (lower()) {
ChangeToPureOp(node, Float64Op(node)); ChangeToPureOp(node, Float64Op(node));
...@@ -1283,9 +1283,9 @@ class RepresentationSelector { ...@@ -1283,9 +1283,9 @@ class RepresentationSelector {
if (lower()) ChangeToPureOp(node, Int32Op(node)); if (lower()) ChangeToPureOp(node, Int32Op(node));
return; return;
} }
DCHECK_EQ(CompareOperationHints::kNumber, hint); DCHECK_EQ(CompareOperationHints::kNumberOrOddball, hint);
// default case => Float64 comparison // default case => Float64 comparison
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kBit); MachineRepresentation::kBit);
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
...@@ -1338,7 +1338,7 @@ class RepresentationSelector { ...@@ -1338,7 +1338,7 @@ class RepresentationSelector {
} }
// Checked float64 x float64 => float64 // Checked float64 x float64 => float64
DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode()); DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode());
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number()); MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
...@@ -1409,7 +1409,7 @@ class RepresentationSelector { ...@@ -1409,7 +1409,7 @@ class RepresentationSelector {
} }
// default case => Float64Div // default case => Float64Div
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number()); MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
...@@ -1443,7 +1443,7 @@ class RepresentationSelector { ...@@ -1443,7 +1443,7 @@ class RepresentationSelector {
} }
// Checked float64 x float64 => float64 // Checked float64 x float64 => float64
DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode()); DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode());
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number()); MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
...@@ -1514,7 +1514,7 @@ class RepresentationSelector { ...@@ -1514,7 +1514,7 @@ class RepresentationSelector {
} }
// default case => Float64Mod // default case => Float64Mod
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(), VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number()); MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
...@@ -1969,8 +1969,7 @@ class RepresentationSelector { ...@@ -1969,8 +1969,7 @@ class RepresentationSelector {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged); VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) lowering->DoStringToNumber(node); if (lower()) lowering->DoStringToNumber(node);
} else if (truncation.TruncatesToWord32()) { } else if (truncation.TruncatesToWord32()) {
// TODO(jarin): Extend this to Number \/ Oddball if (InputIs(node, Type::NumberOrOddball())) {
if (InputIs(node, Type::NumberOrUndefined())) {
VisitUnop(node, UseInfo::TruncatingWord32(), VisitUnop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32); MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, node->InputAt(0)); if (lower()) DeferReplacement(node, node->InputAt(0));
...@@ -1983,8 +1982,7 @@ class RepresentationSelector { ...@@ -1983,8 +1982,7 @@ class RepresentationSelector {
} }
} }
} else if (truncation.TruncatesToFloat64()) { } else if (truncation.TruncatesToFloat64()) {
// TODO(jarin): Extend this to Number \/ Oddball if (InputIs(node, Type::NumberOrOddball())) {
if (InputIs(node, Type::NumberOrUndefined())) {
VisitUnop(node, UseInfo::TruncatingFloat64(), VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat64); MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, node->InputAt(0)); if (lower()) DeferReplacement(node, node->InputAt(0));
......
...@@ -20,7 +20,7 @@ BinaryOperationHints::Hint ToBinaryOperationHint(Type* type) { ...@@ -20,7 +20,7 @@ BinaryOperationHints::Hint ToBinaryOperationHint(Type* type) {
if (type->Is(Type::None())) return BinaryOperationHints::kNone; if (type->Is(Type::None())) return BinaryOperationHints::kNone;
if (type->Is(Type::SignedSmall())) return BinaryOperationHints::kSignedSmall; if (type->Is(Type::SignedSmall())) return BinaryOperationHints::kSignedSmall;
if (type->Is(Type::Signed32())) return BinaryOperationHints::kSigned32; if (type->Is(Type::Signed32())) return BinaryOperationHints::kSigned32;
if (type->Is(Type::Number())) return BinaryOperationHints::kNumberOrUndefined; if (type->Is(Type::Number())) return BinaryOperationHints::kNumberOrOddball;
if (type->Is(Type::String())) return BinaryOperationHints::kString; if (type->Is(Type::String())) return BinaryOperationHints::kString;
return BinaryOperationHints::kAny; return BinaryOperationHints::kAny;
} }
...@@ -35,7 +35,7 @@ CompareOperationHints::Hint ToCompareOperationHint( ...@@ -35,7 +35,7 @@ CompareOperationHints::Hint ToCompareOperationHint(
case CompareICState::SMI: case CompareICState::SMI:
return CompareOperationHints::kSignedSmall; return CompareOperationHints::kSignedSmall;
case CompareICState::NUMBER: case CompareICState::NUMBER:
return CompareOperationHints::kNumber; return CompareOperationHints::kNumberOrOddball;
case CompareICState::STRING: case CompareICState::STRING:
return CompareOperationHints::kString; return CompareOperationHints::kString;
case CompareICState::INTERNALIZED_STRING: case CompareICState::INTERNALIZED_STRING:
......
...@@ -16,8 +16,8 @@ std::ostream& operator<<(std::ostream& os, BinaryOperationHints::Hint hint) { ...@@ -16,8 +16,8 @@ std::ostream& operator<<(std::ostream& os, BinaryOperationHints::Hint hint) {
return os << "SignedSmall"; return os << "SignedSmall";
case BinaryOperationHints::kSigned32: case BinaryOperationHints::kSigned32:
return os << "Signed32"; return os << "Signed32";
case BinaryOperationHints::kNumberOrUndefined: case BinaryOperationHints::kNumberOrOddball:
return os << "NumberOrUndefined"; return os << "NumberOrOddball";
case BinaryOperationHints::kString: case BinaryOperationHints::kString:
return os << "String"; return os << "String";
case BinaryOperationHints::kAny: case BinaryOperationHints::kAny:
...@@ -39,8 +39,8 @@ std::ostream& operator<<(std::ostream& os, CompareOperationHints::Hint hint) { ...@@ -39,8 +39,8 @@ std::ostream& operator<<(std::ostream& os, CompareOperationHints::Hint hint) {
return os << "Boolean"; return os << "Boolean";
case CompareOperationHints::kSignedSmall: case CompareOperationHints::kSignedSmall:
return os << "SignedSmall"; return os << "SignedSmall";
case CompareOperationHints::kNumber: case CompareOperationHints::kNumberOrOddball:
return os << "Number"; return os << "NumberOrOddball";
case CompareOperationHints::kString: case CompareOperationHints::kString:
return os << "String"; return os << "String";
case CompareOperationHints::kInternalizedString: case CompareOperationHints::kInternalizedString:
...@@ -112,10 +112,10 @@ bool BinaryOperationHints::Is(Hint h1, Hint h2) { ...@@ -112,10 +112,10 @@ bool BinaryOperationHints::Is(Hint h1, Hint h2) {
case kNone: case kNone:
return true; return true;
case kSignedSmall: case kSignedSmall:
return h2 == kSigned32 || h2 == kNumberOrUndefined || h2 == kAny; return h2 == kSigned32 || h2 == kNumberOrOddball || h2 == kAny;
case kSigned32: case kSigned32:
return h2 == kNumberOrUndefined || h2 == kAny; return h2 == kNumberOrOddball || h2 == kAny;
case kNumberOrUndefined: case kNumberOrOddball:
return h2 == kAny; return h2 == kAny;
case kString: case kString:
return h2 == kAny; return h2 == kAny;
......
...@@ -15,14 +15,7 @@ namespace compiler { ...@@ -15,14 +15,7 @@ namespace compiler {
// Type hints for an binary operation. // Type hints for an binary operation.
class BinaryOperationHints final { class BinaryOperationHints final {
public: public:
enum Hint { enum Hint { kNone, kSignedSmall, kSigned32, kNumberOrOddball, kString, kAny };
kNone,
kSignedSmall,
kSigned32,
kNumberOrUndefined,
kString,
kAny
};
BinaryOperationHints() : BinaryOperationHints(kNone, kNone, kNone) {} BinaryOperationHints() : BinaryOperationHints(kNone, kNone, kNone) {}
BinaryOperationHints(Hint left, Hint right, Hint result) BinaryOperationHints(Hint left, Hint right, Hint result)
...@@ -71,7 +64,7 @@ class CompareOperationHints final { ...@@ -71,7 +64,7 @@ class CompareOperationHints final {
kNone, kNone,
kBoolean, kBoolean,
kSignedSmall, kSignedSmall,
kNumber, kNumberOrOddball,
kString, kString,
kInternalizedString, kInternalizedString,
kUniqueName, kUniqueName,
......
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