aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-19 03:41:05 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-19 03:41:05 +0800
commit219b315373ef34ca20cc78b89bf3c3d19442ffbd (patch)
treee65feacb93b93fee1d591486b97573ce7b78b85e /backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
parent3cc064e41f6913b176fbfb2d6e65d049f611b1d4 (diff)
downloadrcc-project-219b315373ef34ca20cc78b89bf3c3d19442ffbd.tar.gz
rcc-project-219b315373ef34ca20cc78b89bf3c3d19442ffbd.tar.xz
[RISCV][GlobalISel] Generate integer load selection
Diffstat (limited to 'backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp')
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp138
1 files changed, 64 insertions, 74 deletions
diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 2cceb92..18b986d 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -212,6 +212,55 @@ directIntegerConstant(const MachineRegisterInfo &RegisterInfo, Register ValueReg
return Value ? std::optional<std::int64_t>(*Value) : std::nullopt;
}
+struct SelectedAddress final {
+ MachineOperand Base;
+ std::int64_t Offset = 0;
+};
+
+[[nodiscard]] std::optional<SelectedAddress> selectAddress(const MachineInstr &Instruction,
+ const MachineFunction &Function,
+ std::uint32_t OperandIndex) {
+ const MachineOperand *Root = Instruction.operandAt(OperandIndex);
+ const Register *RootRegister = Root == nullptr ? nullptr : Root->getIf<Register>();
+ if (RootRegister == nullptr || !RootRegister->isVirtual())
+ return std::nullopt;
+
+ const MachineRegisterInfo &Registers = Function.registerInfo();
+ const MachineInstr *RootDefinition = Registers.getVRegDef(*RootRegister);
+ if (RootDefinition != nullptr &&
+ RootDefinition->opcode() == opcode(GenericOpcode::G_FRAME_INDEX)) {
+ const MachineOperand *FrameIndex = RootDefinition->operandAt(1);
+ if (FrameIndex == nullptr)
+ return std::nullopt;
+ return SelectedAddress{.Base = FrameIndex->cloneDetached(), .Offset = 0};
+ }
+
+ if (RootDefinition != nullptr && RootDefinition->opcode() == opcode(GenericOpcode::G_PTR_ADD)) {
+ const MachineOperand *Base = RootDefinition->operandAt(1);
+ const MachineOperand *Offset = RootDefinition->operandAt(2);
+ const Register *BaseRegister = Base == nullptr ? nullptr : Base->getIf<Register>();
+ const Register *OffsetRegister = Offset == nullptr ? nullptr : Offset->getIf<Register>();
+ if (BaseRegister != nullptr && OffsetRegister != nullptr) {
+ const std::optional<std::int64_t> Constant =
+ directIntegerConstant(Registers, *OffsetRegister);
+ if (Constant && *Constant >= -2048 && *Constant <= 2047) {
+ const MachineInstr *BaseDefinition =
+ BaseRegister->isVirtual() ? Registers.getVRegDef(*BaseRegister) : nullptr;
+ if (BaseDefinition != nullptr &&
+ BaseDefinition->opcode() == opcode(GenericOpcode::G_FRAME_INDEX)) {
+ const MachineOperand *FrameIndex = BaseDefinition->operandAt(1);
+ if (FrameIndex == nullptr)
+ return std::nullopt;
+ return SelectedAddress{.Base = FrameIndex->cloneDetached(), .Offset = *Constant};
+ }
+ return SelectedAddress{.Base = Base->cloneDetached(), .Offset = *Constant};
+ }
+ }
+ }
+
+ return SelectedAddress{.Base = Root->cloneDetached(), .Offset = 0};
+}
+
struct SelectedIntegerCondition final {
Register Left;
Register Right;
@@ -337,6 +386,21 @@ public:
renderComplexOperand(std::string_view Name, const MachineInstr &Instruction,
const MachineFunction &Function, const TargetDescription &Target,
std::uint32_t OperandIndex) const override {
+ if (Name == "addr_reg_imm_base" || Name == "addr_reg_imm_offset") {
+ std::optional<SelectedAddress> Address = selectAddress(Instruction, Function, OperandIndex);
+ if (!Address)
+ return std::optional<GIMatchComplexOperand>{};
+ if (Name == "addr_reg_imm_offset") {
+ return GIMatchComplexOperand{
+ .Operand = MachineOperand::immediate(Address->Offset),
+ .Instruction = std::nullopt,
+ };
+ }
+ return GIMatchComplexOperand{
+ .Operand = std::move(Address->Base),
+ .Instruction = std::nullopt,
+ };
+ }
if (Name == "select_condition_lhs" || Name == "select_condition_rhs" ||
Name == "select_condition_code") {
auto Condition = selectIntegerCondition(Instruction, Function, OperandIndex);
@@ -551,9 +615,6 @@ public:
"RISC-V integer constant requires an immediate operand");
}
return {};
- case GenericOpcode::G_LOAD:
- case GenericOpcode::G_SEXTLOAD:
- case GenericOpcode::G_ZEXTLOAD:
case GenericOpcode::G_FPEXTLOAD:
case GenericOpcode::G_FPTRUNCSTORE:
case GenericOpcode::G_STORE:
@@ -617,12 +678,6 @@ public:
const std::optional<LowLevelType> Type = resultType(Function, Instruction);
switch (Generic) {
- case GenericOpcode::G_LOAD:
- return selectLoad(Instruction, Function, Type);
- case GenericOpcode::G_SEXTLOAD:
- return selectExtLoad(Instruction, Type, true);
- case GenericOpcode::G_ZEXTLOAD:
- return selectExtLoad(Instruction, Type, false);
case GenericOpcode::G_FPEXTLOAD:
return selectFloatExtLoad(Instruction, Function, Target);
case GenericOpcode::G_STORE:
@@ -1211,71 +1266,6 @@ private:
return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FENCE));
}
- [[nodiscard]] Expected<void> selectLoad(MachineInstr &Instruction, MachineFunction &Function,
- std::optional<LowLevelType> Type) const {
- if (!Type)
- return makeUnexpected(ErrorCode::VerificationError,
- "load result has no virtual-register type");
- const auto Bytes = memoryAccessBytes(Instruction);
- if (!Bytes)
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V load size does not match its result type");
- const MachineOperand *DestinationOperand = Instruction.operandAt(0);
- const Register *Destination =
- DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
- if (Destination == nullptr)
- return makeUnexpected(ErrorCode::VerificationError, "RISC-V load has no destination");
- auto Bank = registerBank(Function, *Destination);
- if (!Bank)
- return std::unexpected(Bank.error());
- if (Instruction.memOperands().front()->isAtomic()) {
- if (*Bank == fprBank() || !isSupportedIntegerType(*Type) || (*Bytes != 4 && *Bytes != 8))
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V atomic load requires a 32-bit or 64-bit GPR value");
- return Instruction.setOpcode(
- instructionOpcode(*Bytes == 4 ? InstructionOpcode::LR_W : InstructionOpcode::LR_D));
- }
- auto AppendOffset = appendImmediate(Instruction, 0);
- if (!AppendOffset)
- return std::unexpected(AppendOffset.error());
- if (*Bank != fprBank() && isSupportedIntegerType(*Type)) {
- const InstructionOpcode Selected = *Bytes == 1 ? InstructionOpcode::LB
- : *Bytes == 2 ? InstructionOpcode::LH
- : *Bytes == 4 ? InstructionOpcode::LW
- : *Bytes == 8 ? InstructionOpcode::LD
- : InstructionOpcode::Invalid;
- if (Selected == InstructionOpcode::Invalid)
- return makeUnexpected(ErrorCode::Unsupported, "RISC-V integer load width is unsupported");
- return Instruction.setOpcode(instructionOpcode(Selected));
- }
- if (*Bank == fprBank() && Type->scalarBitWidth() == 32 && *Bytes == 4)
- return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FLW));
- if (*Bank == fprBank() && Type->scalarBitWidth() == 64 && *Bytes == 8)
- return Instruction.setOpcode(instructionOpcode(InstructionOpcode::FLD));
- return makeUnexpected(ErrorCode::Unsupported, "RISC-V cannot select this generic load type");
- }
-
- [[nodiscard]] Expected<void> selectExtLoad(MachineInstr &Instruction,
- std::optional<LowLevelType> Type, bool Signed) const {
- if (!Type || !isSupportedIntegerType(*Type))
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V extension load requires an integer result");
- const auto Bytes = memoryAccessBytes(Instruction);
- if (!Bytes)
- return makeUnexpected(ErrorCode::Unsupported, "RISC-V extension load has an invalid width");
- const InstructionOpcode Selected =
- *Bytes == 1 ? (Signed ? InstructionOpcode::LB : InstructionOpcode::LBU)
- : *Bytes == 2 ? (Signed ? InstructionOpcode::LH : InstructionOpcode::LHU)
- : *Bytes == 4 ? (Signed ? InstructionOpcode::LW : InstructionOpcode::LWU)
- : InstructionOpcode::Invalid;
- if (Selected == InstructionOpcode::Invalid)
- return makeUnexpected(ErrorCode::Unsupported, "RISC-V extension load width is unsupported");
- auto Immediate = appendImmediate(Instruction, 0);
- if (!Immediate)
- return std::unexpected(Immediate.error());
- return Instruction.setOpcode(instructionOpcode(Selected));
- }
-
[[nodiscard]] Expected<void> selectFloatExtLoad(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target) const {