We were crashing when lowering interleave shuffles like
(shuffle <0,3,1,4>, x:v4i8, y:v4i8)
Where it was technically an unary shuffle (both EvenSrc and OddSrc point
to the first operand), but the resulting extract_subvectors were out of
bounds.
This checks to make sure that the vectors being extracted are within
range.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | ||
---|---|---|
3283–3284 | I think this needs to be int to avoid signed/unsigned comparison warnings against EvenSrc/OddSrc. |
I think this made us no longer support
define <8 x i8> @foo(<8 x i8> %x, <8 x i8> %y) { ; V128-LABEL: unary_interleave_v4i8_invalid: ; V128: # %bb.0: ; V128-NEXT: lui a0, %hi(.LCPI17_0) ; V128-NEXT: addi a0, a0, %lo(.LCPI17_0) ; V128-NEXT: vsetivli zero, 4, e8, mf4, ta, ma ; V128-NEXT: vle8.v v10, (a0) ; V128-NEXT: vrgather.vv v9, v8, v10 ; V128-NEXT: vmv1r.v v8, v9 ; V128-NEXT: ret ; ; V512-LABEL: unary_interleave_v4i8_invalid: ; V512: # %bb.0: ; V512-NEXT: lui a0, %hi(.LCPI17_0) ; V512-NEXT: addi a0, a0, %lo(.LCPI17_0) ; V512-NEXT: vsetivli zero, 4, e8, mf8, ta, ma ; V512-NEXT: vle8.v v10, (a0) ; V512-NEXT: vrgather.vv v9, v8, v10 ; V512-NEXT: vmv1r.v v8, v9 ; V512-NEXT: ret %a = shufflevector <8 x i8> %x, <8 x i8> %y, <8 x i32> <i32 0, i32 12, i32 1, i32 13, i32 2, i32 14, i32 3, i32 15> ret <8 x i8> %a }
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | ||
---|---|---|
3297 | I wonder if the fix should be if (EvenSrc % (NumElts / 2) != 0 || OddSrc % (NumElts /2) != 0) |
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | ||
---|---|---|
3297 | That works for the first two cases mentioned but then it seems to miss the interleave in this case: ; This interleaves the first 2 elements of a vector in opposite order. With ; undefs for the remaining elements. We use to miscompile this. define <4 x i8> @unary_interleave_10uu_v4i8(<4 x i8> %x) { %a = shufflevector <4 x i8> %x, <4 x i8> poison, <4 x i32> <i32 1, i32 0, i32 undef, i32 undef> ret <4 x i8> %a } I noticed we also probably want to support non-multiple-of-numelts offsets like this: shufflevector <4 x i32> %x, <4 x i32> %y, <4 x i32> <i32 0, i32 5, i32 1, i32 6> I've updated the patch to check the range given we know the start indices and size of each vector being interleaved, but there's probably a more elegant way of expressing this that I'm missing |
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | ||
---|---|---|
3297 | Does that case in unary_interleave_10uu_v4i8 violate this rule for the extract_subvector? /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR. /// Let the result type be T, then IDX represents the starting element number /// from which a subvector of type T is extracted. IDX must be a constant /// multiple of T's known minimum vector length. |
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | ||
---|---|---|
3299 | I think you maybe you want I think maybe you can do something like int HalfNumElts = NumElts / 2; return (((EvenSrc % NumElts) + HalfNumElts) <= NumElts) && (((OddSrc % NumElts) + HalfNumElts) <= NumElts); |
I think this needs to be int to avoid signed/unsigned comparison warnings against EvenSrc/OddSrc.