1

[編集: ここに動機があります: 変数のポインターを外部関数に渡すと、外部関数によって元のポインターから計算された隣接変数へのポインターを取得する可能性があるため、「隣接する」変数の最適化が誤って壊れる可能性があります。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使用される可能性があるため、十分に公平です。したがって、アウェイの負荷を最適化するのは安全ではありません。offsetoftt.at.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;
}
4

1 に答える 1