Index: src/compiler/arm64/instruction-selector-arm64.cc |
diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc |
index eac1ec63e9557b73dc88087b2dc538c4773c9ac1..d2239149793fad5c730354d0fc33314c947c5866 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -267,45 +267,119 @@ void InstructionSelector::VisitStore(Node* node) { |
} |
+template <typename Matcher> |
+static void VisitLogical(InstructionSelector* selector, Node* node, Matcher* m, |
+ ArchOpcode opcode, bool left_can_cover, |
+ bool right_can_cover, ImmediateMode imm_mode) { |
+ Arm64OperandGenerator g(selector); |
+ |
+ // Map instruction to equivalent operation with inverted right input. |
+ ArchOpcode inv_opcode = opcode; |
+ switch (opcode) { |
+ case kArm64And32: |
+ inv_opcode = kArm64Bic32; |
+ break; |
+ case kArm64And: |
+ inv_opcode = kArm64Bic; |
+ break; |
+ case kArm64Or32: |
+ inv_opcode = kArm64Orn32; |
+ break; |
+ case kArm64Or: |
+ inv_opcode = kArm64Orn; |
+ break; |
+ case kArm64Eor32: |
+ inv_opcode = kArm64Eon32; |
+ break; |
+ case kArm64Eor: |
+ inv_opcode = kArm64Eon; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ } |
+ |
+ // Select Logical(y, ~x) for Logical(Xor(x, -1), y). |
+ if ((m->left().IsWord32Xor() || m->left().IsWord64Xor()) && left_can_cover) { |
+ Matcher mleft(m->left().node()); |
+ if (mleft.right().Is(-1)) { |
+ // TODO(all): support shifted operand on right. |
+ selector->Emit(inv_opcode, g.DefineAsRegister(node), |
+ g.UseRegister(m->right().node()), |
+ g.UseRegister(mleft.left().node())); |
+ return; |
+ } |
+ } |
+ |
+ // Select Logical(x, ~y) for Logical(x, Xor(y, -1)). |
+ if ((m->right().IsWord32Xor() || m->right().IsWord64Xor()) && |
+ right_can_cover) { |
+ Matcher mright(m->right().node()); |
+ if (mright.right().Is(-1)) { |
+ // TODO(all): support shifted operand on right. |
+ selector->Emit(inv_opcode, g.DefineAsRegister(node), |
+ g.UseRegister(m->left().node()), |
+ g.UseRegister(mright.left().node())); |
+ return; |
+ } |
+ } |
+ |
+ if (m->IsWord32Xor() && m->right().Is(-1)) { |
+ selector->Emit(kArm64Not32, g.DefineAsRegister(node), |
+ g.UseRegister(m->left().node())); |
+ } else if (m->IsWord64Xor() && m->right().Is(-1)) { |
+ selector->Emit(kArm64Not, g.DefineAsRegister(node), |
+ g.UseRegister(m->left().node())); |
+ } else { |
+ VisitBinop<Matcher>(selector, node, opcode, imm_mode); |
+ } |
+} |
+ |
+ |
void InstructionSelector::VisitWord32And(Node* node) { |
- VisitBinop<Int32BinopMatcher>(this, node, kArm64And32, kLogical32Imm); |
+ Int32BinopMatcher m(node); |
+ VisitLogical<Int32BinopMatcher>( |
+ this, node, &m, kArm64And32, CanCover(node, m.left().node()), |
+ CanCover(node, m.right().node()), kLogical32Imm); |
} |
void InstructionSelector::VisitWord64And(Node* node) { |
- VisitBinop<Int64BinopMatcher>(this, node, kArm64And, kLogical64Imm); |
+ Int64BinopMatcher m(node); |
+ VisitLogical<Int64BinopMatcher>( |
+ this, node, &m, kArm64And, CanCover(node, m.left().node()), |
+ CanCover(node, m.right().node()), kLogical64Imm); |
} |
void InstructionSelector::VisitWord32Or(Node* node) { |
- VisitBinop<Int32BinopMatcher>(this, node, kArm64Or32, kLogical32Imm); |
+ Int32BinopMatcher m(node); |
+ VisitLogical<Int32BinopMatcher>( |
+ this, node, &m, kArm64Or32, CanCover(node, m.left().node()), |
+ CanCover(node, m.right().node()), kLogical32Imm); |
} |
void InstructionSelector::VisitWord64Or(Node* node) { |
- VisitBinop<Int64BinopMatcher>(this, node, kArm64Or, kLogical64Imm); |
+ Int64BinopMatcher m(node); |
+ VisitLogical<Int64BinopMatcher>( |
+ this, node, &m, kArm64Or, CanCover(node, m.left().node()), |
+ CanCover(node, m.right().node()), kLogical64Imm); |
} |
void InstructionSelector::VisitWord32Xor(Node* node) { |
- Arm64OperandGenerator g(this); |
Int32BinopMatcher m(node); |
- if (m.right().Is(-1)) { |
- Emit(kArm64Not32, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
- } else { |
- VisitBinop<Int32BinopMatcher>(this, node, kArm64Xor32, kLogical32Imm); |
- } |
+ VisitLogical<Int32BinopMatcher>( |
+ this, node, &m, kArm64Eor32, CanCover(node, m.left().node()), |
+ CanCover(node, m.right().node()), kLogical32Imm); |
} |
void InstructionSelector::VisitWord64Xor(Node* node) { |
- Arm64OperandGenerator g(this); |
Int64BinopMatcher m(node); |
- if (m.right().Is(-1)) { |
- Emit(kArm64Not, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
- } else { |
- VisitBinop<Int64BinopMatcher>(this, node, kArm64Xor, kLogical32Imm); |
- } |
+ VisitLogical<Int64BinopMatcher>( |
+ this, node, &m, kArm64Eor, CanCover(node, m.left().node()), |
+ CanCover(node, m.right().node()), kLogical64Imm); |
} |