ShuffleAnalysis.h (4756B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef jit_ShuffleAnalysis_h 7 #define jit_ShuffleAnalysis_h 8 9 #include "jit/IonTypes.h" 10 11 namespace js { 12 namespace jit { 13 14 class MDefinition; 15 16 // Permutation operations. NOTE: these may still be x86-centric, but the set 17 // can accomodate operations from other architectures. 18 // 19 // The "low-order" byte is in lane 0 of an 8x16 datum, the "high-order" byte 20 // in lane 15. The low-order byte is also the "rightmost". In wasm, the 21 // constant (v128.const i8x16 0 1 2 ... 15) has 0 in the low-order byte and 15 22 // in the high-order byte. 23 enum class SimdPermuteOp { 24 // A single byte lane is copied into all the other byte lanes. control_[0] 25 // has the source lane. 26 BROADCAST_8x16, 27 28 // A single word lane is copied into all the other word lanes. control_[0] 29 // has the source lane. 30 BROADCAST_16x8, 31 32 // Copy input to output. 33 MOVE, 34 35 // control_ has bytes in range 0..15 s.t. control_[i] holds the source lane 36 // for output lane i. 37 PERMUTE_8x16, 38 39 // control_ has int16s in range 0..7, as for 8x16. In addition, the high 40 // byte of control_[0] has flags detailing the operation, values taken 41 // from the Perm16x8Action enum below. 42 PERMUTE_16x8, 43 44 // control_ has int32s in range 0..3, as for 8x16. 45 PERMUTE_32x4, 46 47 // control_[0] has the number of places to rotate by. 48 ROTATE_RIGHT_8x16, 49 50 // Zeroes are shifted into high-order bytes and low-order bytes are lost. 51 // control_[0] has the number of places to shift by. 52 SHIFT_RIGHT_8x16, 53 54 // Zeroes are shifted into low-order bytes and high-order bytes are lost. 55 // control_[0] has the number of places to shift by. 56 SHIFT_LEFT_8x16, 57 58 // Reverse bytes of 16-bit lanes. 59 REVERSE_16x8, 60 61 // Reverse bytes of 32-bit lanes. 62 REVERSE_32x4, 63 64 // Reverse bytes of 64-bit lanes. 65 REVERSE_64x2, 66 67 // Zero extends. 68 ZERO_EXTEND_8x16_TO_16x8, 69 ZERO_EXTEND_8x16_TO_32x4, 70 ZERO_EXTEND_8x16_TO_64x2, 71 ZERO_EXTEND_16x8_TO_32x4, 72 ZERO_EXTEND_16x8_TO_64x2, 73 ZERO_EXTEND_32x4_TO_64x2, 74 }; 75 76 // Shuffle operations. NOTE: these may still be x86-centric, but the set can 77 // accomodate operations from other architectures. 78 enum class SimdShuffleOp { 79 // Blend bytes. control_ has the blend mask as an I8x16: 0 to select from 80 // the lhs, -1 to select from the rhs. 81 BLEND_8x16, 82 83 // Blend words. control_ has the blend mask as an I16x8: 0 to select from 84 // the lhs, -1 to select from the rhs. 85 BLEND_16x8, 86 87 // Concat the lhs in front of the rhs and shift right by bytes, extracting 88 // the low 16 bytes; control_[0] has the shift count. 89 CONCAT_RIGHT_SHIFT_8x16, 90 91 // Interleave qwords/dwords/words/bytes from high/low halves of operands. 92 // The low-order item in the result comes from the lhs, then the next from 93 // the rhs, and so on. control_ is ignored. 94 INTERLEAVE_HIGH_8x16, 95 INTERLEAVE_HIGH_16x8, 96 INTERLEAVE_HIGH_32x4, 97 INTERLEAVE_HIGH_64x2, 98 INTERLEAVE_LOW_8x16, 99 INTERLEAVE_LOW_16x8, 100 INTERLEAVE_LOW_32x4, 101 INTERLEAVE_LOW_64x2, 102 103 // Fully general shuffle+blend. control_ has the shuffle mask. 104 SHUFFLE_BLEND_8x16, 105 }; 106 107 // Representation of the result of the shuffle analysis. 108 struct SimdShuffle { 109 enum class Operand { 110 // Both inputs, in the original lhs-rhs order 111 BOTH, 112 // Both inputs, but in rhs-lhs order 113 BOTH_SWAPPED, 114 // Only the lhs input 115 LEFT, 116 // Only the rhs input 117 RIGHT, 118 }; 119 120 Operand opd; 121 SimdConstant control; 122 mozilla::Maybe<SimdPermuteOp> permuteOp; // Single operands 123 mozilla::Maybe<SimdShuffleOp> shuffleOp; // Double operands 124 125 static SimdShuffle permute(Operand opd, SimdConstant control, 126 SimdPermuteOp op) { 127 MOZ_ASSERT(opd == Operand::LEFT || opd == Operand::RIGHT); 128 SimdShuffle s{opd, control, mozilla::Some(op), mozilla::Nothing()}; 129 return s; 130 } 131 132 static SimdShuffle shuffle(Operand opd, SimdConstant control, 133 SimdShuffleOp op) { 134 MOZ_ASSERT(opd == Operand::BOTH || opd == Operand::BOTH_SWAPPED); 135 SimdShuffle s{opd, control, mozilla::Nothing(), mozilla::Some(op)}; 136 return s; 137 } 138 139 bool equals(const SimdShuffle* other) const { 140 return permuteOp == other->permuteOp && shuffleOp == other->shuffleOp && 141 opd == other->opd && control.bitwiseEqual(other->control); 142 } 143 }; 144 145 #ifdef ENABLE_WASM_SIMD 146 147 SimdShuffle AnalyzeSimdShuffle(SimdConstant control, MDefinition* lhs, 148 MDefinition* rhs); 149 150 #endif 151 152 } // namespace jit 153 } // namespace js 154 155 #endif // jit_ShuffleAnalysis_h