[turbofan] Optimize Int32Mod by power-of-two.
TEST=mjsunit/asm/int32-tmod,unittests R=dcarney@chromium.org Review URL: https://codereview.chromium.org/649083005 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24554 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
a2f4963abd
commit
5c1f7b5aa1
@ -262,19 +262,8 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kInt32Mod: {
|
||||
Int32BinopMatcher m(node);
|
||||
if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
|
||||
if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
|
||||
// TODO(turbofan): if (m.left().Is(0))
|
||||
// TODO(turbofan): if (m.right().IsPowerOf2())
|
||||
// TODO(turbofan): if (m.right().Is(0))
|
||||
// TODO(turbofan): if (m.LeftEqualsRight())
|
||||
if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K
|
||||
return ReplaceInt32(m.left().Value() % m.right().Value());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kInt32Mod:
|
||||
return ReduceInt32Mod(node);
|
||||
case IrOpcode::kUint32Mod: {
|
||||
Uint32BinopMatcher m(node);
|
||||
if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
|
||||
@ -510,6 +499,44 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
|
||||
}
|
||||
|
||||
|
||||
Reduction MachineOperatorReducer::ReduceInt32Mod(Node* const node) {
|
||||
Int32BinopMatcher m(node);
|
||||
if (m.right().Is(1)) return ReplaceInt32(0); // x % 1 => 0
|
||||
if (m.right().Is(-1)) return ReplaceInt32(0); // x % -1 => 0
|
||||
// TODO(turbofan): if (m.left().Is(0))
|
||||
// TODO(turbofan): if (m.right().Is(0))
|
||||
// TODO(turbofan): if (m.LeftEqualsRight())
|
||||
if (m.IsFoldable() && !m.right().Is(0)) { // K % K => K
|
||||
return ReplaceInt32(m.left().Value() % m.right().Value());
|
||||
}
|
||||
if (m.right().IsPowerOf2()) {
|
||||
int32_t const divisor = m.right().Value();
|
||||
Node* zero = Int32Constant(0);
|
||||
Node* mask = Int32Constant(divisor - 1);
|
||||
Node* dividend = m.left().node();
|
||||
|
||||
Node* check = graph()->NewNode(machine()->Int32LessThan(), dividend, zero);
|
||||
Node* branch =
|
||||
graph()->NewNode(common()->Branch(), check, graph()->start());
|
||||
|
||||
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
||||
Node* neg = graph()->NewNode(
|
||||
machine()->Int32Sub(), zero,
|
||||
graph()->NewNode(
|
||||
machine()->Word32And(),
|
||||
graph()->NewNode(machine()->Int32Sub(), zero, dividend), mask));
|
||||
|
||||
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
||||
Node* pos = graph()->NewNode(machine()->Word32And(), dividend, mask);
|
||||
|
||||
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
|
||||
Node* phi = graph()->NewNode(common()->Phi(kMachInt32, 2), neg, pos, merge);
|
||||
return Replace(phi);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
|
||||
Reduction MachineOperatorReducer::ReduceProjection(size_t index, Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kInt32AddWithOverflow: {
|
||||
|
@ -49,6 +49,7 @@ class MachineOperatorReducer FINAL : public Reducer {
|
||||
return Replace(Int64Constant(value));
|
||||
}
|
||||
|
||||
Reduction ReduceInt32Mod(Node* node);
|
||||
Reduction ReduceProjection(size_t index, Node* node);
|
||||
|
||||
Graph* graph() const;
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
function Module(stdlib, foreign, heap) {
|
||||
"use asm";
|
||||
function f0(i) {
|
||||
i = i|0;
|
||||
return i % 2 | 0;
|
||||
}
|
||||
function f1(i) {
|
||||
i = i|0;
|
||||
return i % 3 | 0;
|
||||
@ -20,12 +24,13 @@ function Module(stdlib, foreign, heap) {
|
||||
i = i|0;
|
||||
return i % 3333339 | 0;
|
||||
}
|
||||
return { f1: f1, f2: f2, f3: f3, f4: f4 };
|
||||
return { f0: f0, f1: f1, f2: f2, f3: f3, f4: f4 };
|
||||
}
|
||||
|
||||
var m = Module(this, {}, new ArrayBuffer(1024));
|
||||
|
||||
for (var i = -2147483648; i < 2147483648; i += 3999773) {
|
||||
assertEquals(i % 2 | 0, m.f0(i));
|
||||
assertEquals(i % 3 | 0, m.f1(i));
|
||||
assertEquals(i % 9 | 0, m.f2(i));
|
||||
assertEquals(i % 1024 | 0, m.f3(i));
|
||||
|
@ -948,7 +948,9 @@ IS_BINOP_MATCHER(Word64Sar)
|
||||
IS_BINOP_MATCHER(Word64Shl)
|
||||
IS_BINOP_MATCHER(Word64Equal)
|
||||
IS_BINOP_MATCHER(Int32AddWithOverflow)
|
||||
IS_BINOP_MATCHER(Int32Sub)
|
||||
IS_BINOP_MATCHER(Int32Mul)
|
||||
IS_BINOP_MATCHER(Int32LessThan)
|
||||
IS_BINOP_MATCHER(Uint32LessThan)
|
||||
IS_BINOP_MATCHER(Uint32LessThanOrEqual)
|
||||
#undef IS_BINOP_MATCHER
|
||||
|
@ -148,8 +148,12 @@ Matcher<Node*> IsWord64Equal(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsInt32AddWithOverflow(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsInt32Sub(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsInt32Mul(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsInt32LessThan(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsUint32LessThan(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher);
|
||||
Matcher<Node*> IsUint32LessThanOrEqual(const Matcher<Node*>& lhs_matcher,
|
||||
|
@ -7,6 +7,11 @@
|
||||
#include "src/compiler/machine-operator-reducer.h"
|
||||
#include "src/compiler/typer.h"
|
||||
#include "test/unittests/compiler/graph-unittest.h"
|
||||
#include "testing/gmock-support.h"
|
||||
|
||||
using testing::AllOf;
|
||||
using testing::Capture;
|
||||
using testing::CaptureEq;
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -563,6 +568,37 @@ TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Int32Mod
|
||||
|
||||
|
||||
TEST_F(MachineOperatorReducerTest, Int32ModWithPowerOfTwo) {
|
||||
Node* p0 = Parameter(0);
|
||||
TRACED_FORRANGE(int32_t, x, 1, 30) {
|
||||
int32_t const divisor = 1 << x;
|
||||
Node* node =
|
||||
graph()->NewNode(machine()->Int32Mod(), p0, Int32Constant(divisor));
|
||||
Reduction r = Reduce(node);
|
||||
ASSERT_TRUE(r.Changed());
|
||||
|
||||
Capture<Node*> branch;
|
||||
Node* phi = r.replacement();
|
||||
int32_t const mask = divisor - 1;
|
||||
EXPECT_THAT(
|
||||
phi, IsPhi(kMachInt32,
|
||||
IsInt32Sub(IsInt32Constant(0),
|
||||
IsWord32And(IsInt32Sub(IsInt32Constant(0), p0),
|
||||
IsInt32Constant(mask))),
|
||||
IsWord32And(p0, IsInt32Constant(mask)),
|
||||
IsMerge(IsIfTrue(CaptureEq(&branch)),
|
||||
IsIfFalse(AllOf(
|
||||
CaptureEq(&branch),
|
||||
IsBranch(IsInt32LessThan(p0, IsInt32Constant(0)),
|
||||
graph()->start()))))));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Int32AddWithOverflow
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user