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