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@xxxxxxxxxxxx>: > > 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