aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 17:28:49 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 17:28:49 +0800
commit864a29abbdce86353ec91c3587757711d3a42f10 (patch)
tree772390cad70fe8e47044f5c921174b254bd8297a /backend/lib/Target
parentca25d25d4c5131491a50b1a94e63e9b2d3c34ed4 (diff)
downloadrcc-project-864a29abbdce86353ec91c3587757711d3a42f10.tar.gz
rcc-project-864a29abbdce86353ec91c3587757711d3a42f10.tar.xz
[RISCV][GlobalISel] Generate integer comparisons
Diffstat (limited to 'backend/lib/Target')
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp176
-rw-r--r--backend/lib/Target/RISCV/RISCVGISel.rccdesc652
2 files changed, 635 insertions, 193 deletions
diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 68574a3..38ef1af 100644
--- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -268,7 +268,6 @@ public:
case GenericOpcode::G_SEXT:
case GenericOpcode::G_SEXT_INREG:
case GenericOpcode::G_ZEXT:
- case GenericOpcode::G_ICMP:
case GenericOpcode::G_FCMP:
case GenericOpcode::G_FPEXT:
case GenericOpcode::G_FPTRUNC:
@@ -476,8 +475,6 @@ public:
return Instruction.setOpcode(opcode(GenericOpcode::COPY));
case GenericOpcode::G_SEXT_INREG:
return selectSignExtendInRegister(Instruction, Function, Target, Type);
- case GenericOpcode::G_ICMP:
- return selectIntegerCompare(Instruction, Function, Target);
case GenericOpcode::G_FCMP:
return selectFloatingCompare(Instruction, Function, Target);
case GenericOpcode::G_FPEXT:
@@ -748,9 +745,9 @@ private:
const TargetDescription &Target,
Register Source, LowLevelType Type,
bool Signed) const {
- if (!isSupportedIntegerScalar(Type))
+ if (!isSupportedIntegerType(Type))
return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V integer normalization requires a scalar i1-i64 type");
+ "RISC-V integer normalization requires an integer scalar or a 64-bit pointer");
const std::uint32_t Bits = Type.scalarBitWidth();
if (Bits == 64)
return Source;
@@ -1741,175 +1738,6 @@ private:
return {};
}
- [[nodiscard]] Expected<void> selectIntegerCompare(MachineInstr &Instruction,
- MachineFunction &Function,
- const TargetDescription &Target) const {
- const MachineOperand *PredicateMO = Instruction.operandAt(1);
- const auto *Predicate =
- PredicateMO == nullptr ? nullptr : PredicateMO->getIf<PredicateOperand>();
- const MachineOperand *DestinationOperand = Instruction.operandAt(0);
- const MachineOperand *LeftOperand = Instruction.operandAt(2);
- const MachineOperand *RightOperand = Instruction.operandAt(3);
- const Register *Destination =
- DestinationOperand == nullptr ? nullptr : DestinationOperand->getIf<Register>();
- const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf<Register>();
- const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf<Register>();
- const std::optional<LowLevelType> LeftType = operandType(Function, Instruction, 2);
- if (Predicate == nullptr || Predicate->integerPredicate() == nullptr ||
- Destination == nullptr || Left == nullptr || Right == nullptr || !LeftType)
- return makeUnexpected(ErrorCode::VerificationError,
- "RISC-V integer comparison has invalid operands");
- const IntegerPredicate Condition = *Predicate->integerPredicate();
- const Register DestinationRegister = *Destination;
- const bool SignedOperands = Condition == IntegerPredicate::SignedGreaterThan ||
- Condition == IntegerPredicate::SignedGreaterEqual ||
- Condition == IntegerPredicate::SignedLessThan ||
- Condition == IntegerPredicate::SignedLessEqual;
- auto LeftRegister =
- normalizeIntegerBefore(Instruction, Function, Target, *Left, *LeftType, SignedOperands);
- auto RightRegister =
- normalizeIntegerBefore(Instruction, Function, Target, *Right, *LeftType, SignedOperands);
- if (!LeftRegister || !RightRegister)
- return std::unexpected(!LeftRegister ? LeftRegister.error() : RightRegister.error());
- auto ErasePredicate = Instruction.eraseOperand(1);
- if (!ErasePredicate)
- return std::unexpected(ErasePredicate.error());
-
- const auto SetSources = [&Instruction](Register NewLeft, Register NewRight) -> Expected<void> {
- auto SetLeft = Instruction.operandAt(1)->setRegister(NewLeft);
- if (!SetLeft)
- return std::unexpected(SetLeft.error());
- return Instruction.operandAt(2)->setRegister(NewRight);
- };
- const auto StrictOpcode = [](IntegerPredicate Value) -> std::optional<InstructionOpcode> {
- switch (Value) {
- case IntegerPredicate::SignedLessThan:
- return InstructionOpcode::SLT;
- case IntegerPredicate::UnsignedLessThan:
- return InstructionOpcode::SLTU;
- default:
- return std::nullopt;
- }
- };
-
- IntegerPredicate StrictCondition = Condition;
- bool Swap = false;
- bool Invert = false;
- switch (Condition) {
- case IntegerPredicate::Equal:
- case IntegerPredicate::NotEqual:
- break;
- case IntegerPredicate::SignedGreaterThan:
- StrictCondition = IntegerPredicate::SignedLessThan;
- Swap = true;
- break;
- case IntegerPredicate::SignedGreaterEqual:
- StrictCondition = IntegerPredicate::SignedLessThan;
- Invert = true;
- break;
- case IntegerPredicate::SignedLessThan:
- StrictCondition = IntegerPredicate::SignedLessThan;
- break;
- case IntegerPredicate::SignedLessEqual:
- StrictCondition = IntegerPredicate::SignedLessThan;
- Swap = true;
- Invert = true;
- break;
- case IntegerPredicate::UnsignedGreaterThan:
- StrictCondition = IntegerPredicate::UnsignedLessThan;
- Swap = true;
- break;
- case IntegerPredicate::UnsignedGreaterEqual:
- StrictCondition = IntegerPredicate::UnsignedLessThan;
- Invert = true;
- break;
- case IntegerPredicate::UnsignedLessThan:
- StrictCondition = IntegerPredicate::UnsignedLessThan;
- break;
- case IntegerPredicate::UnsignedLessEqual:
- StrictCondition = IntegerPredicate::UnsignedLessThan;
- Swap = true;
- Invert = true;
- break;
- case IntegerPredicate::Count:
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V integer comparison predicate is invalid");
- }
-
- MachineIRBuilder Builder(Function, Target);
- if (Condition == IntegerPredicate::Equal || Condition == IntegerPredicate::NotEqual) {
- auto Temporary = createTemporary(Function, *LeftType, Target);
- if (!Temporary)
- return std::unexpected(Temporary.error());
- auto SetDestination = Instruction.operandAt(0)->setRegister(*Temporary);
- if (!SetDestination)
- return std::unexpected(SetDestination.error());
- auto Set = SetSources(*LeftRegister, *RightRegister);
- if (!Set)
- return std::unexpected(Set.error());
- auto SetOpcode = Instruction.setOpcode(instructionOpcode(InstructionOpcode::XOR));
- if (!SetOpcode)
- return std::unexpected(SetOpcode.error());
- if (Condition == IntegerPredicate::Equal) {
- auto Result = buildImmediateAfter(Builder, Instruction, InstructionOpcode::SLTIU,
- DestinationRegister, *Temporary, 1);
- if (!Result)
- return std::unexpected(Result.error());
- } else {
- auto Zero = physicalRegister(PhysicalRegisterID::X0);
- if (!Zero)
- return std::unexpected(Zero.error());
- auto Result =
- buildBinaryAfter(Builder, Instruction, InstructionOpcode::SLTU, DestinationRegister,
- Register::fromPhysical(*Zero), *Temporary);
- if (!Result)
- return std::unexpected(Result.error());
- }
- return {};
- }
-
- const std::optional<InstructionOpcode> OpcodeValue = StrictOpcode(StrictCondition);
- if (!OpcodeValue)
- return makeUnexpected(ErrorCode::Unsupported,
- "RISC-V integer comparison predicate is invalid");
- if (Invert) {
- auto Temporary = createTemporary(Function, *LeftType, Target);
- if (!Temporary)
- return std::unexpected(Temporary.error());
- auto SetDestination = Instruction.operandAt(0)->setRegister(*Temporary);
- if (!SetDestination)
- return std::unexpected(SetDestination.error());
- const Register Base = *Temporary;
- if (Swap) {
- auto Set = SetSources(*RightRegister, *LeftRegister);
- if (!Set)
- return std::unexpected(Set.error());
- } else {
- auto Set = SetSources(*LeftRegister, *RightRegister);
- if (!Set)
- return std::unexpected(Set.error());
- }
- auto SetOpcode = Instruction.setOpcode(instructionOpcode(*OpcodeValue));
- if (!SetOpcode)
- return std::unexpected(SetOpcode.error());
- auto Result = buildImmediateAfter(Builder, Instruction, InstructionOpcode::XORI,
- DestinationRegister, Base, 1);
- if (!Result)
- return std::unexpected(Result.error());
- return {};
- }
- if (Swap) {
- auto Set = SetSources(*RightRegister, *LeftRegister);
- if (!Set)
- return std::unexpected(Set.error());
- } else {
- auto Set = SetSources(*LeftRegister, *RightRegister);
- if (!Set)
- return std::unexpected(Set.error());
- }
- return Instruction.setOpcode(instructionOpcode(*OpcodeValue));
- }
-
[[nodiscard]] Expected<void> selectFloatingCompare(MachineInstr &Instruction,
MachineFunction &Function,
const TargetDescription &Target) const {
diff --git a/backend/lib/Target/RISCV/RISCVGISel.rccdesc b/backend/lib/Target/RISCV/RISCVGISel.rccdesc
index bd946be..d8b0a42 100644
--- a/backend/lib/Target/RISCV/RISCVGISel.rccdesc
+++ b/backend/lib/Target/RISCV/RISCVGISel.rccdesc
@@ -12,7 +12,11 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 1, bank: GPR }
- { index: 2, bank: GPR }
- apply: { opcode: SLLW }
+ apply:
+ instructions:
+ - opcode: SLLW
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_sraw
priority: 100
@@ -26,7 +30,11 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 1, bank: GPR }
- { index: 2, bank: GPR }
- apply: { opcode: SRAW }
+ apply:
+ instructions:
+ - opcode: SRAW
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_srlw
priority: 100
@@ -40,7 +48,11 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 1, bank: GPR }
- { index: 2, bank: GPR }
- apply: { opcode: SRLW }
+ apply:
+ instructions:
+ - opcode: SRLW
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_divw
priority: 100
@@ -54,7 +66,11 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 1, bank: GPR }
- { index: 2, bank: GPR }
- apply: { opcode: DIVW }
+ apply:
+ instructions:
+ - opcode: DIVW
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_divuw
priority: 100
@@ -68,7 +84,11 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 1, bank: GPR }
- { index: 2, bank: GPR }
- apply: { opcode: DIVUW }
+ apply:
+ instructions:
+ - opcode: DIVUW
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_remuw
priority: 100
@@ -82,7 +102,11 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 1, bank: GPR }
- { index: 2, bank: GPR }
- apply: { opcode: REMUW }
+ apply:
+ instructions:
+ - opcode: REMUW
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_fcvt_w_rv64_s32
priority: 100
@@ -94,7 +118,11 @@ selection_rules:
operand_banks:
- { index: 0, bank: GPR }
- { index: 1, bank: FPR }
- apply: { opcode: FCVT_W_S }
+ apply:
+ instructions:
+ - opcode: FCVT_W_S
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_fcvt_w_rv64_s64
priority: 100
@@ -106,7 +134,11 @@ selection_rules:
operand_banks:
- { index: 0, bank: GPR }
- { index: 1, bank: FPR }
- apply: { opcode: FCVT_W_D }
+ apply:
+ instructions:
+ - opcode: FCVT_W_D
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_fcvt_wu_rv64_s32
priority: 100
@@ -118,7 +150,11 @@ selection_rules:
operand_banks:
- { index: 0, bank: GPR }
- { index: 1, bank: FPR }
- apply: { opcode: FCVT_WU_S }
+ apply:
+ instructions:
+ - opcode: FCVT_WU_S
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_fcvt_wu_rv64_s64
priority: 100
@@ -130,7 +166,11 @@ selection_rules:
operand_banks:
- { index: 0, bank: GPR }
- { index: 1, bank: FPR }
- apply: { opcode: FCVT_WU_D }
+ apply:
+ instructions:
+ - opcode: FCVT_WU_D
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }]
-
id: select_g_fclass_s32
priority: 100
@@ -142,7 +182,11 @@ selection_rules:
operand_banks:
- { index: 0, bank: GPR }
- { index: 1, bank: FPR }
- apply: { opcode: FCLASS_S }
+ apply:
+ instructions:
+ - opcode: FCLASS_S
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }]
-
id: select_g_fclass_s64
priority: 100
@@ -154,10 +198,207 @@ selection_rules:
operand_banks:
- { index: 0, bank: GPR }
- { index: 1, bank: FPR }
- apply: { opcode: FCLASS_D }
+ apply:
+ instructions:
+ - opcode: FCLASS_D
+ root: true
+ operands: [{ operand: 0 }, { operand: 1 }]
+ -
+ id: select_g_icmp_eq_zero
+ priority: 500
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: eq }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: 0, max: 0 }]
+ apply:
+ instructions:
+ - opcode: SLTIU
+ root: true
+ operands: [{ operand: 0 }, { operand: 2 }, { immediate: 1 }]
+ erase_operand_definitions: [3]
-
id: select_g_icmp_ne_zero
- priority: 200
+ priority: 500
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ne }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: 0, max: 0 }]
+ apply:
+ instructions:
+ - opcode: SLTU
+ root: true
+ operands:
+ - { operand: 0 }
+ - { physical_register: X0, flags: [use] }
+ - { operand: 2 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_ult_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ult }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ instructions:
+ - opcode: SLTIU
+ root: true
+ operands:
+ - { operand: 0 }
+ - { operand: 2 }
+ - { captured_immediate: 3 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_slt_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: slt }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ instructions:
+ - opcode: SLTI
+ root: true
+ operands:
+ - { operand: 0 }
+ - { operand: 2 }
+ - { captured_immediate: 3 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_ugt_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ugt }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges:
+ - { min: -2049, max: -2 }
+ - { min: 1, max: 2046 }
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLTIU
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 2 }
+ - { captured_immediate: 3, transform: plus_one }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_sgt_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: sgt }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges:
+ - { min: -2049, max: -1 }
+ - { min: 1, max: 2046 }
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLTI
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 2 }
+ - { captured_immediate: 3, transform: plus_one }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_eq_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: eq }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: -2047, max: 2048 }]
+ apply:
+ temporaries:
+ - { id: difference, type_from_operand: 2 }
+ instructions:
+ - opcode: ADDI
+ root: true
+ operands:
+ - { temporary: difference, flags: [define] }
+ - { operand: 2 }
+ - { captured_immediate: 3, transform: negate }
+ - opcode: SLTIU
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: difference, flags: [use] }
+ - { immediate: 1 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_ne_immediate
+ priority: 400
match:
opcode: G_ICMP
result_type: { kind: scalar, bits: 64 }
@@ -168,11 +409,384 @@ selection_rules:
- { index: 0, bank: GPR }
- { index: 2, bank: GPR }
operand_def_constants:
- - { index: 3, value: 0 }
+ - index: 3
+ ranges: [{ min: -2047, max: 2048 }]
+ apply:
+ temporaries:
+ - { id: difference, type_from_operand: 2 }
+ instructions:
+ - opcode: ADDI
+ root: true
+ operands:
+ - { temporary: difference, flags: [define] }
+ - { operand: 2 }
+ - { captured_immediate: 3, transform: negate }
+ - opcode: SLTU
+ root: false
+ operands:
+ - { operand: 0 }
+ - { physical_register: X0, flags: [use] }
+ - { temporary: difference, flags: [use] }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_ule_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ule }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges:
+ - { min: -2049, max: -2 }
+ - { min: 1, max: 2046 }
+ apply:
+ instructions:
+ - opcode: SLTIU
+ root: true
+ operands:
+ - { operand: 0 }
+ - { operand: 2 }
+ - { captured_immediate: 3, transform: plus_one }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_sle_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: sle }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges:
+ - { min: -2049, max: -1 }
+ - { min: 1, max: 2046 }
+ apply:
+ instructions:
+ - opcode: SLTI
+ root: true
+ operands:
+ - { operand: 0 }
+ - { operand: 2 }
+ - { captured_immediate: 3, transform: plus_one }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_uge_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: uge }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: -2048, max: 2047 }]
apply:
- opcode: SLTU
- operands:
- - { operand: 0 }
- - { physical_register: X0, flags: [use] }
- - { operand: 2 }
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLTIU
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 2 }
+ - { captured_immediate: 3 }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_sge_immediate
+ priority: 400
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: sge }
+ operand_types:
+ - { index: 2, kind: scalar, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ operand_def_constants:
+ - index: 3
+ ranges: [{ min: -2048, max: 2047 }]
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLTI
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 2 }
+ - { captured_immediate: 3 }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
+ erase_operand_definitions: [3]
+ -
+ id: select_g_icmp_ult_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ult }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ instructions:
+ - opcode: SLTU
+ root: true
+ operands: [{ operand: 0 }, { operand: 2 }, { operand: 3 }]
+ -
+ id: select_g_icmp_slt_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: slt }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ instructions:
+ - opcode: SLT
+ root: true
+ operands: [{ operand: 0 }, { operand: 2 }, { operand: 3 }]
+ -
+ id: select_g_icmp_ugt_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ugt }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ instructions:
+ - opcode: SLTU
+ root: true
+ operands: [{ operand: 0 }, { operand: 3 }, { operand: 2 }]
+ -
+ id: select_g_icmp_sgt_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: sgt }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ instructions:
+ - opcode: SLT
+ root: true
+ operands: [{ operand: 0 }, { operand: 3 }, { operand: 2 }]
+ -
+ id: select_g_icmp_eq_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: eq }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ temporaries:
+ - { id: difference, type_from_operand: 2 }
+ instructions:
+ - opcode: XOR
+ root: true
+ operands:
+ - { temporary: difference, flags: [define] }
+ - { operand: 2 }
+ - { operand: 3 }
+ - opcode: SLTIU
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: difference, flags: [use] }
+ - { immediate: 1 }
+ -
+ id: select_g_icmp_ne_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ne }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ temporaries:
+ - { id: difference, type_from_operand: 2 }
+ instructions:
+ - opcode: XOR
+ root: true
+ operands:
+ - { temporary: difference, flags: [define] }
+ - { operand: 2 }
+ - { operand: 3 }
+ - opcode: SLTU
+ root: false
+ operands:
+ - { operand: 0 }
+ - { physical_register: X0, flags: [use] }
+ - { temporary: difference, flags: [use] }
+ -
+ id: select_g_icmp_ule_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: ule }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLTU
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 3 }
+ - { operand: 2 }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
+ -
+ id: select_g_icmp_sle_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: sle }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLT
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 3 }
+ - { operand: 2 }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
+ -
+ id: select_g_icmp_uge_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: uge }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLTU
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 2 }
+ - { operand: 3 }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }
+ -
+ id: select_g_icmp_sge_register
+ priority: 100
+ match:
+ opcode: G_ICMP
+ result_type: { kind: scalar, bits: 64 }
+ integer_predicate: { index: 1, value: sge }
+ operand_types:
+ - { index: 2, kind: any, bits: 64 }
+ operand_banks:
+ - { index: 0, bank: GPR }
+ - { index: 2, bank: GPR }
+ - { index: 3, bank: GPR }
+ apply:
+ temporaries:
+ - { id: compare, type_from_operand: 2 }
+ instructions:
+ - opcode: SLT
+ root: true
+ operands:
+ - { temporary: compare, flags: [define] }
+ - { operand: 2 }
+ - { operand: 3 }
+ - opcode: XORI
+ root: false
+ operands:
+ - { operand: 0 }
+ - { temporary: compare, flags: [use] }
+ - { immediate: 1 }