[edit: Here is the motivation: passing a pointer of a variable to an external function may accidentally break some optimization for "adjacent" variables, because of the possibility to get pointers to the adjacent variables calculated from the original pointer by the external function. The following is the original post, in which the volatile
is to simulate an external function inaccessible to the current compiler unit, e.g. virtual function call, closed source library function, etc.]
I wondered if the return t.a;
in the following code would be optimized to 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;
}
Well it's not.
Fair enough because the code in function f
may use offsetof
to acquire a pointer to t
then change t.a
.
So it's not safe to optimize the load of t.a
away.
[edit: At a second thought, offsetof
is not enough here. We need container_of
, which there seems no way to implement in standard C++.]
But offsetof
cannot be used on non-standard-layout types. So I tried the following code:
//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;
}
Unfortunately it's still not working.
My questions are:
- whether it's safe to optimize the load of
t.a
away in the above case (revision 2) - if it's not, is there some arrangement in existence/proposal to make it possible? (e.g. making
T
a more special type, or some attribute specifier for memberb
inT
)
P.S. The following code is optimized for return t.a;
, but the yielded code for the loop is a bit inefficient.
And still, the temporary variable juggling is cumbersome.
//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;
}