Instruction
VPERMQ
Rearranges quadwords across the whole register, controlled by an immediate or by an index vector.
VPERMQ rearranges the quadwords of a vector freely, across the 128-bit lanes that most AVX2 shuffles cannot cross. AVX2 gave it one form: an immediate with two bits per result element, each naming one of the four quadwords of a YMM register or of memory, so that any arrangement, repeats included, is one instruction. Common values:
0xD8(elements 0, 2, 1, 3) restores the order after an in-lane pack such as VPACKUSWB; GCC 14 at -O2 narrows 16-bit elements to bytes that way, while Clang 23 packs the two halves of each register in XMM registers instead.0x1Breverses the four quadwords: GCC compiles a loop that copies an array of 64-bit integers backwards to VPERMQ with a memory source.0x4Eswaps the two halves, as VPERM2I128 can.0x08and0x0Dgather the even and the odd elements into the low half; Intel’s optimization guide suggests them, after one load, in place of a gather for a small stride (Section 15.16.4).
Immediate or index vector
AVX-512 added a form that takes the selectors from a vector register, as VPERMD does for doublewords, with masking and broadcast; only the low three bits of each index count in a ZMM register and the low two in a YMM one. The immediate form also has a ZMM version, but there it is not a permutation of eight elements: it applies the same four selectors to each 256-bit half separately, as the page’s pseudocode shows. Use the index form, or VPERMT2Q for two tables, to move quadwords between the halves.
VPERMPD is the same instruction for doubles, and Clang
23 picks between the two by the instructions around them:
_mm256_permute4x64_epi64 on its own compiles to VPERMPD, and followed
by an integer addition to VPERMQ. GCC 14 keeps VPERMQ.
Intel’s guide lists VPERMQ, with VPERMD, VPERMPS and VPERMPD, among the instructions that falsely depend on their destination register in the Golden Cove microarchitecture, and recommends a zero idiom on the destination before them (Section 2.4.1.2). In Crestmont they take two micro-ops and a seven-cycle latency (Section 4.1.9.1).
In the optimization guide
What the optimization guide says about VPERMQ, a line per claim. Each links to the claim in the guide, with its sources and where they differ.
Crestmont and Gracemont
- Vectors and AVX2: Shuffles that move data across the 128-bit halves are slower: VPERM2I128, VPERM2F128, VPERMD, VPERMQ, VPERMPS and VPERMPD on 256 bits are two micro-ops with a latency of 7 cycles, the second holding a port for two cycles.
Golden Cove and Raptor Cove
- Vectors, AVX-512 and AMX: VPERMD, VPERMQ, VPERMPS, VPERMPD, VPMULLQ,
vrange,vgetmantand the half-precision complex multiplications wait for the old value of their destination, which they then overwrite.
Zen 2
- Vectors and floating point: AMD’s spreadsheet makes the AVX2 permutes that cross the 128-bit lanes, VPERMD,
vpermps,vpermqandvpermpd, microcoded, whilevperm2f128is one macro-op of three cycles on pipe 2. sources differ
Forms
| Instruction | Encoding | Requires |
|---|---|---|
VPERMQ ymm, m256, imm8
VPERMQ_YMMqq_MEMqq_IMMb | VEX.256.66.0F3A.W1 00 /r ib | AVX2 |
VPERMQ ymm, ymm, imm8
VPERMQ_YMMqq_YMMqq_IMMb | VEX.256.66.0F3A.W1 00 /r ib | AVX2 |
VPERMQ zmm {k}{z}, zmm, imm8
VPERMQ_ZMMu64_MASKmskw_ZMMu64_IMM8_AVX512 | EVEX.512.66.0F3A.W1 00 /r ib | AVX10.1 or AVX512F |
VPERMQ zmm {k}{z}, m512/m64bcst, imm8
VPERMQ_ZMMu64_MASKmskw_MEMu64_IMM8_AVX512 | EVEX.512.66.0F3A.W1 00 /r ib | AVX10.1 or AVX512F |
VPERMQ zmm {k}{z}, zmm, zmm
VPERMQ_ZMMu64_MASKmskw_ZMMu64_ZMMu64_AVX512 | EVEX.512.66.0F38.W1 36 /r | AVX10.1 or AVX512F |
VPERMQ zmm {k}{z}, zmm, m512/m64bcst
VPERMQ_ZMMu64_MASKmskw_ZMMu64_MEMu64_AVX512 | EVEX.512.66.0F38.W1 36 /r | AVX10.1 or AVX512F |
VPERMQ ymm {k}{z}, ymm, imm8
VPERMQ_YMMu64_MASKmskw_YMMu64_IMM8_AVX512 | EVEX.256.66.0F3A.W1 00 /r ib | AVX10.1 or AVX512F + AVX512VL |
VPERMQ ymm {k}{z}, m256/m64bcst, imm8
VPERMQ_YMMu64_MASKmskw_MEMu64_IMM8_AVX512 | EVEX.256.66.0F3A.W1 00 /r ib | AVX10.1 or AVX512F + AVX512VL |
VPERMQ ymm {k}{z}, ymm, ymm
VPERMQ_YMMu64_MASKmskw_YMMu64_YMMu64_AVX512 | EVEX.256.66.0F38.W1 36 /r | AVX10.1 or AVX512F + AVX512VL |
VPERMQ ymm {k}{z}, ymm, m256/m64bcst
VPERMQ_YMMu64_MASKmskw_YMMu64_MEMu64_AVX512 | EVEX.256.66.0F38.W1 36 /r | AVX10.1 or AVX512F + AVX512VL |
Latency and throughput
| Model | ymm, m256, imm8 | ymm, ymm, imm8 | zmm {k}{z}, zmm, imm8ymm {k}{z}, ymm, imm8 | zmm {k}{z}, m512/m64bcst, imm8ymm {k}{z}, m256/m64bcst, imm8 | zmm {k}{z}, zmm, zmm | zmm {k}{z}, zmm, m512/m64bcstymm {k}{z}, ymm, m256/m64bcst | ymm {k}{z}, ymm, ymm |
|---|---|---|---|---|---|---|---|
| Haswell, Skylake | 10 / 1p5 | 3 / 1p5 | |||||
| Broadwell | 9 / 1p5 | 3 / 1p5 | |||||
| Skylake-SP, Ice Lake | 10 / 1p5 | 3 / 1p5 | 3 / 1p5 | 10 / 1p5 | 3 / 1p5 | 10 / 1p5 | 3 / 1p5 |
| Alder Lake | 11 / 1p5 | 3 / 1p5 | |||||
| Sapphire Rapids | 11 / 1p5 | 3 / 1p5 | 3 / 1p5 | 11 / 1p5 | 3 / 1p5 | 11 / 1p5 | 3 / 1p5 |
| Lunar Lake | 11 / 0.5V2 V3 | 3 / 0.5V2 V3 | |||||
| Zen | 9 / 1FPU1 FPU2 | 2 / 1FPU1 FPU2 | |||||
| Zen 2 | 9 / 0.5FPU1 FPU2 | 2 / 0.5FPU1 FPU2 | |||||
| Zen 3 | 12 / 2FP1 | 6 / 1FP1 | |||||
| Zen 4 | 11 / 1FP1 | 4 / 1FP1 | 1 / 11FP1 | 8 / 1FP1 | 1 / 0.52FP1 FP2 | 8 / 0.5FP1 FP2 | 4 / 13FP1 FP2 |
- Zen 4 model, zmm form: AMD's spreadsheets give latency 4 for Zen 4 and Zen 5 (AMD 57647, row 2292; AMD 58455, row 566).
- Zen 4 model: AMD's spreadsheets give latency 5 for Zen 4 and Zen 5 (AMD 57647, row 2293; AMD 58455, row 578).
- Zen 4 model: AMD's spreadsheets give reciprocal throughput 0.5 for Zen 4 and Zen 5 (AMD 57647, row 2290; AMD 58455, row 577).
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.
VPERMQ ymm, ymm/m256, imm8 VPERMQ ymm {k}{z}, ymm/m256/m64bcst, imm8 VPERMQ zmm {k}{z}, zmm/m512/m64bcst, imm8Example: imm8 = 0x1E (0001 1110 in binary). The zmm form does this in each 256-bit half. The EVEX forms write under a mask: where its bit is 0, the element keeps its old value, or zeroes it with {z}. With m64bcst, one quadword from memory stands for every element of ymm2.
With imm8 = 0x1E, result quadwords 3 to 0: a0, unchanged (bit 2 of k1 is 0), a3, a2.
VPERMQ ymm {k}{z}, ymm, ymm/m256/m64bcst VPERMQ zmm {k}{z}, zmm, zmm/m512/m64bcstExample index vector in zmm2 (element 0 on the right); only its low 3 bits count. Shown for the zmm form; the ymm form works the same on 4 quadwords. 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 quadwords 7 to 0: b1, unchanged (bit 6 of k1 is 0), b3, b3, b0, b7, b2, b5.
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
VPERMQ ymm, ymm/m256, imm8 VPERMQ ymm {k}{z}, ymm/m256/m64bcst, imm8 VPERMQ zmm {k}{z}, zmm/m512/m64bcst, imm8for i in range(VL // 64):
k = imm8 >> 2 * (i % 4) & 3
j = i - i % 4 + k
if k1[i]: # 1 without a write mask
zmm1.q[i] = src2.q[j]
elif zeroing:
zmm1.q[i] = 0
# else: zmm1.q[i] keeps its value
# m64bcst: src2.q[i] is the m64 for every i
# zmm1 is zeroed from bit VL upRun on AMD Zen 5 (EPYC 9645): 6 cases.
VPERMQ ymm {k}{z}, ymm, ymm/m256/m64bcst VPERMQ zmm {k}{z}, zmm, zmm/m512/m64bcstn = VL // 64 # 4 in ymm, 8 in zmm
for i in range(n):
if k1[i]:
zmm1.q[i] = src3.q[zmm2.q[i] % n]
elif zeroing:
zmm1.q[i] = 0
# else: zmm1.q[i] keeps its value
# m64bcst: src3.q[i] is the m64 for every i
# zmm1 is zeroed from bit VL upRun on AMD Zen 5 (EPYC 9645): 4 cases.
Operands
| Operand | Kind | Action |
|---|---|---|
VPERMQ ymm, ymm/m256, imm8 | ||
ymm | explicit | write |
ymm/m256 | explicit | read |
imm8 | explicit | read |
VPERMQ ymm {k}{z}, ymm/m256/m64bcst, imm8 VPERMQ zmm {k}{z}, zmm/m512/m64bcst, imm8 | ||
ymm, zmm | explicit | write (masked) |
{k} | explicit | read (write mask) |
ymm/m256/m64bcst, zmm/m512/m64bcst | explicit | read |
imm8 | explicit | read |
VPERMQ ymm {k}{z}, ymm, ymm/m256/m64bcst VPERMQ zmm {k}{z}, zmm, zmm/m512/m64bcst | ||
ymm, zmm | explicit | write (masked) |
{k} | explicit | read (write mask) |
ymm, zmm | explicit | read |
ymm/m256/m64bcst, zmm/m512/m64bcst | 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.
- VEX forms
avx-type-4- EVEX forms
AVX512-E4NF
Attributes
What else XED records about the forms. How to read.
- EVEX forms
- write masking
- EVEX memory forms
- embedded broadcast (tuple Full)
Intrinsics
The C intrinsics of Clang 23.1.2 that compile to VPERMQ, 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 |
|---|---|
_mm256_permute4x64_epi64
__m256i _mm256_permute4x64_epi64(__m256i V, const int M) |
|
_mm256_permutex_epi64
__m256i _mm256_permutex_epi64(__m256i X, const int C) |
|
_mm256_permutexvar_epi64
__m256i _mm256_permutexvar_epi64(__m256i __X, __m256i __Y) |
|
_mm256_mask_permutex_epi64
__m256i _mm256_mask_permutex_epi64(__m256i W, __mmask8 U, __m256i X, const int C) |
|
_mm256_mask_permutexvar_epi64
__m256i _mm256_mask_permutexvar_epi64(__m256i __W, __mmask8 __M, __m256i __X, __m256i __Y) |
|
_mm256_maskz_permutex_epi64
__m256i _mm256_maskz_permutex_epi64(__mmask8 U, __m256i X, const int C) |
|
_mm256_maskz_permutexvar_epi64
__m256i _mm256_maskz_permutexvar_epi64(__mmask8 __M, __m256i __X, __m256i __Y) |
|
_mm512_permutex_epi64
__m512i _mm512_permutex_epi64(__m512i X, const int C) |
|
_mm512_permutexvar_epi64
__m512i _mm512_permutexvar_epi64(__m512i __X, __m512i __Y) |
|
_mm512_mask_permutex_epi64
__m512i _mm512_mask_permutex_epi64(__m512i W, __mmask8 U, __m512i X, const int C) |
|
_mm512_mask_permutexvar_epi64
__m512i _mm512_mask_permutexvar_epi64(__m512i __W, __mmask8 __M, __m512i __X, __m512i __Y) |
|
_mm512_maskz_permutex_epi64
__m512i _mm512_maskz_permutex_epi64(__mmask8 U, __m512i X, const int C) |
|
_mm512_maskz_permutexvar_epi64
__m512i _mm512_maskz_permutexvar_epi64(__mmask8 __M, __m512i __X, __m512i __Y) |
|
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.
More AVX2 instructions
- VPAVGW
- VPBLENDD
- VPBLENDVB
- VPBLENDW
- VPBROADCASTB
- VPBROADCASTD
- VPBROADCASTQ
- VPBROADCASTW
- VPCMPEQB
- VPCMPEQD
- VPCMPEQQ
- VPCMPEQW
- VPCMPGTB
- VPCMPGTD
- VPCMPGTQ
- VPCMPGTW
- VPERM2I128
- VPERMD
- VPERMPD
- VPERMPS
- VPGATHERDD
- VPGATHERDQ
- VPGATHERQD
- VPGATHERQQ
- VPHADDD
- VPHADDSW
- VPHADDW
- VPHSUBD
- VPHSUBSW
- VPHSUBW
- VPMADDUBSW
- VPMADDWD
- VPMASKMOVD
- VPMASKMOVQ
- VPMAXSB
- VPMAXSD
- VPMAXSW
- VPMAXUB
- VPMAXUD
- VPMAXUW
More AVX10.1 instructions
- VPCOMPRESSQ
- VPCOMPRESSW
- VPCONFLICTD
- VPCONFLICTQ
- VPDPBUSD
- VPDPBUSDS
- VPDPWSSD
- VPDPWSSDS
- VPERMB
- VPERMD
- VPERMI2B
- VPERMI2D
- VPERMI2PD
- VPERMI2PS
- VPERMI2Q
- VPERMI2W
- VPERMILPD
- VPERMILPS
- VPERMPD
- VPERMPS
- VPERMT2B
- VPERMT2D
- VPERMT2PD
- VPERMT2PS
- VPERMT2Q
- VPERMT2W
- VPERMW
- VPEXPANDB
- VPEXPANDD
- VPEXPANDQ
- VPEXPANDW
- VPEXTRB
- VPEXTRD
- VPEXTRQ
- VPEXTRW
- VPGATHERDD
- VPGATHERDQ
- VPGATHERQD
- VPGATHERQQ
- VPINSRB
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 64 and IA-32 Architectures Software Developer's Manual, Volume 2 (325383-093, September 2026): Volume 2C, page 5-529 (VPERMQ)
- Intel Advanced Vector Extensions 10.2 Architecture Specification, revision 7.0 (361050-007, April 2026)
- Intel 64 and IA-32 Architectures Optimization Reference Manual, Volume 1 (248966-051, October 2026)
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.