• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_WASM_SIMD_SHUFFLE_H_
6 #define V8_WASM_SIMD_SHUFFLE_H_
7 
8 #include "src/base/macros.h"
9 #include "src/common/globals.h"
10 
11 namespace v8 {
12 namespace internal {
13 namespace wasm {
14 
15 class V8_EXPORT_PRIVATE SimdShuffle {
16  public:
17   // Converts a shuffle into canonical form, meaning that the first lane index
18   // is in the range [0 .. 15]. Set |inputs_equal| true if this is an explicit
19   // swizzle. Returns canonicalized |shuffle|, |needs_swap|, and |is_swizzle|.
20   // If |needs_swap| is true, inputs must be swapped. If |is_swizzle| is true,
21   // the second input can be ignored.
22   static void CanonicalizeShuffle(bool inputs_equal, uint8_t* shuffle,
23                                   bool* needs_swap, bool* is_swizzle);
24 
25   // Tries to match an 8x16 byte shuffle to the identity shuffle, which is
26   // [0 1 ... 15]. This should be called after canonicalizing the shuffle, so
27   // the second identity shuffle, [16 17 .. 31] is converted to the first one.
28   static bool TryMatchIdentity(const uint8_t* shuffle);
29 
30   // Tries to match a byte shuffle to a scalar splat operation. Returns the
31   // index of the lane if successful.
32   template <int LANES>
TryMatchSplat(const uint8_t * shuffle,int * index)33   static bool TryMatchSplat(const uint8_t* shuffle, int* index) {
34     const int kBytesPerLane = kSimd128Size / LANES;
35     // Get the first lane's worth of bytes and check that indices start at a
36     // lane boundary and are consecutive.
37     uint8_t lane0[kBytesPerLane];
38     lane0[0] = shuffle[0];
39     if (lane0[0] % kBytesPerLane != 0) return false;
40     for (int i = 1; i < kBytesPerLane; ++i) {
41       lane0[i] = shuffle[i];
42       if (lane0[i] != lane0[0] + i) return false;
43     }
44     // Now check that the other lanes are identical to lane0.
45     for (int i = 1; i < LANES; ++i) {
46       for (int j = 0; j < kBytesPerLane; ++j) {
47         if (lane0[j] != shuffle[i * kBytesPerLane + j]) return false;
48       }
49     }
50     *index = lane0[0] / kBytesPerLane;
51     return true;
52   }
53 
54   // Tries to match an 8x16 byte shuffle to an equivalent 32x4 shuffle. If
55   // successful, it writes the 32x4 shuffle word indices. E.g.
56   // [0 1 2 3 8 9 10 11 4 5 6 7 12 13 14 15] == [0 2 1 3]
57   static bool TryMatch32x4Shuffle(const uint8_t* shuffle, uint8_t* shuffle32x4);
58 
59   // Tries to match an 8x16 byte shuffle to an equivalent 16x8 shuffle. If
60   // successful, it writes the 16x8 shuffle word indices. E.g.
61   // [0 1 8 9 2 3 10 11 4 5 12 13 6 7 14 15] == [0 4 1 5 2 6 3 7]
62   static bool TryMatch16x8Shuffle(const uint8_t* shuffle, uint8_t* shuffle16x8);
63 
64   // Tries to match a byte shuffle to a concatenate operation, formed by taking
65   // 16 bytes from the 32 byte concatenation of the inputs.  If successful, it
66   // writes the byte offset. E.g. [4 5 6 7 .. 16 17 18 19] concatenates both
67   // source vectors with offset 4. The shuffle should be canonicalized.
68   static bool TryMatchConcat(const uint8_t* shuffle, uint8_t* offset);
69 
70   // Tries to match a byte shuffle to a blend operation, which is a shuffle
71   // where no lanes change position. E.g. [0 9 2 11 .. 14 31] interleaves the
72   // even lanes of the first source with the odd lanes of the second.  The
73   // shuffle should be canonicalized.
74   static bool TryMatchBlend(const uint8_t* shuffle);
75 
76   // Packs a 4 lane shuffle into a single imm8 suitable for use by pshufd,
77   // pshuflw, and pshufhw.
78   static uint8_t PackShuffle4(uint8_t* shuffle);
79   // Gets an 8 bit lane mask suitable for 16x8 pblendw.
80   static uint8_t PackBlend8(const uint8_t* shuffle16x8);
81   // Gets an 8 bit lane mask suitable for 32x4 pblendw.
82   static uint8_t PackBlend4(const uint8_t* shuffle32x4);
83   // Packs 4 bytes of shuffle into a 32 bit immediate.
84   static int32_t Pack4Lanes(const uint8_t* shuffle);
85   // Packs 16 bytes of shuffle into an array of 4 uint32_t.
86   static void Pack16Lanes(uint32_t* dst, const uint8_t* shuffle);
87 };
88 }  // namespace wasm
89 }  // namespace internal
90 }  // namespace v8
91 
92 #endif  // V8_WASM_SIMD_SHUFFLE_H_
93