Commit 24ef71d9 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] More efficient code generation for unsigned modulus.

If we know statically that x and y are both in Unsigned32 or NaN or -0,
and we have SignedSmall or Signed32 feedback for x % y, then we can take
the feedback on the inputs and lower to Uint32Mod.

Drive-by-fix: Refactor this logic into a separate method.

R=jarin@chromium.org
BUG=v8:5267

Review-Url: https://codereview.chromium.org/2287303002
Cr-Commit-Position: refs/heads/master@{#38975}
parent d90d76bd
...@@ -1175,6 +1175,110 @@ class RepresentationSelector { ...@@ -1175,6 +1175,110 @@ class RepresentationSelector {
return; return;
} }
void VisitSpeculativeNumberModulus(Node* node, Truncation truncation,
SimplifiedLowering* lowering) {
// ToNumber(x) can throw if x is either a Receiver or a Symbol, so we
// can only eliminate an unused speculative number operation if we know
// that the inputs are PlainPrimitive, which excludes everything that's
// might have side effects or throws during a ToNumber conversion.
if (BothInputsAre(node, Type::PlainPrimitive())) {
if (truncation.IsUnused()) return VisitUnused(node);
}
if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
// => unsigned Uint32Mod
VisitWord32TruncatingBinop(node);
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
return;
}
if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Signed32()))) {
// => signed Int32Mod
VisitWord32TruncatingBinop(node);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
return;
}
// Try to use type feedback.
NumberOperationHint hint = NumberOperationHintOf(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 == NumberOperationHint::kSignedSmall ||
hint == NumberOperationHint::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 both the inputs the feedback are int32, use the overflow op.
if (hint == NumberOperationHint::kSignedSmall ||
hint == NumberOperationHint::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
return;
}
}
if (hint == NumberOperationHint::kSignedSmall ||
hint == NumberOperationHint::kSigned32) {
// If the result is truncated, we only need to check the inputs.
if (truncation.IsUsedAsWord32()) {
VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
} else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) {
VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
MachineRepresentation::kWord32, Type::Unsigned32());
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
} else {
VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
}
return;
}
if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
// We can only promise Float64 truncation here, as the decision is
// based on the feedback types of the inputs.
VisitBinop(node,
UseInfo(MachineRepresentation::kWord32, Truncation::Float64()),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
return;
}
if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Signed32()))) {
// We can only promise Float64 truncation here, as the decision is
// based on the feedback types of the inputs.
VisitBinop(node,
UseInfo(MachineRepresentation::kWord32, Truncation::Float64()),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
return;
}
// default case => Float64Mod
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
}
// Dispatching routine for visiting the node {node} with the usage {use}. // Dispatching routine for visiting the node {node} with the usage {use}.
// Depending on the operator, propagate new usage info to the inputs. // Depending on the operator, propagate new usage info to the inputs.
void VisitNode(Node* node, Truncation truncation, void VisitNode(Node* node, Truncation truncation,
...@@ -1592,104 +1696,8 @@ class RepresentationSelector { ...@@ -1592,104 +1696,8 @@ class RepresentationSelector {
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
} }
case IrOpcode::kSpeculativeNumberModulus: { case IrOpcode::kSpeculativeNumberModulus:
// ToNumber(x) can throw if x is either a Receiver or a Symbol, so we return VisitSpeculativeNumberModulus(node, truncation, lowering);
// can only eliminate an unused speculative number operation if we know
// that the inputs are PlainPrimitive, which excludes everything that's
// might have side effects or throws during a ToNumber conversion.
if (BothInputsAre(node, Type::PlainPrimitive())) {
if (truncation.IsUnused()) return VisitUnused(node);
}
if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
// => unsigned Uint32Mod
VisitWord32TruncatingBinop(node);
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
return;
}
if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Signed32()))) {
// => signed Int32Mod
VisitWord32TruncatingBinop(node);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
return;
}
// Try to use type feedback.
NumberOperationHint hint = NumberOperationHintOf(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 == NumberOperationHint::kSignedSmall ||
hint == NumberOperationHint::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 both the inputs the feedback are int32, use the overflow op.
if (hint == NumberOperationHint::kSignedSmall ||
hint == NumberOperationHint::kSigned32) {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
return;
}
}
if (hint == NumberOperationHint::kSignedSmall ||
hint == NumberOperationHint::kSigned32) {
// If the result is truncated, we only need to check the inputs.
if (truncation.IsUsedAsWord32()) {
VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
} else {
VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint),
MachineRepresentation::kWord32, Type::Signed32());
if (lower()) ChangeToInt32OverflowOp(node);
}
return;
}
if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32()) &&
TypeOf(node->InputAt(1))->Is(Type::Unsigned32()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Unsigned32()))) {
// We can only promise Float64 truncation here, as the decision is
// based on the feedback types of the inputs.
VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
Truncation::Float64()),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
return;
}
if (TypeOf(node->InputAt(0))->Is(Type::Signed32()) &&
TypeOf(node->InputAt(1))->Is(Type::Signed32()) &&
(truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node)->Is(Type::Signed32()))) {
// We can only promise Float64 truncation here, as the decision is
// based on the feedback types of the inputs.
VisitBinop(node, UseInfo(MachineRepresentation::kWord32,
Truncation::Float64()),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
return;
}
// default case => Float64Mod
VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(),
MachineRepresentation::kFloat64, Type::Number());
if (lower()) ChangeToPureOp(node, Float64Op(node));
return;
}
case IrOpcode::kNumberModulus: { case IrOpcode::kNumberModulus: {
if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) &&
(truncation.IsUsedAsWord32() || (truncation.IsUsedAsWord32() ||
......
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