[RISCV][P-ext] Generalize lowerVECTOR_SHUFFLEAsRV32PNarrowingShift (#210522)
The previous implementation only matches `shuffle(extract_subvector(src), extract_subvector(src), mask)`. This patch generalizes it to `shuffle(a, b, mask)`, so we can now lower it to `PNSRL(concat(a,b), element_bits)` if it is a deinterleave shuffle. And we use `foldConcatVector` to handle the original pattern with `extract_subvector`.
This commit is contained in:
parent
b8300a7665
commit
b9b454166e
3 changed files with 142 additions and 31 deletions
|
|
@ -2574,3 +2574,71 @@ int16x4_t test_pnziph_i16x4(int32x2_t rs1, int32x2_t rs2) {
|
|||
uint16x4_t test_pnziph_u16x4(uint32x2_t rs1, uint32x2_t rs2) {
|
||||
return __riscv_pnziph_u16x4(rs1, rs2);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_pzip_i8x8:
|
||||
// RV32: wzip8p
|
||||
// RV64: zip8p
|
||||
int8x8_t test_pzip_i8x8(int8x4_t a, int8x4_t b) {
|
||||
return __riscv_pzip_i8x8(a, b);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_pzip_u8x8:
|
||||
// RV32: wzip8p
|
||||
// RV64: zip8p
|
||||
uint8x8_t test_pzip_u8x8(uint8x4_t a, uint8x4_t b) {
|
||||
return __riscv_pzip_u8x8(a, b);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_pzip_i16x4:
|
||||
// RV32: wzip16p
|
||||
// RV64: zip16p
|
||||
int16x4_t test_pzip_i16x4(int16x2_t a, int16x2_t b) {
|
||||
return __riscv_pzip_i16x4(a, b);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_pzip_u16x4:
|
||||
// RV32: wzip16p
|
||||
// RV64: zip16p
|
||||
uint16x4_t test_pzip_u16x4(uint16x2_t a, uint16x2_t b) {
|
||||
return __riscv_pzip_u16x4(a, b);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_punzipe_i8x4:
|
||||
// RV32: pncvt.b
|
||||
// RV64: pncvt.wb
|
||||
int8x4_t test_punzipe_i8x4(int8x8_t a) { return __riscv_punzipe_i8x4(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipo_i8x4:
|
||||
// RV32: pncvth.b
|
||||
// RV64: pncvth.wb
|
||||
int8x4_t test_punzipo_i8x4(int8x8_t a) { return __riscv_punzipo_i8x4(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipe_u8x4:
|
||||
// RV32: pncvt.b
|
||||
// RV64: pncvt.wb
|
||||
uint8x4_t test_punzipe_u8x4(uint8x8_t a) { return __riscv_punzipe_u8x4(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipo_u8x4:
|
||||
// RV32: pncvth.b
|
||||
// RV64: pncvth.wb
|
||||
uint8x4_t test_punzipo_u8x4(uint8x8_t a) { return __riscv_punzipo_u8x4(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipe_i16x2:
|
||||
// RV32: pncvt.h
|
||||
// RV64: pncvt.wh
|
||||
int16x2_t test_punzipe_i16x2(int16x4_t a) { return __riscv_punzipe_i16x2(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipo_i16x2:
|
||||
// RV32: pncvth.h
|
||||
// RV64: pncvth.wh
|
||||
int16x2_t test_punzipo_i16x2(int16x4_t a) { return __riscv_punzipo_i16x2(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipe_u16x2:
|
||||
// RV32: pncvt.h
|
||||
// RV64: pncvt.wh
|
||||
uint16x2_t test_punzipe_u16x2(uint16x4_t a) { return __riscv_punzipe_u16x2(a); }
|
||||
|
||||
// CHECK-LABEL: test_punzipo_u16x2:
|
||||
// RV32: pncvth.h
|
||||
// RV64: pncvth.wh
|
||||
uint16x2_t test_punzipo_u16x2(uint16x4_t a) { return __riscv_punzipo_u16x2(a); }
|
||||
|
|
|
|||
|
|
@ -6457,12 +6457,8 @@ static SDValue lowerVECTOR_SHUFFLEAsPUnzip(ShuffleVectorSDNode *SVN,
|
|||
return DAG.getNode(Opc, DL, VT, V1, V2);
|
||||
}
|
||||
|
||||
// Match a legalized single-source deinterleave shuffle where the source
|
||||
// vector was split into two extract_subvectors of the same vector, e.g.
|
||||
// t20: v4i8 = extract_subvector t5, 0
|
||||
// t19: v4i8 = extract_subvector t5, 4
|
||||
// t21: v4i8 = vector_shuffle<0,2,4,6> t20, t19
|
||||
// and lower it to an RV32 P narrowing shift on the original source.
|
||||
// Match a legalized deinterleave shuffle on two RV32 vector halves and lower
|
||||
// it to an RV32 P narrowing shift on the concatenated source.
|
||||
static SDValue
|
||||
lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(ShuffleVectorSDNode *SVN,
|
||||
const RISCVSubtarget &Subtarget,
|
||||
|
|
@ -6473,41 +6469,24 @@ lowerVECTOR_SHUFFLEAsRV32PNarrowingShift(ShuffleVectorSDNode *SVN,
|
|||
|
||||
SDValue V1 = SVN->getOperand(0);
|
||||
SDValue V2 = SVN->getOperand(1);
|
||||
SDLoc DL(SVN);
|
||||
unsigned NumElts = VT.getVectorNumElements();
|
||||
|
||||
// The inputs should be two extract_subvectors from the same source.
|
||||
using namespace llvm::SDPatternMatch;
|
||||
SDValue Src;
|
||||
int64_t V1Index, V2Index;
|
||||
if (!sd_match(V1, m_ExtractSubvector(m_Value(Src), m_ConstInt(V1Index))) ||
|
||||
!sd_match(V2, m_ExtractSubvector(m_Specific(Src), m_ConstInt(V2Index))))
|
||||
return SDValue();
|
||||
SDValue Src = foldConcatVector(V1, V2);
|
||||
if (!Src) {
|
||||
MVT SrcVT = VT == MVT::v4i8 ? MVT::v8i8 : MVT::v4i16;
|
||||
Src = DAG.getNode(ISD::CONCAT_VECTORS, DL, SrcVT, V1, V2);
|
||||
}
|
||||
|
||||
// The source vector should be twice the size.
|
||||
unsigned NumElts = VT.getVectorNumElements();
|
||||
if (Src.getValueType().getVectorNumElements() != 2 * NumElts)
|
||||
return SDValue();
|
||||
|
||||
// The two extract_subvectors should be from different halves.
|
||||
if ((V1Index != 0 || V2Index != NumElts) &&
|
||||
(V1Index != NumElts || V2Index != 0))
|
||||
return SDValue();
|
||||
|
||||
// Translate the shuffle mask, which indexes into the concatenation of V1
|
||||
// and V2, into indices into Src.
|
||||
SmallVector<int, 4> Indices(NumElts, -1);
|
||||
for (auto [I, M] : enumerate(SVN->getMask())) {
|
||||
if (M < 0)
|
||||
continue;
|
||||
int64_t Base = static_cast<unsigned>(M) < NumElts ? V1Index : V2Index;
|
||||
Indices[I] = Base + (M % NumElts);
|
||||
}
|
||||
|
||||
unsigned Index = 0;
|
||||
if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(Indices, 2, Index))
|
||||
if (!ShuffleVectorInst::isDeInterleaveMaskOfFactor(SVN->getMask(), 2, Index))
|
||||
return SDValue();
|
||||
|
||||
unsigned EltBits = VT.getVectorElementType().getSizeInBits();
|
||||
SDLoc DL(SVN);
|
||||
return DAG.getNode(RISCVISD::PNSRL, DL, VT, Src,
|
||||
DAG.getConstant(Index * EltBits, DL, MVT::i32));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,5 +254,69 @@ define <4 x i16> @test_unzip16hp_v4i16_partial_poison(<4 x i16> %a, <4 x i16> %b
|
|||
%r = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 1, i32 3, i32 poison, i32 7>
|
||||
ret <4 x i16> %r
|
||||
}
|
||||
|
||||
define i32 @test_punzipe_v4i8_coerce(i64 %a.coerce) {
|
||||
; RV32-LABEL: test_punzipe_v4i8_coerce:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: pncvt.b a0, a0
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: test_punzipe_v4i8_coerce:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: pncvt.wb a0, a0
|
||||
; RV64-NEXT: ret
|
||||
%a = bitcast i64 %a.coerce to <8 x i8>
|
||||
%r = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
|
||||
%ret = bitcast <4 x i8> %r to i32
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_punzipo_v4i8_coerce(i64 %a.coerce) {
|
||||
; RV32-LABEL: test_punzipo_v4i8_coerce:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: pncvth.b a0, a0
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: test_punzipo_v4i8_coerce:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: pncvth.wb a0, a0
|
||||
; RV64-NEXT: ret
|
||||
%a = bitcast i64 %a.coerce to <8 x i8>
|
||||
%r = shufflevector <8 x i8> %a, <8 x i8> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
|
||||
%ret = bitcast <4 x i8> %r to i32
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_punzipe_v2i16_coerce(i64 %a.coerce) {
|
||||
; RV32-LABEL: test_punzipe_v2i16_coerce:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: pncvt.h a0, a0
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: test_punzipe_v2i16_coerce:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: pncvt.wh a0, a0
|
||||
; RV64-NEXT: ret
|
||||
%a = bitcast i64 %a.coerce to <4 x i16>
|
||||
%r = shufflevector <4 x i16> %a, <4 x i16> poison, <2 x i32> <i32 0, i32 2>
|
||||
%ret = bitcast <2 x i16> %r to i32
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_punzipo_v2i16_coerce(i64 %a.coerce) {
|
||||
; RV32-LABEL: test_punzipo_v2i16_coerce:
|
||||
; RV32: # %bb.0:
|
||||
; RV32-NEXT: pncvth.h a0, a0
|
||||
; RV32-NEXT: ret
|
||||
;
|
||||
; RV64-LABEL: test_punzipo_v2i16_coerce:
|
||||
; RV64: # %bb.0:
|
||||
; RV64-NEXT: pncvth.wh a0, a0
|
||||
; RV64-NEXT: ret
|
||||
%a = bitcast i64 %a.coerce to <4 x i16>
|
||||
%r = shufflevector <4 x i16> %a, <4 x i16> poison, <2 x i32> <i32 1, i32 3>
|
||||
%ret = bitcast <2 x i16> %r to i32
|
||||
ret i32 %ret
|
||||
}
|
||||
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
|
||||
; CHECK: {{.*}}
|
||||
|
|
|
|||
Loading…
Reference in a new issue