[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:
parent
66e96fc9d7
commit
a86397d890
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user