4

restrictC99 に追加されたキーワードの主な用途の 1 つは、コンパイラが何かをレジスタにロードし、レジスタがロードされた変数の状態を反映すると想定できるようにすることです。与えられた

void foo1(int * restrict a, int * restrict b) {
  (*a)++; (*b)++; (*b)+=(*a);
}

(*b)コンパイラーは、 への書き込みが に影響を及ぼさないと想定する権利があるため、書き込み後(*a)に再ロードする必要がなくなり(*a)ます。restrictエイリアシングに他の影響はありますか? たとえば、次のようになります。

extern void foo2a(int * restrict q);
extern void foo2b(void);
int x;
int foo2(restrict int *q) {
  int z=x;
  x++; *q++; x++;
  foo2a(&z);
  x++; *q++; z++;
  foo2b();
  x++; *q++; z++;
  return x+(*q)+z;
}

コンパイラは、 のインクリメント、および*qへの呼び出しがすべて を妨害した可能性があること、および呼び出しがおよびの値に「関心がある」可能性があることを予測する必要がありますか? コンパイラは、 への呼び出しがそのパラメータを永続化した可能性があると想定する必要がありますか?foo2a()foo2b()xx*qfoo2a()restrictfoo2b()z

キーワードにもかかわらず、コンパイラーが最悪の場合の仮定の下で動作する必要がある場合restrict、コンパイラーが関数呼び出しの前に特定の変数への変更を保存し、次回それをリロードする通常の義務を無視する許可を与える方法はありますか?それは必要ですか?

4

1 に答える 1

6

タイトルの質問に答えるには: はい。修飾されたrestrictポインターは、問題のオブジェクト全体がそのポインターのみを介してのみアクセスできることを保証することを意味します。これは、同じタイプのファイル スコープ オブジェクトとエイリアスできないことも意味します。

質問の残りの部分では、物事を混ぜています。restrict呼び出し元を保証するものではありません。呼び出し元はrestrictキーワードを「見る」ことさえせず、型修飾はインターフェースの一部ではありません。したがって、呼び出しから戻ったときにファイル スコープ変数が変更されているかどうかは、 とは関係ありませんrestrict

restrict呼び出し元が呼び出し先に与える保証にすぎません。呼び出し先は最適化のために内部で情報を使用できます。

于 2015-04-28T20:18:32.977 に答える