Commit e6ca0146 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce a SpeculativeToNumber operator.

Add a dedicated operator for ToNumber(x) with feedback instead of
translating to SpeculativeNumberMultiply(x,1), which allows us to
treat the case where x is already a Number specially, ignoring the
feedback on the operator. This recovers most of the regression in
the crypto benchmark.

BUG=chromium:709398,v8:6214,v8:5267
R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2802113003
Cr-Commit-Position: refs/heads/master@{#44484}
parent e434d11f
...@@ -2053,8 +2053,7 @@ void BytecodeGraphBuilder::VisitToNumber() { ...@@ -2053,8 +2053,7 @@ void BytecodeGraphBuilder::VisitToNumber() {
Node* node = nullptr; Node* node = nullptr;
FeedbackSlot slot = FeedbackSlot slot =
feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1)); feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
if (Node* simplified = TryBuildSimplifiedBinaryOp( if (Node* simplified = TryBuildSimplifiedToNumber(object, slot)) {
javascript()->Multiply(), object, jsgraph()->OneConstant(), slot)) {
node = simplified; node = simplified;
} else { } else {
node = NewNode(javascript()->ToNumber(), object); node = NewNode(javascript()->ToNumber(), object);
...@@ -2481,6 +2480,19 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, ...@@ -2481,6 +2480,19 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op,
return nullptr; return nullptr;
} }
Node* BytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value,
FeedbackSlot slot) {
Node* effect = environment()->GetEffectDependency();
Node* control = environment()->GetControlDependency();
Reduction early_reduction = type_hint_lowering().ReduceToNumberOperation(
value, effect, control, slot);
if (early_reduction.Changed()) {
ApplyEarlyReduction(early_reduction);
return early_reduction.replacement();
}
return nullptr;
}
Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op,
Node* receiver, Node* receiver,
FeedbackSlot slot) { FeedbackSlot slot) {
......
...@@ -180,6 +180,7 @@ class BytecodeGraphBuilder { ...@@ -180,6 +180,7 @@ class BytecodeGraphBuilder {
// any other invocation of {NewNode} would do. // any other invocation of {NewNode} would do.
Node* TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, Node* right, Node* TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, Node* right,
FeedbackSlot slot); FeedbackSlot slot);
Node* TryBuildSimplifiedToNumber(Node* input, FeedbackSlot slot);
Node* TryBuildSimplifiedLoadNamed(const Operator* op, Node* receiver, Node* TryBuildSimplifiedLoadNamed(const Operator* op, Node* receiver,
FeedbackSlot slot); FeedbackSlot slot);
Node* TryBuildSimplifiedLoadKeyed(const Operator* op, Node* receiver, Node* TryBuildSimplifiedLoadKeyed(const Operator* op, Node* receiver,
......
...@@ -14,6 +14,30 @@ namespace v8 { ...@@ -14,6 +14,30 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
namespace {
bool BinaryOperationHintToNumberOperationHint(
BinaryOperationHint binop_hint, NumberOperationHint* number_hint) {
switch (binop_hint) {
case BinaryOperationHint::kSignedSmall:
*number_hint = NumberOperationHint::kSignedSmall;
return true;
case BinaryOperationHint::kSigned32:
*number_hint = NumberOperationHint::kSigned32;
return true;
case BinaryOperationHint::kNumberOrOddball:
*number_hint = NumberOperationHint::kNumberOrOddball;
return true;
case BinaryOperationHint::kAny:
case BinaryOperationHint::kNone:
case BinaryOperationHint::kString:
break;
}
return false;
}
} // namespace
class JSSpeculativeBinopBuilder final { class JSSpeculativeBinopBuilder final {
public: public:
JSSpeculativeBinopBuilder(const JSTypeHintLowering* lowering, JSSpeculativeBinopBuilder(const JSTypeHintLowering* lowering,
...@@ -40,22 +64,8 @@ class JSSpeculativeBinopBuilder final { ...@@ -40,22 +64,8 @@ class JSSpeculativeBinopBuilder final {
} }
bool GetBinaryNumberOperationHint(NumberOperationHint* hint) { bool GetBinaryNumberOperationHint(NumberOperationHint* hint) {
switch (GetBinaryOperationHint()) { return BinaryOperationHintToNumberOperationHint(GetBinaryOperationHint(),
case BinaryOperationHint::kSignedSmall: hint);
*hint = NumberOperationHint::kSignedSmall;
return true;
case BinaryOperationHint::kSigned32:
*hint = NumberOperationHint::kSigned32;
return true;
case BinaryOperationHint::kNumberOrOddball:
*hint = NumberOperationHint::kNumberOrOddball;
return true;
case BinaryOperationHint::kAny:
case BinaryOperationHint::kNone:
case BinaryOperationHint::kString:
break;
}
return false;
} }
bool GetCompareNumberOperationHint(NumberOperationHint* hint) { bool GetCompareNumberOperationHint(NumberOperationHint* hint) {
...@@ -228,6 +238,22 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op, ...@@ -228,6 +238,22 @@ Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op,
return Reduction(); return Reduction();
} }
Reduction JSTypeHintLowering::ReduceToNumberOperation(Node* input, Node* effect,
Node* control,
FeedbackSlot slot) const {
DCHECK(!slot.IsInvalid());
BinaryOpICNexus nexus(feedback_vector(), slot);
NumberOperationHint hint;
if (BinaryOperationHintToNumberOperationHint(
nexus.GetBinaryOperationFeedback(), &hint)) {
Node* node = jsgraph()->graph()->NewNode(
jsgraph()->simplified()->SpeculativeToNumber(hint), input, effect,
control);
return Reduction(node);
}
return Reduction();
}
Reduction JSTypeHintLowering::ReduceLoadNamedOperation( Reduction JSTypeHintLowering::ReduceLoadNamedOperation(
const Operator* op, Node* obj, Node* effect, Node* control, const Operator* op, Node* obj, Node* effect, Node* control,
FeedbackSlot slot) const { FeedbackSlot slot) const {
......
...@@ -55,6 +55,10 @@ class JSTypeHintLowering { ...@@ -55,6 +55,10 @@ class JSTypeHintLowering {
Node* effect, Node* control, Node* effect, Node* control,
FeedbackSlot slot) const; FeedbackSlot slot) const;
// Potential reduction to ToNumber operations
Reduction ReduceToNumberOperation(Node* value, Node* effect, Node* control,
FeedbackSlot slot) const;
// Potential reduction of property access operations. // Potential reduction of property access operations.
Reduction ReduceLoadNamedOperation(const Operator* op, Node* obj, Reduction ReduceLoadNamedOperation(const Operator* op, Node* obj,
Node* effect, Node* control, Node* effect, Node* control,
......
...@@ -84,6 +84,7 @@ class V8_EXPORT_PRIVATE JSTypedLowering final ...@@ -84,6 +84,7 @@ class V8_EXPORT_PRIVATE JSTypedLowering final
Reduction ReduceUI32Shift(Node* node, Signedness signedness); Reduction ReduceUI32Shift(Node* node, Signedness signedness);
Reduction ReduceCreateConsString(Node* node); Reduction ReduceCreateConsString(Node* node);
Reduction ReduceSpeculativeNumberAdd(Node* node); Reduction ReduceSpeculativeNumberAdd(Node* node);
Reduction ReduceSpeculativeNumberMultiply(Node* node);
Reduction ReduceSpeculativeNumberBinop(Node* node); Reduction ReduceSpeculativeNumberBinop(Node* node);
Reduction ReduceSpeculativeNumberComparison(Node* node); Reduction ReduceSpeculativeNumberComparison(Node* node);
......
...@@ -317,7 +317,8 @@ InductionVariable* LoopVariableOptimizer::TryGetInductionVariable(Node* phi) { ...@@ -317,7 +317,8 @@ InductionVariable* LoopVariableOptimizer::TryGetInductionVariable(Node* phi) {
// TODO(jarin) Support both sides. // TODO(jarin) Support both sides.
if (arith->InputAt(0) != phi) { if (arith->InputAt(0) != phi) {
if (arith->InputAt(0)->opcode() != IrOpcode::kJSToNumber || if ((arith->InputAt(0)->opcode() != IrOpcode::kJSToNumber &&
arith->InputAt(0)->opcode() != IrOpcode::kSpeculativeToNumber) ||
arith->InputAt(0)->InputAt(0) != phi) { arith->InputAt(0)->InputAt(0) != phi) {
return nullptr; return nullptr;
} }
......
...@@ -301,6 +301,8 @@ ...@@ -301,6 +301,8 @@
V(NumberToUint8Clamped) \ V(NumberToUint8Clamped) \
V(NumberSilenceNaN) V(NumberSilenceNaN)
#define SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(V) V(SpeculativeToNumber)
#define SIMPLIFIED_OTHER_OP_LIST(V) \ #define SIMPLIFIED_OTHER_OP_LIST(V) \
V(PlainPrimitiveToNumber) \ V(PlainPrimitiveToNumber) \
V(PlainPrimitiveToWord32) \ V(PlainPrimitiveToWord32) \
...@@ -356,6 +358,7 @@ ...@@ -356,6 +358,7 @@
SIMPLIFIED_NUMBER_BINOP_LIST(V) \ SIMPLIFIED_NUMBER_BINOP_LIST(V) \
SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \ SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(V) \
SIMPLIFIED_NUMBER_UNOP_LIST(V) \ SIMPLIFIED_NUMBER_UNOP_LIST(V) \
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(V) \
SIMPLIFIED_OTHER_OP_LIST(V) SIMPLIFIED_OTHER_OP_LIST(V)
// Opcodes for Machine-level operators. // Opcodes for Machine-level operators.
......
...@@ -970,8 +970,8 @@ Type* OperationTyper::NumberPow(Type* lhs, Type* rhs) { ...@@ -970,8 +970,8 @@ Type* OperationTyper::NumberPow(Type* lhs, Type* rhs) {
#define SPECULATIVE_NUMBER_BINOP(Name) \ #define SPECULATIVE_NUMBER_BINOP(Name) \
Type* OperationTyper::Speculative##Name(Type* lhs, Type* rhs) { \ Type* OperationTyper::Speculative##Name(Type* lhs, Type* rhs) { \
lhs = ToNumber(Type::Intersect(lhs, Type::NumberOrOddball(), zone())); \ lhs = SpeculativeToNumber(lhs); \
rhs = ToNumber(Type::Intersect(rhs, Type::NumberOrOddball(), zone())); \ rhs = SpeculativeToNumber(rhs); \
return Name(lhs, rhs); \ return Name(lhs, rhs); \
} }
SPECULATIVE_NUMBER_BINOP(NumberAdd) SPECULATIVE_NUMBER_BINOP(NumberAdd)
...@@ -987,6 +987,10 @@ SPECULATIVE_NUMBER_BINOP(NumberShiftRight) ...@@ -987,6 +987,10 @@ SPECULATIVE_NUMBER_BINOP(NumberShiftRight)
SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical) SPECULATIVE_NUMBER_BINOP(NumberShiftRightLogical)
#undef SPECULATIVE_NUMBER_BINOP #undef SPECULATIVE_NUMBER_BINOP
Type* OperationTyper::SpeculativeToNumber(Type* type) {
return ToNumber(Type::Intersect(type, Type::NumberOrOddball(), zone()));
}
Type* OperationTyper::ToPrimitive(Type* type) { Type* OperationTyper::ToPrimitive(Type* type) {
if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) { if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
return type; return type;
......
...@@ -39,6 +39,7 @@ class V8_EXPORT_PRIVATE OperationTyper { ...@@ -39,6 +39,7 @@ class V8_EXPORT_PRIVATE OperationTyper {
// Number unary operators. // Number unary operators.
#define DECLARE_METHOD(Name) Type* Name(Type* type); #define DECLARE_METHOD(Name) Type* Name(Type* type);
SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD) SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD)
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_METHOD)
#undef DECLARE_METHOD #undef DECLARE_METHOD
// Number binary operators. // Number binary operators.
......
...@@ -454,6 +454,16 @@ class RepresentationSelector { ...@@ -454,6 +454,16 @@ class RepresentationSelector {
SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
#undef DECLARE_CASE #undef DECLARE_CASE
#define DECLARE_CASE(Name) \
case IrOpcode::k##Name: { \
new_type = \
Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0))), \
info->restriction_type(), graph_zone()); \
break; \
}
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
#undef DECLARE_CASE
case IrOpcode::kPlainPrimitiveToNumber: case IrOpcode::kPlainPrimitiveToNumber:
new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
break; break;
...@@ -840,11 +850,12 @@ class RepresentationSelector { ...@@ -840,11 +850,12 @@ class RepresentationSelector {
} }
// Helper for unops of the I -> O variety. // Helper for unops of the I -> O variety.
void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) { void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output,
Type* restriction_type = Type::Any()) {
DCHECK_EQ(1, node->op()->ValueInputCount()); DCHECK_EQ(1, node->op()->ValueInputCount());
ProcessInput(node, 0, input_use); ProcessInput(node, 0, input_use);
ProcessRemainingInputs(node, 1); ProcessRemainingInputs(node, 1);
SetOutput(node, output); SetOutput(node, output, restriction_type);
} }
// Helper for leaf nodes. // Helper for leaf nodes.
...@@ -2572,6 +2583,23 @@ class RepresentationSelector { ...@@ -2572,6 +2583,23 @@ class RepresentationSelector {
} }
return; return;
} }
case IrOpcode::kSpeculativeToNumber: {
NumberOperationHint const hint = NumberOperationHintOf(node->op());
switch (hint) {
case NumberOperationHint::kSigned32:
case NumberOperationHint::kSignedSmall:
VisitUnop(node, CheckedUseInfoAsWord32FromHint(hint),
MachineRepresentation::kWord32, Type::Signed32());
break;
case NumberOperationHint::kNumber:
case NumberOperationHint::kNumberOrOddball:
VisitUnop(node, CheckedUseInfoAsFloat64FromHint(hint),
MachineRepresentation::kFloat64);
break;
}
if (lower()) DeferReplacement(node, node->InputAt(0));
return;
}
case IrOpcode::kObjectIsDetectableCallable: { case IrOpcode::kObjectIsDetectableCallable: {
VisitObjectIs(node, Type::DetectableCallable(), lowering); VisitObjectIs(node, Type::DetectableCallable(), lowering);
return; return;
......
...@@ -371,7 +371,8 @@ size_t hash_value(NumberOperationHint hint) { ...@@ -371,7 +371,8 @@ size_t hash_value(NumberOperationHint hint) {
} }
NumberOperationHint NumberOperationHintOf(const Operator* op) { NumberOperationHint NumberOperationHintOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kSpeculativeNumberAdd || DCHECK(op->opcode() == IrOpcode::kSpeculativeToNumber ||
op->opcode() == IrOpcode::kSpeculativeNumberAdd ||
op->opcode() == IrOpcode::kSpeculativeNumberSubtract || op->opcode() == IrOpcode::kSpeculativeNumberSubtract ||
op->opcode() == IrOpcode::kSpeculativeNumberMultiply || op->opcode() == IrOpcode::kSpeculativeNumberMultiply ||
op->opcode() == IrOpcode::kSpeculativeNumberDivide || op->opcode() == IrOpcode::kSpeculativeNumberDivide ||
...@@ -696,6 +697,26 @@ struct SimplifiedOperatorGlobalCache final { ...@@ -696,6 +697,26 @@ struct SimplifiedOperatorGlobalCache final {
SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP) SPECULATIVE_NUMBER_BINOP_LIST(SPECULATIVE_NUMBER_BINOP)
#undef SPECULATIVE_NUMBER_BINOP #undef SPECULATIVE_NUMBER_BINOP
template <NumberOperationHint kHint>
struct SpeculativeToNumberOperator final
: public Operator1<NumberOperationHint> {
SpeculativeToNumberOperator()
: Operator1<NumberOperationHint>(
IrOpcode::kSpeculativeToNumber, // opcode
Operator::kFoldable | Operator::kNoThrow, // flags
"SpeculativeToNumber", // name
1, 1, 1, 1, 1, 0, // counts
kHint) {} // parameter
};
SpeculativeToNumberOperator<NumberOperationHint::kSignedSmall>
kSpeculativeToNumberSignedSmallOperator;
SpeculativeToNumberOperator<NumberOperationHint::kSigned32>
kSpeculativeToNumberSigned32Operator;
SpeculativeToNumberOperator<NumberOperationHint::kNumber>
kSpeculativeToNumberNumberOperator;
SpeculativeToNumberOperator<NumberOperationHint::kNumberOrOddball>
kSpeculativeToNumberNumberOrOddballOperator;
#define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \ #define BUFFER_ACCESS(Type, type, TYPE, ctype, size) \
struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \ struct LoadBuffer##Type##Operator final : public Operator1<BufferAccess> { \
LoadBuffer##Type##Operator() \ LoadBuffer##Type##Operator() \
...@@ -807,6 +828,22 @@ const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole( ...@@ -807,6 +828,22 @@ const Operator* SimplifiedOperatorBuilder::CheckFloat64Hole(
return nullptr; return nullptr;
} }
const Operator* SimplifiedOperatorBuilder::SpeculativeToNumber(
NumberOperationHint hint) {
switch (hint) {
case NumberOperationHint::kSignedSmall:
return &cache_.kSpeculativeToNumberSignedSmallOperator;
case NumberOperationHint::kSigned32:
return &cache_.kSpeculativeToNumberSigned32Operator;
case NumberOperationHint::kNumber:
return &cache_.kSpeculativeToNumberNumberOperator;
case NumberOperationHint::kNumberOrOddball:
return &cache_.kSpeculativeToNumberNumberOrOddballOperator;
}
UNREACHABLE();
return nullptr;
}
const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() { const Operator* SimplifiedOperatorBuilder::EnsureWritableFastElements() {
return &cache_.kEnsureWritableFastElements; return &cache_.kEnsureWritableFastElements;
} }
......
...@@ -381,6 +381,8 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final ...@@ -381,6 +381,8 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* StringFromCodePoint(UnicodeEncoding encoding); const Operator* StringFromCodePoint(UnicodeEncoding encoding);
const Operator* StringIndexOf(); const Operator* StringIndexOf();
const Operator* SpeculativeToNumber(NumberOperationHint hint);
const Operator* PlainPrimitiveToNumber(); const Operator* PlainPrimitiveToNumber();
const Operator* PlainPrimitiveToWord32(); const Operator* PlainPrimitiveToWord32();
const Operator* PlainPrimitiveToFloat64(); const Operator* PlainPrimitiveToFloat64();
......
...@@ -96,6 +96,8 @@ Reduction TypedOptimization::Reduce(Node* node) { ...@@ -96,6 +96,8 @@ Reduction TypedOptimization::Reduce(Node* node) {
return ReduceReferenceEqual(node); return ReduceReferenceEqual(node);
case IrOpcode::kSelect: case IrOpcode::kSelect:
return ReduceSelect(node); return ReduceSelect(node);
case IrOpcode::kSpeculativeToNumber:
return ReduceSpeculativeToNumber(node);
default: default:
break; break;
} }
...@@ -311,6 +313,18 @@ Reduction TypedOptimization::ReduceSelect(Node* node) { ...@@ -311,6 +313,18 @@ Reduction TypedOptimization::ReduceSelect(Node* node) {
return NoChange(); return NoChange();
} }
Reduction TypedOptimization::ReduceSpeculativeToNumber(Node* node) {
DCHECK_EQ(IrOpcode::kSpeculativeToNumber, node->opcode());
Node* const input = NodeProperties::GetValueInput(node, 0);
Type* const input_type = NodeProperties::GetType(input);
if (input_type->Is(Type::Number())) {
// SpeculativeToNumber(x:number) => x
ReplaceWithValue(node, input);
return Replace(input);
}
return NoChange();
}
Factory* TypedOptimization::factory() const { return isolate()->factory(); } Factory* TypedOptimization::factory() const { return isolate()->factory(); }
Graph* TypedOptimization::graph() const { return jsgraph()->graph(); } Graph* TypedOptimization::graph() const { return jsgraph()->graph(); }
......
...@@ -52,6 +52,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final ...@@ -52,6 +52,7 @@ class V8_EXPORT_PRIVATE TypedOptimization final
Reduction ReducePhi(Node* node); Reduction ReducePhi(Node* node);
Reduction ReduceReferenceEqual(Node* node); Reduction ReduceReferenceEqual(Node* node);
Reduction ReduceSelect(Node* node); Reduction ReduceSelect(Node* node);
Reduction ReduceSpeculativeToNumber(Node* node);
CompilationDependencies* dependencies() const { return dependencies_; } CompilationDependencies* dependencies() const { return dependencies_; }
Factory* factory() const; Factory* factory() const;
......
...@@ -108,6 +108,7 @@ class Typer::Visitor : public Reducer { ...@@ -108,6 +108,7 @@ class Typer::Visitor : public Reducer {
case IrOpcode::k##x: \ case IrOpcode::k##x: \
return UpdateType(node, TypeUnaryOp(node, x)); return UpdateType(node, TypeUnaryOp(node, x));
SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
#undef DECLARE_CASE #undef DECLARE_CASE
#define DECLARE_CASE(x) case IrOpcode::k##x: #define DECLARE_CASE(x) case IrOpcode::k##x:
...@@ -173,6 +174,7 @@ class Typer::Visitor : public Reducer { ...@@ -173,6 +174,7 @@ class Typer::Visitor : public Reducer {
case IrOpcode::k##x: \ case IrOpcode::k##x: \
return TypeUnaryOp(node, x); return TypeUnaryOp(node, x);
SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE)
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
#undef DECLARE_CASE #undef DECLARE_CASE
#define DECLARE_CASE(x) case IrOpcode::k##x: #define DECLARE_CASE(x) case IrOpcode::k##x:
...@@ -274,6 +276,7 @@ class Typer::Visitor : public Reducer { ...@@ -274,6 +276,7 @@ class Typer::Visitor : public Reducer {
return t->operation_typer_.Name(type); \ return t->operation_typer_.Name(type); \
} }
SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD) SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_METHOD)
SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_METHOD)
#undef DECLARE_METHOD #undef DECLARE_METHOD
#define DECLARE_METHOD(Name) \ #define DECLARE_METHOD(Name) \
static Type* Name(Type* lhs, Type* rhs, Typer* t) { \ static Type* Name(Type* lhs, Type* rhs, Typer* t) { \
......
...@@ -914,6 +914,11 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -914,6 +914,11 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Number()); CheckValueInputIs(node, 0, Type::Number());
CheckTypeIs(node, Type::Unsigned32()); CheckTypeIs(node, Type::Unsigned32());
break; break;
case IrOpcode::kSpeculativeToNumber:
// Any -> Number
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Number());
break;
case IrOpcode::kPlainPrimitiveToNumber: case IrOpcode::kPlainPrimitiveToNumber:
// PlainPrimitive -> Number // PlainPrimitive -> Number
CheckValueInputIs(node, 0, Type::PlainPrimitive()); CheckValueInputIs(node, 0, Type::PlainPrimitive());
......
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