Skip to content

Commit

Permalink
[RISCV] Recognize de-interleave shuffles with 2 sources. (#127272)
Browse files Browse the repository at this point in the history
We can use vnsrl+trunc on each source and concatenate the results
with vslideup.
    
For low LMUL it would be better to concat first, but I'm leaving
this for later.
  • Loading branch information
topperc authored Feb 17, 2025
1 parent 5d62a79 commit 9b7282e
Show file tree
Hide file tree
Showing 5 changed files with 543 additions and 41 deletions.
14 changes: 14 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5593,6 +5593,20 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
1 < count_if(Mask, [](int Idx) { return Idx != -1; })) {
if (SDValue Src = getSingleShuffleSrc(VT, V1, V2))
return getDeinterleaveShiftAndTrunc(DL, VT, Src, Factor, Index, DAG);
if (1 < count_if(Mask,
[&Mask](int Idx) { return Idx < (int)Mask.size(); }) &&
1 < count_if(Mask, [&Mask](int Idx) {
return Idx >= (int)Mask.size();
})) {
// Narrow each source and concatenate them.
// FIXME: For small LMUL it is better to concatenate first.
MVT HalfVT = VT.getHalfNumVectorElementsVT();
SDValue Lo =
getDeinterleaveShiftAndTrunc(DL, HalfVT, V1, Factor, Index, DAG);
SDValue Hi =
getDeinterleaveShiftAndTrunc(DL, HalfVT, V2, Factor, Index, DAG);
return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
}
}
}
}
Expand Down
34 changes: 13 additions & 21 deletions llvm/test/CodeGen/RISCV/rvv/fixed-vectors-deinterleave-load.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,26 @@ define {<16 x i1>, <16 x i1>} @vector_deinterleave_load_v16i1_v32i1(ptr %p) {
; CHECK-LABEL: vector_deinterleave_load_v16i1_v32i1:
; CHECK: # %bb.0:
; CHECK-NEXT: li a1, 32
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vmv.v.i v10, 0
; CHECK-NEXT: vid.v v9
; CHECK-NEXT: vsetvli zero, a1, e8, m2, ta, ma
; CHECK-NEXT: vlm.v v8, (a0)
; CHECK-NEXT: li a0, -256
; CHECK-NEXT: vlm.v v0, (a0)
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vadd.vv v11, v9, v9
; CHECK-NEXT: vsetvli zero, zero, e16, m2, ta, ma
; CHECK-NEXT: vmv.s.x v9, a0
; CHECK-NEXT: vsetvli zero, zero, e8, m1, ta, ma
; CHECK-NEXT: vadd.vi v12, v11, -16
; CHECK-NEXT: vmv.v.i v8, 0
; CHECK-NEXT: vmerge.vim v9, v8, 1, v0
; CHECK-NEXT: vsetivli zero, 2, e8, mf4, ta, ma
; CHECK-NEXT: vslidedown.vi v0, v8, 2
; CHECK-NEXT: vslidedown.vi v0, v0, 2
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
; CHECK-NEXT: vnsrl.wi v10, v9, 0
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vadd.vi v11, v11, -15
; CHECK-NEXT: vmerge.vim v13, v10, 1, v0
; CHECK-NEXT: vmv1r.v v0, v8
; CHECK-NEXT: vmerge.vim v8, v10, 1, v0
; CHECK-NEXT: vmerge.vim v8, v8, 1, v0
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
; CHECK-NEXT: vnsrl.wi v10, v8, 0
; CHECK-NEXT: vnsrl.wi v9, v9, 8
; CHECK-NEXT: vnsrl.wi v11, v8, 0
; CHECK-NEXT: vnsrl.wi v8, v8, 8
; CHECK-NEXT: vmv1r.v v0, v9
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, mu
; CHECK-NEXT: vrgather.vv v10, v13, v12, v0.t
; CHECK-NEXT: vrgather.vv v8, v13, v11, v0.t
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vslideup.vi v10, v11, 8
; CHECK-NEXT: vslideup.vi v9, v8, 8
; CHECK-NEXT: vmsne.vi v0, v10, 0
; CHECK-NEXT: vmsne.vi v8, v8, 0
; CHECK-NEXT: vmsne.vi v8, v9, 0
; CHECK-NEXT: ret
%vec = load <32 x i1>, ptr %p
%deinterleaved.results = call {<16 x i1>, <16 x i1>} @llvm.vector.deinterleave2.v32i1(<32 x i1> %vec)
Expand Down
86 changes: 86 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,89 @@ entry:
store <2 x i8> %shuffle.i5, ptr %out, align 1
ret void
}

define void @deinterleave4_0_i8_two_source(ptr %in0, ptr %in1, ptr %out) {
; CHECK-LABEL: deinterleave4_0_i8_two_source:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
; CHECK-NEXT: vle8.v v8, (a1)
; CHECK-NEXT: vle8.v v9, (a0)
; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma
; CHECK-NEXT: vnsrl.wi v8, v8, 0
; CHECK-NEXT: vnsrl.wi v9, v9, 0
; 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, 8, e8, mf2, ta, ma
; CHECK-NEXT: vslideup.vi v9, v8, 4
; CHECK-NEXT: vse8.v v9, (a2)
; CHECK-NEXT: ret
entry:
%0 = load <8 x i8>, ptr %in0, align 1
%1 = load <8 x i8>, ptr %in1, align 1
%shuffle.i5 = shufflevector <8 x i8> %0, <8 x i8> %1, <8 x i32> <i32 0, i32 4, i32 8, i32 12, i32 undef, i32 undef, i32 undef, i32 undef>
store <8 x i8> %shuffle.i5, ptr %out, align 1
ret void
}

define void @deinterleave4_8_i8_two_source(ptr %in0, ptr %in1, ptr %out) {
; CHECK-LABEL: deinterleave4_8_i8_two_source:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
; CHECK-NEXT: vle8.v v8, (a1)
; CHECK-NEXT: vle8.v v9, (a0)
; CHECK-NEXT: vsetivli zero, 2, e16, mf4, ta, ma
; CHECK-NEXT: vnsrl.wi v8, v8, 8
; CHECK-NEXT: vnsrl.wi v9, v9, 8
; 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, 8, e8, mf2, ta, ma
; CHECK-NEXT: vslideup.vi v9, v8, 4
; CHECK-NEXT: vse8.v v9, (a2)
; CHECK-NEXT: ret
entry:
%0 = load <8 x i8>, ptr %in0, align 1
%1 = load <8 x i8>, ptr %in1, align 1
%shuffle.i5 = shufflevector <8 x i8> %0, <8 x i8> %1, <8 x i32> <i32 1, i32 5, i32 9, i32 13, i32 undef, i32 undef, i32 undef, i32 undef>
store <8 x i8> %shuffle.i5, ptr %out, align 1
ret void
}

define void @deinterleave8_0_i8_two_source(ptr %in0, ptr %in1, ptr %out) {
; CHECK-LABEL: deinterleave8_0_i8_two_source:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
; CHECK-NEXT: vle8.v v8, (a0)
; CHECK-NEXT: vsetivli zero, 2, e8, mf2, ta, ma
; CHECK-NEXT: vle8.v v9, (a1)
; CHECK-NEXT: vsetvli zero, zero, e8, mf2, tu, ma
; CHECK-NEXT: vslideup.vi v8, v9, 1
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
; CHECK-NEXT: vse8.v v8, (a2)
; CHECK-NEXT: ret
entry:
%0 = load <8 x i8>, ptr %in0, align 1
%1 = load <8 x i8>, ptr %in1, align 1
%shuffle.i5 = shufflevector <8 x i8> %0, <8 x i8> %1, <8 x i32> <i32 0, i32 8, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
store <8 x i8> %shuffle.i5, ptr %out, align 1
ret void
}

define void @deinterleave8_8_i8_two_source(ptr %in0, ptr %in1, ptr %out) {
; CHECK-LABEL: deinterleave8_8_i8_two_source:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, mu
; CHECK-NEXT: vle8.v v8, (a0)
; CHECK-NEXT: vle8.v v9, (a1)
; CHECK-NEXT: vmv.v.i v0, -3
; CHECK-NEXT: vrgather.vi v9, v8, 1, v0.t
; CHECK-NEXT: vse8.v v9, (a2)
; CHECK-NEXT: ret
entry:
%0 = load <8 x i8>, ptr %in0, align 1
%1 = load <8 x i8>, ptr %in1, align 1
%shuffle.i5 = shufflevector <8 x i8> %0, <8 x i8> %1, <8 x i32> <i32 1, i32 9, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef>
store <8 x i8> %shuffle.i5, ptr %out, align 1
ret void
}
Loading

0 comments on commit 9b7282e

Please sign in to comment.