This is the mail archive of the
gcc-help@gcc.gnu.org
mailing list for the GCC project.
Re: why the barrier() can not take effect?
I have modified the code as follows:
#include <stdio.h>
#define barrier() __asm__ __volatile__("": : :"memory")
int main()
{
int i, n;
int s = 0;
int *p;
scanf("%d", &n);
for (i = 0; i < n; i++)
s += i;
barrier();
p = &s; <--- for s, the & operator is used
printf("%d %d %d\n", i, n, *p); <--- the s is referenced through a pointer
return 0;
}
and the corresponding asm code is as follows:
leal -8(%ebp), %eax
pushl %eax
pushl $.LC0
call scanf
movl -8(%ebp), %edx
addl $16, %esp
testl %edx, %edx
jg .L2
movl $0, %eax
movl $0, %ecx
jmp .L4
.L2:
movl $0, %eax
movl $0, %ecx
.L5:
addl %eax, %ecx
incl %eax
cmpl %edx, %eax
jne .L5
.L4:
<--- after the barrier(()
pushl %ecx <--- In spite of using the '&' operator, the
value of s is still gotten from the register rather than the
corresponding memory location.
pushl -8(%ebp) <--- the value of n is gotten from its
memory location indeed
pushl %eax
pushl $.LC1
call printf
Alough the '&' operator is used for both 's' and 'n', gcc deals with
them differently. The former's value is in a register, while the
latter's value is retrieved from the corresponding memory location. I
wonder the difference.
2010/12/22 Andrew Haley <aph@redhat.com>:
> On 12/22/2010 03:16 PM, Parmenides wrote:
>>
>> Hi,
>>
>> ? ? According to the gcc's manual, in an extended assembly statement,
>> if the string "memory" is added to the list of of clobbered registers,
>> it will cause "gcc to not keep memory values cached in registers
>> across the assembler instrution and not optimize stores or loads to
>> that memory". To this end, IMO, after this kind of statement all
>> values cached in registers should be write into the corresponding
>> memory locations. But, the following example illustrates some
>> different thing.
>>
>> #define barrier() __asm__ __volatile__("": : :"memory")
>>
>> int main()
>> {
>> ? ? int i, n;
>> ? ? int s = 0;
>>
>> ? ? scanf("%d",&n);
>> ? ? for (i = 0; i< ?n; i++)
>> ? ? ? ? ?s += i;
>> ? ? barrier();
>> ? ? printf("%d\n", s);
>>
>> ? ? return 0;
>> }
>>
>> # gcc -S -O tst.c
>>
>> We get the assembly code like this:
>>
>> ? ? ? ?leal ? ?-8(%ebp), %eax
>> ? ? ? ?pushl ? %eax
>> ? ? ? ?pushl ? $.LC0
>> ? ? ? ?call ? ?scanf
>> ? ? ? ?movl ? ?-8(%ebp), %edx<--- cache n into edx
>> ? ? addl ? ?$16, %esp
>> ? ? ? ?testl ? %edx, %edx
>> ? ? ? ?jg ? ? ?.L2
>> ? ? ? ?movl ? ?$0, %ecx
>> ? ? ? ?jmp ? ? .L4
>> .L2:
>> ? ? ? ?movl ? ?$0, %eax<--- cache i into eax
>> ? ? movl ? ?$0, %ecx<--- ?cache s into ecx
>> .L5:
>> ? ? ? ?addl ? ?%eax, %ecx
>> ? ? ? ?incl ? ?%eax
>> ? ? cmpl ? ?%eax, %edx
>> ? ? ? ?jne ? ? .L5
>> .L4:
>> <--- at this point, I think the barrier() will cause the values cached
>> in edx, eax and ecx will be write back to n, i, and s, respectively.
>> But, this is not really the case.
>>
>> ? ? ? ?subl ? ?$8, %esp
>> ? ? ? ?pushl ? %ecx
>> ? ? pushl ? $.LC1
>> ? ? ? ?call ? ?printf
>
> Well, i and s never have their address taken, so they are not forced
> into memory, and the memory clobber can't affect them.
>
> Andrew.
>