[llvm] [Hexagon] Translate 6 more IEEE HVX intrinsics to QFloat (PR #227779)
Fateme Hosseini via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 1 08:56:33 PDT 2026
https://github.com/fhossein-quic updated https://github.com/llvm/llvm-project/pull/227779
>From fdb3bde1c7359867b3f780831eba604f4d7c7e7f Mon Sep 17 00:00:00 2001
From: Fateme Hosseini <fhossein at qti.qualcomm.com>
Date: Thu, 13 Aug 2026 13:26:47 -0700
Subject: [PATCH] [Hexagon] Translate 6 more IEEE HVX intrinsics to QFloat
Extend translateIEEEIntrinsicToQFloat to cover six more
HVX IEEE intrinsics on v79 and above, taking the count
from 22 to 28:
V6_vcvt_hf_sf V6_vcvt_hf_b V6_vdmpy_sf_hf
V6_vcvt_hf_uh V6_vcvt_hf_ub V6_vdmpy_sf_hf_acc
The conversions either widen through qf32 or go through
the integer pipeline with unpack/pack, then convert back
to hf with vconv. vdmpy becomes a qf32 multiply followed
by a qf32 add of the two halves; the accumulating form
folds in the incoming sf accumulator with vadd_qf32_mix.
The zero vector these sequences need is materialized
with V6_vd0 instead of a vsplat of 0, so no scalar
register is tied up producing it.
isIEEEHVXIntrinsic only lists intrinsics that have a
real translation. The remaining IEEE intrinsics keep
falling through to normal selection rather than
reaching the llvm_unreachable in the switch default.
Drop the XFAIL from two post-RA QFP tests that were
waiting on this translation.
Co-authored-by: Sumanth Gundapaneni <sgundapa at quicinc.com>
Change-Id: I1e7fc652c36e40c0a1a05f472f3fa65f62892050
---
.../Target/Hexagon/HexagonISelDAGToDAGHVX.cpp | 204 +++++++++++++++++-
.../CodeGen/Hexagon/autohvx/ieeetoqfloat.ll | 144 +++++++++++++
.../autohvx/xqf-postra-conv-double2.ll | 2 -
.../Hexagon/autohvx/xqf-postra-subreg2.ll | 2 -
4 files changed, 347 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
index 129f3071a3a884e..b11a1d378e9a232 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
@@ -3031,7 +3031,13 @@ bool HexagonDAGToDAGISel::isIEEEHVXIntrinsic(unsigned Opcode) {
Opcode == Intrinsic::hexagon_V6_vmpy_hf_hf_128B ||
Opcode == Intrinsic::hexagon_V6_vmpy_sf_sf_128B ||
Opcode == Intrinsic::hexagon_V6_vcvt_sf_hf_128B ||
- Opcode == Intrinsic::hexagon_V6_vcvt_hf_h_128B;
+ Opcode == Intrinsic::hexagon_V6_vcvt_hf_h_128B ||
+ Opcode == Intrinsic::hexagon_V6_vcvt_hf_sf_128B ||
+ Opcode == Intrinsic::hexagon_V6_vcvt_hf_uh_128B ||
+ Opcode == Intrinsic::hexagon_V6_vcvt_hf_b_128B ||
+ Opcode == Intrinsic::hexagon_V6_vcvt_hf_ub_128B ||
+ Opcode == Intrinsic::hexagon_V6_vdmpy_sf_hf_128B ||
+ Opcode == Intrinsic::hexagon_V6_vdmpy_sf_hf_acc_128B;
}
// Translate IEEE HVX intrinsics to QFloat instructions.
@@ -3464,6 +3470,202 @@ void HexagonDAGToDAGISel::translateIEEEIntrinsicToQFloat(SDNode *N,
return;
}
+ // v0.sf = vdmpy(v0.hf,v1.hf) is translated to
+ // v1:0.qf32 = vmpy(v0.hf,v1.hf); v2.qf32 = vadd(v0.sf,v1.sf);
+ // v0.sf = v2.qf32
+ case Intrinsic::hexagon_V6_vdmpy_sf_hf_128B: {
+ SDNode *MpyNode =
+ CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf, DL, ResTy,
+ N->getOperand(1), N->getOperand(2));
+ SDValue LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(MpyNode, 0));
+ SDValue HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(MpyNode, 0));
+ SDNode *AddNode =
+ CurDAG->getMachineNode(Hexagon::V6_vadd_qf32, DL, ResTy, LoReg, HiReg);
+
+ SDNode *ConvNode = CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32, DL,
+ ResTy, SDValue(AddNode, 0));
+
+ ReplaceUses(SDValue(N, 0), SDValue(ConvNode, 0));
+ CurDAG->RemoveDeadNode(N);
+ return;
+ }
+
+ // v0.sf += vdmpy(v1.hf,v2.hf) is translated to
+ // v3:2.qf32 = vmpy(v1.hf,v2.hf); v3.qf32 = vadd(v2.qf32,v3.qf32);
+ // v4.qf32 = vadd(v3.qf32,v0.sf); v0.sf = v4.qf32
+ case Intrinsic::hexagon_V6_vdmpy_sf_hf_acc_128B: {
+ SDNode *MpyNode =
+ CurDAG->getMachineNode(Hexagon::V6_vmpy_qf32_hf, DL, ResTy,
+ N->getOperand(2), N->getOperand(3));
+ SDValue LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(MpyNode, 0));
+ SDValue HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(MpyNode, 0));
+ SDNode *AddNode =
+ CurDAG->getMachineNode(Hexagon::V6_vadd_qf32, DL, ResTy, LoReg, HiReg);
+ SDNode *AccNode =
+ CurDAG->getMachineNode(Hexagon::V6_vadd_qf32_mix, DL, ResTy,
+ SDValue(AddNode, 0), N->getOperand(1));
+ SDNode *ConvNode = CurDAG->getMachineNode(Hexagon::V6_vconv_sf_qf32, DL,
+ ResTy, SDValue(AccNode, 0));
+ ReplaceUses(SDValue(N, 0), SDValue(ConvNode, 0));
+ CurDAG->RemoveDeadNode(N);
+ return;
+ }
+
+ // v0.hf = vcvt(v0.sf,v1.sf) is translated to
+ // v2 = vxor(v2,v2); v0.qf32 = vadd(v0.sf,v2.sf);
+ // v1.qf32 = vadd(v1.sf,v2.sf); v0.hf = v1:0.qf32
+ case Intrinsic::hexagon_V6_vcvt_hf_sf_128B: {
+ SDNode *ZeroNode = CurDAG->getMachineNode(Hexagon::V6_vd0, DL, ResTy);
+ SDNode *AddOp1Node = CurDAG->getMachineNode(
+ Hexagon::V6_vadd_sf, DL, ResTy, N->getOperand(1), SDValue(ZeroNode, 0));
+ SDNode *AddOp2Node = CurDAG->getMachineNode(
+ Hexagon::V6_vadd_sf, DL, ResTy, N->getOperand(2), SDValue(ZeroNode, 0));
+
+ SDValue RC =
+ CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID, DL, MVT::i32);
+ SDValue SubRegL = CurDAG->getTargetConstant(Hexagon::vsub_lo, DL, MVT::i32);
+ SDValue SubRegH = CurDAG->getTargetConstant(Hexagon::vsub_hi, DL, MVT::i32);
+ const SDValue Ops[] = {RC, SDValue(AddOp2Node, 0), SubRegH,
+ SDValue(AddOp1Node, 0), SubRegL};
+ SDNode *RS = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
+ MVT::v64i32, Ops);
+ SDNode *ConvNode = CurDAG->getMachineNode(Hexagon::V6_vconv_hf_qf32, DL,
+ ResTy, SDValue(RS, 0));
+
+ ReplaceUses(SDValue(N, 0), SDValue(ConvNode, 0));
+ CurDAG->RemoveDeadNode(N);
+ return;
+ }
+
+ // v0.hf = vcvt(v0.uh) is translated to
+ // v1 = vxor(v1,v1); v1:0.w = vadd(v0.uh,v1.uh);
+ // v2.h = vpack(v1.w,v0.w):sat; v3.h = vshuff(v2.h); v0.hf = v3.h
+ case Intrinsic::hexagon_V6_vcvt_hf_uh_128B: {
+ SDNode *ZeroNode = CurDAG->getMachineNode(Hexagon::V6_vd0, DL, ResTy);
+ SDNode *WidenAddNode = CurDAG->getMachineNode(
+ Hexagon::V6_vadduhw, DL, ResTy, N->getOperand(1), SDValue(ZeroNode, 0));
+
+ SDValue LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(WidenAddNode, 0));
+ SDValue HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(WidenAddNode, 0));
+
+ SDNode *PackNode = CurDAG->getMachineNode(Hexagon::V6_vpackwh_sat, DL,
+ ResTy, HiReg, LoReg);
+ SDNode *ShuffNode = CurDAG->getMachineNode(Hexagon::V6_vshuffh, DL, ResTy,
+ SDValue(PackNode, 0));
+ SDNode *ConvNode = CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h, DL, ResTy,
+ SDValue(ShuffNode, 0));
+
+ ReplaceUses(SDValue(N, 0), SDValue(ConvNode, 0));
+ CurDAG->RemoveDeadNode(N);
+ return;
+ }
+
+ // v1:0.hf = vcvt(v0.b) is translated to
+ // v1.h = vdeal(v0.h); v3:2.h = vunpack(v1.b) -Lower in V0, upper in V1
+ // v0.hf = v2.h; v1.hf = v3.h
+ case Intrinsic::hexagon_V6_vcvt_hf_b_128B: {
+
+ SDNode *DealNode =
+ CurDAG->getMachineNode(Hexagon::V6_vdealh, DL, ResTy, N->getOperand(1));
+
+ SDNode *UnpackNode = CurDAG->getMachineNode(Hexagon::V6_vunpackb, DL, ResTy,
+ SDValue(DealNode, 0));
+
+ SDValue LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(UnpackNode, 0));
+ SDValue HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(UnpackNode, 0));
+
+ SDNode *ConvLoNode =
+ CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h, DL, MVT::v32i32, LoReg);
+ SDNode *ConvHiNode =
+ CurDAG->getMachineNode(Hexagon::V6_vconv_hf_h, DL, MVT::v32i32, HiReg);
+
+ SDValue RC =
+ CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID, DL, MVT::i32);
+ SDValue SubRegL = CurDAG->getTargetConstant(Hexagon::vsub_lo, DL, MVT::i32);
+ SDValue SubRegH = CurDAG->getTargetConstant(Hexagon::vsub_hi, DL, MVT::i32);
+ const SDValue Ops[] = {RC, SDValue(ConvHiNode, 0), SubRegH,
+ SDValue(ConvLoNode, 0), SubRegL};
+ SDNode *RS = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
+ MVT::v64i32, Ops);
+
+ ReplaceUses(SDValue(N, 0), SDValue(RS, 0));
+ CurDAG->RemoveDeadNode(N);
+ return;
+ }
+
+ // v1:0.hf = vcvt(v0.ub) is translated to
+ // v1.h = vdeal(v0.h); v2 = vxor(v2,v2)
+ // v5:4.uh = vunpack(v1.ub) - Lower in V0, upper in V1
+ // v7:6.w = vadd(v4.uh,v2.uh); v31:30.w = vadd(v5.uh,v2.uh)
+ // v4.h = vpack(v7.w,v6.w):sat; v3.h = vpack(v31.w,v30.w):sat
+ // v30.h = vshuff(v4.h);v31.h = vshuff(v3.h)
+ // v0.hf = v30.h;v1.hf = v31.h
+ case Intrinsic::hexagon_V6_vcvt_hf_ub_128B: {
+
+ SDNode *DealNode =
+ CurDAG->getMachineNode(Hexagon::V6_vdealh, DL, ResTy, N->getOperand(1));
+ SDNode *UnpackNode = CurDAG->getMachineNode(Hexagon::V6_vunpackub, DL,
+ ResTy, SDValue(DealNode, 0));
+
+ SDValue LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(UnpackNode, 0));
+ SDValue HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(UnpackNode, 0));
+
+ SDNode *ZeroNode = CurDAG->getMachineNode(Hexagon::V6_vd0, DL, ResTy);
+
+ // Handle Lo Reg.
+ SDNode *WidenAddLoNode = CurDAG->getMachineNode(
+ Hexagon::V6_vadduhw, DL, ResTy, LoReg, SDValue(ZeroNode, 0));
+ SDValue Lo_LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(WidenAddLoNode, 0));
+ SDValue Lo_HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(WidenAddLoNode, 0));
+
+ SDNode *PackLoNode = CurDAG->getMachineNode(
+ Hexagon::V6_vpackwh_sat, DL, MVT::v32i32, Lo_HiReg, Lo_LoReg);
+ SDNode *ShufLoNode = CurDAG->getMachineNode(
+ Hexagon::V6_vshuffh, DL, MVT::v32i32, SDValue(PackLoNode, 0));
+ SDNode *ConvLoNode = CurDAG->getMachineNode(
+ Hexagon::V6_vconv_hf_h, DL, MVT::v32i32, SDValue(ShufLoNode, 0));
+
+ // Handle Hi Reg.
+ SDNode *WidenAddHiNode = CurDAG->getMachineNode(
+ Hexagon::V6_vadduhw, DL, ResTy, HiReg, SDValue(ZeroNode, 0));
+ SDValue Hi_LoReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_lo, DL, MVT::v32i32, SDValue(WidenAddHiNode, 0));
+ SDValue Hi_HiReg = CurDAG->getTargetExtractSubreg(
+ Hexagon::vsub_hi, DL, MVT::v32i32, SDValue(WidenAddHiNode, 0));
+
+ SDNode *PackHiNode = CurDAG->getMachineNode(
+ Hexagon::V6_vpackwh_sat, DL, MVT::v32i32, Hi_HiReg, Hi_LoReg);
+ SDNode *ShufHiNode = CurDAG->getMachineNode(
+ Hexagon::V6_vshuffh, DL, MVT::v32i32, SDValue(PackHiNode, 0));
+ SDNode *ConvHiNode = CurDAG->getMachineNode(
+ Hexagon::V6_vconv_hf_h, DL, MVT::v32i32, SDValue(ShufHiNode, 0));
+
+ SDValue RC =
+ CurDAG->getTargetConstant(Hexagon::HvxWRRegClassID, DL, MVT::i32);
+ SDValue SubRegL = CurDAG->getTargetConstant(Hexagon::vsub_lo, DL, MVT::i32);
+ SDValue SubRegH = CurDAG->getTargetConstant(Hexagon::vsub_hi, DL, MVT::i32);
+ const SDValue Ops[] = {RC, SDValue(ConvHiNode, 0), SubRegH,
+ SDValue(ConvLoNode, 0), SubRegL};
+ SDNode *RS = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
+ MVT::v64i32, Ops);
+
+ ReplaceUses(SDValue(N, 0), SDValue(RS, 0));
+ CurDAG->RemoveDeadNode(N);
+ return;
+ }
+
default:
llvm_unreachable("Unexpected HVX IEEE intrinsic: no QFloat translation");
return;
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/ieeetoqfloat.ll b/llvm/test/CodeGen/Hexagon/autohvx/ieeetoqfloat.ll
index 86204f17257d9d6..9c05a894a4ef547 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/ieeetoqfloat.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/ieeetoqfloat.ll
@@ -445,6 +445,144 @@ entry:
ret <64 x i32> %0
}
+; Function Attrs:
+;On v79 and above,
+;v0.hf = vcvt(v0.sf,v1.sf) is translated to
+;v2 = vxor(v2,v2); v0.qf32 = vadd(v0.sf,v2.sf);
+;v1.qf32 = vadd(v1.sf,v2.sf); v0.hf = v1:0.qf32
+
+; CHECK-LABEL: convhfsfsf:
+; CHECK-NOT: v0.hf = vcvt(v0.sf,v1.sf)
+; CHECK: v[[REG1:[0-9]+]] = vxor(v[[REG0:[0-9]+]],v[[REG0]])
+; CHECK-DAG: v[[REG2:[0-9]+]].qf32 = vadd(v0.sf,v[[REG1]].sf)
+; CHECK-DAG: v[[REG3:[0-9]+]].qf32 = vadd(v1.sf,v[[REG1]].sf)
+; CHECK: v0.hf = v[[REG3]]:[[REG2]].qf32
+
+; V75-LABEL: convhfsfsf:
+; V75: v0.hf = vcvt(v0.sf,v1.sf)
+
+define dso_local inreg <32 x i32> @convhfsfsf(<32 x i32> noundef %Vu, <32 x i32> noundef %Vv) local_unnamed_addr {
+entry:
+ %0 = tail call <32 x i32> @llvm.hexagon.V6.vcvt.hf.sf.128B(<32 x i32> %Vu, <32 x i32> %Vv)
+ ret <32 x i32> %0
+}
+
+;On v79 and above,
+;v0.hf = vcvt(v0.uh) is translated to
+;v1 = vxor(v1,v1); v1:0.w = vadd(v0.uh,v1.uh);
+;v2.h = vpack(v1.w,v0.w):sat; v3.h = vshuff(v2.h); v0.hf = v3.h
+
+; CHECK-LABEL: convhfuh:
+; CHECK-NOT: v0.hf = vcvt(v0.uh)
+; CHECK: v[[REG1:[0-9]+]] = vxor(v[[REG0:[0-9]+]],v[[REG0]])
+; CHECK: v[[REG3:[0-9]+]]:[[REG2:[0-9]+]].w = vadd(v0.uh,v[[REG1]].uh)
+; CHECK: v[[REG4:[0-9]+]].h = vpack(v[[REG3]].w,v[[REG2]].w):sat
+; CHECK: v[[REG5:[0-9]+]].h = vshuff(v[[REG4]].h)
+; CHECK: v0.hf = v[[REG5]].h
+
+; V75-LABEL: convhfuh:
+; V75: v0.hf = vcvt(v0.uh)
+
+define dso_local inreg <32 x i32> @convhfuh(<32 x i32> noundef %Vu) local_unnamed_addr {
+entry:
+ %0 = tail call <32 x i32> @llvm.hexagon.V6.vcvt.hf.uh.128B(<32 x i32> %Vu)
+ ret <32 x i32> %0
+}
+
+;On v79 and above,
+;v1:0.hf = vcvt(v0.b) is translated to
+;v1.h = vdeal(v0.h); v3:2.h = vunpack(v1.b)
+;v0.hf = v2.h; v1.hf = v3.h
+
+; CHECK-LABEL: convhfb:
+; CHECK-NOT: v1:0.hf = vcvt(v0.b)
+; CHECK: v[[REG0:[0-9]+]].h = vdeal(v0.h)
+; CHECK: v[[REG2:[0-9]+]]:[[REG1:[0-9]+]].h = vunpack(v[[REG0]].b)
+; CHECK-DAG: v0.hf = v[[REG1]].h
+; CHECK-DAG: v1.hf = v[[REG2]].h
+
+; V75-LABEL: convhfb:
+; V75: v1:0.hf = vcvt(v0.b)
+
+define dso_local inreg <64 x i32> @convhfb(<32 x i32> noundef %Vu) local_unnamed_addr {
+entry:
+ %0 = tail call <64 x i32> @llvm.hexagon.V6.vcvt.hf.b.128B(<32 x i32> %Vu)
+ ret <64 x i32> %0
+}
+
+;On v79 and above,
+;v1:0.hf = vcvt(v0.ub) is translated to
+;v1.h = vdeal(v0.h); v2 = vxor(v2,v2)
+;v5:4.uh = vunpack(v1.ub)
+;v7:6.w = vadd(v4.uh,v2.uh); v31:30.w = vadd(v5.uh,v2.uh)
+;v4.h = vpack(v7.w,v6.w):sat; v3.h = vpack(v31.w,v30.w):sat
+;v30.h = vshuff(v4.h);v31.h = vshuff(v3.h)
+;v0.hf = v30.h;v1.hf = v31.h
+
+; CHECK-LABEL: convhfub:
+; CHECK-NOT: v1:0.hf = vcvt(v0.ub)
+; CHECK: v[[REG1:[0-9]+]].h = vdeal(v0.h)
+; CHECK-DAG: v[[REG5:[0-9]+]]:[[REG4:[0-9]+]].uh = vunpack(v[[REG1]].ub)
+; CHECK-DAG: v[[REG2:[0-9]+]] = vxor(v[[REG22:[0-9]+]],v[[REG22]])
+; CHECK-DAG: v[[REG7:[0-9]+]]:[[REG6:[0-9]+]].w = vadd(v[[REG4]].uh,v[[REG2]].uh)
+; CHECK-DAG: v[[REG31:[0-9]+]]:[[REG30:[0-9]+]].w = vadd(v[[REG5]].uh,v[[REG2]].uh)
+; CHECK-DAG: v[[REG44:[0-9]+]].h = vpack(v[[REG7]].w,v[[REG6]].w):sat
+; CHECK-DAG: v[[REG33:[0-9]+]].h = vpack(v[[REG31]].w,v[[REG30]].w):sat
+; CHECK-DAG: v[[REG3030:[0-9]+]].h = vshuff(v[[REG44]].h)
+; CHECK-DAG: v[[REG3131:[0-9]+]].h = vshuff(v[[REG33]].h)
+; CHECK-DAG: v0.hf = v[[REG3030]].h
+; CHECK-DAG: v1.hf = v[[REG3131]].h
+
+; V75-LABEL: convhfub:
+; V75: v1:0.hf = vcvt(v0.ub)
+
+define dso_local inreg <64 x i32> @convhfub(<32 x i32> noundef %Vu) local_unnamed_addr {
+entry:
+ %0 = tail call <64 x i32> @llvm.hexagon.V6.vcvt.hf.ub.128B(<32 x i32> %Vu)
+ ret <64 x i32> %0
+}
+
+;On v79 and above,
+;v0.sf = vdmpy(v0.hf,v1.hf) is translated to
+;v1:0.qf32 = vmpy(v0.hf,v1.hf); v2.qf32 = vadd(v0.sf,v1.sf);
+;v0.sf = v2.qf32
+
+; CHECK-LABEL: sfvdmpyhf:
+; CHECK-NOT: v{{.*}}.sf = vdmpy(v{{.*}}.hf,v{{.*}}.hf)
+; CHECK: v[[REG0:[0-9]+]]:[[REG1:[0-9]+]].qf32 = vmpy(v0.hf,v1.hf)
+; CHECK: v[[REG2:[0-9]+]].qf32 = vadd(v{{[0-9]+}}.qf32,v{{[0-9]+}}.qf32)
+; CHECK: v0.sf = v[[REG2]].qf32
+
+; V75-LABEL: sfvdmpyhf:
+; V75: v{{.*}}.sf = vdmpy(v{{.*}}.hf,v{{.*}}.hf)
+
+define dso_local inreg <32 x i32> @sfvdmpyhf(<32 x i32> noundef %Vu, <32 x i32> noundef %Vv) local_unnamed_addr {
+entry:
+ %0 = tail call <32 x i32> @llvm.hexagon.V6.vdmpy.sf.hf.128B(<32 x i32> %Vu, <32 x i32> %Vv)
+ ret <32 x i32> %0
+}
+
+;On v79 and above,
+;v0.sf += vdmpy(v1.hf,v2.hf) is translated to
+;v3:2.qf32 = vmpy(v1.hf,v2.hf); v3.qf32 = vadd(v2.qf32,v3.qf32);
+;v4.qf32 = vadd(v3.qf32,v0.sf); v0.sf = v4.qf32
+
+; CHECK-LABEL: sfvdmpyhf_acc:
+; CHECK-NOT: v{{.*}}.sf += vdmpy(v{{.*}}.hf,v{{.*}}.hf)
+; CHECK: v[[REG3:[0-9]+]]:[[REG2:[0-9]+]].qf32 = vmpy(v1.hf,v2.hf)
+; CHECK: v[[REG4:[0-9]+]].qf32 = vadd(v{{[0-9]+}}.qf32,v{{[0-9]+}}.qf32)
+; CHECK: v[[REG5:[0-9]+]].qf32 = vadd(v[[REG4]].qf32,v0.sf)
+; CHECK: v0.sf = v[[REG5]].qf32
+
+; V75-LABEL: sfvdmpyhf_acc:
+; V75: v{{.*}}.sf += vdmpy(v{{.*}}.hf,v{{.*}}.hf)
+
+define dso_local inreg <32 x i32> @sfvdmpyhf_acc(<32 x i32> noundef %Vx, <32 x i32> noundef %Vu, <32 x i32> noundef %Vv) local_unnamed_addr {
+entry:
+ %0 = tail call <32 x i32> @llvm.hexagon.V6.vdmpy.sf.hf.acc.128B(<32 x i32> %Vx, <32 x i32> %Vu, <32 x i32> %Vv)
+ ret <32 x i32> %0
+}
+
declare <32 x i32> @llvm.hexagon.V6.vabs.hf.128B(<32 x i32>)
declare <32 x i32> @llvm.hexagon.V6.vabs.sf.128B(<32 x i32>)
declare <32 x i32> @llvm.hexagon.V6.vassign.fp.128B(<32 x i32>)
@@ -471,3 +609,9 @@ declare <32 x i32> @llvm.hexagon.V6.vfneg.hf.128B(<32 x i32>)
declare <32 x i32> @llvm.hexagon.V6.vfneg.sf.128B(<32 x i32>)
declare <32 x i32> @llvm.hexagon.V6.vcvt.hf.h.128B(<32 x i32>)
declare <64 x i32> @llvm.hexagon.V6.vcvt.sf.hf.128B(<32 x i32>)
+declare <32 x i32> @llvm.hexagon.V6.vcvt.hf.sf.128B(<32 x i32>, <32 x i32>)
+declare <32 x i32> @llvm.hexagon.V6.vcvt.hf.uh.128B(<32 x i32>)
+declare <64 x i32> @llvm.hexagon.V6.vcvt.hf.b.128B(<32 x i32>)
+declare <64 x i32> @llvm.hexagon.V6.vcvt.hf.ub.128B(<32 x i32>)
+declare <32 x i32> @llvm.hexagon.V6.vdmpy.sf.hf.128B(<32 x i32>, <32 x i32>)
+declare <32 x i32> @llvm.hexagon.V6.vdmpy.sf.hf.acc.128B(<32 x i32>, <32 x i32>, <32 x i32>)
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll
index beb4d421d5e4d77..fa4b62479f27cb6 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-conv-double2.ll
@@ -1,7 +1,5 @@
; Checks if conversion is only inserted for the spilled register
; instead of 2 conversions for the W register
-; XFAIL: *
-; NOTE: XFAIL until Hexagon HVX IEEEâQFloat isel translation is upstreamed; remove XFAIL when that lands.
; RUN: llc -O2 -march=hexagon -mcpu=hexagonv81 -enable-xqf-gen=true \
; RUN: -hexagon-qfloat-mode=ieee -mattr=+hvxv81,+hvx-length128B \
; RUN: -enable-postra-xqf-check -debug-only=handle-qfp 2>&1 < %s -o /dev/null | FileCheck %s
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll
index 7c1ec0249f43f6b..4d7b2c939514668 100644
--- a/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll
+++ b/llvm/test/CodeGen/Hexagon/autohvx/xqf-postra-subreg2.ll
@@ -1,8 +1,6 @@
; Test passes if we don't generate conversion for both
; of the subregisters since only one is live at the use.
-; XFAIL: *
-; Will re-enable once the fix for incorrect subregister liveness is upstreamed.
; REQUIRES: asserts
; RUN: llc -O2 -mtriple=hexagon -mattr=+hvxv81,+hvx-length128B \
; RUN: -enable-xqf-gen=true -hexagon-qfloat-mode=lossy \
More information about the llvm-commits
mailing list