Instruction
VPERMW
Rearranges the words of a vector across the whole register using an index vector.
- Extensions
- Forms
- 6 (6 EVEX)
- Data
- Intel XED v2026.08.23
VPERMW builds each word of its result by picking a word of a table: the index word in the same position of the first source says which word of the second source to take, anywhere in the register. It came with AVX512BW and has no VEX form. Before it, no single instruction moved 16-bit elements across the 128-bit lanes of a vector: AVX2 code combines VPSHUFB, which picks bytes within each lane, with a lane move such as VPERMQ. Intel’s optimization manual lists VPERMW among AVX-512’s new shuffles, the one-table permute beside the two-table VPERMI2W and VPERMT2W (Section 17.8).
Indices and operand order
Only the low 3, 4 or 5 bits of an index count, for the 8, 16 or 32
words of the xmm, ymm and zmm forms; the bits above are ignored, so no
index gives a zero word, and zeros come from a write mask with {z}
instead. In a case recorded on Zen 5 with the xmm form, the index 7239h
took word 1 of the table and E22Bh word 3. As in
VPERMB and VPERMD, the indices are
the first source, always a register, and the table is the operand that
may be in memory, as the intrinsic _mm512_permutexvar_epi16(idx, table) orders them. Unlike VPERMD, VPERMW has no embedded broadcast:
the memory operand is always a whole vector.
Where it appears
GCC 14 and Clang 23 at -O2 with -march=x86-64-v4 compile a reversal
of the 32 words of a 512-bit vector, written with
__builtin_shufflevector, to one VPERMW with the indices loaded from
memory. The same reversal of the 8 words of an xmm register stays a
VPSHUFB, which reaches every byte of a single lane.
Words are also the size of FP16 and BF16 numbers, and a permute only
moves bits: Clang’s _mm512_permutexvar_ph (AVX512-FP16) and
_mm512_permutexvar_pbh (AVX10.2) compile to VPERMW as well.
AMD’s Zen 5 guide lists VPERMW as one macro-op with a latency of 2, 4 and 5 cycles for the xmm, ymm and zmm forms, the same as VPERMB.
Forms
| Instruction | Encoding | Requires |
|---|---|---|
VPERMW xmm {k}{z}, xmm, xmm
VPERMW_XMMu16_MASKmskw_XMMu16_XMMu16_AVX512 | EVEX.128.66.0F38.W1 8D /r | AVX10.1 or AVX512BW + AVX512VL |
VPERMW xmm {k}{z}, xmm, m128
VPERMW_XMMu16_MASKmskw_XMMu16_MEMu16_AVX512 | EVEX.128.66.0F38.W1 8D /r | AVX10.1 or AVX512BW + AVX512VL |
VPERMW ymm {k}{z}, ymm, ymm
VPERMW_YMMu16_MASKmskw_YMMu16_YMMu16_AVX512 | EVEX.256.66.0F38.W1 8D /r | AVX10.1 or AVX512BW + AVX512VL |
VPERMW ymm {k}{z}, ymm, m256
VPERMW_YMMu16_MASKmskw_YMMu16_MEMu16_AVX512 | EVEX.256.66.0F38.W1 8D /r | AVX10.1 or AVX512BW + AVX512VL |
VPERMW zmm {k}{z}, zmm, zmm
VPERMW_ZMMu16_MASKmskw_ZMMu16_ZMMu16_AVX512 | EVEX.512.66.0F38.W1 8D /r | AVX10.1 or AVX512BW |
VPERMW zmm {k}{z}, zmm, m512
VPERMW_ZMMu16_MASKmskw_ZMMu16_MEMu16_AVX512 | EVEX.512.66.0F38.W1 8D /r | AVX10.1 or AVX512BW |
Latency and throughput
| Model | xmm {k}{z}, xmm, xmmno mask | xmm {k}{z}, xmm, xmmwith a mask, zeroing | xmm {k}{z}, xmm, m128no mask | xmm {k}{z}, xmm, m128with a mask, zeroing | ymm {k}{z}, ymm, ymmno mask | ymm {k}{z}, ymm, ymmwith a mask, zeroing | ymm {k}{z}, ymm, m256no mask | ymm {k}{z}, ymm, m256with a mask, zeroing | zmm {k}{z}, zmm, zmmno mask | zmm {k}{z}, zmm, zmmwith a mask, zeroing | zmm {k}{z}, zmm, m512no mask | zmm {k}{z}, zmm, m512with a mask, zeroing |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Skylake-SP, Ice Lake | 6 / 2p5 | 6 / 2p5 | 12 / 2p5 | 12 / 2p5 | 6 / 2p5 | 6 / 2p5 | 13 / 2p5 | 13 / 2p5 | 6 / 2p5 | 6 / 2p5 | 13 / 2p5 | 13 / 2p5 |
| Sapphire Rapids | 4 / 1p015 | 6 / 1p015 | 10 / 1p015 | 13 / 1p015 | 4 / 1p015 | 6 / 1p015 | 11 / 1p015 | 13 / 1p015 | 4 / 1p05 | 6 / 1p05 | 11 / 1p05 | 13 / 1p05 |
| Zen 4 | 2 / 11FP1 FP2 | 2 / 11FP1 FP2 | 8 / 0.5FP1 FP2 | 8 / 0.5FP1 FP2 | 4 / 12FP1 FP2 | 4 / 12FP1 FP2 | 8 / 0.5FP1 FP2 | 8 / 0.5FP1 FP2 | 5 / 1FP1 FP2 | 5 / 1FP1 FP2 | 8 / 0.5FP1 FP2 | 8 / 0.5FP1 FP2 |
Data flow
Where the elements of the sources go, element 0 on the right; results that depend on a control value are drawn for an example. How to read.
Example index vector in ymm2 (element 0 on the right); only its low 4 bits count. Shown for the ymm form; the xmm and zmm forms work the same on 8 and 32 words. The forms write under a mask: where its bit is 0, the element keeps its old value, or zeroes it with {z}.
With the example indices, result words 15 to 0: b8, unchanged (bit 14 of k1 is 0), b7, b10, b1, b5, b12, b5, b15, b2, b9, b6, b14, b0, b11, b3.
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
n = VL // 16 # 8 in xmm, 16 in ymm, 32 in zmm
for i in range(n):
if k1[i]:
zmm1.w[i] = src3.w[zmm2.w[i] % n]
elif zeroing:
zmm1.w[i] = 0
# else: zmm1.w[i] keeps its value
# zmm1 is zeroed from bit VL upRun on AMD Zen 5 (EPYC 9645): 6 cases.
Operands
| Operand | Kind | Action |
|---|---|---|
VPERMW xmm {k}{z}, xmm, xmm/m128 VPERMW ymm {k}{z}, ymm, ymm/m256 VPERMW zmm {k}{z}, zmm, zmm/m512 | ||
xmm, ymm, zmm | explicit | write (masked) |
{k} | explicit | read (write mask) |
xmm, ymm, zmm | explicit | read |
xmm/m128, ymm/m256, zmm/m512 | explicit | read |
Flags
None: XED records no flag that the forms test or change.
Exceptions
The exception class is XED's name for the set of exception conditions that a form follows. How to read.
- All forms
AVX512-E4NF
Attributes
What else XED records about the forms. How to read.
- All forms
- write masking
Intrinsics
The C intrinsics of Clang 23.1.2 that compile to VPERMW, each with the form it compiles to and the Clang options it needs. The forms come from compiling every intrinsic and decoding the result with Intel XED; all intrinsics A–Z explains the method.
| Intrinsic | Compiles to |
|---|---|
_mm_permutexvar_epi16
__m128i _mm_permutexvar_epi16(__m128i __A, __m128i __B) |
|
_mm_permutexvar_pbh
__m128bh _mm_permutexvar_pbh(__m128i __A, __m128bh __B) |
|
_mm_permutexvar_ph
__m128h _mm_permutexvar_ph(__m128i __A, __m128h __B) |
|
_mm_mask_permutexvar_epi16
__m128i _mm_mask_permutexvar_epi16(__m128i __W, __mmask8 __M, __m128i __A, __m128i __B) |
|
_mm_maskz_permutexvar_epi16
__m128i _mm_maskz_permutexvar_epi16(__mmask8 __M, __m128i __A, __m128i __B) |
|
_mm256_permutexvar_epi16
__m256i _mm256_permutexvar_epi16(__m256i __A, __m256i __B) |
|
_mm256_permutexvar_pbh
__m256bh _mm256_permutexvar_pbh(__m256i __A, __m256bh __B) |
|
_mm256_permutexvar_ph
__m256h _mm256_permutexvar_ph(__m256i __A, __m256h __B) |
|
_mm256_mask_permutexvar_epi16
__m256i _mm256_mask_permutexvar_epi16(__m256i __W, __mmask16 __M, __m256i __A, __m256i __B) |
|
_mm256_maskz_permutexvar_epi16
__m256i _mm256_maskz_permutexvar_epi16(__mmask16 __M, __m256i __A, __m256i __B) |
|
_mm512_permutexvar_epi16
__m512i _mm512_permutexvar_epi16(__m512i __A, __m512i __B) |
|
_mm512_permutexvar_pbh
__m512bh _mm512_permutexvar_pbh(__m512i __A, __m512bh __B) |
|
_mm512_permutexvar_ph
__m512h _mm512_permutexvar_ph(__m512i __A, __m512h __B) |
|
_mm512_mask_permutexvar_epi16
__m512i _mm512_mask_permutexvar_epi16(__m512i __W, __mmask32 __M, __m512i __A, __m512i __B) |
|
_mm512_maskz_permutexvar_epi16
__m512i _mm512_maskz_permutexvar_epi16(__mmask32 __M, __m512i __A, __m512i __B) |
|
CPUID and processors
Each form belongs to an XED ISA set. A form can be used when the processor reports every CPUID bit of one of its ISA set's alternatives.
| ISA set | CPUID | Processors |
|---|---|---|
AVX512BW_128 | AVX10.1 or AVX512BW + AVX512VL | Cannon Lake, Ice Lake (client), Tiger Lake, Nova Lake, Skylake-SP, Cascade Lake, Cooper Lake, Ice Lake (server), Sapphire Rapids, Emerald Rapids, Granite Rapids, Diamond Rapids, Zen 4, Zen 5, Zen 6 |
AVX512BW_256 | Same as AVX512BW_128 | Same as AVX512BW_128 |
AVX512BW_512 | AVX10.1 or AVX512BW | Same as AVX512BW_128 |
More AVX10.1 instructions
- VPDPWSSDS
- VPERMB
- VPERMD
- VPERMI2B
- VPERMI2D
- VPERMI2PD
- VPERMI2PS
- VPERMI2Q
- VPERMI2W
- VPERMILPD
- VPERMILPS
- VPERMPD
- VPERMPS
- VPERMQ
- VPERMT2B
- VPERMT2D
- VPERMT2PD
- VPERMT2PS
- VPERMT2Q
- VPERMT2W
- VPEXPANDB
- VPEXPANDD
- VPEXPANDQ
- VPEXPANDW
- VPEXTRB
- VPEXTRD
- VPEXTRQ
- VPEXTRW
- VPGATHERDD
- VPGATHERDQ
- VPGATHERQD
- VPGATHERQQ
- VPINSRB
- VPINSRD
- VPINSRQ
- VPINSRW
- VPLZCNTD
- VPLZCNTQ
- VPMADD52HUQ
- VPMADD52LUQ
Sources
- Intel XED v2026.08.23 (commit
0bcb6237345c): forms, encodings, operands, flags, exception classes, attributes, ISA sets, CPUID bits and chip model. - The CPU data of x86-64.net: Zen 3 to Zen 6, from GCC’s
-marchfeature sets and AMD’s Processor Programming References, which the page of each processor cites. - Clang's x86 intrinsic headers, LLVM 23.1.2 (commit
85ac56026243): the intrinsics, their signatures and doc comments, and the Clang of that release, which compiled each of them. - LLVM 23.1.2's x86 scheduling models (commit
85ac56026243): the latency, reciprocal throughput and ports of each form, as llvm-mca reports them. - Intel Advanced Vector Extensions 10.2 Architecture Specification, revision 7.0 (361050-007, April 2026)
- Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2 (325383-093, September 2026): Volume 2C, page 5-500 (VPERMD/
VPERMW) - Intel 64 and IA-32 Architectures Optimization Reference Manual, Volume 1 (248966-051, October 2026)
- Software Optimization Guide for the AMD Zen5 Microarchitecture (58455, rev. 1.00, August 2024), Wayback Machine copy of AMD's ZIP
The tables are derived from Intel XED, Copyright Intel Corporation, licensed under the Apache License 2.0; x86-64.net converted and reformatted them. The intrinsics and their signatures come from Clang and the timings from LLVM's scheduling models, both part of the LLVM Project, licensed under the Apache License 2.0 with LLVM Exceptions. The text is our own.