Commit 565d404f authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Remove shuffle functions from instruction-selector

Change all the callers in backend specific instruction-selector
to call the functions in simd-shuffle.h

Also copy over the documentation that was in instruction-selector.h
to simd-shuffle.h.

Bug: v8:10696
Change-Id: Ic9339d6481316f18c19f35c45460e700b45ec38e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2327182
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69150}
parent 2d395f65
...@@ -2877,12 +2877,12 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2877,12 +2877,12 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
uint8_t shuffle32x4[4]; uint8_t shuffle32x4[4];
ArmOperandGenerator g(this); ArmOperandGenerator g(this);
int index = 0; int index = 0;
if (TryMatch32x4Shuffle(shuffle, shuffle32x4)) { if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
if (TryMatchDup<4>(shuffle, &index)) { if (wasm::SimdShuffle::TryMatchSplat<4>(shuffle, &index)) {
DCHECK_GT(4, index); DCHECK_GT(4, index);
Emit(kArmS128Dup, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArmS128Dup, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseImmediate(Neon32), g.UseImmediate(index % 4)); g.UseImmediate(Neon32), g.UseImmediate(index % 4));
} else if (TryMatchIdentity(shuffle)) { } else if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) {
EmitIdentity(node); EmitIdentity(node);
} else { } else {
// 32x4 shuffles are implemented as s-register moves. To simplify these, // 32x4 shuffles are implemented as s-register moves. To simplify these,
...@@ -2894,13 +2894,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2894,13 +2894,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
} }
return; return;
} }
if (TryMatchDup<8>(shuffle, &index)) { if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) {
DCHECK_GT(8, index); DCHECK_GT(8, index);
Emit(kArmS128Dup, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArmS128Dup, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseImmediate(Neon16), g.UseImmediate(index % 8)); g.UseImmediate(Neon16), g.UseImmediate(index % 8));
return; return;
} }
if (TryMatchDup<16>(shuffle, &index)) { if (wasm::SimdShuffle::TryMatchSplat<16>(shuffle, &index)) {
DCHECK_GT(16, index); DCHECK_GT(16, index);
Emit(kArmS128Dup, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArmS128Dup, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseImmediate(Neon8), g.UseImmediate(index % 16)); g.UseImmediate(Neon8), g.UseImmediate(index % 16));
...@@ -2913,7 +2913,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2913,7 +2913,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
return; return;
} }
uint8_t offset; uint8_t offset;
if (TryMatchConcat(shuffle, &offset)) { if (wasm::SimdShuffle::TryMatchConcat(shuffle, &offset)) {
Emit(kArmS8x16Concat, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArmS8x16Concat, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseRegister(input1), g.UseImmediate(offset)); g.UseRegister(input1), g.UseImmediate(offset));
return; return;
......
...@@ -3609,18 +3609,18 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3609,18 +3609,18 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
Node* input0 = node->InputAt(0); Node* input0 = node->InputAt(0);
Node* input1 = node->InputAt(1); Node* input1 = node->InputAt(1);
uint8_t offset; uint8_t offset;
if (TryMatchConcat(shuffle, &offset)) { if (wasm::SimdShuffle::TryMatchConcat(shuffle, &offset)) {
Emit(kArm64S8x16Concat, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArm64S8x16Concat, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseRegister(input1), g.UseImmediate(offset)); g.UseRegister(input1), g.UseImmediate(offset));
return; return;
} }
int index = 0; int index = 0;
if (TryMatch32x4Shuffle(shuffle, shuffle32x4)) { if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
if (TryMatchDup<4>(shuffle, &index)) { if (wasm::SimdShuffle::TryMatchSplat<4>(shuffle, &index)) {
DCHECK_GT(4, index); DCHECK_GT(4, index);
Emit(kArm64S128Dup, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArm64S128Dup, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseImmediate(4), g.UseImmediate(index % 4)); g.UseImmediate(4), g.UseImmediate(index % 4));
} else if (TryMatchIdentity(shuffle)) { } else if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) {
EmitIdentity(node); EmitIdentity(node);
} else { } else {
Emit(kArm64S32x4Shuffle, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArm64S32x4Shuffle, g.DefineAsRegister(node), g.UseRegister(input0),
...@@ -3628,13 +3628,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3628,13 +3628,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
} }
return; return;
} }
if (TryMatchDup<8>(shuffle, &index)) { if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) {
DCHECK_GT(8, index); DCHECK_GT(8, index);
Emit(kArm64S128Dup, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArm64S128Dup, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseImmediate(8), g.UseImmediate(index % 8)); g.UseImmediate(8), g.UseImmediate(index % 8));
return; return;
} }
if (TryMatchDup<16>(shuffle, &index)) { if (wasm::SimdShuffle::TryMatchSplat<16>(shuffle, &index)) {
DCHECK_GT(16, index); DCHECK_GT(16, index);
Emit(kArm64S128Dup, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kArm64S128Dup, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseImmediate(16), g.UseImmediate(index % 16)); g.UseImmediate(16), g.UseImmediate(index % 16));
......
...@@ -2748,7 +2748,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2748,7 +2748,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
uint8_t shuffle16x8[8]; uint8_t shuffle16x8[8];
int index; int index;
const ShuffleEntry* arch_shuffle; const ShuffleEntry* arch_shuffle;
if (TryMatchConcat(shuffle, &offset)) { if (wasm::SimdShuffle::TryMatchConcat(shuffle, &offset)) {
// Swap inputs from the normal order for (v)palignr. // Swap inputs from the normal order for (v)palignr.
SwapShuffleInputs(node); SwapShuffleInputs(node);
is_swizzle = false; // It's simpler to just handle the general case. is_swizzle = false; // It's simpler to just handle the general case.
...@@ -2765,10 +2765,10 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2765,10 +2765,10 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
// same-as-first. // same-as-first.
src1_needs_reg = use_avx && arch_shuffle->src1_needs_reg; src1_needs_reg = use_avx && arch_shuffle->src1_needs_reg;
no_same_as_first = use_avx; no_same_as_first = use_avx;
} else if (TryMatch32x4Shuffle(shuffle, shuffle32x4)) { } else if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
uint8_t shuffle_mask = PackShuffle4(shuffle32x4); uint8_t shuffle_mask = PackShuffle4(shuffle32x4);
if (is_swizzle) { if (is_swizzle) {
if (TryMatchIdentity(shuffle)) { if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) {
// Bypass normal shuffle code generation in this case. // Bypass normal shuffle code generation in this case.
EmitIdentity(node); EmitIdentity(node);
return; return;
...@@ -2785,7 +2785,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2785,7 +2785,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
} else { } else {
// 2 operand shuffle // 2 operand shuffle
// A blend is more efficient than a general 32x4 shuffle; try it first. // A blend is more efficient than a general 32x4 shuffle; try it first.
if (TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kIA32S16x8Blend; opcode = kIA32S16x8Blend;
uint8_t blend_mask = PackBlend4(shuffle32x4); uint8_t blend_mask = PackBlend4(shuffle32x4);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
...@@ -2802,13 +2802,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2802,13 +2802,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} }
} }
} else if (TryMatch16x8Shuffle(shuffle, shuffle16x8)) { } else if (wasm::SimdShuffle::TryMatch16x8Shuffle(shuffle, shuffle16x8)) {
uint8_t blend_mask; uint8_t blend_mask;
if (TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kIA32S16x8Blend; opcode = kIA32S16x8Blend;
blend_mask = PackBlend8(shuffle16x8); blend_mask = PackBlend8(shuffle16x8);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} else if (TryMatchDup<8>(shuffle, &index)) { } else if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) {
opcode = kIA32S16x8Dup; opcode = kIA32S16x8Dup;
src0_needs_reg = false; src0_needs_reg = false;
imms[imm_count++] = index; imms[imm_count++] = index;
...@@ -2823,7 +2823,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2823,7 +2823,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
imms[imm_count++] = mask_hi; imms[imm_count++] = mask_hi;
if (!is_swizzle) imms[imm_count++] = blend_mask; if (!is_swizzle) imms[imm_count++] = blend_mask;
} }
} else if (TryMatchDup<16>(shuffle, &index)) { } else if (wasm::SimdShuffle::TryMatchSplat<16>(shuffle, &index)) {
opcode = kIA32S8x16Dup; opcode = kIA32S8x16Dup;
no_same_as_first = use_avx; no_same_as_first = use_avx;
src0_needs_reg = true; src0_needs_reg = true;
......
...@@ -3183,29 +3183,6 @@ void InstructionSelector::SwapShuffleInputs(Node* node) { ...@@ -3183,29 +3183,6 @@ void InstructionSelector::SwapShuffleInputs(Node* node) {
node->ReplaceInput(1, input0); node->ReplaceInput(1, input0);
} }
// static
bool InstructionSelector::TryMatch32x4Shuffle(const uint8_t* shuffle,
uint8_t* shuffle32x4) {
return wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4);
}
// static
bool InstructionSelector::TryMatch16x8Shuffle(const uint8_t* shuffle,
uint8_t* shuffle16x8) {
return wasm::SimdShuffle::TryMatch16x8Shuffle(shuffle, shuffle16x8);
}
// static
bool InstructionSelector::TryMatchConcat(const uint8_t* shuffle,
uint8_t* offset) {
return wasm::SimdShuffle::TryMatchConcat(shuffle, offset);
}
// static
bool InstructionSelector::TryMatchBlend(const uint8_t* shuffle) {
return wasm::SimdShuffle::TryMatchBlend(shuffle);
}
// static // static
int32_t InstructionSelector::Pack4Lanes(const uint8_t* shuffle) { int32_t InstructionSelector::Pack4Lanes(const uint8_t* shuffle) {
int32_t result = 0; int32_t result = 0;
......
...@@ -636,42 +636,6 @@ class V8_EXPORT_PRIVATE InstructionSelector final { ...@@ -636,42 +636,6 @@ class V8_EXPORT_PRIVATE InstructionSelector final {
// to specific architectural instructions. // to specific architectural instructions.
void SwapShuffleInputs(Node* node); void SwapShuffleInputs(Node* node);
// Tries to match an 8x16 byte shuffle to the identity shuffle, which is
// [0 1 ... 15]. This should be called after canonicalizing the shuffle, so
// the second identity shuffle, [16 17 .. 31] is converted to the first one.
static bool TryMatchIdentity(const uint8_t* shuffle) {
return wasm::SimdShuffle::TryMatchIdentity(shuffle);
}
// Tries to match a byte shuffle to a scalar splat operation. Returns the
// index of the lane if successful.
template <int LANES>
static bool TryMatchDup(const uint8_t* shuffle, int* index) {
return wasm::SimdShuffle::TryMatchSplat<LANES>(shuffle, index);
}
// Tries to match an 8x16 byte shuffle to an equivalent 32x4 shuffle. If
// successful, it writes the 32x4 shuffle word indices. E.g.
// [0 1 2 3 8 9 10 11 4 5 6 7 12 13 14 15] == [0 2 1 3]
static bool TryMatch32x4Shuffle(const uint8_t* shuffle, uint8_t* shuffle32x4);
// Tries to match an 8x16 byte shuffle to an equivalent 16x8 shuffle. If
// successful, it writes the 16x8 shuffle word indices. E.g.
// [0 1 8 9 2 3 10 11 4 5 12 13 6 7 14 15] == [0 4 1 5 2 6 3 7]
static bool TryMatch16x8Shuffle(const uint8_t* shuffle, uint8_t* shuffle16x8);
// Tries to match a byte shuffle to a concatenate operation, formed by taking
// 16 bytes from the 32 byte concatenation of the inputs. If successful, it
// writes the byte offset. E.g. [4 5 6 7 .. 16 17 18 19] concatenates both
// source vectors with offset 4. The shuffle should be canonicalized.
static bool TryMatchConcat(const uint8_t* shuffle, uint8_t* offset);
// Tries to match a byte shuffle to a blend operation, which is a shuffle
// where no lanes change position. E.g. [0 9 2 11 .. 14 31] interleaves the
// even lanes of the first source with the odd lanes of the second. The
// shuffle should be canonicalized.
static bool TryMatchBlend(const uint8_t* shuffle);
// Packs 4 bytes of shuffle into a 32 bit immediate. // Packs 4 bytes of shuffle into a 32 bit immediate.
static int32_t Pack4Lanes(const uint8_t* shuffle); static int32_t Pack4Lanes(const uint8_t* shuffle);
......
...@@ -2393,12 +2393,12 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2393,12 +2393,12 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
Node* input1 = node->InputAt(1); Node* input1 = node->InputAt(1);
uint8_t offset; uint8_t offset;
MipsOperandGenerator g(this); MipsOperandGenerator g(this);
if (TryMatchConcat(shuffle, &offset)) { if (wasm::SimdShuffle::TryMatchConcat(shuffle, &offset)) {
Emit(kMipsS8x16Concat, g.DefineSameAsFirst(node), g.UseRegister(input1), Emit(kMipsS8x16Concat, g.DefineSameAsFirst(node), g.UseRegister(input1),
g.UseRegister(input0), g.UseImmediate(offset)); g.UseRegister(input0), g.UseImmediate(offset));
return; return;
} }
if (TryMatch32x4Shuffle(shuffle, shuffle32x4)) { if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
Emit(kMipsS32x4Shuffle, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kMipsS32x4Shuffle, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseRegister(input1), g.UseImmediate(Pack4Lanes(shuffle32x4))); g.UseRegister(input1), g.UseImmediate(Pack4Lanes(shuffle32x4)));
return; return;
......
...@@ -3088,12 +3088,12 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3088,12 +3088,12 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
Node* input1 = node->InputAt(1); Node* input1 = node->InputAt(1);
uint8_t offset; uint8_t offset;
Mips64OperandGenerator g(this); Mips64OperandGenerator g(this);
if (TryMatchConcat(shuffle, &offset)) { if (wasm::SimdShuffle::TryMatchConcat(shuffle, &offset)) {
Emit(kMips64S8x16Concat, g.DefineSameAsFirst(node), g.UseRegister(input1), Emit(kMips64S8x16Concat, g.DefineSameAsFirst(node), g.UseRegister(input1),
g.UseRegister(input0), g.UseImmediate(offset)); g.UseRegister(input0), g.UseImmediate(offset));
return; return;
} }
if (TryMatch32x4Shuffle(shuffle, shuffle32x4)) { if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
Emit(kMips64S32x4Shuffle, g.DefineAsRegister(node), g.UseRegister(input0), Emit(kMips64S32x4Shuffle, g.DefineAsRegister(node), g.UseRegister(input0),
g.UseRegister(input1), g.UseImmediate(Pack4Lanes(shuffle32x4))); g.UseRegister(input1), g.UseImmediate(Pack4Lanes(shuffle32x4)));
return; return;
......
...@@ -3315,7 +3315,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3315,7 +3315,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
uint8_t shuffle16x8[8]; uint8_t shuffle16x8[8];
int index; int index;
const ShuffleEntry* arch_shuffle; const ShuffleEntry* arch_shuffle;
if (TryMatchConcat(shuffle, &offset)) { if (wasm::SimdShuffle::TryMatchConcat(shuffle, &offset)) {
// Swap inputs from the normal order for (v)palignr. // Swap inputs from the normal order for (v)palignr.
SwapShuffleInputs(node); SwapShuffleInputs(node);
is_swizzle = false; // It's simpler to just handle the general case. is_swizzle = false; // It's simpler to just handle the general case.
...@@ -3334,10 +3334,10 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3334,10 +3334,10 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
// same-as-first. // same-as-first.
src1_needs_reg = arch_shuffle->src1_needs_reg; src1_needs_reg = arch_shuffle->src1_needs_reg;
no_same_as_first = false; no_same_as_first = false;
} else if (TryMatch32x4Shuffle(shuffle, shuffle32x4)) { } else if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
uint8_t shuffle_mask = PackShuffle4(shuffle32x4); uint8_t shuffle_mask = PackShuffle4(shuffle32x4);
if (is_swizzle) { if (is_swizzle) {
if (TryMatchIdentity(shuffle)) { if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) {
// Bypass normal shuffle code generation in this case. // Bypass normal shuffle code generation in this case.
EmitIdentity(node); EmitIdentity(node);
return; return;
...@@ -3354,7 +3354,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3354,7 +3354,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
} else { } else {
// 2 operand shuffle // 2 operand shuffle
// A blend is more efficient than a general 32x4 shuffle; try it first. // A blend is more efficient than a general 32x4 shuffle; try it first.
if (TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kX64S16x8Blend; opcode = kX64S16x8Blend;
uint8_t blend_mask = PackBlend4(shuffle32x4); uint8_t blend_mask = PackBlend4(shuffle32x4);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
...@@ -3371,13 +3371,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3371,13 +3371,13 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} }
} }
} else if (TryMatch16x8Shuffle(shuffle, shuffle16x8)) { } else if (wasm::SimdShuffle::TryMatch16x8Shuffle(shuffle, shuffle16x8)) {
uint8_t blend_mask; uint8_t blend_mask;
if (TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kX64S16x8Blend; opcode = kX64S16x8Blend;
blend_mask = PackBlend8(shuffle16x8); blend_mask = PackBlend8(shuffle16x8);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} else if (TryMatchDup<8>(shuffle, &index)) { } else if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) {
opcode = kX64S16x8Dup; opcode = kX64S16x8Dup;
src0_needs_reg = false; src0_needs_reg = false;
imms[imm_count++] = index; imms[imm_count++] = index;
...@@ -3392,7 +3392,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3392,7 +3392,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
imms[imm_count++] = mask_hi; imms[imm_count++] = mask_hi;
if (!is_swizzle) imms[imm_count++] = blend_mask; if (!is_swizzle) imms[imm_count++] = blend_mask;
} }
} else if (TryMatchDup<16>(shuffle, &index)) { } else if (wasm::SimdShuffle::TryMatchSplat<16>(shuffle, &index)) {
opcode = kX64S8x16Dup; opcode = kX64S8x16Dup;
no_same_as_first = false; no_same_as_first = false;
src0_needs_reg = true; src0_needs_reg = true;
......
...@@ -22,6 +22,9 @@ class V8_EXPORT_PRIVATE SimdShuffle { ...@@ -22,6 +22,9 @@ class V8_EXPORT_PRIVATE SimdShuffle {
static void CanonicalizeShuffle(bool inputs_equal, uint8_t* shuffle, static void CanonicalizeShuffle(bool inputs_equal, uint8_t* shuffle,
bool* needs_swap, bool* is_swizzle); bool* needs_swap, bool* is_swizzle);
// Tries to match an 8x16 byte shuffle to the identity shuffle, which is
// [0 1 ... 15]. This should be called after canonicalizing the shuffle, so
// the second identity shuffle, [16 17 .. 31] is converted to the first one.
static bool TryMatchIdentity(const uint8_t* shuffle); static bool TryMatchIdentity(const uint8_t* shuffle);
// Tries to match a byte shuffle to a scalar splat operation. Returns the // Tries to match a byte shuffle to a scalar splat operation. Returns the
...@@ -48,12 +51,26 @@ class V8_EXPORT_PRIVATE SimdShuffle { ...@@ -48,12 +51,26 @@ class V8_EXPORT_PRIVATE SimdShuffle {
return true; return true;
} }
// Tries to match an 8x16 byte shuffle to an equivalent 32x4 shuffle. If
// successful, it writes the 32x4 shuffle word indices. E.g.
// [0 1 2 3 8 9 10 11 4 5 6 7 12 13 14 15] == [0 2 1 3]
static bool TryMatch32x4Shuffle(const uint8_t* shuffle, uint8_t* shuffle32x4); static bool TryMatch32x4Shuffle(const uint8_t* shuffle, uint8_t* shuffle32x4);
// Tries to match an 8x16 byte shuffle to an equivalent 16x8 shuffle. If
// successful, it writes the 16x8 shuffle word indices. E.g.
// [0 1 8 9 2 3 10 11 4 5 12 13 6 7 14 15] == [0 4 1 5 2 6 3 7]
static bool TryMatch16x8Shuffle(const uint8_t* shuffle, uint8_t* shuffle16x8); static bool TryMatch16x8Shuffle(const uint8_t* shuffle, uint8_t* shuffle16x8);
// Tries to match a byte shuffle to a concatenate operation, formed by taking
// 16 bytes from the 32 byte concatenation of the inputs. If successful, it
// writes the byte offset. E.g. [4 5 6 7 .. 16 17 18 19] concatenates both
// source vectors with offset 4. The shuffle should be canonicalized.
static bool TryMatchConcat(const uint8_t* shuffle, uint8_t* offset); static bool TryMatchConcat(const uint8_t* shuffle, uint8_t* offset);
// Tries to match a byte shuffle to a blend operation, which is a shuffle
// where no lanes change position. E.g. [0 9 2 11 .. 14 31] interleaves the
// even lanes of the first source with the odd lanes of the second. The
// shuffle should be canonicalized.
static bool TryMatchBlend(const uint8_t* shuffle); static bool TryMatchBlend(const uint8_t* shuffle);
}; };
} // namespace wasm } // namespace wasm
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment