[編集: ここに動機があります: 変数のポインターを外部関数に渡すと、外部関数によって元のポインターから計算された隣接変数へのポインターを取得する可能性があるため、「隣接する」変数の最適化が誤って壊れる可能性があります。volatile
以下は、現在のコンパイラ ユニットにアクセスできない外部関数 (仮想関数呼び出し、クローズド ソース ライブラリ関数など) をシミュレートする元の投稿です。]
return t.a;
次のコードの が に最適化されるかどうか疑問に思いましたreturn 0;
。
//revision 1
struct T
{
int a;
int b;
};
void f_(int * p)
{
*p = 1;
}
auto volatile f = f_;
int main()
{
T t;
t.a = 0;
t.b = 0;
for (int i = 0; i < 20; ++i)
{
f(&t.b);
}
return t.a;
}
そうではありません。関数内のコードは、変更へのポインタを取得するためにf
使用される可能性があるため、十分に公平です。したがって、アウェイの負荷を最適化するのは安全ではありません。offsetof
t
t.a
t.a
[編集: よく考えてみると、offsetof
ここでは十分ではありません。container_of
標準 C++ で実装する方法がないように思われる が必要です。]
ただしoffsetof
、非標準レイアウト タイプでは使用できません。そこで、次のコードを試しました。
//revision 2
#include <type_traits>
struct T
{
private:
char dummy = 0;
public:
int a;
int b;
};
static_assert(!std::is_standard_layout_v<T>);
void f_(int * p)
{
*p = 1;
}
auto volatile f = f_;
int main()
{
T t;
t.a = 0;
t.b = 0;
for (int i = 0; i < 20; ++i)
{
f(&t.b);
}
return t.a;
}
残念ながら、まだ機能していません。
私の質問は次のとおりです。
- 上記の場合にアウェイの負荷を最適化しても安全かどうか
t.a
(リビジョン 2) - そうでない場合、それを可能にするための取り決め/提案はありますか? (たとえば
T
、より特殊な型を作成したり、メンバーの属性指定子を作成したりb
しますT
)
PS 次のコードは 用に最適化されreturn t.a;
ていますが、ループ用に生成されたコードは少し非効率的です。それでも、一時変数のジャグリングは面倒です。
//revision 3
struct T
{
int a;
int b;
};
void f_(int * p)
{
*p = 1;
}
auto volatile f = f_;
int main()
{
T t;
t.a = 0;
t.b = 0;
for (int i = 0; i < 20; ++i)
{
int b = t.b;
f(&b);
t.b = b;
}
return t.a;
}