/* -*- 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 permuteOp; // Single operands mozilla::Maybe 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