From 4d285efa781e2ceb4a65f7b4b06015a8ea86bb8c Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sun, 16 Aug 2026 20:29:40 +0800 Subject: [RISCV][GlobalISel] Generate copy sign selections --- .../RISCV/GISel/RISCVInstructionSelector.cpp | 76 +++++-------- .../lib/Target/RISCV/RISCVGISelFloating.rccdesc | 126 +++++++++++++++++++++ 2 files changed, 154 insertions(+), 48 deletions(-) (limited to 'backend/lib/Target') diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index d9e3fce..29cc77c 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -157,6 +157,34 @@ public: renderComplexOperand(std::string_view Name, const MachineInstr &Instruction, const MachineFunction &Function, const TargetDescription &Target, std::uint32_t OperandIndex) const override { + if (Name == "fcopysign_to_s32" || Name == "fcopysign_to_s64") { + const MachineOperand *SourceOperand = Instruction.operandAt(OperandIndex); + const Register *Source = + SourceOperand == nullptr ? nullptr : SourceOperand->getIf(); + if (Source == nullptr || !Source->isVirtual()) + return std::optional{}; + const std::uint32_t DestinationWidth = Name == "fcopysign_to_s32" ? 32U : 64U; + auto DestinationType = LowLevelType::makeCategoryNeutralScalar(DestinationWidth); + if (!DestinationType) + return std::unexpected(DestinationType.error()); + auto SourceUse = MachineOperand::registerOperand(*Source, {RegisterOperandFlag::Use}); + if (!SourceUse) + return std::unexpected(SourceUse.error()); + std::vector Operands; + Operands.push_back(std::move(*SourceUse)); + Operands.push_back(MachineOperand::immediate(DestinationWidth == 32 ? 7 : 0)); + return GIMatchComplexOperand{ + .Operand = std::nullopt, + .Instruction = + GIMatchComplexInstruction{ + .ResultOpcode = + instructionOpcode(DestinationWidth == 32 ? InstructionOpcode::FCVT_S_D + : InstructionOpcode::FCVT_D_S), + .ResultType = *DestinationType, + .Operands = std::move(Operands), + }, + }; + } const std::uint64_t ShiftWidth = Name == "shift_mask_xlen" ? 64U : Name == "shift_mask_32" ? 32U : 0U; @@ -329,11 +357,6 @@ public: case GenericOpcode::G_BR: case GenericOpcode::G_BRCOND: return {}; - case GenericOpcode::G_FCOPYSIGN: - if (!Float()) - return makeUnexpected(ErrorCode::Unsupported, - "RISC-V selector requires f32 or f64 floating values"); - return {}; case GenericOpcode::G_FCONSTANT: { const MachineOperand *Immediate = Instruction.operandAt(1); const auto *Floating = @@ -447,8 +470,6 @@ public: case GenericOpcode::G_PTRTOINT: case GenericOpcode::G_INTTOPTR: return Instruction.setOpcode(opcode(GenericOpcode::COPY)); - case GenericOpcode::G_FCOPYSIGN: - return selectCopySign(Instruction, Function, Target, Type); case GenericOpcode::G_ANYEXT: case GenericOpcode::G_SEXT: case GenericOpcode::G_ZEXT: @@ -1738,47 +1759,6 @@ private: "RISC-V floating comparison predicate is invalid"); } - [[nodiscard]] Expected selectCopySign(MachineInstr &Instruction, MachineFunction &Function, - const TargetDescription &Target, - std::optional Type) const { - const MachineOperand *SignOperand = Instruction.operandAt(2); - const Register *SignRegister = - SignOperand == nullptr ? nullptr : SignOperand->getIf(); - const std::optional SignType = operandType(Function, Instruction, 2); - if (!Type || !SignType || SignRegister == nullptr || !Type->isCategoryNeutralScalar() || - !SignType->isCategoryNeutralScalar()) { - return makeUnexpected(ErrorCode::VerificationError, - "RISC-V floating copy-sign has invalid operand types"); - } - - const std::uint32_t ResultWidth = Type->scalarBitWidth(); - const std::uint32_t SignWidth = SignType->scalarBitWidth(); - if ((ResultWidth != 32 && ResultWidth != 64) || (SignWidth != 32 && SignWidth != 64)) { - return makeUnexpected(ErrorCode::Unsupported, - "RISC-V cannot select this floating copy-sign type"); - } - - if (ResultWidth != SignWidth) { - auto Temporary = createTemporary(Function, *Type, Target, fprBank()); - if (!Temporary) - return std::unexpected(Temporary.error()); - MachineIRBuilder Builder(Function, Target); - const InstructionOpcode Conversion = - ResultWidth == 32 ? InstructionOpcode::FCVT_S_D : InstructionOpcode::FCVT_D_S; - const std::int64_t RoundingMode = ResultWidth == 32 ? 7 : 0; - auto Built = buildImmediateBefore(Builder, Instruction, Conversion, *Temporary, *SignRegister, - RoundingMode); - if (!Built) - return std::unexpected(Built.error()); - auto ReplaceSign = Instruction.operandAt(2)->setRegister(*Temporary); - if (!ReplaceSign) - return std::unexpected(ReplaceSign.error()); - } - - return Instruction.setOpcode(instructionOpcode(ResultWidth == 32 ? InstructionOpcode::FSGNJ_S - : InstructionOpcode::FSGNJ_D)); - } - [[nodiscard]] Expected selectFence(MachineInstr &Instruction) const { const auto Ordering = signedImmediate(*Instruction.operandAt(0)); if (!Ordering) diff --git a/backend/lib/Target/RISCV/RISCVGISelFloating.rccdesc b/backend/lib/Target/RISCV/RISCVGISelFloating.rccdesc index ff8c613..bcf12c0 100644 --- a/backend/lib/Target/RISCV/RISCVGISelFloating.rccdesc +++ b/backend/lib/Target/RISCV/RISCVGISelFloating.rccdesc @@ -279,6 +279,132 @@ selection_rules: - opcode: FSGNJX_D root: true operands: [{ operand: 0 }, { operand: 1 }, { operand: 1 }] + - + id: select_g_fcopysign_s32_fneg + priority: 200 + match: + opcode: G_FCOPYSIGN + result_type: { kind: scalar, bits: 32 } + operand_types: + - { index: 1, kind: scalar, bits: 32 } + - { index: 2, kind: scalar, bits: 32 } + operand_banks: + - { index: 0, bank: FPR } + - { index: 1, bank: FPR } + - { index: 2, bank: FPR } + def_use: + - operand: 2 + opcode: G_FNEG + captures: + - { id: sign, operand: 1 } + apply: + instructions: + - opcode: FSGNJN_S + root: true + operands: [{ operand: 0 }, { operand: 1 }, { captured_operand: sign }] + erase_operand_definitions: [2] + - + id: select_g_fcopysign_s64_fneg + priority: 200 + match: + opcode: G_FCOPYSIGN + result_type: { kind: scalar, bits: 64 } + operand_types: + - { index: 1, kind: scalar, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: FPR } + - { index: 1, bank: FPR } + - { index: 2, bank: FPR } + def_use: + - operand: 2 + opcode: G_FNEG + captures: + - { id: sign, operand: 1 } + apply: + instructions: + - opcode: FSGNJN_D + root: true + operands: [{ operand: 0 }, { operand: 1 }, { captured_operand: sign }] + erase_operand_definitions: [2] + - + id: select_g_fcopysign_s32_s32 + priority: 100 + match: + opcode: G_FCOPYSIGN + result_type: { kind: scalar, bits: 32 } + operand_types: + - { index: 1, kind: scalar, bits: 32 } + - { index: 2, kind: scalar, bits: 32 } + operand_banks: + - { index: 0, bank: FPR } + - { index: 1, bank: FPR } + - { index: 2, bank: FPR } + apply: + instructions: + - opcode: FSGNJ_S + root: true + operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }] + - + id: select_g_fcopysign_s64_s64 + priority: 100 + match: + opcode: G_FCOPYSIGN + result_type: { kind: scalar, bits: 64 } + operand_types: + - { index: 1, kind: scalar, bits: 64 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: FPR } + - { index: 1, bank: FPR } + - { index: 2, bank: FPR } + apply: + instructions: + - opcode: FSGNJ_D + root: true + operands: [{ operand: 0 }, { operand: 1 }, { operand: 2 }] + - + id: select_g_fcopysign_s32_s64 + priority: 100 + match: + opcode: G_FCOPYSIGN + result_type: { kind: scalar, bits: 32 } + operand_types: + - { index: 1, kind: scalar, bits: 32 } + - { index: 2, kind: scalar, bits: 64 } + operand_banks: + - { index: 0, bank: FPR } + - { index: 1, bank: FPR } + - { index: 2, bank: FPR } + apply: + instructions: + - opcode: FSGNJ_S + root: true + operands: + - { operand: 0 } + - { operand: 1 } + - { complex: fcopysign_to_s32, operand: 2 } + - + id: select_g_fcopysign_s64_s32 + priority: 100 + match: + opcode: G_FCOPYSIGN + result_type: { kind: scalar, bits: 64 } + operand_types: + - { index: 1, kind: scalar, bits: 64 } + - { index: 2, kind: scalar, bits: 32 } + operand_banks: + - { index: 0, bank: FPR } + - { index: 1, bank: FPR } + - { index: 2, bank: FPR } + apply: + instructions: + - opcode: FSGNJ_D + root: true + operands: + - { operand: 0 } + - { operand: 1 } + - { complex: fcopysign_to_s64, operand: 2 } - id: select_g_fminnum_s32 priority: 100 -- cgit v1.2.3