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) {
......
This diff is collapsed.
......@@ -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