diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2638,10 +2638,19 @@ SDValue SelectionDAG::getSplatValue(SDValue V) { int SplatIdx; - if (SDValue SrcVector = getSplatSourceVector(V, SplatIdx)) - return getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(V), - SrcVector.getValueType().getScalarType(), SrcVector, + if (SDValue SrcVector = getSplatSourceVector(V, SplatIdx)) { + EVT SVT = SrcVector.getValueType().getScalarType(); + EVT LegalSVT = SVT; + if (NewNodesMustHaveLegalTypes && !TLI->isTypeLegal(SVT)) { + if (!SVT.isInteger()) + return SDValue(); + LegalSVT = TLI->getTypeToTransformTo(*getContext(), LegalSVT); + if (LegalSVT.bitsLT(SVT)) + return SDValue(); + } + return getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(V), LegalSVT, SrcVector, getVectorIdxConstant(SplatIdx, SDLoc(V))); + } return SDValue(); } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -508,6 +508,7 @@ SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; SDValue lowerSPLAT_VECTOR_PARTS(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerVectorMaskSplat(SDValue Op, SelectionDAG &DAG) const; SDValue lowerVectorMaskExt(SDValue Op, SelectionDAG &DAG, int64_t ExtTrueVal) const; diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1686,8 +1686,8 @@ return splatSplitI64WithVL(DL, VT, Scalar, VL, DAG); } -static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, - const RISCVSubtarget &Subtarget) { +SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, + SelectionDAG &DAG) const { SDValue V1 = Op.getOperand(0); SDValue V2 = Op.getOperand(1); SDLoc DL(Op); @@ -1696,7 +1696,7 @@ unsigned NumElts = VT.getVectorNumElements(); ShuffleVectorSDNode *SVN = cast(Op.getNode()); - MVT ContainerVT = getContainerForFixedLengthVector(DAG, VT, Subtarget); + MVT ContainerVT = getContainerForFixedLengthVector(VT); SDValue TrueMask, VL; std::tie(TrueMask, VL) = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget); @@ -2298,7 +2298,7 @@ return lowerVectorMaskSplat(Op, DAG); return lowerSPLAT_VECTOR(Op, DAG, Subtarget); case ISD::VECTOR_SHUFFLE: - return lowerVECTOR_SHUFFLE(Op, DAG, Subtarget); + return lowerVECTOR_SHUFFLE(Op, DAG); case ISD::CONCAT_VECTORS: { // Split CONCAT_VECTORS into a series of INSERT_SUBVECTOR nodes. This is // better than going through the stack, as the default expansion does. diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -28090,6 +28090,17 @@ return SDValue(); } +// A version of SelectionDAG::getSplatValue which may return illegal types, +// even after type legalization. +static SDValue getSplatValue(SDValue V, SelectionDAG &DAG) { + int SplatIdx; + if (SDValue SrcVector = DAG.getSplatSourceVector(V, SplatIdx)) + return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(V), + SrcVector.getValueType().getScalarType(), SrcVector, + DAG.getVectorIdxConstant(SplatIdx, SDLoc(V))); + return SDValue(); +} + static SDValue LowerScalarVariableShift(SDValue Op, SelectionDAG &DAG, const X86Subtarget &Subtarget) { MVT VT = Op.getSimpleValueType(); @@ -28100,7 +28111,7 @@ unsigned X86OpcI = getTargetVShiftUniformOpcode(Opcode, false); unsigned X86OpcV = getTargetVShiftUniformOpcode(Opcode, true); - if (SDValue BaseShAmt = DAG.getSplatValue(Amt)) { + if (SDValue BaseShAmt = getSplatValue(Amt, DAG)) { if (SupportedVectorShiftWithBaseAmnt(VT, Subtarget, Opcode)) { MVT EltVT = VT.getVectorElementType(); assert(EltVT.bitsLE(MVT::i64) && "Unexpected element type!"); diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll @@ -347,3 +347,29 @@ %s = shufflevector <8 x i64> %x, <8 x i64> , <8 x i32> ret <8 x i64> %s } + +define <4 x i8> @interleave_shuffles(<4 x i8> %x) { +; CHECK-LABEL: interleave_shuffles: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli zero, zero, e8,mf4,ta,mu +; CHECK-NEXT: vmv.x.s a0, v8 +; CHECK-NEXT: vsetivli a1, 4, e8,mf4,ta,mu +; CHECK-NEXT: vrgather.vi v25, v8, 1 +; CHECK-NEXT: addi a1, zero, 1 +; CHECK-NEXT: vmv.s.x v26, a1 +; CHECK-NEXT: vmv.v.i v27, 0 +; CHECK-NEXT: vsetivli a1, 4, e8,mf4,tu,mu +; CHECK-NEXT: vslideup.vi v27, v26, 3 +; CHECK-NEXT: addi a1, zero, 10 +; CHECK-NEXT: vsetivli a2, 1, e8,mf8,ta,mu +; CHECK-NEXT: vmv.s.x v0, a1 +; CHECK-NEXT: vsetivli a1, 4, e8,mf4,ta,mu +; CHECK-NEXT: vmv.v.x v8, a0 +; CHECK-NEXT: vsetivli a0, 4, e8,mf4,tu,mu +; CHECK-NEXT: vrgather.vv v8, v25, v27, v0.t +; CHECK-NEXT: ret + %y = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> + %z = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> + %w = shufflevector <4 x i8> %y, <4 x i8> %z, <4 x i32> + ret <4 x i8> %w +}