2016-12-26 7 views
1

clangに変数を宣言して、変数を使用する場所をさらに最適化できるようにする方法はありますか?clangで変数を宣言していますか?

restrictは、ポインタを非エイリアシングとして宣言するために使用できます。

しかし、私はポインタになる可能性のある変数についても疑問に思います。私は(おそらく間違って)、コンパイラは毎回それを再フェッチするのではなく、変数の値をキャッシュできるようにすることに注意しなければならないと思います。

例:サンプルコードでの質問への答えが「イエス」である

class Data 
{ 
public: 
    void updateVal() { 
     // Updates m_val with some value each time it's called (value may differ across different calls) 
     ... 
    } 
    int complicatedCalculation() const { 
     return 3 * m_val + 2; 
    } 
    int m_val; 
}; 

class User 
{ 
    User(Data& data) : m_data{data} {} 
    void f() 
    { 
     m_data.updateVal(); 
     for (int i=0; i<1000; ++i) 
      g(); 
    } 
    void g() 
    { 
     // Will the optimizer be able to cache calc's value for use in all the calls to g() from f()? 
     int calc = m_data.complicatedCalculation(); 

     // Do more work 
     ... 
    } 

    Data& m_data; 
}; 

場合でも、コードが複雑であれば、それは「ノー」に(// Do more work下にあるなどの作業)を変更しない場合がありますポインターがm_data.m_valを指していた可能性があるため、ポインターの内容が変更される可能性があるためです。または、コードのどこかでm_valのアドレスが取られていないと見なさない限り、コンパイラは何も起こらないと想定していますか?

それはがいることを前提としていない、あるいはそれがなく、m_valのアドレスがどこかに取ら取得んん(私たちは、その内容が変更されることはありません知っている)、できるようにするにはいいだろう場合m_valをエイリアシングの懸念から「安全」とマークするため、その値はポインタアクセスによって変更されないものと想定できます。

+0

[制限](http://stackoverflow.com/questions/776283/what-does-the-restrict-keyword-mean-in-c)をお探しですか? – Jarod42

+0

はい、ありがとうございます。しかし、私はポインタ以外の変数についても疑問を抱いています。より詳細な情報を提供します。 – Danra

+0

詳細を追加しました。 – Danra

答えて

0

コンパイラは、gにレジスタcalcを格納するようにレジスタに割り当てます。ただし、レジスタに格納する方が望ましい他のより高い変数があると判断しない限り、

今でもcalcがレジスタに格納されていても、complicatedCalculationへの関数呼び出しとm_valへのメモリアクセスが必要な場合があります。コンパイラはcomplicatedCalculationをインライン化して関数呼び出しを排除できますが、m_valが常に定数であると判断できない限り、メモリアクセスを排除することはできません。

あなたが本当に望むのは、ループ内のm_valへの不要なメモリアクセスをgではなくfにすることです。これを実現するには、コンパイラはgfにインライン展開に適格であるとみなさなければなりません。インライン化されている場合のみ、コンパイラは不要なメモリアクセスを排除できます。 gが直接m_valを変更したとしても、コンパイラは依然としてcalcをレジスタに割り当ててそれに応じて修正することができます。ここでの唯一の注意点は、gmay例外をスローする場合です。例外がスローされると、例外が伝播される前にm_valのメモリ内バージョンを最新の値に更新する必要があります。コンパイラはこれを保証するコードを発行しなければなりません。このコードがなければ、すべての反復でm_valのメモリ内バージョンを更新する必要があります。私はclangのどのバージョンがどのアプローチを使用しているのかわかりません。生成されたアセンブリコードを調べる必要があります。

m_valueのアドレスがコード内のどこかで使用された場合、コンパイラはメモリアクセスを排除できない場合があります。この場合、restrictを使用すると役立ちます。 m_valueは、標準に違反し、定義されていない動作を引き起こすため、他のポインタで変更しないでください。それを確実にするのはあなたの責任です。

これは、コード内のパフォーマンスのボトルネックであることが実験的に判断されたか、他の理由ではなく好奇心が強いからだと思います。

関連する問題