aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-15 19:04:08 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-15 19:04:08 +0800
commit220c9cd426ec0590f6a43550b28fb344d8dfd8fd (patch)
tree733b69782971fdd0a88e8f4581900a11a5dbdcbd /backend
parent2c7a437b066ad243a21af6d2c1ce1550e467f5f5 (diff)
downloadrcc-project-220c9cd426ec0590f6a43550b28fb344d8dfd8fd.tar.gz
rcc-project-220c9cd426ec0590f6a43550b28fb344d8dfd8fd.tar.xz
[RISCV][GlobalISel] Legalize floating-point to integer conversions
Diffstat (limited to 'backend')
-rw-r--r--backend/include/rcc/TableGen/Record.h1
-rw-r--r--backend/lib/TableGen/Parser.cpp12
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp19
-rw-r--r--backend/lib/Target/RISCV/RISCV.rccdesc76
-rw-r--r--backend/utils/TableGen/Common/CodeGenInstruction.cpp13
-rw-r--r--backend/utils/TableGen/Common/CodeGenTarget.h1
-rw-r--r--backend/utils/TableGen/InstrInfoEmitter.cpp11
7 files changed, 93 insertions, 40 deletions
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<std::string> NameSymbol;
+ std::optional<std::uint16_t> 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<std::uint16_t>::max()) {
+ fail(TypeIndex->range(), "instruction operand type_index is outside the uint16 range");
+ return std::nullopt;
+ }
+ Result.TypeIndex = static_cast<std::uint16_t>(*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<void> 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<GenericOpcode>(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<SourceImplicitRegist
return std::ranges::find(Normalized.Flags, Flag) != Normalized.Flags.end();
};
const bool IsTerminator = HasFlag("Terminator");
+ if (!HasFlag("Generic") &&
+ std::ranges::any_of(Normalized.Operands, [](const NormalizedOperand &Operand) {
+ return Operand.TypeIndex.has_value();
+ })) {
+ fail(Instruction.Range,
+ "instruction type_index operands require the generic instruction flag");
+ return false;
+ }
if ((HasFlag("Branch") || HasFlag("Return") || HasFlag("Barrier") ||
HasFlag("IndirectBranch")) &&
!IsTerminator) {
diff --git a/backend/utils/TableGen/Common/CodeGenTarget.h b/backend/utils/TableGen/Common/CodeGenTarget.h
index 139cfc8..cbddd4a 100644
--- a/backend/utils/TableGen/Common/CodeGenTarget.h
+++ b/backend/utils/TableGen/Common/CodeGenTarget.h
@@ -131,6 +131,7 @@ struct NormalizedOperand final {
bool VariadicGroup = false;
bool AllowSubReg = false;
std::optional<std::uint32_t> Name;
+ std::optional<std::uint16_t> 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,