[turbofan] Reduces x << y ^ x >>> (32 - y) to x ror (32 - y).

The MachineOperatorReducer was only reducing word32 expressions of the type x << y | x >>> (32 - y) (and variants) to the equivalent Word32Ror. This CL applies the same pattern-matching logic to Word32Xor.

BUG=

Review-Url: https://codereview.chromium.org/2199323003
Cr-Commit-Position: refs/heads/master@{#38284}
This commit is contained in:
epertoso 2016-08-03 03:56:05 -07:00 committed by Commit bot
parent 66e96fc9d7
commit a86397d890
3 changed files with 78 additions and 37 deletions

View File

@ -150,21 +150,8 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
return ReduceWord32And(node);
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
if (m.IsFoldable()) { // K ^ K => K
return ReplaceInt32(m.left().Value() ^ m.right().Value());
}
if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
if (m.left().IsWord32Xor() && m.right().Is(-1)) {
Int32BinopMatcher mleft(m.left().node());
if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
return Replace(mleft.left().node());
}
}
break;
}
case IrOpcode::kWord32Xor:
return ReduceWord32Xor(node);
case IrOpcode::kWord32Shl:
return ReduceWord32Shl(node);
case IrOpcode::kWord32Shr:
@ -1106,22 +1093,17 @@ Reduction MachineOperatorReducer::ReduceWord32And(Node* node) {
return NoChange();
}
Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
Reduction MachineOperatorReducer::TryMatchWord32Ror(Node* node) {
DCHECK(IrOpcode::kWord32Or == node->opcode() ||
IrOpcode::kWord32Xor == node->opcode());
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 = nullptr;
Node* shr = nullptr;
// Recognize rotation, we are matching either:
// Recognize rotation, we are matching:
// * x << y | x >>> (32 - y) => x ror (32 - y), i.e x rol y
// * x << (32 - y) | x >>> y => x ror y
// * 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();
@ -1163,6 +1145,36 @@ Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
return Changed(node);
}
Reduction MachineOperatorReducer::ReduceWord32Or(Node* node) {
DCHECK_EQ(IrOpcode::kWord32Or, node->opcode());
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
return TryMatchWord32Ror(node);
}
Reduction MachineOperatorReducer::ReduceWord32Xor(Node* node) {
DCHECK_EQ(IrOpcode::kWord32Xor, node->opcode());
Int32BinopMatcher m(node);
if (m.right().Is(0)) return Replace(m.left().node()); // x ^ 0 => x
if (m.IsFoldable()) { // K ^ K => K
return ReplaceInt32(m.left().Value() ^ m.right().Value());
}
if (m.LeftEqualsRight()) return ReplaceInt32(0); // x ^ x => 0
if (m.left().IsWord32Xor() && m.right().Is(-1)) {
Int32BinopMatcher mleft(m.left().node());
if (mleft.right().Is(-1)) { // (x ^ -1) ^ -1 => x
return Replace(mleft.left().node());
}
}
return TryMatchWord32Ror(node);
}
Reduction MachineOperatorReducer::ReduceFloat64InsertLowWord32(Node* node) {
DCHECK_EQ(IrOpcode::kFloat64InsertLowWord32, node->opcode());

View File

@ -79,7 +79,9 @@ class MachineOperatorReducer final : public Reducer {
Reduction ReduceWord32Shr(Node* node);
Reduction ReduceWord32Sar(Node* node);
Reduction ReduceWord32And(Node* node);
Reduction TryMatchWord32Ror(Node* node);
Reduction ReduceWord32Or(Node* node);
Reduction ReduceWord32Xor(Node* node);
Reduction ReduceFloat64InsertLowWord32(Node* node);
Reduction ReduceFloat64InsertHighWord32(Node* node);
Reduction ReduceFloat64Compare(Node* node);

View File

@ -729,25 +729,52 @@ TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithParameters) {
EXPECT_EQ(reduction2.replacement(), node2);
EXPECT_THAT(reduction2.replacement(), IsWord32Ror(value, sub));
// (x << y) ^ (x >>> (32 - y)) => x ror (32 - y)
Node* node3 = graph()->NewNode(machine()->Word32Xor(), shl_l, shr_l);
Reduction reduction3 = Reduce(node3);
EXPECT_TRUE(reduction3.Changed());
EXPECT_EQ(reduction3.replacement(), node3);
EXPECT_THAT(reduction3.replacement(), IsWord32Ror(value, sub));
// (x >>> (32 - y)) ^ (x << y) => x ror (32 - y)
Node* node4 = graph()->NewNode(machine()->Word32Xor(), shr_l, shl_l);
Reduction reduction4 = Reduce(node4);
EXPECT_TRUE(reduction4.Changed());
EXPECT_EQ(reduction4.replacement(), node4);
EXPECT_THAT(reduction4.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));
Node* node5 = graph()->NewNode(machine()->Word32Or(), shl_r, shr_r);
Reduction reduction5 = Reduce(node5);
EXPECT_TRUE(reduction5.Changed());
EXPECT_EQ(reduction5.replacement(), node5);
EXPECT_THAT(reduction5.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));
}
Node* node6 = graph()->NewNode(machine()->Word32Or(), shr_r, shl_r);
Reduction reduction6 = Reduce(node6);
EXPECT_TRUE(reduction6.Changed());
EXPECT_EQ(reduction6.replacement(), node6);
EXPECT_THAT(reduction6.replacement(), IsWord32Ror(value, shift));
// (x << (32 - y)) ^ (x >>> y) => x ror y
Node* node7 = graph()->NewNode(machine()->Word32Xor(), shl_r, shr_r);
Reduction reduction7 = Reduce(node7);
EXPECT_TRUE(reduction7.Changed());
EXPECT_EQ(reduction7.replacement(), node7);
EXPECT_THAT(reduction7.replacement(), IsWord32Ror(value, shift));
// (x >>> y) ^ (x << (32 - y)) => x ror y
Node* node8 = graph()->NewNode(machine()->Word32Xor(), shr_r, shl_r);
Reduction reduction8 = Reduce(node8);
EXPECT_TRUE(reduction8.Changed());
EXPECT_EQ(reduction8.replacement(), node8);
EXPECT_THAT(reduction8.replacement(), IsWord32Ror(value, shift));
}
TEST_F(MachineOperatorReducerTest, ReduceToWord32RorWithConstant) {
Node* value = Parameter(0);