public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Clarification Req: Regarding "+m" constraints in inline asm
@ 2004-03-03 14:44 Ashok.A
  2004-03-04 20:45 ` Jim Wilson
  0 siblings, 1 reply; 9+ messages in thread
From: Ashok.A @ 2004-03-03 14:44 UTC (permalink / raw)
  To: gcc; +Cc: ashok_kumar_ak

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=us-ascii, Size: 911 bytes --]

Hi All,

I need clarification regarding the "+m" constraints.
I heard that "+m" constraints cannot be used
in "inline asm". Is it true?

Example:

----------
  int temp;
  asm ("lw %0,%1     \n\t"
       "addu %0,%0,1 \n\t"
       "sw %0,%1"
       : "=r" (temp), "=m" (data)  /* outputs */
       : "1" (data));              /* inputs  */
----------

  Can I use the following instead of the above?
  Will it be exactly same as above?

----------
  int temp;
  asm ("lw %0,%1     \n\t"
       "addu %0,%0,1 \n\t"
       "sw %0,%1"
       : "=r" (temp), "+m" (data)  /* outputs */
----------

I believe "+m" constraint is processor independent.
Anyhow, I need clarification for MIPS processor.

It would be great help if you can clarify this
issue. Thanks in advance.

Thanks,
Ashok

__________________________________
Do you Yahoo!?
Yahoo! Search - Find what you’re looking for faster
http://search.yahoo.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "+m" constraints in inline asm
  2004-03-03 14:44 Clarification Req: Regarding "+m" constraints in inline asm Ashok.A
@ 2004-03-04 20:45 ` Jim Wilson
  2004-03-26 13:34   ` Clarification Req: Regarding "memory" clobber for cache operation is required (?) Ashok.A
  0 siblings, 1 reply; 9+ messages in thread
From: Jim Wilson @ 2004-03-04 20:45 UTC (permalink / raw)
  To: Ashok.A; +Cc: gcc

Ashok.A wrote:
> I need clarification regarding the "+m" constraints.
> I heard that "+m" constraints cannot be used
> in "inline asm". Is it true?

Current sources will give a warning for both of your examples.  Neither 
read-write "+" or matching "1" constraints should be used with mems in 
an asm.  These both require that the operands are the same, but the 
compiler is not able to guarantee this for mems.  We can only make this 
work for register constraints.

Try changing the lw to use %2 instead of %1, and then use "m" for the 
second operand.  I think this is the way it is supposed to work nowadays.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-04 20:45 ` Jim Wilson
@ 2004-03-26 13:34   ` Ashok.A
  2004-03-27 19:54     ` Ashok.A
  2004-03-30  0:38     ` Jim Wilson
  0 siblings, 2 replies; 9+ messages in thread
From: Ashok.A @ 2004-03-26 13:34 UTC (permalink / raw)
  To: gcc, Jim Wilson; +Cc: ashok_kumar_ak

Hello,

Need one clarification regarding the issue given
below. Could you please clarify it? 

To invalidate a cache line, do we really need to
use "memory" clobber in inline asm?

Example: (for MIPS-III architecture) 

   asm ("cache 17, 0(%0)"
        : /* no outputs */
        : "r"(ptr));

Where, 'ptr' (pointer to unsigned char type) points
to base address of cache to be invalidated.

For this case, do we need "memory" clobber in the
inline asm? Or, anyway to specifiy appropriate 
memory constraints?

Expecting for yours response ...

Thanks,
Ashok

P.S: I have checked the linux source. Looks neither
     "memory" clobber nor any memory constraint is
     specified in inline asm for similar operations
     in linux source.

     
--- Jim Wilson <wilson@specifixinc.com> wrote:
> Ashok.A wrote:
> > I need clarification regarding the "+m"
> constraints.
> > I heard that "+m" constraints cannot be used
> > in "inline asm". Is it true?
> 
> Current sources will give a warning for both of your
> examples.  Neither 
> read-write "+" or matching "1" constraints should be
> used with mems in 
> an asm.  These both require that the operands are
> the same, but the 
> compiler is not able to guarantee this for mems.  We
> can only make this 
> work for register constraints.
> 
> Try changing the lw to use %2 instead of %1, and
> then use "m" for the 
> second operand.  I think this is the way it is
> supposed to work nowadays.
> -- 
> Jim Wilson, GNU Tools Support,
> http://www.SpecifixInc.com
> 


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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-26 13:34   ` Clarification Req: Regarding "memory" clobber for cache operation is required (?) Ashok.A
@ 2004-03-27 19:54     ` Ashok.A
  2004-03-30  0:38     ` Jim Wilson
  1 sibling, 0 replies; 9+ messages in thread
From: Ashok.A @ 2004-03-27 19:54 UTC (permalink / raw)
  To: gcc, Jim Wilson; +Cc: ashok_kumar_ak


--- "Ashok.A" <ashok_kumar_ak@yahoo.com> wrote:
> Hello,
> 
> Need one clarification regarding the issue given
> below. Could you please clarify it? 
> 
> To invalidate a cache line, do we really need to
> use "memory" clobber in inline asm?
> 
> Example: (for MIPS-III architecture) 
> 
>    asm ("cache 17, 0(%0)"
>         : /* no outputs */
>         : "r"(ptr));
> 
> Where, 'ptr' (pointer to unsigned char type) points
> to base address of cache to be invalidated.
> 
> For this case, do we need "memory" clobber in the
> inline asm? Or, anyway to specifiy appropriate 
> memory constraints?
> 
> Expecting for yours response ...
> 
> Thanks,
> Ashok
> 
> P.S: I have checked the linux source. Looks neither
>      "memory" clobber nor any memory constraint is
>      specified in inline asm for similar operations
>      in linux source.
> 
>      
> --- Jim Wilson <wilson@specifixinc.com> wrote:
> > Ashok.A wrote:
> > > I need clarification regarding the "+m"
> > constraints.
> > > I heard that "+m" constraints cannot be used
> > > in "inline asm". Is it true?
> > 
> > Current sources will give a warning for both of
> your
> > examples.  Neither 
> > read-write "+" or matching "1" constraints should
> be
> > used with mems in 
> > an asm.  These both require that the operands are
> > the same, but the 
> > compiler is not able to guarantee this for mems. 
> We
> > can only make this 
> > work for register constraints.
> > 
> > Try changing the lw to use %2 instead of %1, and
> > then use "m" for the 
> > second operand.  I think this is the way it is
> > supposed to work nowadays.
> > -- 
> > Jim Wilson, GNU Tools Support,
> > http://www.SpecifixInc.com
> > 
> 
> 
> __________________________________
> Do you Yahoo!?
> Yahoo! Finance Tax Center - File online. File on
> time.
> http://taxes.yahoo.com/filing.html


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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-26 13:34   ` Clarification Req: Regarding "memory" clobber for cache operation is required (?) Ashok.A
  2004-03-27 19:54     ` Ashok.A
@ 2004-03-30  0:38     ` Jim Wilson
  2004-03-30 21:26       ` Ashok.A
  2004-03-31  1:45       ` Richard Henderson
  1 sibling, 2 replies; 9+ messages in thread
From: Jim Wilson @ 2004-03-30  0:38 UTC (permalink / raw)
  To: Ashok.A; +Cc: gcc

On Thu, 2004-03-25 at 22:34, Ashok.A wrote:
> To invalidate a cache line, do we really need to
> use "memory" clobber in inline asm?

This is a difficult question to answer.

If it does not work without the memory clobber, then obviously you need
it.

If it does appear to work without the memory clobber, then whether you
need it depends on the context and how the asm is written, and possibly
on what gcc versions you have and what compiler optimizations are
enabled.  There is no simple answer here, other than to say that you are
safer with a memory clobber than without one.

You don't need the memory clobber if you use an alternative method for
describing the dependencies.  For instance, if you make the asm
volatile.  Or if you have memory input(s) with size and address that
covers the cache line being invalidated.

You don't need the memory clobber if you are sure that the function that
contains the asm will never contain any memory references that will
conflict with the cache line that is being invalidated.  (And the
function is not marked inline or you are not compiling with
-finline-functions, etc.)

Personally, I would include the clobber, or better yet, make the asm
volatile.

> P.S: I have checked the linux source. Looks neither
>      "memory" clobber nor any memory constraint is
>      specified in inline asm for similar operations
>      in linux source.

It looks like the linux sources use volatile instead of memory
clobbers.  Volatile is a stronger statement than a memory clobber.
-- 
Jim Wilson, GNU Tools Support, http://www.SpecifixInc.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-30  0:38     ` Jim Wilson
@ 2004-03-30 21:26       ` Ashok.A
  2004-03-30 22:02         ` Paul Koning
  2004-03-31  1:45       ` Richard Henderson
  1 sibling, 1 reply; 9+ messages in thread
From: Ashok.A @ 2004-03-30 21:26 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc, ashok_kumar_ak

Hello,

Thanks a lot for your clarification! (and your time)
I have a doubt in the following response.

-------
> > P.S: I have checked the linux source. Looks
neither
> >      "memory" clobber nor any memory constraint is
> >      specified in inline asm for similar
operations
> >      in linux source.
> 
> It looks like the linux sources use volatile instead
> of memory clobbers.  Volatile is a stronger 
> statement than a memory clobber.
-------

Looks the "volatile" doesn't fullfil the purpose of
"memory" clobber and memory constraint. It looks like
just avoid reordering the inline asm instructions,
as part of optimization (please correct me if I am
wrong)

I have tested it with a small testcase (given below). 

<<<<< START copy.c >>>>>

static inline void copy_inline(char *dst, char *src,
int size)
{
    char temp;
    asm volatile ("0:   subu    %3,%3,1   \n"
                  "     bltz    %3, end   \n"
                  "     lbu     %0, 0(%2) \n"
                  "     sb      %0, 0(%1) \n"
                  "     b       0b        \n"
                  "end:"
                  : "=&r" (temp)
                  : "r" (dst), "r" (src), "r" (size));

     /* NOTE: "memory" clobber is not used here, but
              supposed to be used eventhough
              "volatile" is specified (?). */
}

int test ()
{
    char source[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
};
    char dest[10] = { 0 };
    char *ptr = &dest[9];  /* 'ptr' points to last 
                              element of 'dest[]' */
    *ptr = 0;
    copy_inline (dest, source, 10);
    if (*ptr != 9)
        return 0; /* Failure */
    return 1;
}
<<<<< END copy.c >>>>>

Generated .s file (given below) for the above testcase
with the following options

  Options          : -O2 -S
  Compiler Version : 2.95.3 (for mips-III arch)

<<<<< START copy.s (comments inlined) >>>>>

        <snipped>

        .globl  test
        .text
        .ent    test
test:
        .frame  $sp,88,$31  # vars= 32, regs= 3/0,
                            # args= 32, extra=0
        .mask   0x80030000,-8
        .fmask  0x00000000,0
        subu    $sp,$sp,88
        lui     $2,%hi($LC0) # high
        sd      $17,72($sp)
        addu    $17,$sp,32
        sd      $16,64($sp)
        addu    $16,$sp,48
        sd      $31,80($sp)
        addiu   $6,$2,%lo($LC0)
        ldl     $3,0($6)
        ldr     $3,7($6)
        lb      $4,8($6)
        lb      $5,9($6)
        sdl     $3,32($sp)
        sdr     $3,39($sp)
        sb      $4,40($sp)
        sb      $5,41($sp)
        move    $4,$16
        move    $5,$0
        .set    noreorder
        .set    nomacro
        jal     memset
        li      $6,10                   # 0xa
        .set    macro
        .set    reorder

        li      $2,10                   # 0xa
        sb      $0,57($sp)
 #APP
        0:      subu    $2,$2,1
        bltz    $2, end
        lbu     $3, 0($17)
        sb      $3, 0($16)
        b       0b
end:
 #NO_APP
        ld      $31,80($sp)
        ld      $17,72($sp)
        ld      $16,64($sp)
        move    $2,$0

==> Always returns 0. Expected behaviour is, *ptr
    should not be cached (or assumed as 0) as it is 
    being changed in copy_inline().

    If "memory" clobber is used in the inline asm,
    then it loads the *ptr from memory just before
this
    line and compares it with '9' as expected.

        .set    noreorder
        .set    nomacro
        j       $31
        addu    $sp,$sp,88
        .set    macro
        .set    reorder

        .end    test

<<<<< END copy.s >>>>>

Another question is, can we use the following like
constraints instead of using more costlier "memory"
clobber?

----------
typedef char helper [DCACHE_LINE_SIZE];
...
...

inline void invalidate_cache_line(void *ptr)
{
   asm volatile ("cache 17, 0(%1)"
                 : "=m" (*(helper *)ptr)
                 : "r" (ptr));
}

Please share your thoughts.

Thanks,
Ashok

--- Jim Wilson <wilson@specifixinc.com> wrote:
> On Thu, 2004-03-25 at 22:34, Ashok.A wrote:
> > To invalidate a cache line, do we really need to
> > use "memory" clobber in inline asm?
> 
> This is a difficult question to answer.
> 
> If it does not work without the memory clobber, then
> obviously you need
> it.
> 
> If it does appear to work without the memory
> clobber, then whether you
> need it depends on the context and how the asm is
> written, and possibly
> on what gcc versions you have and what compiler
> optimizations are
> enabled.  There is no simple answer here, other than
> to say that you are
> safer with a memory clobber than without one.
> 
> You don't need the memory clobber if you use an
> alternative method for
> describing the dependencies.  For instance, if you
> make the asm
> volatile.  Or if you have memory input(s) with size
> and address that
> covers the cache line being invalidated.
> 
> You don't need the memory clobber if you are sure
> that the function that
> contains the asm will never contain any memory
> references that will
> conflict with the cache line that is being
> invalidated.  (And the
> function is not marked inline or you are not
> compiling with
> -finline-functions, etc.)
> 
> Personally, I would include the clobber, or better
> yet, make the asm
> volatile.
> 
> > P.S: I have checked the linux source. Looks
> neither
> >      "memory" clobber nor any memory constraint is
> >      specified in inline asm for similar
> operations
> >      in linux source.
> 
> It looks like the linux sources use volatile instead
> of memory
> clobbers.  Volatile is a stronger statement than a
> memory clobber.
> -- 
> Jim Wilson, GNU Tools Support,
> http://www.SpecifixInc.com
> 


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

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-30 21:26       ` Ashok.A
@ 2004-03-30 22:02         ` Paul Koning
  2004-03-31  9:40           ` Ashok.A
  0 siblings, 1 reply; 9+ messages in thread
From: Paul Koning @ 2004-03-30 22:02 UTC (permalink / raw)
  To: ashok_kumar_ak; +Cc: wilson, gcc

>>>>> "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


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-30  0:38     ` Jim Wilson
  2004-03-30 21:26       ` Ashok.A
@ 2004-03-31  1:45       ` Richard Henderson
  1 sibling, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2004-03-31  1:45 UTC (permalink / raw)
  To: Jim Wilson; +Cc: Ashok.A, gcc

On Mon, Mar 29, 2004 at 03:01:35PM -0800, Jim Wilson wrote:
> It looks like the linux sources use volatile instead of memory
> clobbers.  Volatile is a stronger statement than a memory clobber.

No, it makes a completely different statement.


r~

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
  2004-03-30 22:02         ` Paul Koning
@ 2004-03-31  9:40           ` Ashok.A
  0 siblings, 0 replies; 9+ messages in thread
From: Ashok.A @ 2004-03-31  9:40 UTC (permalink / raw)
  To: Paul Koning; +Cc: wilson, gcc, ashok_kumar_ak

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

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2004-03-31  7:43 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-03-03 14:44 Clarification Req: Regarding "+m" constraints in inline asm Ashok.A
2004-03-04 20:45 ` Jim Wilson
2004-03-26 13:34   ` Clarification Req: Regarding "memory" clobber for cache operation is required (?) Ashok.A
2004-03-27 19:54     ` Ashok.A
2004-03-30  0:38     ` Jim Wilson
2004-03-30 21:26       ` Ashok.A
2004-03-30 22:02         ` Paul Koning
2004-03-31  9:40           ` Ashok.A
2004-03-31  1:45       ` Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).