This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)


Hello Paul,

Thanks for your response! 

I am not clear about the statement "you can't make use
of operands to asm that aren't actually used in the
asm text". As you said, I have gone through the
thread about "locking problem with mips atomicity".

>From the thread, I could noticed the following:

----------------------
> -       : "m" (*__mem), "r"(__val));
> +       : "m" (*__mem), "r"(__val), "r"(__mem));

In addition to just adding the new argument, you have
to actually use it in the assembly.
-----------------------

Seems the '"r" (__mem)' is supposed to be used in the
above case (not for all the cases, given one example
below). That's what suggested to use that constraint
in asm template.

>From my understanding, we *can use unused constraint*
in input/output section of the extend inline asm to
inform GCC that corresponding input/output is being
read/written in this inline asm. So GCC won't cache
the corresponding memory value in register before
inline asm. Please correct me if I am wrong, with
some explaination.

Example:

<<<<< START >>>>> test.c
static inline void add_inline(int a, int b, int *c)
{
    int res;
    asm ("addu  %0,%2,%3 \n\t"
         "sw    %0,0(%4)"
         : "=&r" (res), "=m"(*c)
         : "r" (a), "r" (b), "r"(c));
}

int test(int a, int b)
{
   int c = 0;
   add_inline(a, b, &c);
   if (c != a + b)
       return 0; /* Failure */
   return 1;
}

<<<<< END >>>>> test.c

If we remove the *unused* constraint '"=m" (*c)'
in the above example, GCC generates wrong assembly.
It proves that "unused constraint is also significant"
in inline asm.

Please find the difference between specifying unused
constraint and not specifying unused constraint,
in the generate .s file, below.

<<<<< START >>>>> test.s.diff 
***************
*** 7,29 ****
        .text
        .ent    test
  test:
!       .frame  $sp,8,$31     # vars= 8, regs= 0/0,
                              # args= 0, extra= 0
        .mask   0x00000000,0
        .fmask  0x00000000,0
!       subu    $sp,$sp,8
!       sw      $0,0($sp)
!  #APP
!       addu    $2,$4,$5 
!       sw      $2,0($sp)
!  #NO_APP
!       lw      $2,0($sp)
!       addu    $4,$4,$5
!       xor     $2,$2,$4
!       sltu    $2,$2,1
        .set    noreorder
        .set    nomacro
  
--- 7,20 ----
        .text
        .ent    test
  test:
!       .frame  $sp,0,$31    # vars= 0, regs= 0/0,
                             # args= 0, extra= 0
        .mask   0x00000000,0
        .fmask  0x00000000,0
!       addu    $2,$4,$5
        .set    noreorder
        .set    nomacro
        j       $31
!       sltu    $2,$2,1
        .set    macro
        .set    reorder

<<<<< END >>>>> test.s.diff

The .s file generated for the testcase which hasn't
use the "unused constraint" generates the wrong code
(i.e the function 'test' always return 0).

Please share your thoughts! Expecting for yours
response.... (Sorry for this long mail :)

Thanks,
Ashok

--- Paul Koning <pkoning@equallogic.com> wrote:
> >>>>> "Ashok" == Ashok A <Ashok.A> writes:
> 
>  Ashok> Another question is, can we use the
> following like constraints
>  Ashok> instead of using more costlier "memory"
> clobber?
> 
>  Ashok> ---------- typedef char helper
> [DCACHE_LINE_SIZE]; ...  ...
> 
>  Ashok> inline void invalidate_cache_line(void *ptr)
> { asm volatile
>  Ashok> ("cache 17, 0(%1)" : "=m" (*(helper *)ptr) :
> "r" (ptr)); }
> 
> In an earlier discussion (about atomicity) it was
> pointed out that
> this doesn't work -- you can't make use of operands
> to asm that aren't
> actually used in the asm text.  There are no
> references to %0, so the
> "=m" operand doesn't have any effect.
> 
> The way to look at whether you need "memory"
> clobber, or volatile (or
> neither) is to look at what the asm statement does. 
> 
> Take the specific example of a cache invalidate.  If
> the compiler had
> generated a load before the invalidate, that value
> is no longer valid
> afterwards -- if you did another load, you might get
> a different
> answer.  So "clobber memory" is the safe thing to do
> here.
> 
> If you don't have any loads or stores to the
> affected memory in the
> source text before the invalidate, but you do have
> some after it, then
> "volatile" would be sufficient (it keeys the
> compiler from moving
> things before the asm).
> 
> Conversely, if the asm was a cache flush rather than
> a cache
> invalidate, that doesn't make loads or stores
> invalid.  (It affects
> physical memory, but it doesn't affect the view of
> memory that
> software has).  So a flush wouldn't need a memory
> clobber.  It may
> need "volatile", to make sure that externally
> visible memory
> operations happen in the order intended by the
> program.
> 
> 	   paul
> 
> 


__________________________________
Do you Yahoo!?
Yahoo! Finance Tax Center - File online. File on time.
http://taxes.yahoo.com/filing.html


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]