Skip to content

Commit

Permalink
[RISCV] Add basic support for matching shuffles to vslidedown.vi.
Browse files Browse the repository at this point in the history
Specifically the unary shuffle case where the elements being
shifted in are undef. This handles the shuffles produce by expanding
llvm.reduce.mul.

I did not reduce the VL which would increase the number of vsetvlis,
but may improve the execution speed. We'd also want to narrow the
multiplies so we could share vsetvlis between the vslidedown.vi and
the next multiply.

Reviewed By: frasercrmck

Differential Revision: https://reviews.llvm.org/D117239
  • Loading branch information
topperc committed Jan 14, 2022
1 parent ac6b489 commit 2baa1df
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 328 deletions.
43 changes: 43 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Expand Up @@ -2297,6 +2297,35 @@ static SDValue lowerScalarSplat(SDValue Scalar, SDValue VL, MVT VT, SDLoc DL,
return splatSplitI64WithVL(DL, VT, Scalar, VL, DAG);
}

// Is the mask a slidedown that shifts in undefs.
static int matchShuffleAsSlideDown(ArrayRef<int> Mask) {
int Size = Mask.size();

// Elements shifted in should be undef.
auto CheckUndefs = [&](int Shift) {
for (int i = Size - Shift; i != Size; ++i)
if (Mask[i] >= 0)
return false;
return true;
};

// Elements should be shifted or undef.
auto MatchShift = [&](int Shift) {
for (int i = 0; i != Size - Shift; ++i)
if (Mask[i] >= 0 && Mask[i] != Shift + i)
return false;
return true;
};

// Try all possible shifts.
for (int Shift = 1; Shift != Size; ++Shift)
if (CheckUndefs(Shift) && MatchShift(Shift))
return Shift;

// No match.
return -1;
}

static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
SDValue V1 = Op.getOperand(0);
Expand Down Expand Up @@ -2382,6 +2411,20 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
}
}

// Try to match as a slidedown.
int SlideAmt = matchShuffleAsSlideDown(SVN->getMask());
if (SlideAmt >= 0) {
// TODO: Should we reduce the VL to account for the upper undef elements?
// Requires additional vsetvlis, but might be faster to execute.
V1 = convertToScalableVector(ContainerVT, V1, DAG, Subtarget);
SDValue SlideDown =
DAG.getNode(RISCVISD::VSLIDEDOWN_VL, DL, ContainerVT,
DAG.getUNDEF(ContainerVT), V1,
DAG.getConstant(SlideAmt, DL, XLenVT),
TrueMask, VL);
return convertFromScalableVector(VT, SlideDown, DAG, Subtarget);
}

// Detect shuffles which can be re-expressed as vector selects; these are
// shuffles in which each element in the destination is taken from an element
// at the corresponding index in either source vectors.
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv/fixed-vectors-fp-shuffles.ll
Expand Up @@ -235,3 +235,23 @@ define <4 x double> @vrgather_shuffle_vx_v4f64(<4 x double> %x) {
%s = shufflevector <4 x double> %x, <4 x double> <double 2.0, double 2.0, double 2.0, double 2.0>, <4 x i32> <i32 0, i32 3, i32 6, i32 5>
ret <4 x double> %s
}

define <4 x half> @slidedown_v4f16(<4 x half> %x) {
; CHECK-LABEL: slidedown_v4f16:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, mu
; CHECK-NEXT: vslidedown.vi v8, v8, 1
; CHECK-NEXT: ret
%s = shufflevector <4 x half> %x, <4 x half> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 undef>
ret <4 x half> %s
}

define <8 x float> @slidedown_v8f32(<8 x float> %x) {
; CHECK-LABEL: slidedown_v8f32:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, mu
; CHECK-NEXT: vslidedown.vi v8, v8, 3
; CHECK-NEXT: ret
%s = shufflevector <8 x float> %x, <8 x float> poison, <8 x i32> <i32 3, i32 undef, i32 5, i32 6, i32 undef, i32 undef, i32 undef, i32 undef>
ret <8 x float> %s
}
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll
Expand Up @@ -541,3 +541,23 @@ define <8 x i8> @widen_splat_ve3(<4 x i8> %v) {
%shuf = shufflevector <4 x i8> %v, <4 x i8> undef, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
ret <8 x i8> %shuf
}

define <4 x i16> @slidedown_v4i16(<4 x i16> %x) {
; CHECK-LABEL: slidedown_v4i16:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 4, e16, mf2, ta, mu
; CHECK-NEXT: vslidedown.vi v8, v8, 1
; CHECK-NEXT: ret
%s = shufflevector <4 x i16> %x, <4 x i16> poison, <4 x i32> <i32 1, i32 2, i32 3, i32 undef>
ret <4 x i16> %s
}

define <8 x i32> @slidedown_v8i32(<8 x i32> %x) {
; CHECK-LABEL: slidedown_v8i32:
; CHECK: # %bb.0:
; CHECK-NEXT: vsetivli zero, 8, e32, m2, ta, mu
; CHECK-NEXT: vslidedown.vi v8, v8, 3
; CHECK-NEXT: ret
%s = shufflevector <8 x i32> %x, <8 x i32> poison, <8 x i32> <i32 3, i32 undef, i32 5, i32 6, i32 undef, i32 undef, i32 undef, i32 undef>
ret <8 x i32> %s
}

0 comments on commit 2baa1df

Please sign in to comment.