diff options
Diffstat (limited to 'deps/v8/src/compiler/arm64/instruction-selector-arm64.cc')
-rw-r--r-- | deps/v8/src/compiler/arm64/instruction-selector-arm64.cc | 135 |
1 files changed, 95 insertions, 40 deletions
diff --git a/deps/v8/src/compiler/arm64/instruction-selector-arm64.cc b/deps/v8/src/compiler/arm64/instruction-selector-arm64.cc index e07debf9ec..b2e8b4b205 100644 --- a/deps/v8/src/compiler/arm64/instruction-selector-arm64.cc +++ b/deps/v8/src/compiler/arm64/instruction-selector-arm64.cc @@ -1189,6 +1189,8 @@ void InstructionSelector::VisitWord64Ror(Node* node) { V(Word32Clz, kArm64Clz32) \ V(Word32ReverseBits, kArm64Rbit32) \ V(Word64ReverseBits, kArm64Rbit) \ + V(Word32ReverseBytes, kArm64Rev32) \ + V(Word64ReverseBytes, kArm64Rev) \ V(ChangeFloat32ToFloat64, kArm64Float32ToFloat64) \ V(RoundInt32ToFloat32, kArm64Int32ToFloat32) \ V(RoundUint32ToFloat32, kArm64Uint32ToFloat32) \ @@ -1272,10 +1274,6 @@ void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); } -void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); } - -void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); } - void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); } void InstructionSelector::VisitWord64Popcnt(Node* node) { UNREACHABLE(); } @@ -2082,23 +2080,42 @@ void VisitWord64Test(InstructionSelector* selector, Node* node, VisitWordTest(selector, node, kArm64Tst, cont); } -template <typename Matcher, ArchOpcode kOpcode> -bool TryEmitTestAndBranch(InstructionSelector* selector, Node* node, - FlagsContinuation* cont) { - Arm64OperandGenerator g(selector); - Matcher m(node); - if (cont->IsBranch() && !cont->IsPoisoned() && m.right().HasValue() && - base::bits::IsPowerOfTwo(m.right().Value())) { - // If the mask has only one bit set, we can use tbz/tbnz. - DCHECK((cont->condition() == kEqual) || (cont->condition() == kNotEqual)); - selector->EmitWithContinuation( - kOpcode, g.UseRegister(m.left().node()), - g.TempImmediate(base::bits::CountTrailingZeros(m.right().Value())), - cont); - return true; +template <typename Matcher> +struct TestAndBranchMatcher { + TestAndBranchMatcher(Node* node, FlagsContinuation* cont) + : matches_(false), cont_(cont), matcher_(node) { + Initialize(); + } + bool Matches() const { return matches_; } + + unsigned bit() const { + DCHECK(Matches()); + return base::bits::CountTrailingZeros(matcher_.right().Value()); } - return false; -} + + Node* input() const { + DCHECK(Matches()); + return matcher_.left().node(); + } + + private: + bool matches_; + FlagsContinuation* cont_; + Matcher matcher_; + + void Initialize() { + if (cont_->IsBranch() && !cont_->IsPoisoned() && + matcher_.right().HasValue() && + base::bits::IsPowerOfTwo(matcher_.right().Value())) { + // If the mask has only one bit set, we can use tbz/tbnz. + DCHECK((cont_->condition() == kEqual) || + (cont_->condition() == kNotEqual)); + matches_ = true; + } else { + matches_ = false; + } + } +}; // Shared routine for multiple float32 compare operations. void VisitFloat32Compare(InstructionSelector* selector, Node* node, @@ -2228,6 +2245,58 @@ void InstructionSelector::VisitWordCompareZero(Node* user, Node* value, cont->Negate(); } + // Try to match bit checks to create TBZ/TBNZ instructions. + // Unlike the switch below, CanCover check is not needed here. + // If there are several uses of the given operation, we will generate a TBZ + // instruction for each. This is useful even if there are other uses of the + // arithmetic result, because it moves dependencies further back. + switch (value->opcode()) { + case IrOpcode::kWord64Equal: { + Int64BinopMatcher m(value); + if (m.right().Is(0)) { + Node* const left = m.left().node(); + if (left->opcode() == IrOpcode::kWord64And) { + // Attempt to merge the Word64Equal(Word64And(x, y), 0) comparison + // into a tbz/tbnz instruction. + TestAndBranchMatcher<Uint64BinopMatcher> tbm(left, cont); + if (tbm.Matches()) { + Arm64OperandGenerator gen(this); + cont->OverwriteAndNegateIfEqual(kEqual); + this->EmitWithContinuation(kArm64TestAndBranch, + gen.UseRegister(tbm.input()), + gen.TempImmediate(tbm.bit()), cont); + return; + } + } + } + break; + } + case IrOpcode::kWord32And: { + TestAndBranchMatcher<Uint32BinopMatcher> tbm(value, cont); + if (tbm.Matches()) { + Arm64OperandGenerator gen(this); + this->EmitWithContinuation(kArm64TestAndBranch32, + gen.UseRegister(tbm.input()), + gen.TempImmediate(tbm.bit()), cont); + return; + } + break; + } + case IrOpcode::kWord64And: { + TestAndBranchMatcher<Uint64BinopMatcher> tbm(value, cont); + if (tbm.Matches()) { + Arm64OperandGenerator gen(this); + this->EmitWithContinuation(kArm64TestAndBranch, + gen.UseRegister(tbm.input()), + gen.TempImmediate(tbm.bit()), cont); + return; + } + break; + } + default: + break; + } + if (CanCover(user, value)) { switch (value->opcode()) { case IrOpcode::kWord32Equal: @@ -2251,12 +2320,6 @@ void InstructionSelector::VisitWordCompareZero(Node* user, Node* value, if (m.right().Is(0)) { Node* const left = m.left().node(); if (CanCover(value, left) && left->opcode() == IrOpcode::kWord64And) { - // Attempt to merge the Word64Equal(Word64And(x, y), 0) comparison - // into a tbz/tbnz instruction. - if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>( - this, left, cont)) { - return; - } return VisitWordCompare(this, left, kArm64Tst, cont, true, kLogical64Imm); } @@ -2353,17 +2416,9 @@ void InstructionSelector::VisitWordCompareZero(Node* user, Node* value, case IrOpcode::kInt32Sub: return VisitWord32Compare(this, value, cont); case IrOpcode::kWord32And: - if (TryEmitTestAndBranch<Uint32BinopMatcher, kArm64TestAndBranch32>( - this, value, cont)) { - return; - } return VisitWordCompare(this, value, kArm64Tst32, cont, true, kLogical32Imm); case IrOpcode::kWord64And: - if (TryEmitTestAndBranch<Uint64BinopMatcher, kArm64TestAndBranch>( - this, value, cont)) { - return; - } return VisitWordCompare(this, value, kArm64Tst, cont, true, kLogical64Imm); default: @@ -2742,7 +2797,7 @@ void InstructionSelector::VisitWord64AtomicStore(Node* node) { void InstructionSelector::VisitWord32AtomicExchange(Node* node) { ArchOpcode opcode = kArchNop; - MachineType type = AtomicOpRepresentationOf(node->op()); + MachineType type = AtomicOpType(node->op()); if (type == MachineType::Int8()) { opcode = kWord32AtomicExchangeInt8; } else if (type == MachineType::Uint8()) { @@ -2762,7 +2817,7 @@ void InstructionSelector::VisitWord32AtomicExchange(Node* node) { void InstructionSelector::VisitWord64AtomicExchange(Node* node) { ArchOpcode opcode = kArchNop; - MachineType type = AtomicOpRepresentationOf(node->op()); + MachineType type = AtomicOpType(node->op()); if (type == MachineType::Uint8()) { opcode = kArm64Word64AtomicExchangeUint8; } else if (type == MachineType::Uint16()) { @@ -2780,7 +2835,7 @@ void InstructionSelector::VisitWord64AtomicExchange(Node* node) { void InstructionSelector::VisitWord32AtomicCompareExchange(Node* node) { ArchOpcode opcode = kArchNop; - MachineType type = AtomicOpRepresentationOf(node->op()); + MachineType type = AtomicOpType(node->op()); if (type == MachineType::Int8()) { opcode = kWord32AtomicCompareExchangeInt8; } else if (type == MachineType::Uint8()) { @@ -2800,7 +2855,7 @@ void InstructionSelector::VisitWord32AtomicCompareExchange(Node* node) { void InstructionSelector::VisitWord64AtomicCompareExchange(Node* node) { ArchOpcode opcode = kArchNop; - MachineType type = AtomicOpRepresentationOf(node->op()); + MachineType type = AtomicOpType(node->op()); if (type == MachineType::Uint8()) { opcode = kArm64Word64AtomicCompareExchangeUint8; } else if (type == MachineType::Uint16()) { @@ -2820,7 +2875,7 @@ void InstructionSelector::VisitWord32AtomicBinaryOperation( Node* node, ArchOpcode int8_op, ArchOpcode uint8_op, ArchOpcode int16_op, ArchOpcode uint16_op, ArchOpcode word32_op) { ArchOpcode opcode = kArchNop; - MachineType type = AtomicOpRepresentationOf(node->op()); + MachineType type = AtomicOpType(node->op()); if (type == MachineType::Int8()) { opcode = int8_op; } else if (type == MachineType::Uint8()) { @@ -2856,7 +2911,7 @@ void InstructionSelector::VisitWord64AtomicBinaryOperation( Node* node, ArchOpcode uint8_op, ArchOpcode uint16_op, ArchOpcode uint32_op, ArchOpcode uint64_op) { ArchOpcode opcode = kArchNop; - MachineType type = AtomicOpRepresentationOf(node->op()); + MachineType type = AtomicOpType(node->op()); if (type == MachineType::Uint8()) { opcode = uint8_op; } else if (type == MachineType::Uint16()) { |