Instruction
POP
Loads the value on top of the stack into a register, memory or a segment register and moves the stack pointer past it.
- Extensions
- Forms
- 8 (8 Legacy)
- Data
- Intel XED v2026.08.23
POP restores what PUSH saved: a function’s epilogue pops its callee-saved registers in the reverse order of the prologue’s pushes, just before RET. Clang 23 may also drop an 8-byte alignment slot that way, popping it into a scratch register such as RCX, where GCC 14 adds 8 to RSP.
In 64-bit mode a POP moves 8 bytes, or 2 with a 66 prefix; no prefix gives a 32-bit POP. A 16-bit POP into a register writes only its low 16 bits, and bits 63:16 keep their old value, as Zen 5 recorded.
The order of the two steps, reading the slot and moving RSP, shows in two cases:
- POP RSP loads the value from the top of the stack into RSP, and the increment is lost. Zen 5 recorded this, as Intel’s manual describes it.
- POP into memory addressed through RSP, such as
pop qword [rsp+8], computes the address after RSP has moved up, by Intel’s manual, so it writes 8 bytes higher than the same operand names before the instruction. AMD’s manual does not say.
POP DS, POP ES and POP SS are invalid in 64-bit mode. POP FS and POP GS
remain: the selector must name a usable data segment (#GP or #NP
otherwise), and a null selector is allowed. Loading any other selector
also replaces the segment’s base address with the 32-bit base of its
descriptor (Intel’s Volume 3A, Section 3.4.4). In 64-bit code, where
the base of FS is usually the 64-bit address of the thread’s local
storage, set with arch_prctl or WRFSBASE (see the
Linux documentation on FS and GS), a POP FS loses that address.
Unlike POPF, POP changes no flag. APX adds POP2, which restores two registers at once, and POPP, which pairs with PUSHP.
In the optimization guide
What the optimization guide says about POP, a line per claim. Each links to the claim in the guide, with its sources and where they differ.
Out of order
- Renaming and the window: A stack engine lets PUSH, POP, CALL and RET change RSP with no execution unit and no wait, though an explicit use of RSP between them can cost an extra micro-op.
Jaguar and Puma
- Front end: A sideband stack optimizer in the decoder tracks the stack pointer, so a chain of PUSH and POP instructions does not wait on each update of rSP.
Silvermont to Goldmont Plus
- Out-of-order and in-order execution: Goldmont tracks the stack pointer of
push,pop,callandretwithout spending allocation or execution slots on it, and runspushandpopthree a cycle where Silvermont runs one.
Tremont
- Integer execution: LLVM’s tuning treats
push,popandcallwith a memory operand as slow on this core and loads the operand into a register first.
Zen and Zen+
- Integer execution: The decoder tracks RSP, so chains of PUSH and POP do not wait for each other; Agner Fog found PUSH, POP and RET to be one macro-op each, with no latency on RSP.
Zen 2
- Integer execution: A stack engine tracks RSP, so chains of PUSH and POP do not wait for each other; Agner Fog found PUSH, POP and RET to be one macro-op each with no latency on RSP.
Zen 3
- Integer execution: PUSH, POP, CALL and RET update RSP without a dependency, and loads, stores,
leaandmovfrom RSP can use the tracked value.
Zen 4
- Integer execution: PUSH, POP, CALL and RET update RSP without a dependency, and loads, stores,
leaandmovfrom RSP can use the tracked value.
Zen 5
- Integer execution: PUSH, POP, CALL and RET update RSP without a dependency, and loads, stores,
leaandaddorsubof a small immediate through RSP can use the tracked value.
Forms
| Instruction | Encoding | Requires |
|---|---|---|
POP m16/32/64
POP_MEMv | 8F /0 | Base instruction set |
POP r16/32/64
POP_GPRv_8F | 8F /0 | Base instruction set |
POP ES not in 64-bit mode
POP_ES | 07 | Base instruction set |
POP SS not in 64-bit mode
POP_SS | 17 | Base instruction set |
POP DS not in 64-bit mode
POP_DS | 1F | Base instruction set |
POP r16/32/64
POP_GPRv_58 | 58+rREX2.W0 58+r | Base instruction set |
POP FS
POP_FS | 0F A1 | Base instruction set |
POP GS
POP_GS | 0F A9 | Base instruction set |
Latency and throughput
| Model | m16 | m64 | r16 | r64 |
|---|---|---|---|---|
| Sandy Bridge | 6 / 0.5p23 | 6 / 0.5p23 | 6 / 0.5p23 | 6 / 0.5p23 |
| Haswell | 7 / 1p0156 | 7 / 1p0156 | 6 / 0.5p012356 | 6 / 0.5p012356 |
| Broadwell, Skylake, Skylake-SP | 6 / 1p0156 | 6 / 1p0156 | 6 / 0.5p012356 | 6 / 0.5p012356 |
| Ice Lake | 6 / 0.5p0156 | 6 / 0.5p0156 | 6 / 0.5p012356 | 6 / 0.5p012356 |
| Alder Lake, Sapphire Rapids | 12 / 0.5p2 p3 p4 p7 p8 p9 p10 | 12 / 0.5p2 p3 p4 p7 p8 p9 p10 | 6 / 0.33p0 p1 p2 p3 p5 p6 p10 p11 | 5 / 0.33p2 p3 p10 |
| Lunar Lake | 12 / 0.5p10 p11 p20 p21 p22 p25 p26 p27 | 12 / 0.5p10 p11 p20 p21 p22 p25 p26 p27 | 6 / 0.33p0 p1 p2 p3 p4 p5 p20 p21 p22 | 4 / 0.33p20 p21 p22 |
| Bonnell | 3 / 1.5p1 | 3 / 1.5p1 | 2 / 1p01 | 1 / 1p01 |
| Silvermont | 4 / 2IEC0 IEC1 MEC | 4 / 2IEC0 IEC1 MEC | 3 / 1MEC | 3 / 1MEC |
| Piledriver | 6 / 1.5AGLU01 Load Store | 6 / 1.5AGLU01 Load Store | 5 / 1AGLU01 Load | 5 / 1AGLU01 Load |
| Zen | 5 / 0.5AGU0 AGU1 | 5 / 1AGU0 AGU1 | 4 / 0.5AGU0 AGU1 | 4 / 0.5AGU0 AGU1 |
| Zen 2 | 5 / 0.33AGU0 AGU1 AGU2 | 5 / 0.67AGU0 AGU1 AGU2 | 4 / 0.33AGU0 AGU1 AGU2 | 4 / 0.33AGU0 AGU1 AGU2 |
| Zen 3, Zen 4 | 6 / 1AGU0 AGU1 AGU2 LSU Load Store | 6 / 1AGU0 AGU1 AGU2 LSU Load Store | 5 / 0.33AGU0 AGU1 AGU2 LSU Load | 5 / 0.33AGU0 AGU1 AGU2 LSU Load |
| Jaguar | 4 / 1LAGU SAGU | 4 / 1LAGU SAGU | 3 / 1LAGU | 3 / 1LAGU |
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
POP r/m16/32/64v = load(rsp, OSIZE)
rsp = rsp + OSIZE // 8
dest.write(v) # after RSP: POP RSP loads the value
# popped; a memory operand's address
# that uses RSP uses the new one
Run on AMD Zen 5 (EPYC 9645): 36 cases.
POP ES not in 64-bit mode POP SS not in 64-bit mode POP DS not in 64-bit mode POP FS POP GSsel = load(rsp, OSIZE) # the low 16 bits are the selector
load_segment(dest, sel) # checks the descriptor it names;
# FS and GS take its base, or 0
# with a null selector (Zen 5)
rsp = rsp + OSIZE // 8
# after POP SS, interrupts wait until the next instruction is doneRun on AMD Zen 5 (EPYC 9645): 28 cases. The forms that 64-bit mode lacks were not run: the probe runs in 64-bit mode.
Operands
Flags
None: XED records no flag that the forms test or change.
Attributes
What else XED records about the forms. How to read.
POP ESnot in 64-bit modePOP SSnot in 64-bit modePOP DSnot in 64-bit modePOP FSPOP GS- may abort a TSX transaction
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 |
|---|---|---|
I86 | No CPUID bit: part of the base instruction set. | Every x86-64 processor in XED’s model and Zen 3 to Zen 6 |
More General-purpose instructions
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. - 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 2B, page 4-398 (POP)
- Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3 (325384-093, September 2026)
- AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and System Instructions (24594, rev. 3.39, October 2026)
- Linux kernel documentation: Using FS and GS segments in user space applications
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 timings come from LLVM's scheduling models, part of the LLVM Project, licensed under the Apache License 2.0 with LLVM Exceptions. The text is our own.