| Index: src/compiler/effect-control-linearizer.cc
|
| diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
|
| index 575f050601f36c947a747efe6ef8c5b9417932fc..1b6752ab153c019aa3062cc96c4fb5ae17826281 100644
|
| --- a/src/compiler/effect-control-linearizer.cc
|
| +++ b/src/compiler/effect-control-linearizer.cc
|
| @@ -1285,17 +1285,31 @@ EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state,
|
| Node* minusone = jsgraph()->Int32Constant(-1);
|
| Node* minint = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::min());
|
|
|
| + // General case for signed integer modulus, with optimization for (unknown)
|
| + // power of 2 right hand side.
|
| + //
|
| + // if 0 < rhs then
|
| + // msk = rhs - 1
|
| + // if rhs & msk == 0 then
|
| + // if lhs < 0 then
|
| + // -(-lhs & msk)
|
| + // else
|
| + // lhs & msk
|
| + // else
|
| + // lhs % rhs
|
| + // else
|
| + // if rhs < -1 then
|
| + // lhs % rhs
|
| + // else
|
| + // deopt if rhs == 0
|
| + // deopt if lhs == minint
|
| + // zero
|
| + //
|
| 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(DeoptimizeReason::kDivisionByZero), check,
|
| - frame_state, effect, control);
|
| -
|
| - // Check if {lhs} is positive or zero.
|
| - Node* check0 = graph()->NewNode(machine()->Int32LessThanOrEqual(), zero, lhs);
|
| + // Check if {rhs} is strictly positive.
|
| + Node* check0 = graph()->NewNode(machine()->Int32LessThan(), zero, rhs);
|
| Node* branch0 =
|
| graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control);
|
|
|
| @@ -1303,46 +1317,90 @@ EffectControlLinearizer::LowerCheckedInt32Mod(Node* node, Node* frame_state,
|
| Node* etrue0 = effect;
|
| Node* vtrue0;
|
| {
|
| - // Fast case, no additional checking required.
|
| - vtrue0 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true0);
|
| + Node* msk = graph()->NewNode(machine()->Int32Add(), rhs, minusone);
|
| +
|
| + // Check if {rhs} minus one is a valid mask.
|
| + Node* check1 = graph()->NewNode(
|
| + machine()->Word32Equal(),
|
| + graph()->NewNode(machine()->Word32And(), rhs, msk), zero);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
|
| +
|
| + Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| + Node* vtrue1;
|
| + {
|
| + // Check if {lhs} is negative.
|
| + Node* check2 = graph()->NewNode(machine()->Int32LessThan(), lhs, zero);
|
| + Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check2, if_true1);
|
| +
|
| + // Compute the remainder as {-(-lhs & msk)}.
|
| + Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
|
| + Node* vtrue2 = graph()->NewNode(
|
| + machine()->Int32Sub(), zero,
|
| + graph()->NewNode(machine()->Word32And(),
|
| + graph()->NewNode(machine()->Int32Sub(), zero, lhs),
|
| + msk));
|
| +
|
| + // Compute the remainder as {lhs & msk}.
|
| + Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
|
| + Node* vfalse2 = graph()->NewNode(machine()->Word32And(), lhs, msk);
|
| +
|
| + if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
|
| + vtrue1 =
|
| + graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
|
| + vtrue2, vfalse2, if_true1);
|
| + }
|
| +
|
| + // Compute the remainder using the generic {lhs % rhs}.
|
| + Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| + Node* vfalse1 =
|
| + graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false1);
|
| +
|
| + if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| + vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
|
| + vtrue1, vfalse1, if_true0);
|
| }
|
|
|
| Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
|
| Node* efalse0 = effect;
|
| Node* vfalse0;
|
| {
|
| - // Check if {lhs} is kMinInt and {rhs} is -1, in which case we'd have
|
| - // to return -0.
|
| - Node* check1 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
|
| - Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + // Check if {rhs} is strictly less than -1.
|
| + Node* check1 = graph()->NewNode(machine()->Int32LessThan(), rhs, minusone);
|
| + Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
|
| check1, if_false0);
|
|
|
| + // Compute the remainder using the generic {lhs % rhs}.
|
| Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
|
| Node* etrue1 = efalse0;
|
| - {
|
| - // Check if {rhs} is -1.
|
| - Node* check = graph()->NewNode(machine()->Word32Equal(), rhs, minusone);
|
| - if_true1 = etrue1 =
|
| - graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
|
| - check, frame_state, etrue1, if_true1);
|
| - }
|
| + Node* vtrue1 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_true1);
|
|
|
| Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
|
| Node* efalse1 = efalse0;
|
| + Node* vfalse1;
|
| + {
|
| + // Ensure that {rhs} is not zero.
|
| + Node* check2 = graph()->NewNode(machine()->Word32Equal(), rhs, zero);
|
| + if_false1 = efalse1 = graph()->NewNode(
|
| + common()->DeoptimizeIf(DeoptimizeReason::kDivisionByZero), check2,
|
| + frame_state, efalse1, if_false1);
|
| +
|
| + // Now we know that {rhs} is -1, so make sure {lhs} is not kMinInt, as
|
| + // we would otherwise have to return -0.
|
| + Node* check3 = graph()->NewNode(machine()->Word32Equal(), lhs, minint);
|
| + if_false1 = efalse1 =
|
| + graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
|
| + check3, frame_state, efalse1, if_false1);
|
| +
|
| + // The remainder is zero.
|
| + vfalse1 = zero;
|
| + }
|
|
|
| if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
|
| efalse0 =
|
| graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
|
| -
|
| - // Perform the actual integer modulos.
|
| - vfalse0 = graph()->NewNode(machine()->Int32Mod(), lhs, rhs, if_false0);
|
| -
|
| - // Check if the result is zero, because in that case we'd have to return
|
| - // -0 here since we always take the signe of the {lhs} which is negative.
|
| - Node* check = graph()->NewNode(machine()->Word32Equal(), vfalse0, zero);
|
| - if_false0 = efalse0 =
|
| - graph()->NewNode(common()->DeoptimizeIf(DeoptimizeReason::kMinusZero),
|
| - check, frame_state, efalse0, if_false0);
|
| + vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2),
|
| + vtrue1, vfalse1, if_false0);
|
| }
|
|
|
| control = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
|
|
|