This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Clarification Req: Regarding "memory" clobber for cache operation is required (?)
- From: "Ashok.A" <ashok_kumar_ak at yahoo dot com>
- To: Paul Koning <pkoning at equallogic dot com>
- Cc: wilson at specifixinc dot com, gcc at gcc dot gnu dot org, ashok_kumar_ak at yahoo dot com
- Date: Tue, 30 Mar 2004 23:43:29 -0800 (PST)
- Subject: 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