[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