diff options
| -rw-r--r-- | backend/lib/Target/RISCV/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 97 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVGISelAtomic.rccdesc | 363 |
3 files changed, 366 insertions, 95 deletions
diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt index 9a3973d..65d5f82 100644 --- a/backend/lib/Target/RISCV/CMakeLists.txt +++ b/backend/lib/Target/RISCV/CMakeLists.txt @@ -19,6 +19,7 @@ set( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelControlFlow.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelShift.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelFloating.rccdesc" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelAtomic.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelCombiner.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMacroFusion.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMCPseudoLowering.rccdesc" diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index f98f2e5..6486f5c 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -348,6 +348,8 @@ public: [[nodiscard]] Expected<bool> matchesTargetPredicate(std::string_view Name, const MachineInstr &, const MachineFunction &, const TargetDescription &) const override { + if (Name == "a") + return Subtarget.features().has(RISCVExtension::A); if (Name == "zba") return Subtarget.features().has(RISCVExtension::Zba); return makeUnexpected(ErrorCode::VerificationError, @@ -603,17 +605,6 @@ public: return Instruction.setOpcode(opcode(GenericOpcode::COPY)); case GenericOpcode::G_FCMP: return selectFloatingCompare(Instruction, Function, Target); - case GenericOpcode::G_ATOMICRMW_XCHG: - case GenericOpcode::G_ATOMICRMW_ADD: - case GenericOpcode::G_ATOMICRMW_SUB: - case GenericOpcode::G_ATOMICRMW_AND: - case GenericOpcode::G_ATOMICRMW_OR: - case GenericOpcode::G_ATOMICRMW_XOR: - case GenericOpcode::G_ATOMICRMW_MAX: - case GenericOpcode::G_ATOMICRMW_MIN: - case GenericOpcode::G_ATOMICRMW_UMAX: - case GenericOpcode::G_ATOMICRMW_UMIN: - return selectAtomicRMW(Instruction, Function, Target, Type, Generic); case GenericOpcode::G_FENCE: return selectFence(Instruction); case GenericOpcode::G_GLOBAL_VALUE: @@ -962,90 +953,6 @@ private: return *Built; } - [[nodiscard]] Expected<void> selectAtomicRMW(MachineInstr &Instruction, MachineFunction &Function, - const TargetDescription &Target, - std::optional<LowLevelType> Type, - GenericOpcode Generic) const { - const MachineOperand *AddressOperand = Instruction.operandAt(1); - const MachineOperand *ValueOperand = Instruction.operandAt(2); - const Register *Address = - AddressOperand == nullptr ? nullptr : AddressOperand->getIf<Register>(); - const Register *Value = ValueOperand == nullptr ? nullptr : ValueOperand->getIf<Register>(); - if (!Type || Address == nullptr || Value == nullptr) - return makeUnexpected(ErrorCode::VerificationError, "RISC-V atomic RMW has invalid operands"); - Register SelectedValue = *Value; - const bool IsWord = Type->scalarBitWidth() == 32; - if (Generic == GenericOpcode::G_ATOMICRMW_SUB) { - auto Negated = createTemporary(Function, *Type, Target); - auto Zero = physicalRegister(PhysicalRegisterID::X0); - if (!Negated || !Zero) - return std::unexpected(!Negated ? Negated.error() : Zero.error()); - MachineIRBuilder Builder(Function, Target); - auto Point = Builder.setInsertPointBefore(Instruction); - if (!Point) - return std::unexpected(Point.error()); - auto RegisterConstraints = constrainBuilderRegisters(Function, Target, {*Negated, *Value}); - if (!RegisterConstraints) - return std::unexpected(RegisterConstraints.error()); - auto Pending = Builder.buildInstr( - instructionOpcode(IsWord ? InstructionOpcode::SUBW : InstructionOpcode::SUB)); - if (!Pending) - return std::unexpected(Pending.error()); - auto Def = Pending->addDef(*Negated); - if (!Def) - return std::unexpected(Def.error()); - auto Left = Pending->addUse(Register::fromPhysical(*Zero)); - if (!Left) - return std::unexpected(Left.error()); - auto Right = Pending->addUse(*Value); - if (!Right) - return std::unexpected(Right.error()); - auto Built = Pending->build(); - if (!Built) - return std::unexpected(Built.error()); - auto Constraint = constrainSelectedInstruction(**Built, Function, Target); - if (!Constraint) - return std::unexpected(Constraint.error()); - SelectedValue = *Negated; - } - const auto SelectOpcode = [Generic, IsWord]() -> InstructionOpcode { - switch (Generic) { - case GenericOpcode::G_ATOMICRMW_XCHG: - return IsWord ? InstructionOpcode::AMOSWAP_W : InstructionOpcode::AMOSWAP_D; - case GenericOpcode::G_ATOMICRMW_ADD: - case GenericOpcode::G_ATOMICRMW_SUB: - return IsWord ? InstructionOpcode::AMOADD_W : InstructionOpcode::AMOADD_D; - case GenericOpcode::G_ATOMICRMW_AND: - return IsWord ? InstructionOpcode::AMOAND_W : InstructionOpcode::AMOAND_D; - case GenericOpcode::G_ATOMICRMW_OR: - return IsWord ? InstructionOpcode::AMOOR_W : InstructionOpcode::AMOOR_D; - case GenericOpcode::G_ATOMICRMW_XOR: - return IsWord ? InstructionOpcode::AMOXOR_W : InstructionOpcode::AMOXOR_D; - case GenericOpcode::G_ATOMICRMW_MAX: - return IsWord ? InstructionOpcode::AMOMAX_W : InstructionOpcode::AMOMAX_D; - case GenericOpcode::G_ATOMICRMW_MIN: - return IsWord ? InstructionOpcode::AMOMIN_W : InstructionOpcode::AMOMIN_D; - case GenericOpcode::G_ATOMICRMW_UMAX: - return IsWord ? InstructionOpcode::AMOMAXU_W : InstructionOpcode::AMOMAXU_D; - case GenericOpcode::G_ATOMICRMW_UMIN: - return IsWord ? InstructionOpcode::AMOMINU_W : InstructionOpcode::AMOMINU_D; - default: - return InstructionOpcode::Invalid; - } - }; - const InstructionOpcode Selected = SelectOpcode(); - if (Selected == InstructionOpcode::Invalid) - return makeUnexpected(ErrorCode::InternalError, - "RISC-V atomic RMW selection reached an unhandled opcode"); - auto SetValue = Instruction.operandAt(1)->setRegister(SelectedValue); - if (!SetValue) - return std::unexpected(SetValue.error()); - auto SetAddress = Instruction.operandAt(2)->setRegister(*Address); - if (!SetAddress) - return std::unexpected(SetAddress.error()); - return Instruction.setOpcode(instructionOpcode(Selected)); - } - [[nodiscard]] Expected<void> selectFloatingCompare(MachineInstr &Instruction, MachineFunction &Function, const TargetDescription &Target) const { diff --git a/backend/lib/Target/RISCV/RISCVGISelAtomic.rccdesc b/backend/lib/Target/RISCV/RISCVGISelAtomic.rccdesc new file mode 100644 index 0000000..97e21e9 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVGISelAtomic.rccdesc @@ -0,0 +1,363 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +selection_rules: + - + id: select_g_atomicrmw_xchg_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_XCHG + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOSWAP_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_xchg_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_XCHG + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOSWAP_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_add_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_ADD + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOADD_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_add_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_ADD + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOADD_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_and_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_AND + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOAND_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_and_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_AND + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOAND_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_or_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_OR + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOOR_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_or_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_OR + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOOR_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_xor_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_XOR + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOXOR_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_xor_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_XOR + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOXOR_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_max_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_MAX + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMAX_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_max_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_MAX + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMAX_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_min_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_MIN + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMIN_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_min_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_MIN + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMIN_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_umax_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_UMAX + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMAXU_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_umax_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_UMAX + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMAXU_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_umin_m32 + priority: 300 + match: + opcode: G_ATOMICRMW_UMIN + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 4 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMINU_W + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] + - + id: select_g_atomicrmw_umin_m64 + priority: 300 + match: + opcode: G_ATOMICRMW_UMIN + result_type: { kind: scalar, bits: 64 } + memory: { index: 0, bytes: 8 } + target_predicates: [a] + operand_types: + - { index: 1, kind: pointer, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: GPR } + - { index: 1, bank: GPR } + - { index: 2, bank: GPR } + apply: + instructions: + - opcode: AMOMINU_D + root: true + operands: [{ operand: 0 }, { operand: 2 }, { operand: 1 }] |
