aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target/RISCV
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 18:26:43 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 18:26:43 +0800
commit2d05768bedb7f4209038330bebab270a7f1b558d (patch)
tree359a17ab24fe60568d9f282cb233126b95cb3c04 /backend/lib/Target/RISCV
parent46361bea1f4b1483780d91e4d60d6f44cf0b5706 (diff)
downloadrcc-project-2d05768bedb7f4209038330bebab270a7f1b558d.tar.gz
rcc-project-2d05768bedb7f4209038330bebab270a7f1b558d.tar.xz
[RISCV][GlobalISel] Generate integer arithmetic selections
Diffstat (limited to 'backend/lib/Target/RISCV')
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp115
-rw-r--r--backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc260
2 files changed, 264 insertions, 111 deletions
diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 08e9f6c..c3f2a17 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -190,19 +190,13 @@ public:
const auto Integer = [Type] { return Type && isSupportedIntegerType(*Type); };
const auto Float = [Type] { return Type && isSupportedFloatingScalar(*Type); };
switch (Generic) {
- case GenericOpcode::G_ADD:
- case GenericOpcode::G_SUB:
- case GenericOpcode::G_MUL:
- case GenericOpcode::G_SDIV:
- case GenericOpcode::G_UDIV:
- case GenericOpcode::G_SREM:
- case GenericOpcode::G_UREM:
- case GenericOpcode::G_AND:
- case GenericOpcode::G_OR:
- case GenericOpcode::G_XOR:
case GenericOpcode::G_SHL:
case GenericOpcode::G_LSHR:
case GenericOpcode::G_ASHR:
+ if (!Integer())
+ return makeUnexpected(ErrorCode::Unsupported,
+ "RISC-V selector requires an i1-i64 integer or 64-bit pointer value");
+ return {};
case GenericOpcode::G_CONSTANT:
if (!Integer())
return makeUnexpected(ErrorCode::Unsupported,
@@ -251,8 +245,6 @@ public:
case GenericOpcode::G_SEXT_INREG:
case GenericOpcode::G_ZEXT:
case GenericOpcode::G_FCMP:
- case GenericOpcode::G_SDIVREM:
- case GenericOpcode::G_UDIVREM:
case GenericOpcode::G_SMULH:
case GenericOpcode::G_UMULH:
case GenericOpcode::G_SMIN:
@@ -310,48 +302,6 @@ public:
const std::optional<LowLevelType> Type = resultType(Function, Instruction);
switch (Generic) {
- case GenericOpcode::G_ADD:
- return selectIntegerBinary(Instruction, Function, Type, InstructionOpcode::ADD,
- InstructionOpcode::ADDW, InstructionOpcode::ADDI,
- InstructionOpcode::ADDIW, true, 12, 12);
- case GenericOpcode::G_SUB:
- return selectIntegerBinary(Instruction, Type, InstructionOpcode::SUB,
- InstructionOpcode::SUBW);
- case GenericOpcode::G_MUL:
- return selectIntegerBinary(Instruction, Type, InstructionOpcode::MUL,
- InstructionOpcode::MULW);
- case GenericOpcode::G_SDIV:
- return selectNormalizedIntegerBinary(Instruction, Function, Target, Type,
- InstructionOpcode::DIV, InstructionOpcode::DIVW, true,
- true);
- case GenericOpcode::G_UDIV:
- return selectNormalizedIntegerBinary(Instruction, Function, Target, Type,
- InstructionOpcode::DIVU, InstructionOpcode::DIVUW, false,
- true);
- case GenericOpcode::G_SREM:
- return selectNormalizedIntegerBinary(Instruction, Function, Target, Type,
- InstructionOpcode::REM, InstructionOpcode::REMW, true,
- true);
- case GenericOpcode::G_UREM:
- return selectNormalizedIntegerBinary(Instruction, Function, Target, Type,
- InstructionOpcode::REMU, InstructionOpcode::REMUW, false,
- true);
- case GenericOpcode::G_SDIVREM:
- return selectDivRem(Instruction, Function, Target, Type, true);
- case GenericOpcode::G_UDIVREM:
- return selectDivRem(Instruction, Function, Target, Type, false);
- case GenericOpcode::G_AND:
- return selectIntegerBinary(Instruction, Function, Type, InstructionOpcode::AND,
- InstructionOpcode::AND, InstructionOpcode::ANDI,
- InstructionOpcode::ANDI, true, 12, 12);
- case GenericOpcode::G_OR:
- return selectIntegerBinary(Instruction, Function, Type, InstructionOpcode::OR,
- InstructionOpcode::OR, InstructionOpcode::ORI,
- InstructionOpcode::ORI, true, 12, 12);
- case GenericOpcode::G_XOR:
- return selectIntegerBinary(Instruction, Function, Type, InstructionOpcode::XOR,
- InstructionOpcode::XOR, InstructionOpcode::XORI,
- InstructionOpcode::XORI, true, 12, 12);
case GenericOpcode::G_SHL:
return selectIntegerBinary(Instruction, Function, Type, InstructionOpcode::SLL,
InstructionOpcode::SLLW, InstructionOpcode::SLLI,
@@ -777,52 +727,6 @@ private:
FalseValue, *MaskedDifference);
}
- [[nodiscard]] Expected<void> selectDivRem(MachineInstr &Instruction, MachineFunction &Function,
- const TargetDescription &Target,
- std::optional<LowLevelType> Type, bool Signed) const {
- const MachineOperand *RemainderOperand = Instruction.operandAt(1);
- const MachineOperand *LeftOperand = Instruction.operandAt(2);
- const MachineOperand *RightOperand = Instruction.operandAt(3);
- const Register *Remainder =
- RemainderOperand == nullptr ? nullptr : RemainderOperand->getIf<Register>();
- const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf<Register>();
- const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf<Register>();
- if (!Type || Remainder == nullptr || Left == nullptr || Right == nullptr)
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V division-with-remainder has invalid operands");
- const Register RemainderRegister = *Remainder;
- auto LeftRegister = normalizeIntegerBefore(Instruction, Function, Target, *Left, *Type, Signed);
- auto RightRegister =
- normalizeIntegerBefore(Instruction, Function, Target, *Right, *Type, Signed);
- if (!LeftRegister || !RightRegister)
- return std::unexpected(!LeftRegister ? LeftRegister.error() : RightRegister.error());
- auto RemoveRemainder = Instruction.eraseOperand(1);
- if (!RemoveRemainder)
- return std::unexpected(RemoveRemainder.error());
- auto SetLeft = Instruction.operandAt(1)->setRegister(*LeftRegister);
- if (!SetLeft)
- return std::unexpected(SetLeft.error());
- auto SetRight = Instruction.operandAt(2)->setRegister(*RightRegister);
- if (!SetRight)
- return std::unexpected(SetRight.error());
- const bool IsWord = Type->scalarBitWidth() <= 32;
- const InstructionOpcode Division =
- IsWord ? (Signed ? InstructionOpcode::DIVW : InstructionOpcode::DIVUW)
- : (Signed ? InstructionOpcode::DIV : InstructionOpcode::DIVU);
- const InstructionOpcode RemainderOpcode =
- IsWord ? (Signed ? InstructionOpcode::REMW : InstructionOpcode::REMUW)
- : (Signed ? InstructionOpcode::REM : InstructionOpcode::REMU);
- auto SetDivision = Instruction.setOpcode(instructionOpcode(Division));
- if (!SetDivision)
- return std::unexpected(SetDivision.error());
- MachineIRBuilder Builder(Function, Target);
- auto BuiltRemainder = buildBinaryAfter(Builder, Instruction, RemainderOpcode, RemainderRegister,
- *LeftRegister, *RightRegister);
- if (!BuiltRemainder)
- return std::unexpected(BuiltRemainder.error());
- return {};
- }
-
[[nodiscard]] Expected<void> selectMultiplyHigh(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
@@ -1941,17 +1845,6 @@ private:
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::EBREAK));
}
- [[nodiscard]] Expected<void> selectIntegerBinary(MachineInstr &Instruction,
- std::optional<LowLevelType> Type,
- InstructionOpcode DoubleWord,
- InstructionOpcode Word) const {
- if (!Type || !isSupportedIntegerType(*Type))
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V integer instruction requires a supported scalar integer");
- const bool IsWord = Type->isCategoryNeutralScalar() && Type->scalarBitWidth() <= 32;
- return Instruction.setOpcode(instructionOpcode(IsWord ? Word : DoubleWord));
- }
-
[[nodiscard]] Expected<bool> foldRightConstantToImmediate(MachineInstr &Instruction,
const MachineFunction &Function,
bool Signed,
diff --git a/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc b/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc
index 9e32842..0413007 100644
--- a/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc
+++ b/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc
@@ -84,6 +84,266 @@ selection_rules:
root: true
operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
+ id: select_g_add_immediate
+ priority: 400
+ match:
+ opcode: G_ADD
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 1, bank: GPR }
+ operand_def_constants:
+ - index: 2
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ instructions:
+ - opcode: ADDI
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { captured_immediate: 2 }]
+ erase_operand_definitions: [2]
+ -
+ id: select_g_and_immediate
+ priority: 400
+ match:
+ opcode: G_AND
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 1, bank: GPR }
+ operand_def_constants:
+ - index: 2
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ instructions:
+ - opcode: ANDI
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { captured_immediate: 2 }]
+ erase_operand_definitions: [2]
+ -
+ id: select_g_or_immediate
+ priority: 400
+ match:
+ opcode: G_OR
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 1, bank: GPR }
+ operand_def_constants:
+ - index: 2
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ instructions:
+ - opcode: ORI
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { captured_immediate: 2 }]
+ erase_operand_definitions: [2]
+ -
+ id: select_g_xor_immediate
+ priority: 400
+ match:
+ opcode: G_XOR
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 1, bank: GPR }
+ operand_def_constants:
+ - index: 2
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ instructions:
+ - opcode: XORI
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { captured_immediate: 2 }]
+ erase_operand_definitions: [2]
+ -
+ id: select_g_add_register
+ priority: 100
+ match:
+ opcode: G_ADD
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: ADD
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_sub_register
+ priority: 100
+ match:
+ opcode: G_SUB
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: SUB
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_mul_register
+ priority: 100
+ match:
+ opcode: G_MUL
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: MUL
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_sdiv_register
+ priority: 100
+ match:
+ opcode: G_SDIV
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: DIV
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_udiv_register
+ priority: 100
+ match:
+ opcode: G_UDIV
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: DIVU
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_srem_register
+ priority: 100
+ match:
+ opcode: G_SREM
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: REM
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_urem_register
+ priority: 100
+ match:
+ opcode: G_UREM
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: REMU
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_and_register
+ priority: 100
+ match:
+ opcode: G_AND
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: AND
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_or_register
+ priority: 100
+ match:
+ opcode: G_OR
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: OR
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
+ id: select_g_xor_register
+ priority: 100
+ match:
+ opcode: G_XOR
+ result_type: { kind: scalar, bits: 64 }
+ operand_types:
+ - { index: 1, kind: scalar, 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: XOR
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
+ -
id: select_g_sllw
priority: 100
match: