Commit 48854a23 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[turbofan] Unify NumberModulus handling in SimplifiedLowering.

In the spirit of https://chromium-review.googlesource.com/1226033 we can
also unify the handling of NumberModulus based on feedback types.

Drive-by-fix: Add appropriate tests for the corner cases of the
NumberModules with (surrounding) feedback integration.

Bug: v8:8015
Change-Id: I5e3207d2f6e72f9ea1d7658014b7272075088d63
Reviewed-on: https://chromium-review.googlesource.com/1236260
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56094}
parent 96605878
...@@ -1982,47 +1982,25 @@ class RepresentationSelector { ...@@ -1982,47 +1982,25 @@ class RepresentationSelector {
case IrOpcode::kSpeculativeNumberModulus: case IrOpcode::kSpeculativeNumberModulus:
return VisitSpeculativeNumberModulus(node, truncation, lowering); return VisitSpeculativeNumberModulus(node, truncation, lowering);
case IrOpcode::kNumberModulus: { case IrOpcode::kNumberModulus: {
if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && if ((TypeOf(node->InputAt(0)).Is(Type::Unsigned32OrMinusZeroOrNaN()) &&
TypeOf(node->InputAt(1)).Is(Type::Unsigned32OrMinusZeroOrNaN())) &&
(truncation.IsUsedAsWord32() || (truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node).Is(Type::Unsigned32()))) { TypeOf(node).Is(Type::Unsigned32()))) {
// => unsigned Uint32Mod // => unsigned Uint32Mod
VisitWord32TruncatingBinop(node); VisitWord32TruncatingBinop(node);
if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); if (lower()) DeferReplacement(node, lowering->Uint32Mod(node));
return; return;
} }
if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && if ((TypeOf(node->InputAt(0)).Is(Type::Signed32OrMinusZeroOrNaN()) &&
TypeOf(node->InputAt(1)).Is(Type::Signed32OrMinusZeroOrNaN())) &&
(truncation.IsUsedAsWord32() || (truncation.IsUsedAsWord32() ||
NodeProperties::GetType(node).Is(Type::Signed32()))) { TypeOf(node).Is(Type::Signed32()))) {
// => signed Int32Mod // => signed Int32Mod
VisitWord32TruncatingBinop(node); VisitWord32TruncatingBinop(node);
if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); if (lower()) DeferReplacement(node, lowering->Int32Mod(node));
return; return;
} }
if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && // => Float64Mod
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
VisitFloat64Binop(node); VisitFloat64Binop(node);
if (lower()) ChangeToPureOp(node, Float64Op(node)); if (lower()) ChangeToPureOp(node, Float64Op(node));
return; return;
......
...@@ -4,6 +4,64 @@ ...@@ -4,6 +4,64 @@
// Flags: --allow-natives-syntax --opt // Flags: --allow-natives-syntax --opt
// Test that NumberModulus with Number feedback works if only in the
// end SimplifiedLowering figures out that the inputs to this operation
// are actually Unsigned32.
(function() {
// We need a separately polluted % with NumberOrOddball feedback.
function bar(x) { return x % 2; }
bar(undefined); // The % feedback is now NumberOrOddball.
// Now just use the gadget above in a way that only after RETYPE
// in SimplifiedLowering we find out that the `x` is actually in
// Unsigned32 range (based on taking the SignedSmall feedback on
// the + operator).
function foo(x) {
x = (x >>> 0) + 1;
return bar(x) | 0;
}
assertEquals(0, foo(1));
assertEquals(1, foo(2));
assertEquals(0, foo(3));
assertEquals(1, foo(4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(0, foo(1));
assertEquals(1, foo(2));
assertEquals(0, foo(3));
assertEquals(1, foo(4));
assertOptimized(foo);
})();
// Test that NumberModulus with Number feedback works if only in the
// end SimplifiedLowering figures out that the inputs to this operation
// are actually Signed32.
(function() {
// We need a separately polluted % with NumberOrOddball feedback.
function bar(x) { return x % 2; }
bar(undefined); // The % feedback is now NumberOrOddball.
// Now just use the gadget above in a way that only after RETYPE
// in SimplifiedLowering we find out that the `x` is actually in
// Signed32 range (based on taking the SignedSmall feedback on
// the + operator).
function foo(x) {
x = (x | 0) + 1;
return bar(x) | 0;
}
assertEquals(0, foo(1));
assertEquals(1, foo(2));
assertEquals(0, foo(3));
assertEquals(1, foo(4));
%OptimizeFunctionOnNextCall(foo);
assertEquals(0, foo(1));
assertEquals(1, foo(2));
assertEquals(0, foo(3));
assertEquals(1, foo(4));
assertOptimized(foo);
})();
// Test that SpeculativeNumberModulus with Number feedback works if // Test that SpeculativeNumberModulus with Number feedback works if
// only in the end SimplifiedLowering figures out that the inputs to // only in the end SimplifiedLowering figures out that the inputs to
// this operation are actually Unsigned32. // this operation are actually Unsigned32.
......
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