From 220c9cd426ec0590f6a43550b28fb344d8dfd8fd Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 15 Aug 2026 19:04:08 +0800 Subject: [RISCV][GlobalISel] Legalize floating-point to integer conversions --- backend/include/rcc/TableGen/Record.h | 1 + backend/lib/TableGen/Parser.cpp | 12 +++- .../lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 19 ++++++ backend/lib/Target/RISCV/RISCV.rccdesc | 76 +++++++++++----------- .../utils/TableGen/Common/CodeGenInstruction.cpp | 13 ++++ backend/utils/TableGen/Common/CodeGenTarget.h | 1 + backend/utils/TableGen/InstrInfoEmitter.cpp | 11 +++- 7 files changed, 93 insertions(+), 40 deletions(-) (limited to 'backend') diff --git a/backend/include/rcc/TableGen/Record.h b/backend/include/rcc/TableGen/Record.h index b085098..50ac4c9 100644 --- a/backend/include/rcc/TableGen/Record.h +++ b/backend/include/rcc/TableGen/Record.h @@ -170,6 +170,7 @@ struct SourceOperand final { bool VariadicGroup = false; bool AllowSubReg = false; std::optional NameSymbol; + std::optional TypeIndex; std::uint32_t AllowedTargetFlags = 0; TextRange Range; }; diff --git a/backend/lib/TableGen/Parser.cpp b/backend/lib/TableGen/Parser.cpp index 66d10e0..2d7116d 100644 --- a/backend/lib/TableGen/Parser.cpp +++ b/backend/lib/TableGen/Parser.cpp @@ -864,7 +864,7 @@ private: if (!checkKeys(Node, {"kinds", "role", "register_class", "register_bank", "immediate_predicate", "memory_role", "default_tied_operand", "early_clobber", "optional", - "variadic_group", "allow_subreg", "name", "allowed_target_flags"}, + "variadic_group", "allow_subreg", "name", "type_index", "allowed_target_flags"}, "instruction operand")) { return std::nullopt; } @@ -944,6 +944,16 @@ private: return std::nullopt; Result.NameSymbol = *Value; } + if (const yaml::Node *TypeIndex = optionalNode(Node, "type_index")) { + const auto Value = unsignedInteger32(*TypeIndex, "instruction operand type_index"); + if (!Value) + return std::nullopt; + if (*Value > std::numeric_limits::max()) { + fail(TypeIndex->range(), "instruction operand type_index is outside the uint16 range"); + return std::nullopt; + } + Result.TypeIndex = static_cast(*Value); + } if (const yaml::Node *TargetFlags = optionalNode(Node, "allowed_target_flags")) { const auto Value = unsignedInteger32(*TargetFlags, "instruction operand allowed_target_flags"); diff --git a/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp index 06eea7b..864aca5 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp @@ -861,6 +861,25 @@ Expected RISCVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, Helper.Observer.changedInstr(Instruction); return {}; } + if (Instruction.opcode() == opcode(GenericOpcode::G_FPTOSI) || + Instruction.opcode() == opcode(GenericOpcode::G_FPTOUI)) { + auto XLenType = LowLevelType::makeCategoryNeutralScalar(64); + if (!XLenType) + return std::unexpected(XLenType.error()); + + Helper.Observer.changingInstr(Instruction); + if (auto Widened = Helper.widenScalarDst(Instruction, *XLenType); !Widened) + return std::unexpected(Widened.error()); + auto WordOpcode = getRISCVWOpcode(static_cast(Instruction.opcode().value())); + if (!WordOpcode) + return std::unexpected(WordOpcode.error()); + if (auto Changed = Instruction.setOpcode(*WordOpcode); !Changed) + return std::unexpected(Changed.error()); + if (auto RoundingMode = Instruction.addOperand(MachineOperand::immediate(1)); !RoundingMode) + return std::unexpected(RoundingMode.error()); + Helper.Observer.changedInstr(Instruction); + return {}; + } if (Instruction.opcode() == opcode(GenericOpcode::G_ANYEXT) || Instruction.opcode() == opcode(GenericOpcode::G_SEXT) || Instruction.opcode() == opcode(GenericOpcode::G_ZEXT)) { diff --git a/backend/lib/Target/RISCV/RISCV.rccdesc b/backend/lib/Target/RISCV/RISCV.rccdesc index 185ff7c..4896229 100644 --- a/backend/lib/Target/RISCV/RISCV.rccdesc +++ b/backend/lib/Target/RISCV/RISCV.rccdesc @@ -3666,9 +3666,9 @@ instructions: symbol: G_SLLW name: G_SLLW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3678,9 +3678,9 @@ instructions: symbol: G_SRAW name: G_SRAW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3690,9 +3690,9 @@ instructions: symbol: G_DIVW name: G_DIVW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3702,8 +3702,8 @@ instructions: symbol: G_CLZW name: G_CLZW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3713,8 +3713,8 @@ instructions: symbol: G_CTZW name: G_CTZW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3724,8 +3724,8 @@ instructions: symbol: G_FCVT_W_RV64 name: G_FCVT_W_RV64 operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 1 } - { kinds: [immediate] } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] @@ -3736,8 +3736,8 @@ instructions: symbol: G_FCLASS name: G_FCLASS operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 1 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3747,9 +3747,9 @@ instructions: symbol: G_ROLW name: G_ROLW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3759,9 +3759,9 @@ instructions: symbol: G_SRLW name: G_SRLW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3771,9 +3771,9 @@ instructions: symbol: G_DIVUW name: G_DIVUW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3783,9 +3783,9 @@ instructions: symbol: G_REMUW name: G_REMUW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3795,9 +3795,9 @@ instructions: symbol: G_RORW name: G_RORW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3807,8 +3807,8 @@ instructions: symbol: G_BREV8 name: G_BREV8 operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select @@ -3818,8 +3818,8 @@ instructions: symbol: G_FCVT_WU_RV64 name: G_FCVT_WU_RV64 operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 1 } - { kinds: [immediate] } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] @@ -3830,8 +3830,8 @@ instructions: symbol: G_CLSW name: G_CLSW operands: - - { kinds: [register], role: def } - - { kinds: [register], role: use } + - { kinds: [register], role: def, type_index: 0 } + - { kinds: [register], role: use, type_index: 0 } num_explicit_defs: 1 flags: [generic, pseudo, allowed_pre_legalizer] owner: instruction_select diff --git a/backend/utils/TableGen/Common/CodeGenInstruction.cpp b/backend/utils/TableGen/Common/CodeGenInstruction.cpp index cabe8d4..c314304 100644 --- a/backend/utils/TableGen/Common/CodeGenInstruction.cpp +++ b/backend/utils/TableGen/Common/CodeGenInstruction.cpp @@ -287,6 +287,10 @@ pipelineStageEnumerator(std::string_view Value) noexcept { fail(InputOperand.Range, "register definition operands must accept only registers"); return false; } + if (InputOperand.TypeIndex && !IsRegisterOnly) { + fail(InputOperand.Range, "instruction operand type_index requires exactly one register kind"); + return false; + } if (!HasRegisterKind && (InputOperand.RegisterClassSymbol || InputOperand.RegisterBankSymbol || InputOperand.EarlyClobber || InputOperand.AllowSubReg)) { fail(InputOperand.Range, "non-register operands cannot have register constraints"); @@ -337,6 +341,7 @@ pipelineStageEnumerator(std::string_view Value) noexcept { Result.Optional = InputOperand.Optional; Result.VariadicGroup = InputOperand.VariadicGroup; Result.AllowSubReg = InputOperand.AllowSubReg; + Result.TypeIndex = InputOperand.TypeIndex; Result.AllowedTargetFlags = InputOperand.AllowedTargetFlags; return true; } @@ -529,6 +534,14 @@ CodeGenTarget::normalizeImplicitRegisters(const std::vector Name; + std::optional TypeIndex; std::uint32_t AllowedTargetFlags = 0; }; diff --git a/backend/utils/TableGen/InstrInfoEmitter.cpp b/backend/utils/TableGen/InstrInfoEmitter.cpp index b06134f..1f42d4a 100644 --- a/backend/utils/TableGen/InstrInfoEmitter.cpp +++ b/backend/utils/TableGen/InstrInfoEmitter.cpp @@ -49,7 +49,16 @@ void emitOperandDescriptor(std::ostream &Output, const NormalizedOperand &Operan else Output << "std::nullopt"; Output << ", .TargetOperandType = std::nullopt, .AllowedTargetFlags = " - << Operand.AllowedTargetFlags << ", .TypeConstraint = std::nullopt},\n"; + << Operand.AllowedTargetFlags << ", .TypeConstraint = "; + if (Operand.TypeIndex) { + Output << "OperandTypeConstraint{LowLevelTypeKindSet{" + << "LowLevelType::Kind::CategoryNeutralScalar, LowLevelType::Kind::Pointer, " + << "LowLevelType::Kind::Vector, LowLevelType::Kind::VectorPointer}, std::uint16_t{" + << *Operand.TypeIndex << "}}"; + } else { + Output << "std::nullopt"; + } + Output << "},\n"; } void emitImplicitRegisterList(std::ostream &Output, const NormalizedTargetModel &Model, -- cgit v1.2.3