}
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
}
+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();
}
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));
}
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());