x86-64 の ABI は SSE を前提に書かれ、それ以降の各拡張は、呼び出しで扱わなければならないレジスターを加えてきました。AVX と AVX-512 ではより幅の広いベクトルレジスター、マスクレジスター、APX では 16 本の汎用レジスターの追加、そして AMX のタイルです。このページでは、64 ビットの 2 つの ABI、System V と Microsoft x64 からそれらに関する規則を集めています。命令は拡張のページで説明しています。

__m256 と __m512 の引数

System V では、__m256 引数は SSE クラスの eightbyte 1 つと、それに続く SSEUP クラスの eightbyte 3 つからなり、YMM レジスター 1 つを満たします。__m512 は ZMM レジスター 1 つを満たします。これが成り立つのは、それらのレジスターを持つプロセッサー向けにコードをコンパイルした場合だけです。AVX なしでコンパイルすると、同じ関数はベクトルをメモリで受け取るため、呼び出し元と呼び出し先は同じベクトルオプションでコンパイルしなければなりません。GCC と Clang はそのような関数について「AVX vector argument without AVX enabled changes the ABI」と警告します (-Wpsabi)。可変長引数の呼び出しでは、これらの型はいずれにしてもスタックで渡されます。

同じ関数の 3 通りのコンパイル結果。AVX なしの GCC は 2 つのベクトルをスタックで受け取り、結果を RDI にアドレスがあるメモリを通じて返します。-mavx では YMM0 と YMM1 を使います。AVX を有効にした Windows 向けの Clang は、関数が __vectorcall でない限り、それらを RCX と RDX で参照渡しします。

vec256.c

/* A 32-byte vector, like AVX's __m256. Whether it travels in a YMM
   register depends on the processor the code is compiled for. */
typedef float v8sf __attribute__((vector_size(32)));

v8sf add8(v8sf a, v8sf b)
{
	return a + b;
}

#ifdef _WIN32
v8sf __vectorcall add8_vc(v8sf a, v8sf b)
{
	return a + b;
}
#endif

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -S vec256.c

add8:
        movaps  8(%rsp), %xmm0
        addps   40(%rsp), %xmm0
        movq    %rdi, %rax
        movaps  %xmm0, (%rdi)
        movaps  24(%rsp), %xmm0
        addps   56(%rsp), %xmm0
        movaps  %xmm0, 16(%rdi)
        ret

Intel 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -masm=intel -S vec256.c

add8:
        movaps  xmm0, XMMWORD PTR 8[rsp]
        addps   xmm0, XMMWORD PTR 40[rsp]
        mov     rax, rdi
        movaps  XMMWORD PTR [rdi], xmm0
        movaps  xmm0, XMMWORD PTR 24[rsp]
        addps   xmm0, XMMWORD PTR 56[rsp]
        movaps  XMMWORD PTR 16[rdi], xmm0
        ret

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx -S vec256.c

add8:
        vaddps  %ymm1, %ymm0, %ymm0
        ret

Intel 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx -masm=intel -S vec256.c

add8:
        vaddps  ymm0, ymm0, ymm1
        ret

Clang 23.1.2 x86_64-pc-windows-msvc

AT&T 構文 clang --target=x86_64-pc-windows-msvc -O2 -fno-asynchronous-unwind-tables -mavx -S vec256.c

add8:
        vmovaps (%rcx), %ymm0
        vaddps  (%rdx), %ymm0, %ymm0
        retq

add8_vc@@64:
        vaddps  %ymm1, %ymm0, %ymm0
        retq

Intel 構文 clang --target=x86_64-pc-windows-msvc -O2 -fno-asynchronous-unwind-tables -mavx -masm=intel -S vec256.c

add8:
        vmovaps ymm0, ymmword ptr [rcx]
        vaddps  ymm0, ymm0, ymmword ptr [rdx]
        ret

add8_vc@@64:
        vaddps  ymm0, ymm0, ymm1
        ret
AVX-512 では、__m512 の値は ZMM0 と ZMM1 で届き、ZMM0 で返ります。

vec512.c

/* A 64-byte vector, like AVX-512's __m512, in ZMM registers. */
typedef float v16sf __attribute__((vector_size(64)));

v16sf add16(v16sf a, v16sf b)
{
	return a + b;
}

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx512f -S vec512.c

add16:
        vaddps  %zmm1, %zmm0, %zmm0
        ret

Intel 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx512f -masm=intel -S vec512.c

add16:
        vaddps  zmm0, zmm0, zmm1
        ret

Clang 23.1.2 x86_64-linux-gnu

AT&T 構文 clang --target=x86_64-linux-gnu -O2 -fno-asynchronous-unwind-tables -mavx512f -S vec512.c

add16:
        vaddps  %zmm1, %zmm0, %zmm0
        retq

Intel 構文 clang --target=x86_64-linux-gnu -O2 -fno-asynchronous-unwind-tables -mavx512f -masm=intel -S vec512.c

add16:
        vaddps  zmm0, zmm0, zmm1
        ret

Microsoft x64 は、プロセッサーにかかわらず、8 バイトより幅の広いすべてのベクトルを参照渡しします。__m256 の値を YMM レジスターで渡すのは __vectorcall だけです。Apple の macOS のドキュメントは、System V にも同じ依存関係があることを指摘しています。16 バイトより幅の広いベクトルの渡し方は、コードのコンパイル対象のプロセッサー機能によって決まります。

VZEROUPPER

ABI は、呼び出しをまたいで YMM レジスターと ZMM レジスターの上位半分を誰が所有するかを定めていません。上位半分はスクラッチ (scratch) です。しかし、プロセッサーは上位半分にデータがある間は古い SSE エンコーディングの命令を遅く実行するため、コンパイラーは、それらを使った関数が戻る前、または SSE を使うかもしれないほかの関数を呼び出す前に、VZEROUPPER でそれらをクリアします。GCC と Clang は AVX 向けにコンパイルするとき、デフォルトでこれを行います。GCC のマニュアルは -mvzeroupper オプションの項でその理由を説明しています。

square は YMM0 で計算し、next にジャンプする前に VZEROUPPER を実行します。

vzeroupper.c

/* After using the upper halves of the YMM registers, a function clears
   them with VZEROUPPER before it calls or returns to code that may use
   SSE instructions. */
typedef float v8sf __attribute__((vector_size(32)));

extern void next(void);

void square(v8sf *p)
{
	*p = *p * *p;
	next();
}

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx -S vzeroupper.c

square:
        vmovaps (%rdi), %ymm0
        vmulps  %ymm0, %ymm0, %ymm0
        vmovaps %ymm0, (%rdi)
        vzeroupper
        jmp     next@PLT

Intel 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx -masm=intel -S vzeroupper.c

square:
        vmovaps ymm0, YMMWORD PTR [rdi]
        vmulps  ymm0, ymm0, ymm0
        vmovaps YMMWORD PTR [rdi], ymm0
        vzeroupper
        jmp     next@PLT

Clang 23.1.2 x86_64-linux-gnu

AT&T 構文 clang --target=x86_64-linux-gnu -O2 -fno-asynchronous-unwind-tables -mavx -S vzeroupper.c

square:
        vmovaps (%rdi), %ymm0
        vmulps  %ymm0, %ymm0, %ymm0
        vmovaps %ymm0, (%rdi)
        vzeroupper
        jmp     next@PLT

Intel 構文 clang --target=x86_64-linux-gnu -O2 -fno-asynchronous-unwind-tables -mavx -masm=intel -S vzeroupper.c

square:
        vmovaps ymm0, ymmword ptr [rdi]
        vmulps  ymm0, ymm0, ymm0
        vmovaps ymmword ptr [rdi], ymm0
        vzeroupper
        jmp     next@PLT

AVX-512 のマスクレジスター

8 つのマスクレジスター K0 から K7 は、System V ではスクラッチです。関数はそれらを変更でき、どれも引数や結果を運びません。関数に渡すマスクは 16 ビットの __mmask16 などの整数で、汎用レジスターで渡されます。Microsoft の呼び出し規約はマスクレジスターに触れておらず、XMM16 から XMM31 をスクラッチとしています。

比較命令は結果を K1 に書き込み、K1 はその後 2 つのベクトルのどちらかを選びます。どちらのコンパイラーも K1 をスクラッチレジスターとして使います。

avx512-mask.c

/* AVX-512 compares produce a mask in a K register, which selects
   elements; the mask registers are scratch in every ABI. */
typedef int v16si __attribute__((vector_size(64)));

v16si pick(v16si a, v16si b, v16si c)
{
	v16si m = a > b;

	return (m & a) | (~m & c);
}

GCC 14.2.0 (Debian 14.2.0-19) x86_64-linux-gnu

AT&T 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx512f -S avx512-mask.c

pick:
        vpcmpd  $6, %zmm1, %zmm0, %k1
        vpblendmd       %zmm0, %zmm2, %zmm0{%k1}
        ret

Intel 構文 gcc-14 -O2 -fno-asynchronous-unwind-tables -mavx512f -masm=intel -S avx512-mask.c

pick:
        vpcmpd  k1, zmm0, zmm1, 6
        vpblendmd       zmm0{k1}, zmm2, zmm0
        ret

Clang 23.1.2 x86_64-linux-gnu

AT&T 構文 clang --target=x86_64-linux-gnu -O2 -fno-asynchronous-unwind-tables -mavx512f -S avx512-mask.c

pick:
        vpcmpgtd        %zmm1, %zmm0, %k1
        vpblendmd       %zmm0, %zmm2, %zmm0 {%k1}
        retq

Intel 構文 clang --target=x86_64-linux-gnu -O2 -fno-asynchronous-unwind-tables -mavx512f -masm=intel -S avx512-mask.c

pick:
        vpcmpgtd        k1, zmm0, zmm1
        vpblendmd       zmm0 {k1}, zmm2, zmm0
        ret

APX: R16 から R31

APX は 16 本の汎用レジスターを追加します。64 ビットの 2 つの ABI は、これらを異なる方法で扱います。

64 ビットの 2 つの ABI における APX のレジスター
レジスターSystem V x86-64Microsoft x64
R16 から R29スクラッチスクラッチ
R30、R31スクラッチ呼び出し先保存

Microsoft は注意点を 1 つ加えています。jmp_buf には R30 と R31 を入れる場所がないため、関数は setjmp から longjmp につながる呼び出しまでの間にそれらを変更してはなりません。新しいレジスターはどれも引数を運ばないため、APX 向けにコンパイルしたコードは APX なしでコンパイルしたコードを呼び出せ、その逆も可能です。命令は APX 拡張のページ (英語)に一覧があります。

AMX タイル

AMX の 8 つのタイルレジスター TMM0 から TMM7 はどちらの ABI でもスクラッチで、System V ではタイル構成 TILECFG もスクラッチです。タイルを使う関数は LDTILECFG でタイルを構成し、TILERELEASE でタイルを初期状態に戻します。

Linux では、最初に使う前に 1 つの手順が加わります。タイルデータは、カーネルがすべてのスレッドには割り当てない 8 KB の状態なので、プロセスは arch_prctl(ARCH_REQ_XCOMP_PERM, 18) でそれを要求しなければなりません。18 はタイルデータの XSAVE のコンポーネントの番号です。要求するまでは、最初の AMX 命令が SIGILL を発生させます。要求した後は、カーネルは各スレッドが初めてタイルを使うときに、そのスレッド用のより大きなバッファーを割り当てます。この許可はプロセス全体に有効で、fork 後も保たれ、exec で解除されます。命令については AMX タイル拡張 (英語)を参照してください。

出典

  1. System V Application Binary Interface, AMD64 Architecture Processor Supplement, version 1.0: コミット e1ce098331da、2025-03-12
  2. Microsoft Learn: x64 calling convention: コミット f70d88cd5da7、2026-09-24
  3. Microsoft Learn: Overview of x64 ABI conventions: コミット f70d88cd5da7、2026-09-24
  4. Microsoft Learn: __vectorcall: コミット f70d88cd5da7、2026-09-24
  5. Apple Developer: Writing 64-bit Intel code for Apple Platforms: 2026-09-25 の公開版
  6. GCC 14.2 manual: x86 Options: 2026-09-25 の公開版
  7. Linux 7.3: Documentation/arch/x86/xstate.rst: コミット c03c1a14507d、2026-10-18