0

LLVM の組み込みループ ベクトライザーを実行する方法を理解しようとしています。非常に単純なループを含む小さなプログラムがあります (ある時点で出力があったため、使用されていないにもかかわらず stdio.h がまだ含まれています)。

  1 #include <stdio.h>
  2 
  3 unsigned NUM_ELS = 10000;
  4 
  5 int main() {
  6     int A[NUM_ELS];
  7 
  8 #pragma clang loop vectorize(enable)
  9     for (int i = 0; i < NUM_ELS; ++i) {
 10         A[i] = i*2;
 11     }
 12 
 13     return 0;
 14 }

ご覧のとおり、何も役に立ちません。for ループをベクトル化できるようにするだけです。私はそれをLLVMバイトコードにコンパイルしています

clang -emit-llvm -O0 -c loop1.c -o loop1.bc
llvm-dis -f loop1.bc

次に、ベクトライザーを適用しています

opt -loop-vectorize -force-vector-width=4 -S -debug loop1.ll

ただし、デバッグ出力には次のように表示されます。

LV: Checking a loop in "main" from loop1.bc
LV: Loop hints: force=? width=4 unroll=0
LV: Found a loop: for.cond
LV: SCEV could not compute the loop exit count.
LV: Not vectorizing: Cannot prove legality.

LLVM ソースを少し掘り下げてみたところ、SCEV は ScalarEvolution パスから来ているように見えます。このパスには、(とりわけ) バック エッジの数をループ条件に戻すタスクがあり、この場合は (私が間違っていない場合) は、トリップ数から最初のトリップを引いたもの (この場合は 9,999) である必要があります。このパスをはるかに大きなベンチマークで実行したところ、すべてのループでまったく同じエラーが発生したため、ループ自体ではないと推測していますが、十分な情報を提供していません。

この変換を使用した完全な opt コマンドの例を見つけるために、ドキュメントと Google の結果をくまなく調べましたが、これまでのところ成功していません。何が欠けているかについてのヒントをいただければ幸いです (コードをベクトル化するのは初めてなので、非常に明白なものになる可能性があります)。

ありがとうございました、

スティーブン

4

1 に答える 1

0

ベクトル化は、前に実行する必要がある他の最適化の数に依存します。それらは -O0 ではまったく実行されないため、コードがそこで「ただ」ベクトル化されるとは期待できません。

ここでは、opt コマンドラインで -loop-vectorize の前に -O2 を追加すると役立ちます (「A」配列が外部にあることを確認し、何らかの形で使用されていることを確認してください。そうしないと、すべてが最適化されてしまいます)。

于 2014-11-18T18:21:58.970 に答える