diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-16 01:50:40 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-16 01:50:40 +0800 |
| commit | 0146ac880f8acac482be73a23aac99ad37452c20 (patch) | |
| tree | 39e32576f81e65f729f3b24bbfdc8ac9cfea2f68 /backend | |
| parent | 1be07c7af115630d26dd36da4ac4905190377a0e (diff) | |
| download | rcc-project-0146ac880f8acac482be73a23aac99ad37452c20.tar.gz rcc-project-0146ac880f8acac482be73a23aac99ad37452c20.tar.xz | |
[RISCV][GlobalISel] Select mixed-width copy-sign
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 44 | ||||
| -rw-r--r-- | backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp | 4 |
2 files changed, 44 insertions, 4 deletions
diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index 1d7aec2..099de83 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -492,8 +492,7 @@ public: return selectSignInjection(Instruction, Type, InstructionOpcode::FSGNJX_S, InstructionOpcode::FSGNJX_D); case GenericOpcode::G_FCOPYSIGN: - return selectFloatingMinMax(Instruction, Type, InstructionOpcode::FSGNJ_S, - InstructionOpcode::FSGNJ_D); + return selectCopySign(Instruction, Function, Target, Type); case GenericOpcode::G_ANYEXT: case GenericOpcode::G_SEXT: case GenericOpcode::G_ZEXT: @@ -2171,6 +2170,47 @@ private: "RISC-V cannot select this floating min/max type"); } + [[nodiscard]] Expected<void> selectCopySign(MachineInstr &Instruction, MachineFunction &Function, + const TargetDescription &Target, + std::optional<LowLevelType> Type) const { + const MachineOperand *SignOperand = Instruction.operandAt(2); + const Register *SignRegister = + SignOperand == nullptr ? nullptr : SignOperand->getIf<Register>(); + const std::optional<LowLevelType> 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<void> selectFence(MachineInstr &Instruction) const { const auto Ordering = signedImmediate(*Instruction.operandAt(0)); if (!Ordering) diff --git a/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp b/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp index 66a3371..c299ccb 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp @@ -265,8 +265,8 @@ RISCVRegisterBankInfo::selectBank(const MachineFunction &Function, Register Reg, if (!Required) return std::unexpected(Required.error()); const bool IsConstrained = Required->has_value() || Info.Bank.has_value(); - const RegisterBankID Selected = Required->value_or(gprBank()); - if (Info.Bank && *Info.Bank != Selected) { + const RegisterBankID Selected = Required->value_or(Info.Bank.value_or(gprBank())); + if (Info.Bank && Required->has_value() && *Info.Bank != Selected) { return makeUnexpected(ErrorCode::VerificationError, "RISC-V virtual register has a conflicting register bank"); } |
