Commit 3f705cc7 authored by Ng Zhi An's avatar Ng Zhi An Committed by Commit Bot

[wasm-simd] Move helper functions to pack shuffles to simd-shuffle

Some of these functions will be reused by Liftoff. Move them into
simd-shuffle for sharing (even though these only apply to ia32 and x64).

Bug: v8:10696
Change-Id: Ib83a2fcd443f93f86d7a4c85898205edb8c3925c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2330796Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Commit-Queue: Zhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69180}
parent 9b9ba19e
...@@ -2561,31 +2561,6 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) { ...@@ -2561,31 +2561,6 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) {
namespace { namespace {
// Packs a 4 lane shuffle into a single imm8 suitable for use by pshufd,
// pshuflw, and pshufhw.
uint8_t PackShuffle4(uint8_t* shuffle) {
return (shuffle[0] & 3) | ((shuffle[1] & 3) << 2) | ((shuffle[2] & 3) << 4) |
((shuffle[3] & 3) << 6);
}
// Gets an 8 bit lane mask suitable for 16x8 pblendw.
uint8_t PackBlend8(const uint8_t* shuffle16x8) {
int8_t result = 0;
for (int i = 0; i < 8; ++i) {
result |= (shuffle16x8[i] >= 8 ? 1 : 0) << i;
}
return result;
}
// Gets an 8 bit lane mask suitable for 32x4 pblendw.
uint8_t PackBlend4(const uint8_t* shuffle32x4) {
int8_t result = 0;
for (int i = 0; i < 4; ++i) {
result |= (shuffle32x4[i] >= 4 ? 0x3 : 0) << (i * 2);
}
return result;
}
// Returns true if shuffle can be decomposed into two 16x4 half shuffles // Returns true if shuffle can be decomposed into two 16x4 half shuffles
// followed by a 16x8 blend. // followed by a 16x8 blend.
// E.g. [3 2 1 0 15 14 13 12]. // E.g. [3 2 1 0 15 14 13 12].
...@@ -2766,7 +2741,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2766,7 +2741,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
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 (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) { } else if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
uint8_t shuffle_mask = PackShuffle4(shuffle32x4); uint8_t shuffle_mask = wasm::SimdShuffle::PackShuffle4(shuffle32x4);
if (is_swizzle) { if (is_swizzle) {
if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) { if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) {
// Bypass normal shuffle code generation in this case. // Bypass normal shuffle code generation in this case.
...@@ -2787,7 +2762,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2787,7 +2762,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
// 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 (wasm::SimdShuffle::TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kIA32S16x8Blend; opcode = kIA32S16x8Blend;
uint8_t blend_mask = PackBlend4(shuffle32x4); uint8_t blend_mask = wasm::SimdShuffle::PackBlend4(shuffle32x4);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} else { } else {
opcode = kIA32S32x4Shuffle; opcode = kIA32S32x4Shuffle;
...@@ -2798,7 +2773,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2798,7 +2773,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
src0_needs_reg = true; src0_needs_reg = true;
src1_needs_reg = true; src1_needs_reg = true;
imms[imm_count++] = shuffle_mask; imms[imm_count++] = shuffle_mask;
int8_t blend_mask = PackBlend4(shuffle32x4); int8_t blend_mask = wasm::SimdShuffle::PackBlend4(shuffle32x4);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} }
} }
...@@ -2806,7 +2781,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2806,7 +2781,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
uint8_t blend_mask; uint8_t blend_mask;
if (wasm::SimdShuffle::TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kIA32S16x8Blend; opcode = kIA32S16x8Blend;
blend_mask = PackBlend8(shuffle16x8); blend_mask = wasm::SimdShuffle::PackBlend8(shuffle16x8);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} else if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) { } else if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) {
opcode = kIA32S16x8Dup; opcode = kIA32S16x8Dup;
...@@ -2817,8 +2792,8 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -2817,8 +2792,8 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
// Half-shuffles don't need DefineSameAsFirst or UseRegister(src0). // Half-shuffles don't need DefineSameAsFirst or UseRegister(src0).
no_same_as_first = true; no_same_as_first = true;
src0_needs_reg = false; src0_needs_reg = false;
uint8_t mask_lo = PackShuffle4(shuffle16x8); uint8_t mask_lo = wasm::SimdShuffle::PackShuffle4(shuffle16x8);
uint8_t mask_hi = PackShuffle4(shuffle16x8 + 4); uint8_t mask_hi = wasm::SimdShuffle::PackShuffle4(shuffle16x8 + 4);
imms[imm_count++] = mask_lo; imms[imm_count++] = mask_lo;
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;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h" #include "src/compiler/node-properties.h"
#include "src/roots/roots-inl.h" #include "src/roots/roots-inl.h"
#include "src/wasm/simd-shuffle.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -3148,31 +3149,6 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) { ...@@ -3148,31 +3149,6 @@ void InstructionSelector::VisitInt64AbsWithOverflow(Node* node) {
namespace { namespace {
// Packs a 4 lane shuffle into a single imm8 suitable for use by pshufd,
// pshuflw, and pshufhw.
uint8_t PackShuffle4(uint8_t* shuffle) {
return (shuffle[0] & 3) | ((shuffle[1] & 3) << 2) | ((shuffle[2] & 3) << 4) |
((shuffle[3] & 3) << 6);
}
// Gets an 8 bit lane mask suitable for 16x8 pblendw.
uint8_t PackBlend8(const uint8_t* shuffle16x8) {
int8_t result = 0;
for (int i = 0; i < 8; ++i) {
result |= (shuffle16x8[i] >= 8 ? 1 : 0) << i;
}
return result;
}
// Gets an 8 bit lane mask suitable for 32x4 pblendw.
uint8_t PackBlend4(const uint8_t* shuffle32x4) {
int8_t result = 0;
for (int i = 0; i < 4; ++i) {
result |= (shuffle32x4[i] >= 4 ? 0x3 : 0) << (i * 2);
}
return result;
}
// Returns true if shuffle can be decomposed into two 16x4 half shuffles // Returns true if shuffle can be decomposed into two 16x4 half shuffles
// followed by a 16x8 blend. // followed by a 16x8 blend.
// E.g. [3 2 1 0 15 14 13 12]. // E.g. [3 2 1 0 15 14 13 12].
...@@ -3335,7 +3311,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3335,7 +3311,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
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 (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) { } else if (wasm::SimdShuffle::TryMatch32x4Shuffle(shuffle, shuffle32x4)) {
uint8_t shuffle_mask = PackShuffle4(shuffle32x4); uint8_t shuffle_mask = wasm::SimdShuffle::PackShuffle4(shuffle32x4);
if (is_swizzle) { if (is_swizzle) {
if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) { if (wasm::SimdShuffle::TryMatchIdentity(shuffle)) {
// Bypass normal shuffle code generation in this case. // Bypass normal shuffle code generation in this case.
...@@ -3356,7 +3332,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3356,7 +3332,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
// 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 (wasm::SimdShuffle::TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kX64S16x8Blend; opcode = kX64S16x8Blend;
uint8_t blend_mask = PackBlend4(shuffle32x4); uint8_t blend_mask = wasm::SimdShuffle::PackBlend4(shuffle32x4);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} else { } else {
opcode = kX64S32x4Shuffle; opcode = kX64S32x4Shuffle;
...@@ -3367,7 +3343,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3367,7 +3343,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
src0_needs_reg = true; src0_needs_reg = true;
src1_needs_reg = true; src1_needs_reg = true;
imms[imm_count++] = shuffle_mask; imms[imm_count++] = shuffle_mask;
uint8_t blend_mask = PackBlend4(shuffle32x4); uint8_t blend_mask = wasm::SimdShuffle::PackBlend4(shuffle32x4);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} }
} }
...@@ -3375,7 +3351,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3375,7 +3351,7 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
uint8_t blend_mask; uint8_t blend_mask;
if (wasm::SimdShuffle::TryMatchBlend(shuffle)) { if (wasm::SimdShuffle::TryMatchBlend(shuffle)) {
opcode = kX64S16x8Blend; opcode = kX64S16x8Blend;
blend_mask = PackBlend8(shuffle16x8); blend_mask = wasm::SimdShuffle::PackBlend8(shuffle16x8);
imms[imm_count++] = blend_mask; imms[imm_count++] = blend_mask;
} else if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) { } else if (wasm::SimdShuffle::TryMatchSplat<8>(shuffle, &index)) {
opcode = kX64S16x8Dup; opcode = kX64S16x8Dup;
...@@ -3386,8 +3362,8 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) { ...@@ -3386,8 +3362,8 @@ void InstructionSelector::VisitS8x16Shuffle(Node* node) {
// Half-shuffles don't need DefineSameAsFirst or UseRegister(src0). // Half-shuffles don't need DefineSameAsFirst or UseRegister(src0).
no_same_as_first = true; no_same_as_first = true;
src0_needs_reg = false; src0_needs_reg = false;
uint8_t mask_lo = PackShuffle4(shuffle16x8); uint8_t mask_lo = wasm::SimdShuffle::PackShuffle4(shuffle16x8);
uint8_t mask_hi = PackShuffle4(shuffle16x8 + 4); uint8_t mask_hi = wasm::SimdShuffle::PackShuffle4(shuffle16x8 + 4);
imms[imm_count++] = mask_lo; imms[imm_count++] = mask_lo;
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;
......
...@@ -106,6 +106,27 @@ bool SimdShuffle::TryMatchBlend(const uint8_t* shuffle) { ...@@ -106,6 +106,27 @@ bool SimdShuffle::TryMatchBlend(const uint8_t* shuffle) {
return true; return true;
} }
uint8_t SimdShuffle::PackShuffle4(uint8_t* shuffle) {
return (shuffle[0] & 3) | ((shuffle[1] & 3) << 2) | ((shuffle[2] & 3) << 4) |
((shuffle[3] & 3) << 6);
}
uint8_t SimdShuffle::PackBlend8(const uint8_t* shuffle16x8) {
int8_t result = 0;
for (int i = 0; i < 8; ++i) {
result |= (shuffle16x8[i] >= 8 ? 1 : 0) << i;
}
return result;
}
uint8_t SimdShuffle::PackBlend4(const uint8_t* shuffle32x4) {
int8_t result = 0;
for (int i = 0; i < 4; ++i) {
result |= (shuffle32x4[i] >= 4 ? 0x3 : 0) << (i * 2);
}
return result;
}
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -72,6 +72,14 @@ class V8_EXPORT_PRIVATE SimdShuffle { ...@@ -72,6 +72,14 @@ class V8_EXPORT_PRIVATE SimdShuffle {
// even lanes of the first source with the odd lanes of the second. The // even lanes of the first source with the odd lanes of the second. The
// shuffle should be canonicalized. // shuffle should be canonicalized.
static bool TryMatchBlend(const uint8_t* shuffle); static bool TryMatchBlend(const uint8_t* shuffle);
// Packs a 4 lane shuffle into a single imm8 suitable for use by pshufd,
// pshuflw, and pshufhw.
static uint8_t PackShuffle4(uint8_t* shuffle);
// Gets an 8 bit lane mask suitable for 16x8 pblendw.
static uint8_t PackBlend8(const uint8_t* shuffle16x8);
// Gets an 8 bit lane mask suitable for 32x4 pblendw.
static uint8_t PackBlend4(const uint8_t* shuffle32x4);
}; };
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
......
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