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 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" }