public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Optimization and inline assembly in GCC 4.0/MIPS
@ 2006-10-16 18:44 Simon Kagstrom
  2006-10-16 18:53 ` Ian Lance Taylor
  0 siblings, 1 reply; 3+ messages in thread
From: Simon Kagstrom @ 2006-10-16 18:44 UTC (permalink / raw)
  To: gcc-help

Hello!

I have a problem which I don't know if it's a bug or simply an error
on my part (admittedly I'm stretching some expectations). This code
was working in GCC 3.4, but broke after I switched to 4.0. I think I
have managed to fix it, but am not sure my fix holds.


The problem is that GCC optimizes away more code to setup an
argument. The code I'm working on is part of the Cibyl project [1],
which recompiles MIPS binaries -> Java bytecode. The problematic code
is the following:

   int vStreamOpen(const char *filename, int mode)
   {
     char m[4];

     memset(m, 0, sizeof(m));
     if (mode & (1<<2))
       m[0] = 'r';

     return (int)fopen(filename, m);
   }

the if-statement in this case does not generate any code (GCC assumes
that m is ignored by fopen). fopen is in my case a Java-function,
which is called through a "system call", to which I pass arguments
through a special instruction encoding.

The relevant defintions in this case is

   #define __NR_fopen 16
   static inline _syscall2(FILE*,fopen, const char*, path, const char*, mode);

   ...

   #define _syscall2(type,name,atype,a,btype,b) \
   type name(atype a, btype b) \
   { \
	   register unsigned long __v0 asm("$2"); \
	   \
	   __asm__ volatile ( \
	   ".set  push\n.set  noreorder\n" \
	   ".short 0xfffe\n" \
	   ".short %1\n" \
	   ".short 0xfffe\n" \
	   ".short %2\n" \
	   ".short 0xffff\t#" #name "\n\t" \
	   ".short %3\n" \
	   ".set\tpop\n" \
	   : "=r" (__v0) \
	   : "r"(a), "r"(b), \
	     "i" (__NR_##name) \
	   ); \
	   \
	   return (type) __v0; \
   }

and GCC 4.0 generates

   00000000 <vStreamOpen>:
      0:	27bdfff8 	addiu	sp,sp,-8
      4:	afa00000 	sw	zero,0(sp)
      8:	fffe0004 	0xfffe0004
      c:	fffe0005 	0xfffe001d
     10:	ffff0010 	0xffff0010
     14:	03e00008 	jr	ra
     18:	27bd0008 	addiu	sp,sp,8
     1c:	00000000 	nop

from this (i.e., the if-statement above does not generate any
code). The effect is the same as if I would call a function where GCC
can prove that the passed parameter is unused.


Is there any way to specify that GCC should refrain from optimizing
this code away? I've looked a bit in the _syscall-definitions in the
Linux sources (include/asm-mips/unistd.h) and the GCC info-pages, and
adding a "memory" to clobber-list seems to fix my issue. The question
is then: is the memory clobber enough or does it just work by chance
here?

// Simon

[1] http://spel.bth.se/index.php/Cibyl

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

* Re: Optimization and inline assembly in GCC 4.0/MIPS
  2006-10-16 18:44 Optimization and inline assembly in GCC 4.0/MIPS Simon Kagstrom
@ 2006-10-16 18:53 ` Ian Lance Taylor
  2006-10-16 19:28   ` Simon Kagstrom
  0 siblings, 1 reply; 3+ messages in thread
From: Ian Lance Taylor @ 2006-10-16 18:53 UTC (permalink / raw)
  To: Simon Kagstrom; +Cc: gcc-help

Simon Kagstrom <simon.kagstrom@bth.se> writes:

> 	   : "=r" (__v0) \
> 	   : "r"(a), "r"(b), \
> 	     "i" (__NR_##name) \

You've told gcc that the inline assembler code cares about the value
of 'm', but you haven't told it that it cares about the value of
'm[0]', 'm[1]', etc.

This exact case is covered in the documentation:

    Note that in the following example the memory input is necessary,
    otherwise GCC might optimize the store to x away:

     int foo ()
     {
       int x = 42;
       int *y = &x;
       int result;
       asm ("magic stuff accessing an 'int' pointed to by '%1'"
             "=&d" (r) : "a" (y), "m" (*y));
       return result;
     }

Ian

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

* Re: Optimization and inline assembly in GCC 4.0/MIPS
  2006-10-16 18:53 ` Ian Lance Taylor
@ 2006-10-16 19:28   ` Simon Kagstrom
  0 siblings, 0 replies; 3+ messages in thread
From: Simon Kagstrom @ 2006-10-16 19:28 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-help

At 16 Oct 2006 11:52:49 -0700,
Ian Lance Taylor wrote:
> 
> You've told gcc that the inline assembler code cares about the value
> of 'm', but you haven't told it that it cares about the value of
> 'm[0]', 'm[1]', etc.
> 
> This exact case is covered in the documentation:
> 
>     Note that in the following example the memory input is necessary,
>     otherwise GCC might optimize the store to x away:
> 
>      int foo ()
>      {
>        int x = 42;
>        int *y = &x;
>        int result;
>        asm ("magic stuff accessing an 'int' pointed to by '%1'"
>              "=&d" (r) : "a" (y), "m" (*y));

OK, but in my case _syscall2 is generically defined so I cannot give
individual input restrictions. If I parse the documentation correctly,

   If your assembler instructions access memory in an unpredictable
   fashion, add `memory' to the list of clobbered registers.  This
   will cause GCC to not keep memory values cached in registers across
   the assembler instruction and not optimize stores or loads to that
   memory.

clobbering "memory" should then force GCC to avoid optimizing accesses
away ("not optimize stores or loads to that memory"). I think I
understand this now, thanks.

// Simon

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

end of thread, other threads:[~2006-10-16 19:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-10-16 18:44 Optimization and inline assembly in GCC 4.0/MIPS Simon Kagstrom
2006-10-16 18:53 ` Ian Lance Taylor
2006-10-16 19:28   ` Simon Kagstrom

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).