[llvm] [Hexagon] Add new register input/output types for qf instructions (PR #184398)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 3 12:58:15 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-hexagon
Author: Fateme Hosseini (fhossein-quic)
<details>
<summary>Changes</summary>
The v81 iset has been updated with input and output register
types/extensions for instructions. Currently, it supports qf32/qf16
register types. This patch implements a qf reg type lookup to query
these types. In the future, the register type extractor can be improved
and more APIs can be added to support other register types.
Co-authored-by: <santdas@<!-- -->qti.qualcomm.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/184398.diff
3 Files Affected:
- (modified) llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp (+166)
- (modified) llvm/lib/Target/Hexagon/HexagonInstrInfo.h (+11)
- (modified) llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h (+32)
``````````diff
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
index 9f511efdfb461..a6ec800809f3e 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -4783,6 +4783,172 @@ bool HexagonInstrInfo::isQFPMul(const MachineInstr *MI) const {
MI->getOpcode() == Hexagon::V6_vmpy_qf32);
}
+namespace llvm::HexagonII {
+
+static constexpr RegTypeInfo make(RegType Out, RegType In1 = RegType::Unknown,
+ RegType In2 = RegType::Unknown,
+ RegType In3 = RegType::Unknown) {
+ RegTypeInfo I;
+ I.Output = Out;
+ I.Input1 = In1;
+ I.Input2 = In2;
+ I.Input3 = In3;
+ return I;
+}
+
+RegTypeInfo getRegTypeInfo(unsigned Opcode) {
+ switch (Opcode) {
+ default:
+ return {};
+
+ // Generated from qf reg-type metadata.
+ case Hexagon::V6_vabs_qf16_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vabs_qf16_qf16:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vabs_qf32_qf32:
+ return make(RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vabs_qf32_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vadd_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vadd_qf16:
+ return make(RegType::QF16, RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vadd_qf16_mix:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vadd_qf32:
+ return make(RegType::QF32, RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vadd_qf32_mix:
+ return make(RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vadd_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vconv_bf_qf32:
+ return make(RegType::Unknown, RegType::QF32);
+ case Hexagon::V6_vconv_f8_qf16:
+ return make(RegType::Unknown, RegType::QF16);
+ case Hexagon::V6_vconv_hf_qf16:
+ return make(RegType::Unknown, RegType::QF16);
+ case Hexagon::V6_vconv_hf_qf32:
+ return make(RegType::Unknown, RegType::QF32);
+ case Hexagon::V6_vconv_qf16_f8:
+ return make(RegType::QF16);
+ case Hexagon::V6_vconv_qf16_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vconv_qf16_qf16:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vconv_qf32_qf32:
+ return make(RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vconv_qf32_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vconv_sf_qf32:
+ return make(RegType::Unknown, RegType::QF32);
+ case Hexagon::V6_vilog2_qf16:
+ return make(RegType::Unknown, RegType::QF16);
+ case Hexagon::V6_vilog2_qf32:
+ return make(RegType::Unknown, RegType::QF32);
+ case Hexagon::V6_vmpy_qf16:
+ return make(RegType::QF16, RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vmpy_qf16_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vmpy_qf16_mix_hf:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vmpy_qf32:
+ return make(RegType::QF32, RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vmpy_qf32_hf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vmpy_qf32_mix_hf:
+ return make(RegType::QF32, RegType::QF16);
+ case Hexagon::V6_vmpy_qf32_qf16:
+ return make(RegType::QF32, RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vmpy_qf32_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vmpy_rt_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vmpy_rt_qf16:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vmpy_rt_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vneg_qf16_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vneg_qf16_qf16:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vneg_qf32_qf32:
+ return make(RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vneg_qf32_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vsub_hf:
+ return make(RegType::QF16);
+ case Hexagon::V6_vsub_qf16:
+ return make(RegType::QF16, RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vsub_qf16_mix:
+ return make(RegType::QF16, RegType::QF16);
+ case Hexagon::V6_vsub_qf32:
+ return make(RegType::QF32, RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vsub_qf32_mix:
+ return make(RegType::QF32, RegType::QF32);
+ case Hexagon::V6_vsub_sf:
+ return make(RegType::QF32);
+ case Hexagon::V6_vsub_sf_mix:
+ return make(RegType::QF32, RegType::Unknown, RegType::QF32);
+ case Hexagon::V6_vsub_hf_mix:
+ return make(RegType::QF16, RegType::Unknown, RegType::QF16);
+ }
+}
+
+} // namespace llvm::HexagonII
+
+bool HexagonInstrInfo::usesQF32Operand(MachineInstr *MI, unsigned Index) const {
+ auto Info = HexagonII::getRegTypeInfo(MI->getOpcode());
+ switch (Index) {
+ case 1:
+ return Info.Input1 == HexagonII::RegType::QF32;
+ case 2:
+ return Info.Input2 == HexagonII::RegType::QF32;
+ case 3:
+ return Info.Input3 == HexagonII::RegType::QF32;
+ case 0:
+ return Info.Input1 == HexagonII::RegType::QF32 ||
+ Info.Input2 == HexagonII::RegType::QF32 ||
+ Info.Input3 == HexagonII::RegType::QF32;
+ default:
+ llvm_unreachable("Incorrect input machine operand index encountered!");
+ }
+}
+
+bool HexagonInstrInfo::usesQF16Operand(MachineInstr *MI, unsigned Index) const {
+ auto Info = HexagonII::getRegTypeInfo(MI->getOpcode());
+ switch (Index) {
+ case 1:
+ return Info.Input1 == HexagonII::RegType::QF16;
+ case 2:
+ return Info.Input2 == HexagonII::RegType::QF16;
+ case 3:
+ return Info.Input3 == HexagonII::RegType::QF16;
+ case 0:
+ return Info.Input1 == HexagonII::RegType::QF16 ||
+ Info.Input2 == HexagonII::RegType::QF16 ||
+ Info.Input3 == HexagonII::RegType::QF16;
+ default:
+ llvm_unreachable("Incorrect input machine operand index encountered!");
+ }
+}
+
+bool HexagonInstrInfo::usesQFOperand(MachineInstr *MI, unsigned Index) const {
+ return usesQF32Operand(MI, Index) || usesQF16Operand(MI, Index);
+}
+
+bool HexagonInstrInfo::isQFP32Instr(MachineInstr *MI) const {
+ return HexagonII::getOpRegType(MI->getOpcode()) == HexagonII::RegType::QF32;
+}
+
+bool HexagonInstrInfo::isQFP16Instr(MachineInstr *MI) const {
+ return HexagonII::getOpRegType(MI->getOpcode()) == HexagonII::RegType::QF16;
+}
+
+bool HexagonInstrInfo::isQFPInstr(MachineInstr *MI) const {
+ return isQFP32Instr(MI) || isQFP16Instr(MI);
+}
+
// Addressing mode relations.
short HexagonInstrInfo::changeAddrMode_abs_io(short Opc) const {
return Opc >= 0 ? Hexagon::changeAddrMode_abs_io(Opc) : Opc;
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
index 4535fd6b71ef6..230f5d2228457 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
@@ -540,6 +540,17 @@ class HexagonInstrInfo : public HexagonGenInstrInfo {
MCInst getNop() const override;
bool isQFPMul(const MachineInstr *MF) const;
+
+ // Check if the instruction uses a qf32/qf16 operand.
+ // 'Index' specifies the input operand number (1..3). If 0, check any.
+ bool usesQF32Operand(MachineInstr *MI, unsigned Index = 0) const;
+ bool usesQF16Operand(MachineInstr *MI, unsigned Index = 0) const;
+ bool usesQFOperand(MachineInstr *MI, unsigned Index = 0) const;
+
+ // Check if the instruction has a qf32/qf16 output.
+ bool isQFP32Instr(MachineInstr *MI) const;
+ bool isQFP16Instr(MachineInstr *MI) const;
+ bool isQFPInstr(MachineInstr *MI) const;
};
/// \brief Create RegSubRegPair from a register MachineOperand
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
index e3094b4438e5f..3c5cf4b069ce3 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h
@@ -16,6 +16,8 @@
#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONBASEINFO_H
#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONBASEINFO_H
+#include <cstdint>
+
#include "HexagonDepITypes.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
@@ -46,6 +48,36 @@ namespace HexagonII {
HVXVectorAccess
};
+ // Represents additional operand/result register type constraints attached to
+ // specific instructions (e.g. QF register types).
+ enum class RegType : uint8_t {
+ Unknown = 0,
+ QF32,
+ QF16,
+ };
+
+ struct RegTypeInfo {
+ RegType Output = RegType::Unknown;
+ RegType Input1 = RegType::Unknown;
+ RegType Input2 = RegType::Unknown;
+ RegType Input3 = RegType::Unknown;
+ };
+
+ RegTypeInfo getRegTypeInfo(unsigned Opcode);
+
+ inline RegType getOpRegType(unsigned Opcode) {
+ return getRegTypeInfo(Opcode).Output;
+ }
+ inline RegType getInp1RegType(unsigned Opcode) {
+ return getRegTypeInfo(Opcode).Input1;
+ }
+ inline RegType getInp2RegType(unsigned Opcode) {
+ return getRegTypeInfo(Opcode).Input2;
+ }
+ inline RegType getInp3RegType(unsigned Opcode) {
+ return getRegTypeInfo(Opcode).Input3;
+ }
+
// MCInstrDesc TSFlags
// *** Must match HexagonInstrFormat*.td ***
enum {
``````````
</details>
https://github.com/llvm/llvm-project/pull/184398
More information about the llvm-commits
mailing list