aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/lib/Target/RISCV/CMakeLists.txt1
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp97
-rw-r--r--backend/lib/Target/RISCV/RISCVGISelAtomic.rccdesc363
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 }]