Commit 15ebec03 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Introduce CheckedUint32Div and CheckUint32Mod operators.

Checked integer division and modulus can be done more efficiently
if we know that the inputs are in Unsigned32 range.

Drive-by-fix: Replace the TypeCheckKind on NodeInfo by a proper
restriction type, and thread the feedback type through binary
Number operations similar to what we do for their speculative
versions. Also deal with Unsigned32 inputs for integer multiplication.

R=jarin@chromium.org
BUG=v8:4583,v8:5141

Review-Url: https://codereview.chromium.org/2149493002
Cr-Commit-Position: refs/heads/master@{#37703}
parent 08843650
......@@ -642,6 +642,12 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kCheckedInt32Mod:
state = LowerCheckedInt32Mod(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedUint32Div:
state = LowerCheckedUint32Div(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedUint32Mod:
state = LowerCheckedUint32Mod(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedUint32ToInt32:
state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
break;
......@@ -1248,6 +1254,50 @@ EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32Div(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* zero = jsgraph()->Int32Constant(0);
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
// Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
frame_state, effect, control);
// Perform the actual unsigned integer division.
Node* value = graph()->NewNode(machine()->Uint32Div(), lhs, rhs, control);
// Check if the remainder is non-zero.
check = graph()->NewNode(machine()->Word32Equal(), lhs,
graph()->NewNode(machine()->Int32Mul(), rhs, value));
control = effect = graph()->NewNode(common()->DeoptimizeUnless(), check,
frame_state, effect, control);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32Mod(Node* node, Node* frame_state,
Node* effect, Node* control) {
Node* zero = jsgraph()->Int32Constant(0);
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
// Ensure that {rhs} is not zero, otherwise we'd have to return NaN.
Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
control = effect = graph()->NewNode(common()->DeoptimizeIf(), check,
frame_state, effect, control);
// Perform the actual unsigned integer modulus.
Node* value = graph()->NewNode(machine()->Uint32Mod(), lhs, rhs, control);
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
Node* frame_state,
......
......@@ -79,6 +79,10 @@ class EffectControlLinearizer {
Node* effect, Node* control);
ValueEffectControl LowerCheckedInt32Mod(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedUint32Div(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedUint32Mod(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state,
......
......@@ -182,6 +182,8 @@
V(CheckedInt32Sub) \
V(CheckedInt32Div) \
V(CheckedInt32Mod) \
V(CheckedUint32Div) \
V(CheckedUint32Mod) \
V(CheckedUint32ToInt32) \
V(CheckedFloat64ToInt32) \
V(CheckedTaggedToInt32) \
......
......@@ -663,6 +663,18 @@ const Operator* RepresentationChanger::Uint32OperatorFor(
}
}
const Operator* RepresentationChanger::Uint32OverflowOperatorFor(
IrOpcode::Value opcode) {
switch (opcode) {
case IrOpcode::kSpeculativeNumberDivide:
return simplified()->CheckedUint32Div();
case IrOpcode::kSpeculativeNumberModulus:
return simplified()->CheckedUint32Mod();
default:
UNREACHABLE();
return nullptr;
}
}
const Operator* RepresentationChanger::Float64OperatorFor(
IrOpcode::Value opcode) {
......
......@@ -190,6 +190,7 @@ class RepresentationChanger final {
const Operator* Int32OperatorFor(IrOpcode::Value opcode);
const Operator* Int32OverflowOperatorFor(IrOpcode::Value opcode);
const Operator* Uint32OperatorFor(IrOpcode::Value opcode);
const Operator* Uint32OverflowOperatorFor(IrOpcode::Value opcode);
const Operator* Float64OperatorFor(IrOpcode::Value opcode);
MachineType TypeForBasePointer(const FieldAccess& access) {
......
......@@ -183,7 +183,7 @@ class InputUseInfos {
class RepresentationSelector {
public:
// Information for each node tracked during the fixpoint.
class NodeInfo {
class NodeInfo final {
public:
// Adds new use to the node. Returns true if something has changed
// and the node has to be requeued.
......@@ -207,11 +207,11 @@ class RepresentationSelector {
// Helpers for feedback typing.
void set_feedback_type(Type* type) { feedback_type_ = type; }
Type* feedback_type() { return feedback_type_; }
Type* feedback_type() const { return feedback_type_; }
void set_weakened() { weakened_ = true; }
bool weakened() { return weakened_; }
TypeCheckKind type_check() { return type_check_; }
void set_type_check(TypeCheckKind type_check) { type_check_ = type_check; }
bool weakened() const { return weakened_; }
void set_restriction_type(Type* type) { restriction_type_ = type; }
Type* restriction_type() const { return restriction_type_; }
private:
enum State : uint8_t { kUnvisited, kPushed, kVisited, kQueued };
......@@ -219,8 +219,8 @@ class RepresentationSelector {
MachineRepresentation representation_ =
MachineRepresentation::kNone; // Output representation.
Truncation truncation_ = Truncation::None(); // Information about uses.
TypeCheckKind type_check_ = TypeCheckKind::kNone; // Runtime check kind.
Type* restriction_type_ = Type::Any();
Type* feedback_type_ = nullptr;
bool weakened_ = false;
};
......@@ -343,23 +343,6 @@ class RepresentationSelector {
FeedbackTypeOf(node->InputAt(2)));
}
static Type* TypeOfSpeculativeOp(TypeCheckKind type_check) {
switch (type_check) {
case TypeCheckKind::kNone:
return Type::Any();
case TypeCheckKind::kSigned32:
return Type::Signed32();
case TypeCheckKind::kNumber:
return Type::Number();
// Unexpected cases.
case TypeCheckKind::kNumberOrUndefined:
FATAL("Unexpected checked type.");
break;
}
UNREACHABLE();
return nullptr;
}
bool UpdateFeedbackType(Node* node) {
if (node->op()->ValueOutputCount() == 0) return false;
......@@ -379,6 +362,7 @@ class RepresentationSelector {
}
switch (node->opcode()) {
case IrOpcode::kNumberAdd:
case IrOpcode::kSpeculativeNumberAdd: {
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
......@@ -386,16 +370,13 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumberAdd(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
new_type = Type::Intersect(static_type, feedback_type, graph_zone());
}
Type* computed_type = op_typer_.NumberAdd(lhs, rhs);
new_type = Type::Intersect(computed_type, info->restriction_type(),
graph_zone());
break;
}
case IrOpcode::kNumberSubtract:
case IrOpcode::kSpeculativeNumberSubtract: {
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
......@@ -403,16 +384,13 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumberSubtract(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
new_type = Type::Intersect(static_type, feedback_type, graph_zone());
}
Type* computed_type = op_typer_.NumberSubtract(lhs, rhs);
new_type = Type::Intersect(computed_type, info->restriction_type(),
graph_zone());
break;
}
case IrOpcode::kNumberMultiply:
case IrOpcode::kSpeculativeNumberMultiply: {
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
......@@ -420,16 +398,13 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumberMultiply(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
new_type = Type::Intersect(static_type, feedback_type, graph_zone());
}
Type* computed_type = op_typer_.NumberMultiply(lhs, rhs);
new_type = Type::Intersect(computed_type, info->restriction_type(),
graph_zone());
break;
}
case IrOpcode::kNumberDivide:
case IrOpcode::kSpeculativeNumberDivide: {
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
......@@ -437,16 +412,13 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumberDivide(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
new_type = Type::Intersect(static_type, feedback_type, graph_zone());
}
Type* computed_type = op_typer_.NumberDivide(lhs, rhs);
new_type = Type::Intersect(computed_type, info->restriction_type(),
graph_zone());
break;
}
case IrOpcode::kNumberModulus:
case IrOpcode::kSpeculativeNumberModulus: {
// TODO(jarin) The ToNumber conversion is too conservative here,
// e.g. it will treat true as 1 even though the number check will
......@@ -454,13 +426,9 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumberModulus(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
Type* feedback_type = TypeOfSpeculativeOp(info->type_check());
new_type = Type::Intersect(static_type, feedback_type, graph_zone());
}
Type* computed_type = op_typer_.NumberModulus(lhs, rhs);
new_type = Type::Intersect(computed_type, info->restriction_type(),
graph_zone());
break;
}
......@@ -657,30 +625,25 @@ class RepresentationSelector {
bool propagate() const { return phase_ == PROPAGATE; }
void SetOutput(Node* node, MachineRepresentation representation,
TypeCheckKind type_check = TypeCheckKind::kNone) {
Type* restriction_type = Type::Any()) {
NodeInfo* const info = GetInfo(node);
switch (phase_) {
case PROPAGATE:
info->set_type_check(type_check);
info->set_restriction_type(restriction_type);
break;
case RETYPE:
DCHECK_EQ(info->type_check(), type_check);
DCHECK(info->restriction_type()->Is(restriction_type));
DCHECK(restriction_type->Is(info->restriction_type()));
info->set_output(representation);
break;
case LOWER:
DCHECK_EQ(info->type_check(), type_check);
DCHECK_EQ(info->representation(), representation);
DCHECK(info->restriction_type()->Is(restriction_type));
DCHECK(restriction_type->Is(info->restriction_type()));
break;
}
}
void ResetOutput(Node* node, MachineRepresentation representation,
TypeCheckKind type_check = TypeCheckKind::kNone) {
NodeInfo* info = GetInfo(node);
info->set_output(representation);
info->set_type_check(type_check);
}
Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
bool InputCannotBe(Node* node, Type* type) {
......@@ -777,20 +740,20 @@ class RepresentationSelector {
// Helper for binops of the R x L -> O variety.
void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
MachineRepresentation output,
TypeCheckKind type_check = TypeCheckKind::kNone) {
Type* restriction_type = Type::Any()) {
DCHECK_EQ(2, node->op()->ValueInputCount());
ProcessInput(node, 0, left_use);
ProcessInput(node, 1, right_use);
for (int i = 2; i < node->InputCount(); i++) {
EnqueueInput(node, i);
}
SetOutput(node, output, type_check);
SetOutput(node, output, restriction_type);
}
// Helper for binops of the I x I -> O variety.
void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output,
TypeCheckKind type_check = TypeCheckKind::kNone) {
VisitBinop(node, input_use, input_use, output, type_check);
Type* restriction_type = Type::Any()) {
VisitBinop(node, input_use, input_use, output, restriction_type);
}
// Helper for unops of the I -> O variety.
......@@ -1006,6 +969,10 @@ class RepresentationSelector {
return changer_->Uint32OperatorFor(node->opcode());
}
const Operator* Uint32OverflowOp(Node* node) {
return changer_->Uint32OverflowOperatorFor(node->opcode());
}
const Operator* Float64Op(Node* node) {
return changer_->Float64OperatorFor(node->opcode());
}
......@@ -1108,8 +1075,12 @@ class RepresentationSelector {
NodeProperties::ChangeOp(node, new_op);
}
void ChangeToInt32OverflowOp(Node* node, const Operator* new_op) {
NodeProperties::ChangeOp(node, new_op);
void ChangeToInt32OverflowOp(Node* node) {
NodeProperties::ChangeOp(node, Int32OverflowOp(node));
}
void ChangeToUint32OverflowOp(Node* node) {
NodeProperties::ChangeOp(node, Uint32OverflowOp(node));
}
void VisitSpeculativeAdditiveOp(Node* node, Truncation truncation,
......@@ -1144,10 +1115,8 @@ class RepresentationSelector {
if (hint == BinaryOperationHints::kSignedSmall ||
hint == BinaryOperationHints::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
if (lower()) {
ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
}
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
return;
}
}
......@@ -1155,16 +1124,14 @@ class RepresentationSelector {
if (hint == BinaryOperationHints::kSignedSmall ||
hint == BinaryOperationHints::kSigned32) {
VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
MachineRepresentation::kWord32, TypeCheckKind::kSigned32);
if (lower()) {
ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
}
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
return;
}
// default case => Float64Add/Sub
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
MachineRepresentation::kFloat64, Type::Number());
if (lower()) {
ChangeToPureOp(node, Float64Op(node));
}
......@@ -1348,25 +1315,21 @@ class RepresentationSelector {
}
case IrOpcode::kSpeculativeNumberMultiply:
case IrOpcode::kNumberMultiply: {
if (BothInputsAreSigned32(node)) {
if (NodeProperties::GetType(node)->Is(Type::Signed32())) {
// Multiply reduces to Int32Mul if the inputs and the output
// are integers.
VisitInt32Binop(node);
if (lower()) ChangeToPureOp(node, Int32Op(node));
return;
}
if (truncation.TruncatesToWord32() &&
if (BothInputsAre(node, Type::Integral32()) &&
(NodeProperties::GetType(node)->Is(Type::Signed32()) ||
NodeProperties::GetType(node)->Is(Type::Unsigned32()) ||
(truncation.TruncatesToWord32() &&
NodeProperties::GetType(node)->Is(
type_cache_.kSafeIntegerOrMinusZero)) {
// Multiply reduces to Int32Mul if the inputs are integers,
// the uses are truncating and the result is in the safe
type_cache_.kSafeIntegerOrMinusZero)))) {
// Multiply reduces to Int32Mul if the inputs are integers, and
// (a) the output is either known to be Signed32, or
// (b) the output is known to be Unsigned32, or
// (c) the uses are truncating and the result is in the safe
// integer range.
VisitWord32TruncatingBinop(node);
if (lower()) ChangeToPureOp(node, Int32Op(node));
return;
}
}
// Number x Number => Float64Mul
if (BothInputsAre(node, Type::NumberOrUndefined())) {
VisitFloat64Binop(node);
......@@ -1376,7 +1339,7 @@ class RepresentationSelector {
// Checked float64 x float64 => float64
DCHECK_EQ(IrOpcode::kSpeculativeNumberMultiply, node->opcode());
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
}
......@@ -1405,16 +1368,27 @@ class RepresentationSelector {
// Try to use type feedback.
BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op());
// Handle the case when no uint32 checks on inputs are necessary
// (but an overflow check is needed on the output).
if (BothInputsAreUnsigned32(node)) {
if (hint == BinaryOperationHints::kSignedSmall ||
hint == BinaryOperationHints::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32, Type::Unsigned32());
if (lower()) ChangeToUint32OverflowOp(node);
return;
}
}
// Handle the case when no int32 checks on inputs are necessary
// (but an overflow check is needed on the output).
if (BothInputsAre(node, Type::Signed32())) {
if (BothInputsAreSigned32(node)) {
// If both the inputs the feedback are int32, use the overflow op.
if (hint == BinaryOperationHints::kSignedSmall ||
hint == BinaryOperationHints::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32,
TypeCheckKind::kSigned32);
if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
return;
}
}
......@@ -1428,16 +1402,15 @@ class RepresentationSelector {
if (lower()) DeferReplacement(node, lowering->Int32Div(node));
} else {
VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
MachineRepresentation::kWord32,
TypeCheckKind::kSigned32);
if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
}
return;
}
// default case => Float64Div
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
}
......@@ -1471,7 +1444,7 @@ class RepresentationSelector {
// Checked float64 x float64 => float64
DCHECK_EQ(IrOpcode::kSpeculativeNumberDivide, node->opcode());
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
}
......@@ -1500,6 +1473,18 @@ class RepresentationSelector {
// Try to use type feedback.
BinaryOperationHints::Hint hint = BinaryOperationHintOf(node->op());
// Handle the case when no uint32 checks on inputs are necessary
// (but an overflow check is needed on the output).
if (BothInputsAreUnsigned32(node)) {
if (hint == BinaryOperationHints::kSignedSmall ||
hint == BinaryOperationHints::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32, Type::Unsigned32());
if (lower()) ChangeToUint32OverflowOp(node);
return;
}
}
// Handle the case when no int32 checks on inputs are necessary
// (but an overflow check is needed on the output).
if (BothInputsAre(node, Type::Signed32())) {
......@@ -1507,9 +1492,8 @@ class RepresentationSelector {
if (hint == BinaryOperationHints::kSignedSmall ||
hint == BinaryOperationHints::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32,
TypeCheckKind::kSigned32);
if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
return;
}
}
......@@ -1523,16 +1507,15 @@ class RepresentationSelector {
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
} else {
VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
MachineRepresentation::kWord32,
TypeCheckKind::kSigned32);
if (lower()) ChangeToInt32OverflowOp(node, Int32OverflowOp(node));
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
}
return;
}
// default case => Float64Mod
VisitBinop(node, UseInfo::CheckedNumberOrUndefinedAsFloat64(),
MachineRepresentation::kFloat64, TypeCheckKind::kNumber);
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
}
......
......@@ -321,6 +321,8 @@ CompareOperationHints::Hint CompareOperationHintOf(const Operator* op) {
V(CheckedInt32Sub, 2, 1) \
V(CheckedInt32Div, 2, 1) \
V(CheckedInt32Mod, 2, 1) \
V(CheckedUint32Div, 2, 1) \
V(CheckedUint32Mod, 2, 1) \
V(CheckedUint32ToInt32, 1, 1) \
V(CheckedFloat64ToInt32, 1, 1) \
V(CheckedTaggedToInt32, 1, 1) \
......
......@@ -254,6 +254,8 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckedInt32Sub();
const Operator* CheckedInt32Div();
const Operator* CheckedInt32Mod();
const Operator* CheckedUint32Div();
const Operator* CheckedUint32Mod();
const Operator* CheckedUint32ToInt32();
const Operator* CheckedFloat64ToInt32();
const Operator* CheckedTaggedToInt32();
......
......@@ -946,6 +946,8 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kCheckedInt32Sub:
case IrOpcode::kCheckedInt32Div:
case IrOpcode::kCheckedInt32Mod:
case IrOpcode::kCheckedUint32Div:
case IrOpcode::kCheckedUint32Mod:
case IrOpcode::kCheckedUint32ToInt32:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32:
......
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