diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -7862,20 +7862,45 @@ // to // - assert(Op.getValueType().isVector() && "Vector type expected."); - - SDLoc DL(Op); - SDValue N1 = Op.getOperand(0); - unsigned SrcSize = N1.getValueType().getSizeInBits(); - assert(SrcSize <= 128 && "Source must fit in an Altivec/VSX vector"); - SDValue WideSrc = SrcSize == 128 ? N1 : widenVec(DAG, N1, DL); - EVT TrgVT = Op.getValueType(); + assert(TrgVT.isVector() && "Vector type expected."); unsigned TrgNumElts = TrgVT.getVectorNumElements(); EVT EltVT = TrgVT.getVectorElementType(); + if (!isOperationCustom(Op.getOpcode(), TrgVT) || + TrgVT.getSizeInBits() > 128 || !isPowerOf2_32(TrgNumElts) || + !isPowerOf2_32(EltVT.getSizeInBits())) + return SDValue(); + + SDValue N1 = Op.getOperand(0); + EVT SrcVT = N1.getValueType(); + unsigned SrcSize = SrcVT.getSizeInBits(); + if (SrcSize > 256 || + !isPowerOf2_32(SrcVT.getVectorNumElements()) || + !isPowerOf2_32(SrcVT.getVectorElementType().getSizeInBits())) + return SDValue(); + if (SrcSize == 256 && SrcVT.getVectorNumElements() < 2) + return SDValue(); + unsigned WideNumElts = 128 / EltVT.getSizeInBits(); EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT, WideNumElts); + SDLoc DL(Op); + SDValue Op1, Op2; + if (SrcSize == 256) { + EVT VecIdxTy = getVectorIdxTy(DAG.getDataLayout()); + EVT SplitVT = + N1.getValueType().getHalfNumVectorElementsVT(*DAG.getContext()); + unsigned SplitNumElts = SplitVT.getVectorNumElements(); + Op1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SplitVT, N1, + DAG.getConstant(0, DL, VecIdxTy)); + Op2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SplitVT, N1, + DAG.getConstant(SplitNumElts, DL, VecIdxTy)); + } + else { + Op1 = SrcSize == 128 ? N1 : widenVec(DAG, N1, DL); + Op2 = DAG.getUNDEF(WideVT); + } + // First list the elements we want to keep. unsigned SizeMult = SrcSize / TrgVT.getSizeInBits(); SmallVector ShuffV; @@ -7891,8 +7916,9 @@ // ShuffV.push_back(i + WideNumElts); ShuffV.push_back(WideNumElts + 1); - SDValue Conv = DAG.getNode(ISD::BITCAST, DL, WideVT, WideSrc); - return DAG.getVectorShuffle(WideVT, DL, Conv, DAG.getUNDEF(WideVT), ShuffV); + Op1 = DAG.getNode(ISD::BITCAST, DL, WideVT, Op1); + Op2 = DAG.getNode(ISD::BITCAST, DL, WideVT, Op2); + return DAG.getVectorShuffle(WideVT, DL, Op1, Op2, ShuffV); } /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when @@ -10750,13 +10776,11 @@ Results.push_back(LowerFP_TO_INT(SDValue(N, 0), DAG, dl)); return; case ISD::TRUNCATE: { - EVT TrgVT = N->getValueType(0); - EVT OpVT = N->getOperand(0).getValueType(); - if (TrgVT.isVector() && - isOperationCustom(N->getOpcode(), TrgVT) && - OpVT.getSizeInBits() <= 128 && - isPowerOf2_32(OpVT.getVectorElementType().getSizeInBits())) - Results.push_back(LowerTRUNCATEVector(SDValue(N, 0), DAG)); + if (!N->getValueType(0).isVector()) + return; + SDValue Lowered = LowerTRUNCATEVector(SDValue(N, 0), DAG); + if (Lowered) + Results.push_back(Lowered); return; } case ISD::BITCAST: diff --git a/llvm/test/CodeGen/PowerPC/vec-trunc2.ll b/llvm/test/CodeGen/PowerPC/vec-trunc2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/vec-trunc2.ll @@ -0,0 +1,189 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mattr=+vsx -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ +; RUN: FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -mattr=+vsx -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ +; RUN: FileCheck %s --check-prefix=CHECK-BE + +define dso_local <8 x i8> @test8x32(i32 %i1, i32 %i2, i32 %i3, i32 %i4, + i32 %i5, i32 %i6, i32 %i7, i32 %i8) { +; CHECK-LABEL: test8x32: +; CHECK: # %bb.0: +; CHECK-NEXT: rldimi r3, r4, 32, 0 +; CHECK-NEXT: rldimi r5, r6, 32, 0 +; CHECK-NEXT: addis r11, r2, .LCPI0_0@toc@ha +; CHECK-NEXT: rldimi r7, r8, 32, 0 +; CHECK-NEXT: rldimi r9, r10, 32, 0 +; CHECK-NEXT: mtfprd f0, r3 +; CHECK-NEXT: addi r3, r11, .LCPI0_0@toc@l +; CHECK-NEXT: mtfprd f1, r5 +; CHECK-NEXT: lvx v4, 0, r3 +; CHECK-NEXT: mtfprd f2, r7 +; CHECK-NEXT: mtfprd f3, r9 +; CHECK-NEXT: xxmrghd v2, vs1, vs0 +; CHECK-NEXT: xxmrghd v3, vs3, vs2 +; CHECK-NEXT: vperm v2, v3, v2, v4 +; CHECK-NEXT: blr +; +; CHECK-BE-LABEL: test8x32: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: stw r10, -80(r1) +; CHECK-BE-NEXT: stw r9, -96(r1) +; CHECK-BE-NEXT: stw r8, -112(r1) +; CHECK-BE-NEXT: stw r7, -128(r1) +; CHECK-BE-NEXT: stw r6, -16(r1) +; CHECK-BE-NEXT: stw r5, -32(r1) +; CHECK-BE-NEXT: stw r4, -48(r1) +; CHECK-BE-NEXT: stw r3, -64(r1) +; CHECK-BE-NEXT: addi r3, r1, -80 +; CHECK-BE-NEXT: lxvw4x v2, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -96 +; CHECK-BE-NEXT: lxvw4x v3, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -112 +; CHECK-BE-NEXT: lxvw4x v4, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -128 +; CHECK-BE-NEXT: lxvw4x v5, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -16 +; CHECK-BE-NEXT: lxvw4x v0, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -32 +; CHECK-BE-NEXT: lxvw4x v1, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -48 +; CHECK-BE-NEXT: lxvw4x v6, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -64 +; CHECK-BE-NEXT: lxvw4x v7, 0, r3 +; CHECK-BE-NEXT: addis r3, r2, .LCPI0_0@toc@ha +; CHECK-BE-NEXT: vmrghw v2, v3, v2 +; CHECK-BE-NEXT: vmrghw v3, v5, v4 +; CHECK-BE-NEXT: vmrghw v4, v1, v0 +; CHECK-BE-NEXT: addi r3, r3, .LCPI0_0@toc@l +; CHECK-BE-NEXT: xxmrghd v2, v3, v2 +; CHECK-BE-NEXT: lxvw4x v8, 0, r3 +; CHECK-BE-NEXT: vmrghw v5, v7, v6 +; CHECK-BE-NEXT: xxmrghd v3, v5, v4 +; CHECK-BE-NEXT: vperm v2, v3, v2, v8 +; CHECK-BE-NEXT: blr +%v10 = insertelement <8 x i32> undef, i32 %i1, i32 0 +%v11 = insertelement <8 x i32> %v10, i32 %i2, i32 1 +%v12 = insertelement <8 x i32> %v11, i32 %i3, i32 2 +%v13 = insertelement <8 x i32> %v12, i32 %i4, i32 3 +%v14 = insertelement <8 x i32> %v13, i32 %i5, i32 4 +%v15 = insertelement <8 x i32> %v14, i32 %i6, i32 5 +%v16 = insertelement <8 x i32> %v15, i32 %i7, i32 6 +%v17 = insertelement <8 x i32> %v16, i32 %i8, i32 7 +%v2 = trunc <8 x i32> %v17 to <8 x i8> +ret <8 x i8> %v2 +} + +define dso_local <4 x i16> @test4x64(i64 %i1, i64 %i2, i64 %i3, i64 %i4) { +; CHECK-LABEL: test4x64: +; CHECK: # %bb.0: +; CHECK-NEXT: addis r7, r2, .LCPI1_0@toc@ha +; CHECK-NEXT: mtfprd f0, r5 +; CHECK-NEXT: mtfprd f1, r6 +; CHECK-NEXT: mtfprd f2, r3 +; CHECK-NEXT: addi r3, r7, .LCPI1_0@toc@l +; CHECK-NEXT: mtfprd f3, r4 +; CHECK-NEXT: xxmrghd v2, vs1, vs0 +; CHECK-NEXT: lvx v4, 0, r3 +; CHECK-NEXT: xxmrghd v3, vs3, vs2 +; CHECK-NEXT: vperm v2, v2, v3, v4 +; CHECK-NEXT: blr +; +; CHECK-BE-LABEL: test4x64: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: std r6, -8(r1) +; CHECK-BE-NEXT: std r5, -16(r1) +; CHECK-BE-NEXT: std r4, -24(r1) +; CHECK-BE-NEXT: std r3, -32(r1) +; CHECK-BE-NEXT: addi r3, r1, -32 +; CHECK-BE-NEXT: addis r4, r2, .LCPI1_0@toc@ha +; CHECK-BE-NEXT: addi r7, r1, -16 +; CHECK-BE-NEXT: lxvd2x v3, 0, r3 +; CHECK-BE-NEXT: addi r3, r4, .LCPI1_0@toc@l +; CHECK-BE-NEXT: lxvd2x v2, 0, r7 +; CHECK-BE-NEXT: lxvw4x v4, 0, r3 +; CHECK-BE-NEXT: vperm v2, v3, v2, v4 +; CHECK-BE-NEXT: blr +%v10 = insertelement <4 x i64> undef, i64 %i1, i32 0 +%v11 = insertelement <4 x i64> %v10, i64 %i2, i32 1 +%v12 = insertelement <4 x i64> %v11, i64 %i3, i32 2 +%v13 = insertelement <4 x i64> %v12, i64 %i4, i32 3 +%v2 = trunc <4 x i64> %v13 to <4 x i16> +ret <4 x i16> %v2 +} + +define dso_local <8 x i16> @test8x24(i32 %i1, i32 %i2, i32 %i3, i32 %i4, + i32 %i5, i32 %i6, i32 %i7, i32 %i8) { +; CHECK-LABEL: test8x24: +; CHECK: # %bb.0: +; CHECK-NEXT: mtvsrd v2, r3 +; CHECK-NEXT: mtvsrd v3, r4 +; CHECK-NEXT: mtvsrd v4, r5 +; CHECK-NEXT: mtvsrd v5, r6 +; CHECK-NEXT: mtvsrd v0, r7 +; CHECK-NEXT: mtvsrd v1, r8 +; CHECK-NEXT: vmrghh v2, v3, v2 +; CHECK-NEXT: mtvsrd v3, r9 +; CHECK-NEXT: vmrghh v4, v5, v4 +; CHECK-NEXT: mtvsrd v5, r10 +; CHECK-NEXT: vmrghh v0, v1, v0 +; CHECK-NEXT: vmrghh v3, v5, v3 +; CHECK-NEXT: vmrglw v2, v4, v2 +; CHECK-NEXT: vmrglw v3, v3, v0 +; CHECK-NEXT: xxmrgld v2, v3, v2 +; CHECK-NEXT: blr +; +; CHECK-BE-LABEL: test8x24: +; CHECK-BE: # %bb.0: +; CHECK-BE-NEXT: sth r10, -16(r1) +; CHECK-BE-NEXT: sth r9, -32(r1) +; CHECK-BE-NEXT: sth r8, -48(r1) +; CHECK-BE-NEXT: sth r7, -64(r1) +; CHECK-BE-NEXT: sth r6, -80(r1) +; CHECK-BE-NEXT: sth r5, -96(r1) +; CHECK-BE-NEXT: sth r4, -112(r1) +; CHECK-BE-NEXT: sth r3, -128(r1) +; CHECK-BE-NEXT: addi r3, r1, -16 +; CHECK-BE-NEXT: lxvw4x v2, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -32 +; CHECK-BE-NEXT: lxvw4x v3, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -48 +; CHECK-BE-NEXT: lxvw4x v4, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -64 +; CHECK-BE-NEXT: lxvw4x v5, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -80 +; CHECK-BE-NEXT: lxvw4x v0, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -96 +; CHECK-BE-NEXT: lxvw4x v1, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -112 +; CHECK-BE-NEXT: lxvw4x v6, 0, r3 +; CHECK-BE-NEXT: addi r3, r1, -128 +; CHECK-BE-NEXT: lxvw4x v7, 0, r3 +; CHECK-BE-NEXT: vmrghh v2, v3, v2 +; CHECK-BE-NEXT: vmrghh v3, v5, v4 +; CHECK-BE-NEXT: vmrghh v4, v1, v0 +; CHECK-BE-NEXT: vmrghw v2, v3, v2 +; CHECK-BE-NEXT: vmrghh v5, v7, v6 +; CHECK-BE-NEXT: vmrghw v3, v5, v4 +; CHECK-BE-NEXT: xxmrghd v2, v3, v2 +; CHECK-BE-NEXT: blr +%i11 = trunc i32 %i1 to i24 +%i21 = trunc i32 %i2 to i24 +%i31 = trunc i32 %i3 to i24 +%i41 = trunc i32 %i4 to i24 +%i51 = trunc i32 %i5 to i24 +%i61 = trunc i32 %i6 to i24 +%i71 = trunc i32 %i7 to i24 +%i81 = trunc i32 %i8 to i24 +%v10 = insertelement <8 x i24> undef, i24 %i11, i32 0 +%v11 = insertelement <8 x i24> %v10, i24 %i21, i32 1 +%v12 = insertelement <8 x i24> %v11, i24 %i31, i32 2 +%v13 = insertelement <8 x i24> %v12, i24 %i41, i32 3 +%v14 = insertelement <8 x i24> %v13, i24 %i51, i32 4 +%v15 = insertelement <8 x i24> %v14, i24 %i61, i32 5 +%v16 = insertelement <8 x i24> %v15, i24 %i71, i32 6 +%v17 = insertelement <8 x i24> %v16, i24 %i81, i32 7 +%v2 = trunc <8 x i24> %v17 to <8 x i16> +ret <8 x i16> %v2 +}