はじめに
型に関するcastについて説明します.
Cast
この命令は,C++でのreinterpret_cast
相当であり,データの示す型だけキャストするもので,中の値を返還するものではありません.
演算を含まなく,コンパイル時にすべて解決するため,レイテンシ0の計算になります.
一方でstatic_cast
に相当する,格納する値も変更するようなその場合の命令はConvertにまとめられています.
つまり下記に示す例のように,(1)のように値を型に合わせて変換するものがconvertに相当し,後者の(2)のデータをそのままに保持する型をへ関するのがcastに相当します.
float val = 1.5;
int a = int(val);//(1)
int b = *(int*)(&val);//(2)
このキャストは,主に算術命令ではなくデータの並びを操作するような命令時に,その命令に適切な型がないときにキャストすることでコンパイルを可能にします.
算術演算とは違い,1番目の要素と2番目の要素を入れ替えるなどの操作などは型に依存しません.
例えば,__m256
と__m256i
は整数と浮動小数点と入っている値は違いますが,__m256i
に入っているものがint
であれば,32ビットのビット列が8つづつ収まっている配列であるという概念は同じです.
そのため,データを入れ替える命令は,浮動小数点であっても整数であっても実行可能です.
AVX命令は,概ねその型にあった命令が用意されていますが,いくつかは用意されていません.
例えば,レジスタに1つの要素を代入するinsert命令は,整数命令しか十分な命令が用意されていません.
しかしながら,その命令はただキャストすれば同じように使うことができます.
下記に,全てのキャスト命令の一覧表を示します.
-は,自分自身へのキャストであるため意味がありません.xはその命令が存在しないことを示しています.
同サイズの型はすべて相互変換可能であり,また,サイズが異なるものに対しては,同種(__m128と__m256など)の変換だけ用意されています.つまり,同種にキャストしたのちに任意の型に更にキャストすれば,全ての場合に対応しています.
コンパイラへの指示であるため,どれだけネストしても速度が増えるということはありません.
また,mm128(d/i)から,mm256(d/i)への変換はYMMの値が未定義であるため,zext
を付けた命令を呼ぶと0エクステンションした値としてキャスト可能です.
mm128 | mm128d | mm128i | mm256 | mm256d | mm256i | |
---|---|---|---|---|---|---|
mm128 | - | _mm_castpd_ps | _mm_castsi128_ps | _mm256_castps256_ps128 | x | x |
mm128d | _mm_castps_pd | - | _mm_castsi128_pd | x | _mm256_castpd256_pd128 | x |
mm128i | _mm_castps_si128 | _mm_castpd_si128 | - | x | x | _mm256_castsi256_si128 |
mm256 | _mm256_castps128_ps256 _mm256_zextps128_ps256 |
x | x | - | _mm256_castpd_ps | _mm256_castsi256_ps |
mm256d | x | _mm256_castpd128_pd256 _mm256_zextpd128_pd256 |
x | _mm256_castps_pd | - | _mm256_castsi256_pd |
mm256i | x | x | _mm256_castsi128_si256 _mm256_zextsi128_si256 |
_mm256_castps_si256 | _mm256_castpd_si256 | - |