ぐだぐだ低レベルプログラミング(157)ARM64(AArach64)SIMD 要素毎MUL

Joseph Halfmoon

前回、SIMDレジスタの全要素に、別なSIMDレジスタの1要素を乗じる形の命令を練習しました。この「全要素に他方の一要素を共通で掛け算」する系統の命令は実に33種あり(前回の3種含む)、忘却力の老人が覚えきれるものではありませぬ。そこで今回は一覧表を作って「整理」してみたのだけれど、ダメだ、こんがらがる。。。

※「ぐだぐだ低レベルプログラミング」投稿順indexはこちら

※実機動作確認には以下を使用しております。

    • Raspberry Pi 4 model B、Cortex-A72コア(ARMv8-A)
    • Raspberry Pi OS (64bit) bullseye
    • gcc (Debian 10.2.1-6) 10.2.1 20210110

ARMv8もいろいろレベルがあり、Arm Cortex-A72はARMv8の中でもベーシックな(命令数の少ない)ARMv8p0です。

※A64の最新のマニュアルは以下でダウンロード可能です。

Arm Architecture Reference Manual for A-profile architecture

SIMD by element arithmetic

前回も書きましたが、SIMD演算の場合、各要素毎並列に計算するという通常のスタイルだけでなく、一方のSIMDレジスタの全要素に他方の1要素を作用させるスタイルの計算(多くは積和算)も多用されるじゃないかと思います。前回、MUL、MLA、MLSを練習してますが、一覧表として全て列挙するとこんな形になりました。

multiply multiply-add multiply-subtract
Int, Unsigned MUL MLA MLS
Int, Signed long SMULL, SMULL2 SMLAL, SMLAL2 SMLSL, SMLSL2
Int, Unsigned long UMULL, UMULL2 UMLAL, UMLAL2 UMLSL, UMLSL2
Int, Signed saturating doubling long SQDMULL, SQDMULL2 SQDMLAL, SQDMLAL2 SQDMLSL, SQDMLSL2
Int, Signed saturating doubling long HF SQDMULH
Int, Signed saturating rounding doubling HF SQRDMULH SQRDMLAH SQRDMLSH
FP, fused FMLA FMLS
FP, fused long FMLAL, FMLAL2 FMLSL, FMLSL2
FP FMUL
FP, extended FMULX

いつもの繰り返しですが書いておきます。「命令多過ぎA64」と。

上記で、注釈を書いておかねばならない部分を列挙すると以下のようです。

    • long、結果のビット幅が倍幅になるもの
    • saturating、オーバーフロー時に表現可能な上限、下限へのサチュレーションが起こるもの
    • doubling、結果の値を2倍にするもの
    • fused、積和、積差などの演算時に、掛け算と足し算/引き算のそれぞれで丸めをするのではなく、両方を1度に計算した後、まとめて丸めを行うもの
    • HF(high halfを勝手に略称)、掛け算の場合、結果は倍のビット幅になるが、その上位半分の幅を結果として返すもの
    • rounding、上記のHF処理をするときに下の値を丸めた値を返すもの
    • extended、無限大とゼロの計算が「拡張」されているもの。わしゃ知らんよ。どんなときに使うの?

今回は一覧表を作っただけで疲れました。実習は無ね。

ぐだぐだ低レベルプログラミング(156)ARM64(AArach64)SIMD MUL へ戻る

ぐだぐだ低レベルプログラミング(158)ARM64(AArach64)SIMD要素毎FMUL へ進む