AVX指令集

高級向量擴展指令集（Advanced Vector Extensions，簡稱AVX）是x86架構微處理器中的SIMD擴展指令集，由英特爾在2008年3月提出，並在2011年第一季度發布的Sandy Bridge系列處理器中首次支持。AMD在隨後的2011年第三季度發布的Bulldozer系列處理器中開始支持AVX。AVX指令集提供了新的特性、指令和編碼方案。

AVX是X86指令集的SSE延伸架構，如IA16至IA32般的把暫存器XMM 128bit提升至YMM 256bit，以增加一倍的運算效率。此架構支持了三運算指令（3-Operand Instructions），減少在編碼上需要先複製才能運算的動作。在微碼部分使用了LES LDS這兩少用的指令作為延伸指令Prefix。

AVX2指令集將大多數整數命令操作擴展到256位，並引入了熔合乘法累積（FMA）運算。它們由Intel在2013年發布的Haswell微架構中首次支持。

AVX-512則使用新的EVEX前綴編碼將AVX指令進一步擴展到512位，由Intel在2016年發布的Knights Landing協處理器中首次支持。Intel Xeon Scalable處理器支援AVX-512。

## 介紹

AVX使用十六個YMM寄存器，通過單條指令對多組數據執行操作（參見 SIMD）。每個YMM寄存器可同時存儲並對以下數據進行並行運算：

- 八個 32 位單精度浮點數；或
- 四個 64 位雙精度浮點數。

SIMD 寄存器的寬度從128位擴展至256位，並將XMM0~XMM7重命名為YMM0~YMM7（在x86-64模式下，則為XMM0~XMM15重命名為YMM0~YMM15）。因此傳統的SSE指令仍可通過VEX前綴操作於YMM寄存器的低 128 位。

AVX 引入了一種名為VEX編碼方案的三操作數SIMD指令格式，其中目標寄存器與兩個源操作數不同。例如，原本採用傳統雙操作數形式的SSE指令 a ← a + b，現在可採用非破壞性的三操作數形式 c ← a + b，從而保留兩個源操作數。最初，AVX的三操作數格式僅適用於具有SIMD操作數（YMM）的指令，不包括通用寄存器（如 EAX）相關的指令。隨後在 BMI 等擴展中，該編碼方案被用於為通用寄存器上的新指令進行編碼。VEX 編碼也用於操作 AVX-512 引入的 k0–k7 掩碼寄存器的指令。

SIMD記憶體操作數的對齊要求已被放寬。與未使用VEX編碼的對應指令不同，大多數使用VEX編碼的向量指令不再要求其記憶體操作數必須按向量大小對齊。值得注意的是，VMOVDQA指令仍要求其記憶體操作數必須對齊。

新的VEX編碼方案引入了一組新的代碼前綴，擴展了操作碼空間，允許指令擁有超過兩個操作數，並支持SIMD向量寄存器長度超過128位。該VEX前綴也可用於傳統SSE指令，賦予其三操作數形式，使其無需依賴VZEROUPPER和VZEROALL即可更高效地與AVX指令交互。

AVX指令同時支持128位和256位SIMD。128位版本可用於在不擴大向量化寬度的前提下優化舊代碼，並避免從SSE切換到AVX所帶來的性能懲罰；在某些早期AMD的AVX實現中，這些指令運行更快。此模式有時被稱為 AVX-128。

與SSE系列相比，AVX在數字媒體播放、網頁瀏覽、非對稱加密等方面進一步提升了性能。

## 新指令

這些AVX指令是在對傳統128位SSE指令的256位擴展指令之外新增的；其中大多數既可用於128位操作數，也可用於256位操作數。

指令｜描述

`VBROADCASTSS`, `VBROADCASTSD`, `VBROADCASTF128`｜廣播加載：將一個 32 位、64 位或 128 位的記憶體操作數複製到 XMM 或 YMM 寄存器的所有元素中。

`VINSERTF128`｜128 位替換：將 256 位 YMM 寄存器的下半部分或上半部分替換為一個 128 位源操作數的值，寄存器的另一半保持不變。

`VEXTRACTF128`｜128 位提取：提取 256 位 YMM 寄存器的下半部分或上半部分，並將其複製到 128 位目標操作數中

`VMASKMOVPS`, `VMASKMOVPD`｜條件 SIMD 加載/存儲：根據掩碼，從 SIMD 向量記憶體操作數中有條件地讀取任意數量的元素到目標寄存器，未讀取的元素位置置零；或從 SIMD 向量寄存器中有條件地將任意數量的元素寫入記憶體操作數，記憶體中未被寫入的元素保持不變。需要注意的是，在 AMD Jaguar 處理器架構中，當掩碼為零時，該指令（記憶體源操作數版本）耗時超過 300 個時鐘周期——儘管此時指令本應什麼也不做。這被認為是一個設計缺陷。

`VPERMILPS`, `VPERMILPD`｜通道內置換（Permute In-Lane）：對輸入操作數的 32 位或 64 位向量元素進行打亂。這是一類作用於 256 位的「通道內」指令，即在兩個獨立的 128 位通道內分別執行打亂操作，因此無法跨 128 位通道進行元素交換

`VPERM2F128`｜跨通道打亂（Shuffle）：將兩個 256 位源操作數中的四個 128 位向量元素，依據一個立即數選擇器，打亂後送入 256 位目標操作數

`VTESTPS`, `VTESTPD`｜打包符號位測試：對打包的單精度或雙精度浮點數的符號位進行位測試，根據「與」（AND）的結果設置 ZF 標誌，根據「與非」（ANDN）的結果設置 CF 標誌

`VZEROALL`｜清零所有 YMM 寄存器：將所有 YMM 寄存器置零，並標記為未使用。該操作通常在 128 位與 256 位使用模式切換時執行

`VZEROUPPER`｜清零 YMM 寄存器上半部分：將所有 YMM 寄存器的上半部分置零，用於從 256 位模式切換回 128 位模式時清空高 128 位

## 支援

### CPU對AVX指令集的支持情況

- 英特爾
- Sandy Bridge（2011年Q1）及更新的的處理器（除賽揚和奔騰）均支持
- Tiger Lake（2020年Q3）及更新的的奔騰和賽揚處理器均支持
- 推土機微架構（2011年Q4）及更新的處理器均支持
- 威盛電子
- Nano QuadCore
- Eden X4
- 基於五道口架構的處理器（KX-5000及KH-20000）

### 編譯器和彙編器對AVX指令集的支持情況

- Absoft編譯器支持-mavx選項
- Free Pascal編譯器從2.7.1版本開始為AVX和AVX2提供-CfAVX和-CfAVX2選項
- Delphi從RAD studio v11.0 Alexandria版本開始支持AVX2和AVX512
- GNU彙編器從GNU Binutils 2.19版本開始支持AVX
- 4.6版本的GCC和11.1版本的Intel編譯器套件開始支持AVX
- Open64編譯器從4.5.1版本開始使用-mavx標誌支持AVX
- PathScale編譯器支持-mavx選項
- Vector Pascal編譯器通過-cpuAVX32選項支持AVX
- Visual Studio 2010/2012 編譯器通過內聯函數（intrinsic）和 /arch:AVX選項支持AVX
- NASM從2.03版本開始支持 AVX，並在 2.04 版本中，進行了許多與 AVX 相關的錯誤修復和更新

### 作業系統對AVX指令集的支持情況

AVX通過256 位寬的YMM寄存器添加了新的寄存器狀態，因此需要作業系統顯式支持，以在上下文切換時正確保存和恢復AVX的擴展寄存器。以下作業系統版本支持 AVX：

- DragonFly BSD：在2013年初添加支持
- FreeBSD：在2012年1月21日提交的補丁中添加支持，該補丁包含在9.1穩定版中
- Linux：內核版本2.6.30（發布於2009年6月9日）開始支持
- macOS：從10.6.8版本（Snow Leopard，發布於2011年6月23日）開始支持。macOS Ventura 不支持沒有AVX2指令集的 x86 處理器
- OpenBSD：在2015年3月21日添加支持
- Solaris：在 Solaris 10 Update 10 和 Solaris 11 中開始支持。
- Windows：在 Windows 7 SP1（KB976932）、Windows Server 2008 R2 SP1、Windows 8、Windows 10 中提供支持
- Windows Server 2008 R2 SP1 結合 Hyper-V 需要熱修復（KB2568088）以支持 AMD AVX（Opteron 6200 和 4200 系列）處理器
- Windows XP 和 Windows Server 2003 在內核驅動和使用者應用程式中都不支持 AVX

## 外部連結

- Intel Intrinsics Guide