[llvm] [Hexagon] Add pattern for hvx uint_to_fp lowering (PR #159121)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 16 09:34:47 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-hexagon
Author: None (pkarveti)
<details>
<summary>Changes</summary>
The pattern for this particular lowering does not handle conversion from v32i32 to v32f32. This pattern is added which maintains precision during conversion.
patch-by: Santanu Das
---
Full diff: https://github.com/llvm/llvm-project/pull/159121.diff
4 Files Affected:
- (modified) llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp (+2)
- (modified) llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h (+1)
- (modified) llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp (+35)
- (added) llvm/test/CodeGen/Hexagon/hvx-lower-uinttofp.ll (+27)
``````````diff
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index e285e04543694..53755920fb8e9 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -1024,6 +1024,8 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
case ISD::VECTOR_SHUFFLE: return SelectHvxShuffle(N);
case HexagonISD::VROR: return SelectHvxRor(N);
+ case ISD::UINT_TO_FP:
+ return SelectHvxUIntToFp(N);
}
}
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
index 2d23aeecda6d8..0da72643375de 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
@@ -146,6 +146,7 @@ class HexagonDAGToDAGISel : public SelectionDAGISel {
void SelectHvxShuffle(SDNode *N);
void SelectHvxRor(SDNode *N);
void SelectHvxVAlign(SDNode *N);
+ void SelectHvxUIntToFp(SDNode *N);
// Function postprocessing.
void updateAligna();
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
index 613048be52a2f..4ef284f21ffbd 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
@@ -947,6 +947,7 @@ namespace llvm {
void selectShuffle(SDNode *N);
void selectRor(SDNode *N);
void selectVAlign(SDNode *N);
+ void selectUintToFp(SDNode *N);
static SmallVector<uint32_t, 8> getPerfectCompletions(ShuffleMask SM,
unsigned Width);
@@ -1149,6 +1150,36 @@ bool HvxSelector::selectVectorConstants(SDNode *N) {
return !Nodes.empty();
}
+// UNIT_TO_FP handler for vector type v32i32 --> v32f32
+// V1 = 0
+// V2.uw=vavg(V0.uw, V1.uw) ---> V2 = V0 >> 1
+// V3.w = vsub(V0.w, V2.w) ----> V3 = V0 - V2
+// V4.sf=(V2).w ----> convert V2 to float V4
+// V5.sf=(V3).w ----> convert V3 to float V5
+// V6.sf=vadd(V4.sf, V5.sf) ----> vadd(V4, V5)
+void HvxSelector::selectUintToFp(SDNode *N) {
+
+ if (!(N->getValueType(0) == MVT::v32f32) ||
+ !(N->getOperand(0).getValueType() == MVT::v32i32)) {
+ ISel.SelectCode(N);
+ return;
+ }
+
+ const SDLoc &dl(N);
+ SDNode *ConstZero = DAG.getMachineNode(Hexagon::V6_vd0, dl, MVT::v32i32);
+ SDNode *Vavg = DAG.getMachineNode(Hexagon::V6_vavguw, dl, MVT::v32i32,
+ N->getOperand(0), SDValue(ConstZero, 0));
+ SDNode *Vsubw = DAG.getMachineNode(Hexagon::V6_vsubw, dl, MVT::v32i32,
+ N->getOperand(0), SDValue(Vavg, 0));
+ SDNode *FirstConv = DAG.getMachineNode(Hexagon::V6_vconv_sf_w, dl,
+ MVT::v32f32, SDValue(Vavg, 0));
+ SDNode *SecConv = DAG.getMachineNode(Hexagon::V6_vconv_sf_w, dl, MVT::v32f32,
+ SDValue(Vsubw, 0));
+ SDNode *Vadd = DAG.getMachineNode(Hexagon::V6_vadd_sf_sf, dl, MVT::v32f32,
+ SDValue(FirstConv, 0), SDValue(SecConv, 0));
+ ISel.ReplaceNode(N, Vadd);
+}
+
void HvxSelector::materialize(const ResultStack &Results) {
DEBUG_WITH_TYPE("isel", {
dbgs() << "Materializing\n";
@@ -2874,6 +2905,10 @@ void HexagonDAGToDAGISel::SelectHvxVAlign(SDNode *N) {
HvxSelector(*this, *CurDAG).selectVAlign(N);
}
+void HexagonDAGToDAGISel::SelectHvxUIntToFp(SDNode *N) {
+ HvxSelector(*this, *CurDAG).selectUintToFp(N);
+}
+
void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) {
const SDLoc &dl(N);
SDValue Chain = N->getOperand(0);
diff --git a/llvm/test/CodeGen/Hexagon/hvx-lower-uinttofp.ll b/llvm/test/CodeGen/Hexagon/hvx-lower-uinttofp.ll
new file mode 100644
index 0000000000000..9efc315114032
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/hvx-lower-uinttofp.ll
@@ -0,0 +1,27 @@
+; Check if int_to_fp is lowered correctly for v32i32 --> v32f32
+
+; RUN: llc -march=hexagon -stop-after=hexagon-isel -o - %s | FileCheck %s
+
+; CHECK: [[R2:%[0-9]+]]:hvxvr = V6_vd0
+; CHECK-NEXT: [[R3:%[0-9]+]]:hvxvr = V6_vavguw %0, [[R2]]
+; CHECK-NEXT: [[R4:%[0-9]+]]:hvxvr = V6_vconv_sf_w [[R3]]
+; CHECK-NEXT: [[R5:%[0-9]+]]:hvxvr = V6_vsubw %0, [[R3]]
+; CHECK-NEXT: [[R6:%[0-9]+]]:hvxvr = V6_vconv_sf_w killed [[R5]]
+; CHECK-NEXT: [[R7:%[0-9]+]]:hvxvr = V6_vadd_sf_sf killed [[R4]], killed [[R6]]
+; CHECK-NEXT: [[R8:%[0-9]+]]:hvxvr = V6_vavguw %1, [[R2]]
+; CHECK-NEXT: [[R9:%[0-9]+]]:hvxvr = V6_vconv_sf_w [[R8]]
+; CHECK-NEXT: [[R10:%[0-9]+]]:hvxvr = V6_vsubw %1, [[R8]]
+; CHECK-NEXT: [[R11:%[0-9]+]]:hvxvr = V6_vconv_sf_w killed [[R10]]
+; CHECK-NEXT: [[R12:%[0-9]+]]:hvxvr = V6_vadd_sf_sf killed [[R9]], killed [[R11]]
+; CHECK-NEXT: V6_vmpy_qf32_sf killed [[R7]], killed [[R12]]
+
+
+target triple = "hexagon"
+define <32 x float> @uitofp(<32 x i32> %int0, <32 x i32> %int1) #0
+{
+ %fp0 = uitofp <32 x i32> %int0 to <32 x float>
+ %fp1 = uitofp <32 x i32> %int1 to <32 x float>
+ %out = fmul <32 x float> %fp0, %fp1
+ ret <32 x float> %out
+}
+attributes #0 = { nounwind readnone "target-cpu"="hexagonv79" "target-features"="+hvxv79,+hvx-length128b" }
``````````
</details>
https://github.com/llvm/llvm-project/pull/159121
More information about the llvm-commits
mailing list