Instruction
BSF
Writes the index of the lowest set bit of the source to the destination; a zero source sets ZF and leaves the destination unchanged.
- Extensions
- Forms
- 2 (2 Legacy)
- Data
- Intel XED v2026.08.23
BSF finds the lowest set bit of its source and writes that bit’s index to the destination: for 0x28 it gives 3. ZF says whether there was a bit to find. For a nonzero source BSF clears ZF; for zero it sets ZF and does not write the destination at all, and the other flags are undefined. BSR is the scan from the other end.
Testing ZF
Code that may see a zero source checks ZF right after the scan instead
of testing the source first. __builtin_ffs(x), which returns the
index plus 1, or 0 for no bit, shows how. GCC 14 at -O2 compiles it to
bsf eax, edi,mov edx, -1andcmove eax, edx, taking -1 when ZF is set,add eax, 1;
Clang 23 does the same with CMOVNE the other way round.
For __builtin_ctz, which C leaves undefined for 0, both compilers
emit rep bsf instead, which runs as TZCNT where BMI1
exists and as BSF elsewhere; the TZCNT page explains where the two
differ.
The unchanged destination
Both vendors’ manuals now say that a zero source leaves the
destination alone, so a register loaded beforehand acts as the result
for zero: mov eax, 32 followed by bsf eax, edi gives 32 for x = 0.
Intel’s manual adds that some older processors clear bits 63:32 of a
64-bit register when a 32-bit BSF finds no bit. Zen 5 and the Intel
processor under KVM that recorded this page kept all 64 bits in every
such case. Code meant for any x86-64 processor should still load the
fallback value into the full register, or use TZCNT, which returns the
operand size for zero.
Walking the set bits
A loop that visits the set bits of a mask takes the lowest with BSF or
TZCNT, handles it, and clears it with BLSR or with
m & (m - 1), until the mask is 0; since the loop condition already
excludes zero, the scan never meets an empty source. The instruction
table of AMD’s Zen 5 guide lists BSF, like TZCNT, as one macro-op with
a latency of one cycle.
In the optimization guide
What the optimization guide says about BSF, a line per claim. Each links to the claim in the guide, with its sources and where they differ.
Jaguar and Puma
- Integer execution: LZCNT and POPCNT take one cycle on either ALU and TZCNT two, while BSF and BSR are microcoded, of seven and eight macro-ops and 4 and 5 cycles, so the newer instructions are the better choice where the zero case allows.
Skylake to Cooper Lake
- Integer execution: Port 1 alone runs integer multiplication, PDEP and PEXT,
popcnt,lzcnt,tzcnt,bsf,bsrand the double shifts, with a latency of three cycles and one a cycle in LLVM’s models, as on Golden Cove.
Zen and Zen+
- Integer execution: BSF and BSR are six macro-ops with a latency of three and four cycles, while LZCNT and POPCNT are one macro-op of one cycle and TZCNT two of two cycles. sources differ
Zen 2
- Integer execution: BSF and BSR are six macro-ops with a latency of three and four cycles, while LZCNT and POPCNT are one macro-op of one cycle and TZCNT two; LLVM’s model agrees.
Forms
| Instruction | Encoding | Requires |
|---|---|---|
BSF r16/32/64, m16/32/64
BSF_GPRv_MEMv | 0F BC /rF3 0F BC /r (without BMI1) | Base instruction set |
BSF r16/32/64, r16/32/64
BSF_GPRv_GPRv | 0F BC /rF3 0F BC /r (without BMI1) | Base instruction set |
Latency and throughput
| Model | r16, m16r32, m32r64, m64 | r16, r16r32, r32r64, r64 |
|---|---|---|
| Sandy Bridge, Haswell, Broadwell, Skylake, Skylake-SP, Ice Lake, Alder Lake, Sapphire Rapids | 8 / 1p1 | 3 / 1p1 |
| Lunar Lake | 7 / 0.33p135 | 3 / 0.33p135 |
| Bonnell | 16 / 16p1 | 16 / 16p01 |
| Silvermont | 13 / 10IEC0 IEC1 MEC | 10 / 10IEC0 IEC1 |
| Piledriver | 7 / 3EX0 EX1 | 3 / 3EX0 EX1 |
| Zen, Zen 2 | 7 / 3ALU0 ALU1 ALU2 ALU3 | 3 / 3ALU0 ALU1 ALU2 ALU3 |
| Zen 3 | 7 / 3ALU1 | 3 / 3ALU1 |
| Zen 4 | 5 / 1ALU1 | 1 / 11ALU1 |
| Jaguar | 7 / 4ALU0 ALU1 | 4 / 4ALU0 ALU1 |
Operation
What the forms do, in pseudocode that our tests run against results recorded on real processors. How to read.
s = src.read()
if s == 0:
zf = 1
# dest is not written, as both manuals say; Intel's adds
# that some older processors clear bits 63:32 of it at a
# 32-bit operand size
else:
zf = 0
for i in range(OSIZE):
if s >> i & 1:
dest.write(i) # the number of the lowest 1 bit
break
of = sf = af = pf = cf = UNDEFINEDRun on AMD Zen 5 (EPYC 9645) and an Intel processor under KVM (model hidden): 138 cases.
Operands
| Operand | Kind | Action |
|---|---|---|
BSF r16/32/64, r/m16/32/64 | ||
r16/32/64 | explicit | conditional write |
r/m16/32/64 | explicit | read |
RFLAGS | implicit | write |
Flags
| OF | SF | ZF | AF | PF | CF |
|---|---|---|---|---|---|
| All forms | |||||
| U | U | M | U | U | U |
Intrinsics
The C intrinsics of Clang 23.1.2 that compile to BSF, 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 |
|---|---|
_bit_scan_forward
int _bit_scan_forward(int A) |
|
__bsfd
int __bsfd(int __A) |
|
__bsfq
int __bsfq(long long __A) |
|
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 |
|---|---|---|
I386 | 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. - 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 2A, page 3-107 (BSF)
- AMD64 Architecture Programmer's Manual, Volume 3: General-Purpose and System Instructions (24594, rev. 3.39, 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.