aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'backend/lib/Target')
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp76
-rw-r--r--backend/lib/Target/RISCV/RISCVGISelFloating.rccdesc126
2 files changed, 154 insertions, 48 deletions
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<Register>();
+ if (Source == nullptr || !Source->isVirtual())
+ return std::optional<GIMatchComplexOperand>{};
+ 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<MachineOperand> 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<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/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
@@ -280,6 +280,132 @@ selection_rules:
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
match: