diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 48d8fc23dc1bb..132faf5b85c1a 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -5545,12 +5545,25 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG, })) { // Narrow each source and concatenate them. // FIXME: For small LMUL it is better to concatenate first. - MVT HalfVT = VT.getHalfNumVectorElementsVT(); + MVT EltVT = VT.getVectorElementType(); + auto EltCnt = VT.getVectorElementCount(); + MVT SubVT = + MVT::getVectorVT(EltVT, EltCnt.divideCoefficientBy(Factor)); + SDValue Lo = - getDeinterleaveShiftAndTrunc(DL, HalfVT, V1, Factor, Index, DAG); + getDeinterleaveShiftAndTrunc(DL, SubVT, V1, Factor, Index, DAG); SDValue Hi = - getDeinterleaveShiftAndTrunc(DL, HalfVT, V2, Factor, Index, DAG); - return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi); + getDeinterleaveShiftAndTrunc(DL, SubVT, V2, Factor, Index, DAG); + + SDValue Concat = + DAG.getNode(ISD::CONCAT_VECTORS, DL, + SubVT.getDoubleNumVectorElementsVT(), Lo, Hi); + if (Factor == 2) + return Concat; + + SDValue Vec = DAG.getUNDEF(VT); + return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT, Vec, Concat, + DAG.getVectorIdxConstant(0, DL)); } } } diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll index 5e6d7c1eedb76..0b4231cedcab5 100644 --- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll +++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll @@ -378,8 +378,9 @@ define void @deinterleave4_0_i8_two_source(ptr %in0, ptr %in1, ptr %out) { ; CHECK-NEXT: vsetvli zero, zero, e8, mf8, ta, ma ; CHECK-NEXT: vnsrl.wi v8, v8, 0 ; CHECK-NEXT: vnsrl.wi v9, v9, 0 +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vslideup.vi v9, v8, 2 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma -; CHECK-NEXT: vslideup.vi v9, v8, 4 ; CHECK-NEXT: vse8.v v9, (a2) ; CHECK-NEXT: ret entry: @@ -402,8 +403,9 @@ define void @deinterleave4_8_i8_two_source(ptr %in0, ptr %in1, ptr %out) { ; CHECK-NEXT: vsetvli zero, zero, e8, mf8, ta, ma ; CHECK-NEXT: vnsrl.wi v8, v8, 0 ; CHECK-NEXT: vnsrl.wi v9, v9, 0 +; CHECK-NEXT: vsetivli zero, 4, e8, mf4, ta, ma +; CHECK-NEXT: vslideup.vi v9, v8, 2 ; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma -; CHECK-NEXT: vslideup.vi v9, v8, 4 ; CHECK-NEXT: vse8.v v9, (a2) ; CHECK-NEXT: ret entry: