Re: why the barrier() can not take effect?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxx>:
> 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.
>



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux