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