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); @@ -1845,9 +1845,14 @@ ContainerVT.changeVectorElementType(IndexVT.getScalarType()); SDValue Gather; + // We can't introduce illegal types, so ensure that a splatted element is + // either a constant integer (and can be freely extended to XLenVT) or + // type-legal. // TODO: This doesn't trigger for i64 vectors on RV32, since there we // encounter a bitcasted BUILD_VECTOR with low/high i32 values. - if (SDValue SplatValue = DAG.getSplatValue(V1)) { + SDValue SplatValue = DAG.getSplatValue(V1); + if (SplatValue && (isa(SplatValue) || + isTypeLegal(SplatValue.getValueType()))) { Gather = lowerScalarSplat(SplatValue, VL, ContainerVT, DL, DAG, Subtarget); } else { SDValue LHSIndices = DAG.getBuildVector(IndexVT, DL, GatherIndicesLHS); @@ -2298,7 +2303,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/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,31 @@ %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: vsetivli a0, 4, e8,mf4,ta,mu +; CHECK-NEXT: vrgather.vi v25, v8, 0 +; CHECK-NEXT: vrgather.vi v26, v8, 1 +; CHECK-NEXT: addi a0, zero, 1 +; CHECK-NEXT: vmv.s.x v27, a0 +; CHECK-NEXT: vmv.v.i v28, 0 +; CHECK-NEXT: vsetivli a0, 4, e8,mf4,tu,mu +; CHECK-NEXT: vmv1r.v v29, v28 +; CHECK-NEXT: vslideup.vi v29, v27, 3 +; CHECK-NEXT: vsetivli a0, 3, e8,mf4,tu,mu +; CHECK-NEXT: vslideup.vi v28, v27, 2 +; CHECK-NEXT: vsetivli a0, 4, e8,mf4,ta,mu +; CHECK-NEXT: vrgather.vv v8, v25, v28 +; CHECK-NEXT: addi a0, zero, 10 +; CHECK-NEXT: vsetivli a1, 1, e8,mf8,ta,mu +; CHECK-NEXT: vmv.s.x v0, a0 +; CHECK-NEXT: vsetivli a0, 4, e8,mf4,tu,mu +; CHECK-NEXT: vrgather.vv v8, v26, v29, 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 +}