[llvm] 26bd225 - [RISCV] Ensure shuffle splat operands are type-legal
Fraser Cormack via llvm-commits
llvm-commits at lists.llvm.org
Thu May 20 10:08:08 PDT 2021
Author: Fraser Cormack
Date: 2021-05-20T18:00:03+01:00
New Revision: 26bd2250c1870f1983fd3439becfbb39e369b8a3
URL: https://github.com/llvm/llvm-project/commit/26bd2250c1870f1983fd3439becfbb39e369b8a3
DIFF: https://github.com/llvm/llvm-project/commit/26bd2250c1870f1983fd3439becfbb39e369b8a3.diff
LOG: [RISCV] Ensure shuffle splat operands are type-legal
The use of `SelectionDAG::getSplatValue` isn't guaranteed to return a
type-legal splat value as it may implicitly extract a vector element
from another shuffle. It is not permitted to introduce an illegal type
when lowering shuffles.
This patch addresses the crash by adding a boolean flag to
`getSplatValue`, defaulting to false, which when set will ensure a
type-legal return value. If it is unable to do that it will fail to
return a splat value.
I've been through the existing uses of `getSplatValue` in other targets
and was unable to find a need or test cases showing a need to update
their uses. In some cases, the call is made during `LegalizeVectorOps`
which may still produce illegal scalar types. In other situations, the
illegally-typed splat value may be quickly patched up to a legal type
(such as any-extending the returned `extract_vector_elt` up to a legal
type) before `LegalizeDAG` notices.
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D102687
Added:
Modified:
llvm/include/llvm/CodeGen/SelectionDAG.h
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 1cf30b991f02..ba5f3101d357 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1817,8 +1817,10 @@ class SelectionDAG {
SDValue getSplatSourceVector(SDValue V, int &SplatIndex);
/// If V is a splat vector, return its scalar source operand by extracting
- /// that element from the source vector.
- SDValue getSplatValue(SDValue V);
+ /// that element from the source vector. If LegalTypes is true, this method
+ /// may only return a legally-typed splat value. If it cannot legalize the
+ /// splatted value it will return SDValue().
+ SDValue getSplatValue(SDValue V, bool LegalTypes = false);
/// If a SHL/SRA/SRL node \p V has a constant or splat constant shift amount
/// that is less than the element bit-width of the shift node, return it.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 801bcfcaa00b..475bef0ac1dd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -2636,12 +2636,21 @@ SDValue SelectionDAG::getSplatSourceVector(SDValue V, int &SplatIdx) {
return SDValue();
}
-SDValue SelectionDAG::getSplatValue(SDValue V) {
+SDValue SelectionDAG::getSplatValue(SDValue V, bool LegalTypes) {
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 (LegalTypes && !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.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 1b34432d96fd..4b06e7feee78 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1849,7 +1849,7 @@ static SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG,
SDValue Gather;
// 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)) {
+ if (SDValue SplatValue = DAG.getSplatValue(V1, /*LegalTypes*/ true)) {
Gather = lowerScalarSplat(SplatValue, VL, ContainerVT, DL, DAG, Subtarget);
} else {
SDValue LHSIndices = DAG.getBuildVector(IndexVT, DL, GatherIndicesLHS);
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-shuffles.ll
index 20c2083e06f4..2ec244fd1779 100644
--- 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 @@ define <8 x i64> @vrgather_shuffle_vx_v8i64(<8 x i64> %x) {
%s = shufflevector <8 x i64> %x, <8 x i64> <i64 5, i64 5, i64 5, i64 5, i64 5, i64 5, i64 5, i64 5>, <8 x i32> <i32 0, i32 3, i32 10, i32 9, i32 4, i32 1, i32 7, i32 14>
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> <i32 0, i32 0, i32 0, i32 0>
+ %z = shufflevector <4 x i8> %x, <4 x i8> undef, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
+ %w = shufflevector <4 x i8> %y, <4 x i8> %z, <4 x i32> <i32 0, i32 4, i32 1, i32 5>
+ ret <4 x i8> %w
+}
More information about the llvm-commits
mailing list