Local variables reordering and 'asm volatile("" ::: "memory");'

Ayrat Gaskarov 777grand@gmail.com
Sun Sep 8 19:54:00 GMT 2019


In fact I am interested in two cases:

Time measurements:
other_function_1()
start = measure_time()
function_to_measure()
end = measure_time()
other_function_2()

measure_time - observable function, but other functions are not. So
compiler is free to reorder it in the following way:
other_function_1()
function_to_measure()
start = measure_time()
other_function_2()
end = measure_time()

How could we avoid this? For function_to_measure we can somehow add
asm volatile memory for some argument and return value, but
other_functions are still allowed to move inside measure block.

Another example with mutexes:
some_really_slow_not_observable_function()
mutex_lock()
function_to_lock()
mutex_unlock()

mutex_lock and mutex_unlock are observable. Since
some_really_slow_not_observable_function is not observable or having
other side effects it could be moved inside mutex region:

mutex_lock()
function_to_lock()
some_really_slow_not_observable_function()
mutex_unlock()

How could we avoid this? For example if
some_really_slow_not_observable_function is long running loop using
only local variables.

вс, 8 сент. 2019 г. в 22:09, David Brown <david.brown@hesbynett.no>:
>
> On 08/09/2019 16:46, Andrew Haley wrote:
> > On 9/8/19 1:03 PM, Ayrat Gaskarov wrote:
> >
> >>  From gcc docs: 'The "memory" clobber tells the compiler that the assembly
> >> code performs memory reads or writes to items other than those listed in
> >> the input and output operands (for example, accessing the memory pointed to
> >> by one of the input parameters). To ensure memory contains correct values,
> >> GCC may need to flush specific register values to memory before executing
> >> the asm. Further, the compiler does not assume that any values read from
> >> memory before an asm remain unchanged after that asm; it reloads them as
> >> needed. Using the "memory" clobber effectively forms a read/write memory
> >> barrier for the compiler.'
> >> Does this mean that all data could be accessed including global variables,
> >> data in heap and local variables? Or is it not true for local variables?
> >
> > Yes, but only if the local variable has had its address taken. If it has not,
> > then it is not reachable.
>
> Having its address taken is not enough (AFAIK) - the address must be
> used in a way that forces the data into memory.  You can do useful
> things with an address of a local variable without the variable being
> put in memory:
>
> #include <string.h>
>
> unsigned int raw_float(const float f) {
>      unsigned int x;
>      memcpy(&x, &f, sizeof (x));
>      return x;
> }
>
> Generated x86 code (gcc -O2):
>
> raw_float(float):
>          movd    eax, xmm0
>          ret
>
> Taking the address is not enough to make the local part of memory.
>
>
> >
> >> For example:
> >> int local = 5;
> >> asm volatile("" ::: "memory");
> >> local += 6;
> >> Could it be reordered in the following way (because 'local' is local
> >> variable and could not be accessed):
> >> int local = 5;
> >> local += 6;
> >> asm volatile("" ::: "memory");
> >
> > Yes.
> >
> >> Could 'local' be optimized out in this case?
> >
> > Yes.
> >
>


-- 
Gaskarov Bros. Studio



More information about the Gcc-help mailing list