AVX-512 は、演算のオペランドがメモリの場合、スカラ値をブロードキャストできます。
つまり、条件によっては、_mm512_set1_ps( *mem ) は、コスト無しで実行できます。(今日のタイトルは命令が出ない!という意味でした(わかりづらい))
float x;
void
f(float *p, __m512 a)
{
__m512 b = _mm512_add_ps(a, _mm512_set1_ps(x));
_mm512_storeu_ps(out, b);
}
は、
f:
.LFB2214:
.cfi_startproc
vbroadcastss x(%rip), %zmm1
vaddps %zmm1, %zmm0, %zmm0
vmovups %zmm0, out(%rip)
ret
このように、vaddps で broadcast していることが確認…でき…ない…?
本当なんです!信じてください!メモリをオペランドに取る場合はブロードキャストできるんです!お願いします!信じてください!!
llvm のtrunkで試したら出た。
f: # @f
.cfi_startproc
# BB#0:
pushq %rbp
.Ltmp0:
.cfi_def_cfa_offset 16
.Ltmp1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
.Ltmp2:
.cfi_def_cfa_register %rbp
andq $-64, %rsp
subq $64, %rsp
vmovaps 16(%rbp), %zmm0
vaddps x(%rip){1to16}, %zmm0, %zmm0 ## {1to16}がついてる
movw $-1, %ax
kmovw %eax, %k1
vmovups %zmm0, out(%rip) {%k1}
movq %rbp, %rsp
popq %rbp
retq
1to16 が付いてるオペランドがブロードキャストされますね。しかしllvmさん無駄な命令出過ぎでは…(というかcalling conventionがGCCと一致してなくね?)
また、全てのオペランドがベクタレジスタに乗った512bit値、もしくはスカラ値の場合、追加の命令無しで演算の丸めを制御できます。
__m512
f(__m512 x)
{
return _mm512_add_round_ps(x,x,_MM_FROUND_NO_EXC|_MM_FROUND_TO_NEAREST_INT);
}
f:
.LFB2211:
.cfi_startproc
vaddps {rn-sae}, %zmm0, %zmm0, %zmm0
ret
EVEXについて書く予定は無いと書いてましたが、それなりに調べてしまったので明日は@tanakmuraがEVEXについて書きます。