ポインタを含むループのベクトル化

配列にアクセスする際、多くの場合は、メモリアクセスがオーバーラップしないことをコンパイラ側で検証できます。しかし、ポインタを使用すと、この可能性は低下し、ランタイムテストを実行するか、restrict キーワードを使用する必要が生じます。

コンパイラは、ループが安全であると判断できる場合はポインタを含んでいるループをベクトル化できます。ループ内の配列参照およびポインタ照は、メモリへのベクタアクセスがあるかどうかを判断するために解析されます。場合によっては、コンパイラはランタイムテストを作成し、ストの結果によってループのベクタバージョンかスカラバージョンを実行します。

関数の引数はポインタとして渡される場合があります。複数のポインタ変数を関数に渡す場合は、メモリのオーバーラップしているセクションをイントすることが可能です。実行時にこのようになることはほとんどありませんが、コンパイラは常に安全な方法に従い、代入演算子の左辺おび右辺にポインタがあるループの最適化は回避します。例えば、Example 8 の関数を参照して下さい。

Example 8.  ポインタの条件付きベクトル化

void func (int *pa, int *pb, int x)
{
	int i;
	for (i = 0; i < 100; i++)
    {
       *(pa + i) = *(pb + i) + x;
    }
};

この例では、1 つのループパスの結果によって次のループパスにフィードバックされるようにメモリ内で papb がオーバーラップしていると、ループのベクトル化によって不正な結果が得られることがあります。以下の引数で関数が呼び出された場合は、ベクトル化はあいまいなものになります。

int *a;

func (a, a-1);

コンパイラはランタイムテストを実行して、ポインタのエイリアスの生成が行われるかどうかを調べます。ポインタのエイリアス生成が発生しな場合は、コードのベクトル化バージョンを実行します。ポインタのエイリアス生成が発生する場合は、元のベクトル化されていないコードが代りに実行されます。これによって、ランタイムの効率が良くなりコードサイズが小さくなります。

実際には、関数の引数によってデータの依存関係が生じることはほとんどありません。ベクトル化の問題は別にして、オーバーラップしたポインを渡すプログラムは理解とデバッグが困難です。

Example 8 では、restrictpa に追加するだけで、ランタイムテストを回避できます。

Show/hide関連項目

Copyright © 2010-2011 ARM. All rights reserved.ARM DUI 0472EJ
Non-ConfidentialID081711