diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-16 17:28:49 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-16 17:28:49 +0800 |
| commit | 864a29abbdce86353ec91c3587757711d3a42f10 (patch) | |
| tree | 772390cad70fe8e47044f5c921174b254bd8297a /backend/lib/Target/RISCV | |
| parent | ca25d25d4c5131491a50b1a94e63e9b2d3c34ed4 (diff) | |
| download | rcc-project-864a29abbdce86353ec91c3587757711d3a42f10.tar.gz rcc-project-864a29abbdce86353ec91c3587757711d3a42f10.tar.xz | |
[RISCV][GlobalISel] Generate integer comparisons
Diffstat (limited to 'backend/lib/Target/RISCV')
| -rw-r--r-- | backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 176 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/RISCVGISel.rccdesc | 652 |
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 } |
