diff options
Diffstat (limited to 'js/src/jit/ShuffleAnalysis.h')
-rw-r--r-- | js/src/jit/ShuffleAnalysis.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/js/src/jit/ShuffleAnalysis.h b/js/src/jit/ShuffleAnalysis.h new file mode 100644 index 0000000000..84133ccf5a --- /dev/null +++ b/js/src/jit/ShuffleAnalysis.h @@ -0,0 +1,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 |