aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-17 03:16:26 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-17 03:16:26 +0800
commitf5c592905e6e1ef4b78337d76c8215e543607b8d (patch)
tree193400315338b57af33699ad7f952fb3731b3a65
parent9720e989ccdce77a2c45a8379d36ff4428e6c2bf (diff)
downloadrcc-project-f5c592905e6e1ef4b78337d76c8215e543607b8d.tar.gz
rcc-project-f5c592905e6e1ef4b78337d76c8215e543607b8d.tar.xz
[RISCV][GlobalISel] Generate conditional branch selection
-rw-r--r--backend/include/rcc/CodeGen/GlobalISel/GIMatchTableExecutor.h1
-rw-r--r--backend/include/rcc/TableGen/Record.h1
-rw-r--r--backend/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp32
-rw-r--r--backend/lib/TableGen/Parser.cpp23
-rw-r--r--backend/lib/Target/RISCV/CMakeLists.txt1
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp13
-rw-r--r--backend/lib/Target/RISCV/RISCVGISelControlFlow.rccdesc252
-rw-r--r--backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc10
-rw-r--r--backend/utils/TableGen/Common/CodeGenSelection.cpp17
-rw-r--r--backend/utils/TableGen/Common/CodeGenTarget.h1
-rw-r--r--backend/utils/TableGen/GlobalISelEmitter.cpp8
11 files changed, 322 insertions, 37 deletions
diff --git a/backend/include/rcc/CodeGen/GlobalISel/GIMatchTableExecutor.h b/backend/include/rcc/CodeGen/GlobalISel/GIMatchTableExecutor.h
index 098f9d6..a5b8b8e 100644
--- a/backend/include/rcc/CodeGen/GlobalISel/GIMatchTableExecutor.h
+++ b/backend/include/rcc/CodeGen/GlobalISel/GIMatchTableExecutor.h
@@ -41,6 +41,7 @@ enum class GIMatchTableOpcode : std::uint8_t {
CheckOperandImmediateRanges,
CheckOperandDefConstantRanges,
CheckOperandDefOpcode,
+ CheckOperandDefIntegerPredicate,
CheckOperandDefOperandConstantRanges,
CaptureDefOperand,
CreateTemporary,
diff --git a/backend/include/rcc/TableGen/Record.h b/backend/include/rcc/TableGen/Record.h
index 1f9dea9..17b0e46 100644
--- a/backend/include/rcc/TableGen/Record.h
+++ b/backend/include/rcc/TableGen/Record.h
@@ -267,6 +267,7 @@ struct SourceSelectionDefUseCapture final {
struct SourceSelectionDefUsePredicate final {
std::uint32_t RootOperandIndex = 0;
std::string OpcodeSymbol;
+ std::optional<SourceSelectionIntegerPredicate> IntegerPredicate;
std::vector<SourceSelectionDefUseCapture> Captures;
std::vector<SourceSelectionOperandDefConstantPredicate> OperandDefConstants;
TextRange Range;
diff --git a/backend/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/backend/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp
index 739f12b..d4f73f6 100644
--- a/backend/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp
+++ b/backend/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp
@@ -94,15 +94,16 @@ namespace {
}
[[nodiscard]] Expected<bool> matchesIntegerPredicate(const MachineInstr &Instruction,
- const GIMatchTableInstruction &Step) {
- if (Step.Value >= static_cast<std::uint32_t>(IntegerPredicate::Count)) {
+ std::size_t OperandIndex,
+ std::uint32_t PredicateValue) {
+ if (PredicateValue >= static_cast<std::uint32_t>(IntegerPredicate::Count)) {
return makeUnexpected(ErrorCode::VerificationError,
"generated match table has an invalid integer predicate");
}
- const MachineOperand *Operand = Instruction.operandAt(Step.OperandIndex);
+ const MachineOperand *Operand = Instruction.operandAt(OperandIndex);
const auto *Predicate = Operand == nullptr ? nullptr : Operand->getIf<PredicateOperand>();
const IntegerPredicate *Integer = Predicate == nullptr ? nullptr : Predicate->integerPredicate();
- return Integer != nullptr && static_cast<std::uint32_t>(*Integer) == Step.Value;
+ return Integer != nullptr && static_cast<std::uint32_t>(*Integer) == PredicateValue;
}
[[nodiscard]] std::optional<std::int64_t> immediateValue(const MachineOperand &Operand) {
@@ -206,6 +207,15 @@ operandOrDefConstantValue(const MachineInstr &Instruction, const MachineFunction
}
[[nodiscard]] Expected<bool>
+matchesOperandDefIntegerPredicate(const MachineInstr &Instruction, const MachineFunction &Function,
+ const GIMatchTableInstruction &Step) {
+ const MachineInstr *Definition = operandDefinition(Instruction, Function, Step.OperandIndex);
+ if (Definition == nullptr)
+ return false;
+ return matchesIntegerPredicate(*Definition, Step.Auxiliary, Step.Value);
+}
+
+[[nodiscard]] Expected<bool>
matchesOperandDefOperandConstantRanges(const GIMatchTable &Table, const MachineInstr &Instruction,
const MachineFunction &Function,
const GIMatchTableInstruction &Step) {
@@ -367,7 +377,7 @@ matchRule(const GIMatchTable &Table, const GIMatchTableRule &Rule, const Machine
return makeUnexpected(ErrorCode::VerificationError,
"generated match table performs a predicate after an action");
}
- auto Matched = matchesIntegerPredicate(Instruction, Step);
+ auto Matched = matchesIntegerPredicate(Instruction, Step.OperandIndex, Step.Value);
if (!Matched)
return std::unexpected(Matched.error());
if (!*Matched)
@@ -422,6 +432,18 @@ matchRule(const GIMatchTable &Table, const GIMatchTableRule &Rule, const Machine
return std::optional<MatchedRule>{};
break;
}
+ case GIMatchTableOpcode::CheckOperandDefIntegerPredicate: {
+ if (Applying) {
+ return makeUnexpected(ErrorCode::VerificationError,
+ "generated match table performs a predicate after an action");
+ }
+ auto Matched = matchesOperandDefIntegerPredicate(Instruction, Function, Step);
+ if (!Matched)
+ return std::unexpected(Matched.error());
+ if (!*Matched)
+ return std::optional<MatchedRule>{};
+ break;
+ }
case GIMatchTableOpcode::CheckOperandDefOperandConstantRanges: {
if (Applying) {
return makeUnexpected(ErrorCode::VerificationError,
diff --git a/backend/lib/TableGen/Parser.cpp b/backend/lib/TableGen/Parser.cpp
index 7c6a8de..1a2af30 100644
--- a/backend/lib/TableGen/Parser.cpp
+++ b/backend/lib/TableGen/Parser.cpp
@@ -1152,8 +1152,9 @@ private:
return true;
}
- [[nodiscard]] bool parseSelectionIntegerPredicate(const yaml::Node &Node,
- SourceSelectionRule &Result) {
+ [[nodiscard]] bool
+ parseSelectionIntegerPredicate(const yaml::Node &Node,
+ std::optional<SourceSelectionIntegerPredicate> &Result) {
if (!requireMapping(&Node, "selection integer predicate") ||
!checkKeys(Node, {"index", "value"}, "selection integer predicate")) {
return false;
@@ -1165,7 +1166,7 @@ private:
const auto Index = unsignedInteger32(*IndexNode, "selection integer predicate index");
if (!Index)
return false;
- Result.IntegerPredicate = SourceSelectionIntegerPredicate{
+ Result = SourceSelectionIntegerPredicate{
.OperandIndex = *Index,
.Predicate = *Value,
.Range = Node.range(),
@@ -1303,8 +1304,10 @@ private:
for (const yaml::NodeID ElementID : Node.sequence()) {
const yaml::Node *Element = Input.node(ElementID);
if (!requireMapping(Element, "selection def-use predicate") ||
- !checkKeys(*Element, {"operand", "opcode", "captures", "operand_def_constants"},
- "selection def-use predicate")) {
+ !checkKeys(
+ *Element,
+ {"operand", "opcode", "integer_predicate", "captures", "operand_def_constants"},
+ "selection def-use predicate")) {
return false;
}
const yaml::Node *OperandNode =
@@ -1319,10 +1322,15 @@ private:
SourceSelectionDefUsePredicate Predicate{
.RootOperandIndex = *Operand,
.OpcodeSymbol = *Opcode,
+ .IntegerPredicate = std::nullopt,
.Captures = {},
.OperandDefConstants = {},
.Range = Element->range(),
};
+ if (const yaml::Node *IntegerPredicate = optionalNode(*Element, "integer_predicate")) {
+ if (!parseSelectionIntegerPredicate(*IntegerPredicate, Predicate.IntegerPredicate))
+ return false;
+ }
if (const yaml::Node *Captures = optionalNode(*Element, "captures")) {
if (!requireSequence(Captures, "selection def-use captures"))
return false;
@@ -1352,7 +1360,8 @@ private:
if (!parseSelectionOperandDefConstants(*Constants, Predicate.OperandDefConstants))
return false;
}
- if (Predicate.Captures.empty() && Predicate.OperandDefConstants.empty()) {
+ if (!Predicate.IntegerPredicate && Predicate.Captures.empty() &&
+ Predicate.OperandDefConstants.empty()) {
fail(Element->range(),
"selection def-use predicate requires a capture or constant predicate");
return false;
@@ -1553,7 +1562,7 @@ private:
Result.ResultType = std::move(*Parsed);
}
if (const yaml::Node *Predicate = optionalNode(Node, "integer_predicate")) {
- if (!parseSelectionIntegerPredicate(*Predicate, Result))
+ if (!parseSelectionIntegerPredicate(*Predicate, Result.IntegerPredicate))
return false;
}
if (const yaml::Node *TargetPredicates = optionalNode(Node, "target_predicates")) {
diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt
index f9eb79f..48f3263 100644
--- a/backend/lib/Target/RISCV/CMakeLists.txt
+++ b/backend/lib/Target/RISCV/CMakeLists.txt
@@ -15,6 +15,7 @@ set(
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoZb.rccdesc"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVInstrInfoPseudo.rccdesc"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelInteger.rccdesc"
+ "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelControlFlow.rccdesc"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelShift.rccdesc"
"${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelFloating.rccdesc"
)
diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 89b6ecd..1e2eb92 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -364,7 +364,6 @@ public:
case GenericOpcode::G_FPEXTLOAD:
case GenericOpcode::G_FPTRUNCSTORE:
case GenericOpcode::G_STORE:
- case GenericOpcode::G_BRCOND:
return {};
case GenericOpcode::G_FCONSTANT: {
const MachineOperand *Immediate = Instruction.operandAt(1);
@@ -440,8 +439,6 @@ public:
return selectStore(Instruction, Function);
case GenericOpcode::G_FPTRUNCSTORE:
return selectFloatTruncStore(Instruction, Function, Target);
- case GenericOpcode::G_BRCOND:
- return selectConditionalBranch(Instruction);
case GenericOpcode::G_CONSTANT:
return selectIntegerConstant(Instruction, Function, Target, Type);
case GenericOpcode::G_FCONSTANT:
@@ -1422,16 +1419,6 @@ private:
return makeUnexpected(ErrorCode::Unsupported, "RISC-V cannot select this generic store type");
}
- [[nodiscard]] Expected<void> selectConditionalBranch(MachineInstr &Instruction) const {
- auto Zero = physicalRegister(PhysicalRegisterID::X0);
- if (!Zero)
- return std::unexpected(Zero.error());
- auto Inserted = insertPhysicalRegister(Instruction, 1, *Zero, RegisterOperandFlag::Use);
- if (!Inserted)
- return std::unexpected(Inserted.error());
- return Instruction.setOpcode(instructionOpcode(InstructionOpcode::BNE));
- }
-
[[nodiscard]] Expected<void> selectIntegerConstant(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target,
diff --git a/backend/lib/Target/RISCV/RISCVGISelControlFlow.rccdesc b/backend/lib/Target/RISCV/RISCVGISelControlFlow.rccdesc
new file mode 100644
index 0000000..c58135f
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVGISelControlFlow.rccdesc
@@ -0,0 +1,252 @@
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+selection_rules:
+ -
+ id: select_g_br
+ priority: 100
+ match:
+ opcode: G_BR
+ apply:
+ instructions:
+ - opcode: PseudoBR
+ root: true
+ operands: [{ operand: 0 }]
+ -
+ id: select_g_brcond_sgt_minus_one
+ priority: 600
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: sgt }
+ captures:
+ - { id: lhs, operand: 2 }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: -1, max: -1 }]
+ apply:
+ instructions:
+ - opcode: BGE
+ root: true
+ operands:
+ - { captured_operand: lhs }
+ - { physical_register: X0, flags: [use] }
+ - { operand: 1 }
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_slt_one
+ priority: 600
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: slt }
+ captures:
+ - { id: lhs, operand: 2 }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: 1, max: 1 }]
+ apply:
+ instructions:
+ - opcode: BGE
+ root: true
+ operands:
+ - { physical_register: X0, flags: [use] }
+ - { captured_operand: lhs }
+ - { operand: 1 }
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_eq
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: eq }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BEQ
+ root: true
+ operands: [{ captured_operand: lhs }, { captured_operand: rhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_ne
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: ne }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BNE
+ root: true
+ operands: [{ captured_operand: lhs }, { captured_operand: rhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_slt
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: slt }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BLT
+ root: true
+ operands: [{ captured_operand: lhs }, { captured_operand: rhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_sge
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: sge }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BGE
+ root: true
+ operands: [{ captured_operand: lhs }, { captured_operand: rhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_ult
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: ult }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BLTU
+ root: true
+ operands: [{ captured_operand: lhs }, { captured_operand: rhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_uge
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: uge }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BGEU
+ root: true
+ operands: [{ captured_operand: lhs }, { captured_operand: rhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_sgt
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: sgt }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BLT
+ root: true
+ operands: [{ captured_operand: rhs }, { captured_operand: lhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_sle
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: sle }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BGE
+ root: true
+ operands: [{ captured_operand: rhs }, { captured_operand: lhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_ugt
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: ugt }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BLTU
+ root: true
+ operands: [{ captured_operand: rhs }, { captured_operand: lhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond_ule
+ priority: 400
+ match:
+ opcode: G_BRCOND
+ def_use:
+ - operand: 0
+ opcode: G_ICMP
+ integer_predicate: { index: 1, value: ule }
+ captures:
+ - { id: lhs, operand: 2 }
+ - { id: rhs, operand: 3 }
+ apply:
+ instructions:
+ - opcode: BGEU
+ root: true
+ operands: [{ captured_operand: rhs }, { captured_operand: lhs }, { operand: 1 }]
+ erase_operand_definitions: [0]
+ -
+ id: select_g_brcond
+ priority: 100
+ match:
+ opcode: G_BRCOND
+ apply:
+ instructions:
+ - opcode: BNE
+ root: true
+ operands:
+ - { operand: 0 }
+ - { physical_register: X0, flags: [use] }
+ - { operand: 1 }
diff --git a/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc b/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc
index 6ba88ef..f40e5d4 100644
--- a/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc
+++ b/backend/lib/Target/RISCV/RISCVGISelInteger.rccdesc
@@ -1,15 +1,5 @@
selection_rules:
-
- id: select_g_br
- priority: 100
- match:
- opcode: G_BR
- apply:
- instructions:
- - opcode: PseudoBR
- root: true
- operands: [{ operand: 0 }]
- -
id: select_g_implicit_def
priority: 100
match:
diff --git a/backend/utils/TableGen/Common/CodeGenSelection.cpp b/backend/utils/TableGen/Common/CodeGenSelection.cpp
index 95a924f..df9bf7b 100644
--- a/backend/utils/TableGen/Common/CodeGenSelection.cpp
+++ b/backend/utils/TableGen/Common/CodeGenSelection.cpp
@@ -355,9 +355,22 @@ bool CodeGenTarget::normalizeSelectionRules(NormalizedTargetModel &Result) {
NormalizedSelectionDefUsePredicate NormalizedPredicate{
.RootOperandIndex = Predicate.RootOperandIndex,
.Opcode = *DefOpcode,
+ .IntegerPredicate = std::nullopt,
.Captures = {},
.OperandDefConstants = {},
};
+ if (Predicate.IntegerPredicate) {
+ const auto Integer = integerPredicateValue(Predicate.IntegerPredicate->Predicate);
+ if (!Integer) {
+ fail(Predicate.IntegerPredicate->Range,
+ "selection def-use integer predicate is not a recognized integer predicate");
+ return false;
+ }
+ NormalizedPredicate.IntegerPredicate = {
+ .OperandIndex = Predicate.IntegerPredicate->OperandIndex,
+ .Predicate = *Integer,
+ };
+ }
std::unordered_set<std::uint32_t> CapturedOperands;
for (const SourceSelectionDefUseCapture &Capture : Predicate.Captures) {
if (!isIdentifier(Capture.Symbol) ||
@@ -390,7 +403,9 @@ bool CodeGenTarget::normalizeSelectionRules(NormalizedTargetModel &Result) {
});
}
Normalized.DefUsePredicates.push_back(std::move(NormalizedPredicate));
- Normalized.Specificity += 1U + static_cast<std::uint32_t>(Predicate.Captures.size()) +
+ Normalized.Specificity += 1U +
+ static_cast<std::uint32_t>(Predicate.IntegerPredicate.has_value()) +
+ static_cast<std::uint32_t>(Predicate.Captures.size()) +
static_cast<std::uint32_t>(Predicate.OperandDefConstants.size());
}
diff --git a/backend/utils/TableGen/Common/CodeGenTarget.h b/backend/utils/TableGen/Common/CodeGenTarget.h
index d66cfee..97e1447 100644
--- a/backend/utils/TableGen/Common/CodeGenTarget.h
+++ b/backend/utils/TableGen/Common/CodeGenTarget.h
@@ -217,6 +217,7 @@ struct NormalizedSelectionDefUseCapture final {
struct NormalizedSelectionDefUsePredicate final {
std::uint32_t RootOperandIndex = 0;
std::uint32_t Opcode = 0;
+ std::optional<NormalizedSelectionIntegerPredicate> IntegerPredicate;
std::vector<NormalizedSelectionDefUseCapture> Captures;
std::vector<NormalizedSelectionOperandDefConstantPredicate> OperandDefConstants;
};
diff --git a/backend/utils/TableGen/GlobalISelEmitter.cpp b/backend/utils/TableGen/GlobalISelEmitter.cpp
index 98568b1..d73d691 100644
--- a/backend/utils/TableGen/GlobalISelEmitter.cpp
+++ b/backend/utils/TableGen/GlobalISelEmitter.cpp
@@ -47,7 +47,8 @@ void emitTypePredicate(std::ostream &Output, std::uint32_t OperandIndex,
Rule.OperandImmediates.size() + Rule.OperandDefConstants.size() +
Rule.Temporaries.size() + Rule.EraseOperandDefinitions.size();
for (const NormalizedSelectionDefUsePredicate &Predicate : Rule.DefUsePredicates)
- Count += 1U + Predicate.Captures.size() + Predicate.OperandDefConstants.size();
+ Count += 1U + static_cast<std::size_t>(Predicate.IntegerPredicate.has_value()) +
+ Predicate.Captures.size() + Predicate.OperandDefConstants.size();
for (const NormalizedSelectionAction &Action : Rule.Actions)
Count += 1U + Action.OperandRenderers.size();
return Count;
@@ -137,6 +138,11 @@ std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view
}
for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) {
emitInstruction(Output, "CheckOperandDefOpcode", DefUse.RootOperandIndex, DefUse.Opcode);
+ if (DefUse.IntegerPredicate) {
+ emitInstruction(Output, "CheckOperandDefIntegerPredicate", DefUse.RootOperandIndex,
+ DefUse.IntegerPredicate->Predicate,
+ std::to_string(DefUse.IntegerPredicate->OperandIndex));
+ }
for (const NormalizedSelectionOperandDefConstantPredicate &Predicate :
DefUse.OperandDefConstants) {
emitInstruction(Output, "CheckOperandDefOperandConstantRanges", DefUse.RootOperandIndex,