[llvm] r345361 - [PowerPC] Keep vector int to fp conversions in vector domain

Nemanja Ivanovic via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 25 20:19:13 PDT 2018


Author: nemanjai
Date: Thu Oct 25 20:19:13 2018
New Revision: 345361

URL: http://llvm.org/viewvc/llvm-project?rev=345361&view=rev
Log:
[PowerPC] Keep vector int to fp conversions in vector domain

At present a v2i16 -> v2f64 convert is implemented by extracts to scalar,
scalar converts, and merge back into a vector. Use vector converts instead,
with the int data permuted into the proper position and extended if necessary.

Patch by RolandF.

Differential revision: https://reviews.llvm.org/D53346

Added:
    llvm/trunk/test/CodeGen/PowerPC/vec-itofp.ll
Modified:
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
    llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=345361&r1=345360&r2=345361&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Thu Oct 25 20:19:13 2018
@@ -792,6 +792,9 @@ PPCTargetLowering::PPCTargetLowering(con
       setOperationAction(ISD::FP_TO_SINT, MVT::v2i64, Legal);
       setOperationAction(ISD::FP_TO_UINT, MVT::v2i64, Legal);
 
+      setOperationAction(ISD::UINT_TO_FP, MVT::v2i16, Custom);
+      setOperationAction(ISD::SINT_TO_FP, MVT::v2i16, Custom);
+
       setOperationAction(ISD::FNEG, MVT::v4f32, Legal);
       setOperationAction(ISD::FNEG, MVT::v2f64, Legal);
       setOperationAction(ISD::FABS, MVT::v4f32, Legal);
@@ -7265,10 +7268,75 @@ SDValue PPCTargetLowering::LowerINT_TO_F
   return FP;
 }
 
+static SDValue widenVec(SelectionDAG &DAG, SDValue Vec, const SDLoc &dl) {
+
+  EVT VecVT = Vec.getValueType();
+  assert(VecVT.isVector() && "Expected a vector type.");
+  assert(VecVT.getSizeInBits() < 128 && "Vector is already full width.");
+
+  EVT EltVT = VecVT.getVectorElementType();
+  unsigned WideNumElts = 128 / EltVT.getSizeInBits();
+  EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT, WideNumElts);
+
+  unsigned NumConcat = WideNumElts / VecVT.getVectorNumElements();
+  SmallVector<SDValue, 16> Ops(NumConcat);
+  Ops[0] = Vec;
+  SDValue UndefVec = DAG.getUNDEF(VecVT);
+  for (unsigned i = 1; i < NumConcat; ++i)
+    Ops[i] = UndefVec;
+
+  return DAG.getNode(ISD::CONCAT_VECTORS, dl, WideVT, Ops);
+}
+
+SDValue PPCTargetLowering::LowerINT_TO_FPVector(SDValue Op,
+                                                SelectionDAG &DAG,
+                                                const SDLoc &dl) const {
+
+  unsigned Opc = Op.getOpcode();
+  assert((Opc == ISD::UINT_TO_FP || Opc == ISD::SINT_TO_FP) &&
+         "Unexpected conversion type");
+  assert(Op.getValueType() == MVT::v2f64 && "Supports v2f64 only.");
+
+  // CPU's prior to P9 don't have a way to sign-extend in vectors.
+  bool SignedConv = Opc == ISD::SINT_TO_FP;
+  if (SignedConv && !Subtarget.hasP9Altivec())
+    return SDValue();
+
+  SDValue Wide = widenVec(DAG, Op.getOperand(0), dl);
+  EVT WideVT = Wide.getValueType();
+  unsigned WideNumElts = WideVT.getVectorNumElements();
+
+  SmallVector<int, 16> ShuffV;
+  for (unsigned i = 0; i < WideNumElts; ++i)
+    ShuffV.push_back(i + WideNumElts);
+
+  if (Subtarget.isLittleEndian()) {
+    ShuffV[0] = 0;
+    ShuffV[WideNumElts / 2] = 1;
+  }
+  else {
+    ShuffV[WideNumElts / 2 - 1] = 0;
+    ShuffV[WideNumElts - 1] = 1;
+  }
+
+  SDValue ShuffleSrc2 = SignedConv ? DAG.getUNDEF(WideVT) :
+                                     DAG.getConstant(0, dl, WideVT);
+  SDValue Arrange = DAG.getVectorShuffle(WideVT, dl, Wide, ShuffleSrc2, ShuffV);
+  unsigned ExtendOp = SignedConv ? (unsigned) PPCISD::SExtVElems :
+                                   (unsigned) ISD::BITCAST;
+  SDValue Extend = DAG.getNode(ExtendOp, dl, MVT::v2i64, Arrange);
+
+  return DAG.getNode(Opc, dl, Op.getValueType(), Extend);
+}
+
 SDValue PPCTargetLowering::LowerINT_TO_FP(SDValue Op,
                                           SelectionDAG &DAG) const {
   SDLoc dl(Op);
 
+  if (Op.getValueType() == MVT::v2f64 &&
+      Op.getOperand(0).getValueType() == MVT::v2i16)
+    return LowerINT_TO_FPVector(Op, DAG, dl);
+
   // Conversions to f128 are legal.
   if (EnableQuadPrecision && (Op.getValueType() == MVT::f128))
     return Op;

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h?rev=345361&r1=345360&r2=345361&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.h Thu Oct 25 20:19:13 2018
@@ -927,6 +927,9 @@ namespace llvm {
     SDValue LowerINT_TO_FPDirectMove(SDValue Op, SelectionDAG &DAG,
                                      const SDLoc &dl) const;
 
+    SDValue LowerINT_TO_FPVector(SDValue Op, SelectionDAG &DAG,
+                                 const SDLoc &dl) const;
+
     SDValue getFramePointerFrameIndex(SelectionDAG & DAG) const;
     SDValue getReturnAddrFrameIndex(SelectionDAG & DAG) const;
 

Added: llvm/trunk/test/CodeGen/PowerPC/vec-itofp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/vec-itofp.ll?rev=345361&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/vec-itofp.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/vec-itofp.ll Thu Oct 25 20:19:13 2018
@@ -0,0 +1,192 @@
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:     -mcpu=pwr8 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
+; RUN: FileCheck %s --check-prefix=CHECK-P8
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:     -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
+; RUN: FileCheck %s --check-prefix=CHECK-P9
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
+; RUN:     -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
+; RUN: FileCheck %s --check-prefix=CHECK-BE
+
+define void @test8(<8 x double>* nocapture %Sink, <8 x i16>* nocapture readonly %SrcPtr) {
+entry:
+  %0 = load <8 x i16>, <8 x i16>* %SrcPtr, align 16
+  %1 = uitofp <8 x i16> %0 to <8 x double>
+  store <8 x double> %1, <8 x double>* %Sink, align 16
+  ret void
+; CHECK-P9-LABEL: @test8
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: xvcvuxddp
+; CHECK-P9: xvcvuxddp
+; CHECK-P9: xvcvuxddp
+; CHECK-P9: xvcvuxddp
+; CHECK-P8-LABEL: @test8
+; CHECK-P8: vperm
+; CHECK-P8: vperm
+; CHECK-P8: vperm
+; CHECK-P8: vperm
+; CHECK-P8: xvcvuxddp
+; CHECK-P8: xvcvuxddp
+; CHECK-P8: xvcvuxddp
+; CHECK-P8: xvcvuxddp
+}
+
+define void @test4(<4 x double>* nocapture %Sink, <4 x i16>* nocapture readonly %SrcPtr) {
+entry:
+  %0 = load <4 x i16>, <4 x i16>* %SrcPtr, align 16
+  %1 = uitofp <4 x i16> %0 to <4 x double>
+  store <4 x double> %1, <4 x double>* %Sink, align 16
+  ret void
+; CHECK-P9-LABEL: @test4
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: xvcvuxddp
+; CHECK-P9: xvcvuxddp
+; CHECK-P8-LABEL: @test4
+; CHECK-P8: vperm
+; CHECK-P8: vperm
+; CHECK-P8: xvcvuxddp
+; CHECK-P8: xvcvuxddp
+}
+
+define void @test2(<2 x double>* nocapture %Sink, <2 x i16>* nocapture readonly %SrcPtr) {
+entry:
+  %0 = load <2 x i16>, <2 x i16>* %SrcPtr, align 16
+  %1 = uitofp <2 x i16> %0 to <2 x double>
+  store <2 x double> %1, <2 x double>* %Sink, align 16
+  ret void
+; CHECK-P9-LABEL: .LCPI2_0:
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 30
+; CHECK-P9-NEXT: .byte 13
+; CHECK-P9-NEXT: .byte 12
+; CHECK-P9-NEXT: .byte 11
+; CHECK-P9-NEXT: .byte 10
+; CHECK-P9-NEXT: .byte 9
+; CHECK-P9-NEXT: .byte 8
+; CHECK-P9-NEXT: .byte 29
+; CHECK-P9-NEXT: .byte 28
+; CHECK-P9-NEXT: .byte 5
+; CHECK-P9-NEXT: .byte 4
+; CHECK-P9-NEXT: .byte 3
+; CHECK-P9-NEXT: .byte 2
+; CHECK-P9-NEXT: .byte 1
+; CHECK-P9-NEXT: .byte 0
+; CHECK-P9: addi [[REG1:r[0-9]+]], {{r[0-9]+}}, .LCPI2_0 at toc@l
+; CHECK-P9: lxvx [[REG2:v[0-9]+]], 0, [[REG1]]
+; CHECK-P9: vperm [[REG3:v[0-9]+]], {{v[0-9]+}}, {{v[0-9]+}}, [[REG2]]
+; CHECK-P9: xvcvuxddp {{vs[0-9]+}}, [[REG3]]
+; CHECK-P8-LABEL: @test2
+; CHECK-P8: vperm [[REG1:v[0-9]+]]
+; CHECK-P8: xvcvuxddp {{vs[0-9]+}}, [[REG1]]
+; CHECK-BE-LABEL: .LCPI2_0:
+; CHECK-BE-NEXT: .byte 16
+; CHECK-BE-NEXT: .byte 17
+; CHECK-BE-NEXT: .byte 18
+; CHECK-BE-NEXT: .byte 19
+; CHECK-BE-NEXT: .byte 20
+; CHECK-BE-NEXT: .byte 21
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 1
+; CHECK-BE-NEXT: .byte 24
+; CHECK-BE-NEXT: .byte 25
+; CHECK-BE-NEXT: .byte 26
+; CHECK-BE-NEXT: .byte 27
+; CHECK-BE-NEXT: .byte 28
+; CHECK-BE-NEXT: .byte 29
+; CHECK-BE-NEXT: .byte 2
+; CHECK-BE-NEXT: .byte 3
+; CHECK-BE: addi [[REG1:r[0-9]+]], {{r[0-9]+}}, .LCPI2_0 at toc@l
+; CHECK-BE: lxvx [[REG2:v[0-9]+]], 0, [[REG1]]
+; CHECK-BE: vperm [[REG3:v[0-9]+]], {{v[0-9]+}}, {{v[0-9]+}}, [[REG2]]
+; CHECK-BE: xvcvuxddp {{vs[0-9]+}}, [[REG3]]
+}
+
+define void @stest8(<8 x double>* nocapture %Sink, <8 x i16>* nocapture readonly %SrcPtr) {
+entry:
+  %0 = load <8 x i16>, <8 x i16>* %SrcPtr, align 16
+  %1 = sitofp <8 x i16> %0 to <8 x double>
+  store <8 x double> %1, <8 x double>* %Sink, align 16
+  ret void
+; CHECK-P9-LABEL: @stest8
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: vextsh2d
+; CHECK-P9: vextsh2d
+; CHECK-P9: vextsh2d
+; CHECK-P9: vextsh2d
+; CHECK-P9: xvcvsxddp
+; CHECK-P9: xvcvsxddp
+; CHECK-P9: xvcvsxddp
+; CHECK-P9: xvcvsxddp
+}
+
+define void @stest4(<4 x double>* nocapture %Sink, <4 x i16>* nocapture readonly %SrcPtr) {
+entry:
+  %0 = load <4 x i16>, <4 x i16>* %SrcPtr, align 16
+  %1 = sitofp <4 x i16> %0 to <4 x double>
+  store <4 x double> %1, <4 x double>* %Sink, align 16
+  ret void
+; CHECK-P9-LABEL: @stest4
+; CHECK-P9: vperm
+; CHECK-P9: vperm
+; CHECK-P9: vextsh2d
+; CHECK-P9: vextsh2d
+; CHECK-P9: xvcvsxddp
+; CHECK-P9: xvcvsxddp
+}
+
+define void @stest2(<2 x double>* nocapture %Sink, <2 x i16>* nocapture readonly %SrcPtr) {
+entry:
+  %0 = load <2 x i16>, <2 x i16>* %SrcPtr, align 16
+  %1 = sitofp <2 x i16> %0 to <2 x double>
+  store <2 x double> %1, <2 x double>* %Sink, align 16
+  ret void
+; CHECK-P9-LABEL: .LCPI5_0:
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 30
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 29
+; CHECK-P9-NEXT: .byte 28
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9-NEXT: .byte 31
+; CHECK-P9: vperm [[REG1:v[0-9]+]]
+; CHECK-P9: vextsh2d [[REG2:v[0-9]+]], [[REG1]]
+; CHECK-P9: xvcvsxddp {{vs[0-9]+}}, [[REG2]]
+; CHECK-BE-LABEL: .LCPI5_0:
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 1
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 0
+; CHECK-BE-NEXT: .byte 2
+; CHECK-BE-NEXT: .byte 3
+; CHECK-BE: addi [[REG1:r[0-9]+]], {{r[0-9]+}}, .LCPI5_0 at toc@l
+; CHECK-BE: lxvx [[REG2:v[0-9]+]], 0, [[REG1]]
+; CHECK-BE: vperm [[REG3:v[0-9]+]], {{v[0-9]+}}, {{v[0-9]+}}, [[REG2]]
+; CHECK-BE: vextsh2d [[REG4:v[0-9]+]], [[REG3]]
+; CHECK-BE: xvcvsxddp {{vs[0-9]+}}, [[REG4]]
+}




More information about the llvm-commits mailing list