GENTOO is Rice

x86-64-v2, v3 and v4 Explained and When Building for Them Actually Pays Off

by admin

x86-64-v2, v3 and v4 Explained and When Building for Them Actually Pays Off

For two decades, the standard way to squeeze extra speed out of a Linux machine was the same ritual: set -march=native, rebuild everything, and believe your system was now faster than any binary distribution could ever be. The ritual worked because binary distributions had to ship code that ran on almost every 64-bit x86 processor ever made, including chips from 2003 without SSE3, POPCNT or AVX.

That assumption is now ending. Red Hat Enterprise Linux 10 requires x86-64-v3. Ubuntu builds its 26.04 cloud images for the same level by default and lets desktop users opt in. Gentoo publishes official binary packages built for v3. Fedora debated the same step in 2026. The quiet advantage source-based distributions once had is becoming a standard option, and the vocabulary for it, x86-64-v2, v3 and v4, has moved from compiler documentation into installation requirements.

This article explains what the microarchitecture levels actually contain, how they differ from -march=native, how distributions use them, what performance evidence exists, and how to check which level your hardware supports before a binary refuses to start.

x86-64-v2, v3 and v4 Explained and When Building for Them Actually Pays Off

Where the levels came from

The original 64-bit x86 architecture, introduced by AMD in 2003 and later adopted by Intel, guaranteed a fixed set of features: 64-bit registers, SSE and SSE2. Every processor added since then has brought new instructions, but software built for “x86-64” can only assume that original baseline. Anything newer has to be detected at run time or left unused.

In 2020, developers from the GNU C Library, GCC, LLVM, Red Hat, SUSE and Intel agreed on a small set of named levels in the x86-64 psABI, the document that defines the application binary interface for the architecture. The levels group instruction-set extensions into cumulative tiers, so a distribution or developer can target one name instead of listing dozens of features.

GCC 11 and Clang 12 added support for these names as -march targets, and glibc 2.33 added a mechanism to load libraries built for each level. The names are a convention for describing hardware capability. They are not processor generations or marketing labels.

html

<table>
  <thead>
    <tr>
      <th>Level</th>
      <th>Adds (on top of the previous level)</th>
      <th>Typical hardware that qualifies</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>x86-64 (sometimes called v1)</td>
      <td>CMOV, CX8, FPU, FXSR, MMX, SCE, SSE, SSE2 (the original 64-bit baseline)</td>
      <td>Every 64-bit x86 processor</td>
    </tr>
    <tr>
      <td>x86-64-v2</td>
      <td>CMPXCHG16B, LAHF/SAHF in 64-bit mode, POPCNT, SSE3, SSSE3, SSE4.1, SSE4.2</td>
      <td>Most x86-64 processors from roughly 2009 onward, including Intel Nehalem and later and AMD Bulldozer and later</td>
    </tr>
    <tr>
      <td>x86-64-v3</td>
      <td>AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE support</td>
      <td>Intel Haswell (2013) and later Core and Xeon, Intel Gracemont-based low-power chips (2021 onward), AMD Excavator and all Zen generations</td>
    </tr>
    <tr>
      <td>x86-64-v4</td>
      <td>AVX-512 F, BW, CD, DQ and VL</td>
      <td>Many Intel Xeon processors since Skylake-SP, some Intel client chips such as Ice Lake and Tiger Lake, AMD Zen 4 and Zen 5</td>
    </tr>
  </tbody>
</table>

The hardware column needs two caveats. First, branding is not a reliable guide. For years Intel sold Pentium and Celeron processors based on the same cores as its Core chips but with AVX disabled, and those processors only reach v2. Many low-power Atom-derived chips released before 2021 are also v2 only, even though they were sold alongside v3-capable laptops. Second, v4 is especially inconsistent. Intel’s hybrid client processors from Alder Lake onward do not expose AVX-512, so many recent Intel desktops and laptops stop at v3, while AMD’s Zen 4 and Zen 5 processors qualify for v4.

What the levels deliberately leave out

A common mistake is to treat x86-64-v3 as “everything a 2013-era processor can do”. It is not. The levels were designed to capture widely available, generally useful instructions, and several common extensions are deliberately absent from all of them.

AES-NI, the hardware acceleration for AES encryption, is not part of any level. Neither is PCLMULQDQ, which accelerates carry-less multiplication used in some cryptographic and checksum algorithms. The SHA extensions, VAES, VPCLMULQDQ, and the AVX-512 subsets beyond the five in v4 are also excluded.

That has practical consequences. Code that benefits from these instructions, such as cryptographic libraries, usually does not rely on compile-time -march flags at all. Libraries like OpenSSL detect processor features at run time and choose an optimised code path regardless of how the package was built. A v3 build of such a library may not be faster than a v1 build, because the hot paths were already using AES-NI on any machine that had it.

x86-64-v3 is not the same as -march=native

The levels and -march=native solve different problems.

-march=native tells GCC or Clang to target the exact processor the compiler is running on. It enables every extension that processor reports, including AES-NI, PCLMULQDQ, SHA and any available AVX-512 subsets, and it also sets -mtune for that microarchitecture, so the compiler schedules instructions for that core’s pipeline. The resulting binary is tailored to one machine and may crash with an “illegal instruction” error on another.

-march=x86-64-v3 targets a portable feature set. It enables only the extensions in the level definition and uses generic tuning. A v3 binary runs on any v3-capable processor, whether it is a 2015 AMD laptop, a 2021 Intel mini PC or a 2025 server.

You can see what each target enables with GCC itself. The following commands print the target options GCC would use, filtered for a few interesting extensions:

gcc -march=x86-64-v3 -Q --help=target | grep -E -- '-m(avx2|fma|aes|pclmul|sha) '
gcc -march=native -Q --help=target | grep -E -- '-m(avx2|fma|aes|pclmul|sha|arch=|tune=) '

On a modern processor, the first command shows AVX2 and FMA enabled but AES, PCLMUL and SHA disabled. The second shows everything the local chip supports, plus the resolved architecture and tuning names.

html

<table>
  <thead>
    <tr>
      <th>Property</th>
      <th>-march=x86-64-v3</th>
      <th>-march=native</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Instruction set</td>
      <td>Fixed list defined by the psABI level</td>
      <td>Everything the build machine reports</td>
    </tr>
    <tr>
      <td>Includes AES-NI, PCLMULQDQ, SHA</td>
      <td>No</td>
      <td>Yes, if the build machine has them</td>
    </tr>
    <tr>
      <td>Tuning</td>
      <td>Generic</td>
      <td>Tuned for the build machine's microarchitecture</td>
    </tr>
    <tr>
      <td>Portability</td>
      <td>Any v3-capable processor</td>
      <td>Reliably only the build machine, or identical hardware</td>
    </tr>
    <tr>
      <td>Typical use</td>
      <td>Distribution packages, shared binary caches, containers for a known fleet</td>
      <td>Software built and run on the same machine</td>
    </tr>
  </tbody>
</table>

On Gentoo, this distinction matters when building packages on one machine for use on another, or when sharing a binary package cache between machines. A -march=native build host that feeds packages to a different laptop is a classic way to produce mysterious crashes. Setting a level such as -march=x86-64-v3 in make.conf for shared builds, and keeping -march=native for machine-local builds, avoids that.

How distributions use the levels

Distributions use the levels in three distinct ways, and the differences matter more than the level names themselves.

Raising the baseline

The most aggressive approach is to build the entire distribution for a higher level, so it will not run on older hardware at all. Red Hat Enterprise Linux 9 raised its x86 baseline to x86-64-v2, and RHEL 10 raised it to x86-64-v3. On unsupported hardware, the system’s C library refuses to start programs and reports an error stating that the CPU does not support the required level.

Rebuilds of RHEL have responded differently. AlmaLinux 10 follows RHEL with v3 by default but also provides a separate x86-64-v2 build for older hardware. Its release notes point out the limitation: third-party packages built for RHEL 10 target v3, so v2 users may need to rebuild them, although AlmaLinux approved rebuilding the EPEL 10 add-on repository for v2.

x86-64-v2, v3 and v4 Explained and When Building for Them Actually Pays Off

Optional variant packages

Ubuntu introduced “architecture variants” in Ubuntu 25.10. The first variant, amd64v3, consists of x86-64-v3 builds of packages, supported by changes in dpkg, apt and Launchpad so that one package can have builds for different levels. In 25.10, roughly 2,000 source packages from the main component were rebuilt, with a warning that they had not yet had full testing. Users enable the variant through an apt configuration setting.

With Ubuntu 26.04 LTS, Canonical’s documentation states that AMD64 cloud images on all providers are built with amd64v3 by default. As a result, some older cloud instance types and CPU platforms are no longer supported for those images. On general-purpose installations the variant remains opt-in, for compatibility.

Canonical’s own announcement contained an important warning for anyone who moves disks between computers. A drive with amd64v3 packages installed may not boot on an older machine without v3 support.

Optimised libraries alongside baseline ones

The third approach keeps the whole system at the baseline and adds optimised copies of selected libraries. glibc 2.33 introduced glibc-hwcaps subdirectories, such as glibc-hwcaps/x86-64-v3 inside the library directory. When a program loads a shared library, the dynamic linker first checks the subdirectories for levels the processor supports, from highest to lowest, and falls back to the normal library if no optimised copy is found.

openSUSE Tumbleweed uses this approach. It remains at the x86-64 baseline, but since 2023 it has shipped optional v3-optimised library packages that are installed automatically on compatible hardware through a pattern called patterns-glibc-hwcaps-x86_64_v3, when recommended packages are enabled. Older hardware simply keeps using the baseline libraries. The limitation is that only shared libraries benefit. Executables themselves are not swapped, and the openSUSE announcement noted that only a few packages were enabled at first.

Other distributions

Gentoo has published official binary packages since the end of 2023. In February 2024 it added a second set for amd64 built for x86-64-v3, covering the same packages as the baseline set. Switching between them is a change to the binary repository configuration under /etc/portage/binrepos.conf/. Gentoo did not offer v4 binary packages and suggested that users who want that level build from source.

Fedora still targets the x86-64 baseline. A proposal to add x86-64-v3 as an additional primary architecture was rejected for Fedora 45 in 2026, with a request for more performance data and a plan for installation media before resubmission.

Arch Linux also remains at the baseline. A proposal for an official x86-64-v3 port has existed since 2020 but has not been implemented. Unofficial repositories, such as ALHP, provide optimised builds for those who want them.

html

<table>
  <thead>
    <tr>
      <th>Distribution</th>
      <th>Approach (as of October 2026)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Red Hat Enterprise Linux 10</td>
      <td>Baseline raised to x86-64-v3; RHEL 9 uses x86-64-v2</td>
    </tr>
    <tr>
      <td>AlmaLinux 10</td>
      <td>v3 by default, with a separate x86-64-v2 build for older hardware</td>
    </tr>
    <tr>
      <td>Ubuntu 25.10 and 26.04 LTS</td>
      <td>Optional amd64v3 architecture variant; 26.04 cloud images built with amd64v3 by default</td>
    </tr>
    <tr>
      <td>openSUSE Tumbleweed</td>
      <td>x86-64 baseline plus optional v3 libraries through glibc-hwcaps</td>
    </tr>
    <tr>
      <td>Gentoo</td>
      <td>Source builds with any flags; official binary packages for baseline x86-64 and x86-64-v3</td>
    </tr>
    <tr>
      <td>Fedora</td>
      <td>x86-64 baseline; v3 proposal rejected for Fedora 45, may return for a later release</td>
    </tr>
    <tr>
      <td>Arch Linux</td>
      <td>x86-64 baseline; v3 only through unofficial repositories</td>
    </tr>
  </tbody>
</table>

What the performance evidence actually shows

The case for higher levels rests on performance. The evidence is real but more modest than enthusiasts often assume.

When Canonical announced amd64v3 for Ubuntu 25.10, it summarised its earlier benchmarking: most packages showed a gain of about 1%, with larger improvements in some numerical packages. Fedora’s committee rejected the 2026 proposal partly because it wanted better performance data. Red Hat’s justification for raising RHEL’s baseline rested as much on hardware support policy and long support lifetimes as on raw speed.

The reasons for modest average gains are well understood.

Most software spends its time elsewhere. Typical desktop and server programs spend much of their time waiting for memory, storage, network or the user, or running branch-heavy logic that wide vector instructions cannot accelerate. A different instruction set does not change those bottlenecks.

Performance-critical libraries already use dispatch. Libraries such as glibc’s string functions, OpenSSL, video codecs, compression libraries and math libraries often detect processor features at run time and choose optimised code paths. On v3 hardware they already use AVX2 where it matters, even in a baseline build.

Auto-vectorisation has limits. Compiling with -march=x86-64-v3 allows the compiler to use AVX2 and FMA wherever it can prove it is safe and profitable. In practice it finds such loops mainly in numerical code, image processing and some data handling. General-purpose code rarely contains them.

Wider vectors can have side effects. On some older Intel processors, heavy AVX-512 use lowered clock speeds, which could make mixed workloads slower. This mostly affects v4 and has become less significant on newer processors, but it shows that enabling more instructions does not automatically mean better performance.

The gains are most likely in scientific computing, multimedia processing, compression, and numerical libraries without their own dispatch code. They are least likely in desktop applications, shells, web servers and system utilities. The most reliable way to know is to measure the specific workload, which is the same advice that applies to -O3 and every other optimisation flag.

Checking which level your processor supports

On any system with glibc 2.33 or later, the dynamic linker can report which levels the processor supports. On most x86-64 distributions, run:

/lib64/ld-linux-x86-64.so.2 --help

Some distributions, including Ubuntu, also provide ld.so as a shorter name for the same program. Near the end of the output is a section listing the glibc-hwcaps subdirectories in priority order. Levels the processor supports are marked as supported and searched. A typical v3-capable processor shows x86-64-v3 (supported, searched) and x86-64-v2 (supported, searched), with v4 listed without those markers.

Gentoo users can also inspect individual instruction-set flags with the cpuid2cpuflags tool from the app-portage/cpuid2cpuflags package, which prints the features relevant to Portage’s CPU_FLAGS_X86 variable. This shows, for example, whether a processor that reaches v3 also supports AES-NI or SHA, which the levels do not cover.

Virtual machines and containers

Virtual machines are the most common source of unexpected failures. A hypervisor presents a virtual CPU to the guest, and that virtual CPU may expose fewer features than the physical processor. QEMU’s generic default CPU model, for example, exposes only a conservative set of features, so a guest running RHEL 9 or RHEL 10 may refuse to boot even on a modern host.

The fix is to configure the virtual machine to pass the host CPU features through, or to choose a named CPU model that includes the required extensions. The same consideration applies to cloud instances. Ubuntu’s documentation for 26.04 notes that certain older cloud instance families and CPU platforms no longer meet the requirements for its v3-built images.

Containers do not virtualise the CPU, so a container image built for v3 runs only on a v3-capable host. Organisations that build images for a mixed fleet must either target the lowest common level or maintain separate images for each.

Choosing a level in practice

The right choice depends on where software will run and who controls the hardware.

A personal machine with a source-based distribution. If packages are built and used on the same computer, -march=native remains appropriate. It gives the compiler the most information and the build never leaves that machine.

Several machines sharing binary packages. Choose the highest level all of them support. For most hardware sold in the last decade, that is v3. Setting -march=x86-64-v3 for shared builds avoids crashes when packages move between machines.

A binary distribution on modern hardware. If the distribution offers v3 packages, as Ubuntu and Gentoo do, enabling them is low-risk on v3 hardware and occasionally helps. If you move disks between computers or run older machines, check the level first.

Software you distribute to others. Building for the baseline and using run-time dispatch for hot paths remains the safest approach for broad compatibility. Raising the minimum level is a support decision as much as a technical one, because it excludes users with older hardware.

Servers and data centres. Check the oldest hardware in the fleet, including virtual machine CPU models. RHEL 10’s move to v3 is a reminder that operating system choice can also determine minimum hardware requirements.

The ricer’s question, answered

The microarchitecture levels formalise much of what source-based distribution users have done for decades: use the instructions your processor has instead of the ones every processor has. What has changed is that binary distributions can now do the same at scale, with names that are portable across compilers and recognised by the dynamic linker.

The evidence suggests that the payoff is real but specific. For most software, the difference between a baseline build and a v3 build is around one percent. For numerical, multimedia and compression workloads without their own dispatch, it can be considerably larger. Knowing which level your processor supports, which level your distribution assumes and which workloads actually benefit turns the old ritual of rebuilding everything into a decision based on measurement.