summaryrefslogtreecommitdiffstats
path: root/js/src/jit/ShuffleAnalysis.h
blob: 84133ccf5a0680a7552a268b2b75361fdeec11e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef jit_ShuffleAnalysis_h
#define jit_ShuffleAnalysis_h

#include "jit/IonTypes.h"

namespace js {
namespace jit {

class MDefinition;

// Permutation operations.  NOTE: these may still be x86-centric, but the set
// can accomodate operations from other architectures.
//
// The "low-order" byte is in lane 0 of an 8x16 datum, the "high-order" byte
// in lane 15.  The low-order byte is also the "rightmost".  In wasm, the
// constant (v128.const i8x16 0 1 2 ... 15) has 0 in the low-order byte and 15
// in the high-order byte.
enum class SimdPermuteOp {
  // A single byte lane is copied into all the other byte lanes.  control_[0]
  // has the source lane.
  BROADCAST_8x16,

  // A single word lane is copied into all the other word lanes.  control_[0]
  // has the source lane.
  BROADCAST_16x8,

  // Copy input to output.
  MOVE,

  // control_ has bytes in range 0..15 s.t. control_[i] holds the source lane
  // for output lane i.
  PERMUTE_8x16,

  // control_ has int16s in range 0..7, as for 8x16.  In addition, the high
  // byte of control_[0] has flags detailing the operation, values taken
  // from the Perm16x8Action enum below.
  PERMUTE_16x8,

  // control_ has int32s in range 0..3, as for 8x16.
  PERMUTE_32x4,

  // control_[0] has the number of places to rotate by.
  ROTATE_RIGHT_8x16,

  // Zeroes are shifted into high-order bytes and low-order bytes are lost.
  // control_[0] has the number of places to shift by.
  SHIFT_RIGHT_8x16,

  // Zeroes are shifted into low-order bytes and high-order bytes are lost.
  // control_[0] has the number of places to shift by.
  SHIFT_LEFT_8x16,

  // Reverse bytes of 16-bit lanes.
  REVERSE_16x8,

  // Reverse bytes of 32-bit lanes.
  REVERSE_32x4,

  // Reverse bytes of 64-bit lanes.
  REVERSE_64x2,
};

// Shuffle operations.  NOTE: these may still be x86-centric, but the set can
// accomodate operations from other architectures.
enum class SimdShuffleOp {
  // Blend bytes.  control_ has the blend mask as an I8x16: 0 to select from
  // the lhs, -1 to select from the rhs.
  BLEND_8x16,

  // Blend words.  control_ has the blend mask as an I16x8: 0 to select from
  // the lhs, -1 to select from the rhs.
  BLEND_16x8,

  // Concat the lhs in front of the rhs and shift right by bytes, extracting
  // the low 16 bytes; control_[0] has the shift count.
  CONCAT_RIGHT_SHIFT_8x16,

  // Interleave qwords/dwords/words/bytes from high/low halves of operands.
  // The low-order item in the result comes from the lhs, then the next from
  // the rhs, and so on.  control_ is ignored.
  INTERLEAVE_HIGH_8x16,
  INTERLEAVE_HIGH_16x8,
  INTERLEAVE_HIGH_32x4,
  INTERLEAVE_HIGH_64x2,
  INTERLEAVE_LOW_8x16,
  INTERLEAVE_LOW_16x8,
  INTERLEAVE_LOW_32x4,
  INTERLEAVE_LOW_64x2,

  // Fully general shuffle+blend.  control_ has the shuffle mask.
  SHUFFLE_BLEND_8x16,
};

// Representation of the result of the shuffle analysis.
struct SimdShuffle {
  enum class Operand {
    // Both inputs, in the original lhs-rhs order
    BOTH,
    // Both inputs, but in rhs-lhs order
    BOTH_SWAPPED,
    // Only the lhs input
    LEFT,
    // Only the rhs input
    RIGHT,
  };

  Operand opd;
  SimdConstant control;
  mozilla::Maybe<SimdPermuteOp> permuteOp;  // Single operands
  mozilla::Maybe<SimdShuffleOp> shuffleOp;  // Double operands

  static SimdShuffle permute(Operand opd, SimdConstant control,
                             SimdPermuteOp op) {
    MOZ_ASSERT(opd == Operand::LEFT || opd == Operand::RIGHT);
    SimdShuffle s{opd, control, mozilla::Some(op), mozilla::Nothing()};
    return s;
  }

  static SimdShuffle shuffle(Operand opd, SimdConstant control,
                             SimdShuffleOp op) {
    MOZ_ASSERT(opd == Operand::BOTH || opd == Operand::BOTH_SWAPPED);
    SimdShuffle s{opd, control, mozilla::Nothing(), mozilla::Some(op)};
    return s;
  }

  bool equals(const SimdShuffle* other) const {
    return permuteOp == other->permuteOp && shuffleOp == other->shuffleOp &&
           opd == other->opd && control.bitwiseEqual(other->control);
  }
};

#ifdef ENABLE_WASM_SIMD

SimdShuffle AnalyzeSimdShuffle(SimdConstant control, MDefinition* lhs,
                               MDefinition* rhs);

#endif

}  // namespace jit
}  // namespace js

#endif  // jit_ShuffleAnalysis_h