Commit 55614cfe authored by rodolph.perfetta's avatar rodolph.perfetta Committed by Commit bot

[turbofan] Recognize rotate right.

Extended the rotate left detection code.

BUG=

Review URL: https://codereview.chromium.org/760523004

Cr-Commit-Position: refs/heads/master@{#25517}
parent 6ac4de87
......@@ -152,68 +152,8 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
}
break;
}
case IrOpcode::kWord32Or: {
Int32BinopMatcher m(node);
if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
if (m.IsFoldable()) { // K | K => K
return ReplaceInt32(m.left().Value() | m.right().Value());
}
if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
Int32BinopMatcher mleft(m.left().node());
Int32BinopMatcher mright(m.right().node());
if (mleft.left().node() == mright.left().node()) {
// TODO(turbofan): here we are matching rotate left, shall we add
// support for rotate right?
// (x << y) | (x >>> (32 - y)) => x ror (32 - y)
if (mright.right().IsInt32Sub()) {
Int32BinopMatcher mrightright(mright.right().node());
if (mrightright.left().Is(32) &&
mrightright.right().node() == mleft.right().node()) {
node->set_op(machine()->Word32Ror());
node->ReplaceInput(0, mleft.left().node());
node->ReplaceInput(1, mright.right().node());
return Changed(node);
}
}
// (x << K) | (x >>> (32 - K)) => x ror (32 - K)
if (mleft.right().IsInRange(0, 31) &&
mright.right().Is(32 - mleft.right().Value())) {
node->set_op(machine()->Word32Ror());
node->ReplaceInput(0, mleft.left().node());
node->ReplaceInput(1, mright.right().node());
return Changed(node);
}
}
}
if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
// (x >>> (32 - y)) | (x << y) => x ror (32 -y)
Int32BinopMatcher mleft(m.left().node());
Int32BinopMatcher mright(m.right().node());
if (mleft.left().node() == mright.left().node()) {
if (mleft.right().IsInt32Sub()) {
Int32BinopMatcher mleftright(mleft.right().node());
if (mleftright.left().Is(32) &&
mleftright.right().node() == mright.right().node()) {
node->set_op(machine()->Word32Ror());
node->ReplaceInput(0, mright.left().node());
node->ReplaceInput(1, mleft.right().node());
return Changed(node);
}
}
// (x >>> (32 - K)) | (x << K) => x ror (32 - K)
if (mright.right().IsInRange(0, 31) &&
mleft.right().Is(32 - mright.right().Value())) {
node->set_op(machine()->Word32Ror());
node->ReplaceInput(0, mright.left().node());
node->ReplaceInput(1, mleft.right().node());
return Changed(node);
}
}
}
break;
}
case IrOpcode::kWord32Or:
return ReduceWord32Or(node);
case IrOpcode::kWord32Xor: {
Int32BinopMatcher m(node);
if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
......@@ -841,6 +781,64 @@ Reduction MachineOperatorReducer::ReduceWord32Shifts(Node* node) {
}
Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
DCHECK(node->opcode() == IrOpcode::kWord32Or);
Int32BinopMatcher m(node);
if (m.right().Is(0)) return Replace(m.left().node()); // x | 0 => x
if (m.right().Is(-1)) return Replace(m.right().node()); // x | -1 => -1
if (m.IsFoldable()) { // K | K => K
return ReplaceInt32(m.left().Value() | m.right().Value());
}
if (m.LeftEqualsRight()) return Replace(m.left().node()); // x | x => x
Node* shl = NULL;
Node* shr = NULL;
// Recognize rotation, we are matching either:
// * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
// * x << (32 - y) | x >>> y => x ror y
// as well as their commuted form.
if (m.left().IsWord32Shl() && m.right().IsWord32Shr()) {
shl = m.left().node();
shr = m.right().node();
} else if (m.left().IsWord32Shr() && m.right().IsWord32Shl()) {
shl = m.right().node();
shr = m.left().node();
} else {
return NoChange();
}
Int32BinopMatcher mshl(shl);
Int32BinopMatcher mshr(shr);
if (mshl.left().node() != mshr.left().node()) return NoChange();
if (mshl.right().HasValue() && mshr.right().HasValue()) {
// Case where y is a constant.
if (mshl.right().Value() + mshr.right().Value() != 32) return NoChange();
} else {
Node* sub = NULL;
Node* y = NULL;
if (mshl.right().IsInt32Sub()) {
sub = mshl.right().node();
y = mshr.right().node();
} else if (mshr.right().IsInt32Sub()) {
sub = mshr.right().node();
y = mshl.right().node();
} else {
return NoChange();
}
Int32BinopMatcher msub(sub);
if (!msub.left().Is(32) || msub.right().node() != y) return NoChange();
}
node->set_op(machine()->Word32Ror());
node->ReplaceInput(0, mshl.left().node());
node->ReplaceInput(1, mshr.right().node());
return Changed(node);
}
CommonOperatorBuilder* MachineOperatorReducer::common() const {
return jsgraph()->common();
}
......
......@@ -69,6 +69,7 @@ class MachineOperatorReducer FINAL : public Reducer {
Reduction ReduceStore(Node* node);
Reduction ReduceProjection(size_t index, Node* node);
Reduction ReduceWord32Shifts(Node* node);
Reduction ReduceWord32Or(Node* node);
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
......
......@@ -20,3 +20,18 @@ assertEquals(10, rol(10, 0));
assertEquals(2, rol(1, 1));
assertEquals(0x40000000, rol(1, 30));
assertEquals(-0x80000000, rol(1, 31));
var ror = (function Module(stdlib, foreign, heap) {
"use asm";
function ror(x, y) {
x = x | 0;
y = y | 0;
return (x << (32 - y)) | (x >>> y);
}
return { ror: ror };
})(stdlib, foreign, heap).ror;
assertEquals(10, ror(10, 0));
assertEquals(-0x80000000, ror(1, 1));
assertEquals(0x40000000, ror(1, 2));
assertEquals(2, ror(1, 31));
......@@ -591,23 +591,43 @@ TEST_F(MachineOperatorReducerTest, Word32XorWithWord32XorAndMinusOne) {
TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
Node* value = Parameter(0);
Node* shift = Parameter(1);
Node* shl = graph()->NewNode(machine()->Word32Shl(), value, shift);
Node* sub = graph()->NewNode(machine()->Int32Sub(), Int32Constant(32), shift);
Node* shr = graph()->NewNode(machine()->Word32Shr(), value, sub);
// Testing rotate left.
Node* shl_l = graph()->NewNode(machine()->Word32Shl(), value, shift);
Node* shr_l = graph()->NewNode(machine()->Word32Shr(), value, sub);
// (x << y) | (x >>> (32 - y)) => x ror (32 - y)
Node* node1 = graph()->NewNode(machine()->Word32Or(), shl, shr);
Node* node1 = graph()->NewNode(machine()->Word32Or(), shl_l, shr_l);
Reduction reduction1 = Reduce(node1);
EXPECT_TRUE(reduction1.Changed());
EXPECT_EQ(reduction1.replacement(), node1);
EXPECT_THAT(reduction1.replacement(), IsWord32Ror(value, sub));
// (x >>> (32 - y)) | (x << y) => x ror y
Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
// (x >>> (32 - y)) | (x << y) => x ror (32 - y)
Node* node2 = graph()->NewNode(machine()->Word32Or(), shr_l, shl_l);
Reduction reduction2 = Reduce(node2);
EXPECT_TRUE(reduction2.Changed());
EXPECT_EQ(reduction2.replacement(), node2);
EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
// Testing rotate right.
Node* shl_r = graph()->NewNode(machine()->Word32Shl(), value, sub);
Node* shr_r = graph()->NewNode(machine()->Word32Shr(), value, shift);
// (x << (32 - y)) | (x >>> y) => x ror y
Node* node3 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
Reduction reduction3 = Reduce(node3);
EXPECT_TRUE(reduction3.Changed());
EXPECT_EQ(reduction3.replacement(), node3);
EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, shift));
// (x >>> y) | (x << (32 - y)) => x ror y
Node* node4 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
Reduction reduction4 = Reduce(node4);
EXPECT_TRUE(reduction4.Changed());
EXPECT_EQ(reduction4.replacement(), node4);
EXPECT_THAT(reduction4.replacement(), IsWord32Ror(value, shift));
}
......@@ -627,7 +647,7 @@ TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
EXPECT_THAT(reduction1.replacement(),
IsWord32Ror(value, IsInt32Constant(32 - k)));
// (x >>> (32 - K)) | (x << K) => x ror K
// (x >>> (32 - K)) | (x << K) => x ror (32 - K)
Node* node2 = graph()->NewNode(machine()->Word32Or(), shr, shl);
Reduction reduction2 = Reduce(node2);
EXPECT_TRUE(reduction2.Changed());
......
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