On 03/12/2020 12:47, Andrea Corallo via Gcc-help wrote: > Hi all, > > I've a piece of code that reduced looks like this: > > #+begin_src C > typedef struct { > void (*fun_ptr)(void); > } x_t; > > x_t *x; > > void > f (void) > { > const x_t const *y = x; > for (int i = 0; i < 1000; ++i) > y->fun_ptr (); > } > #+end_src > > What is the correct way (if any) to express to the compiler that the > value of y->fun_ptr does not get clobbered by the function call itself > so the corresponding load to obtain its value can be moved out of the > loop? > > My understanding is that the const qualifier is more for diagnostic > reasons and is not sufficient for GCC to make this assumption. OTOH I > cannot give 'fun_ptr' the attribute pure as it's not. > Imagine you also had : x_t foox; void foo1(void); void foo2(void); void foo1(void) { printf("foo1\n"); foox.fun_ptr = foo2; } void foo2(void) { printf("foo2\n"); foox.fun_ptr = foo1; } void test(void) { x = &foox; f(); } As "f()" runs, the value of "y->fun_ptr" changes with each step as you get alternating "foo1", "foo2" outputs. Thus it is clear (I hope) that the compiler cannot assume that "y->fun_ptr" is not clobbered by the function call. To get the effect you want, you'll have to change the code. The easiest way is (as has been suggested) to capture "y->fun_ptr" in a local variable. Alternatively you could capture "x" to a local variable, or make it static, and ensure that its address doesn't escape - then the compiler can tell that the fun_ptr() call can't change it.