glibc 2.0.5 is miscompiled by egcs 970904

Jim Wilson wilson@chestnut.cygnus.com
Sun Sep 7 17:36:00 GMT 1997


>   asm volatile
>     ("cmoveq %1, 1, %0\n\t"	 
>      "ret $31, (%2), 1"	 
>      : "=r" (retval)
>      : "0" (val), "r" (retpc));

I would call this a bug in the asm.  It is assuming that $0 (retval) will be
used for operand 0.  If this is not done, then the pattern fails because it
contains a return instruction.

However, it is not safe to make this assumption because the use of a matching
contraint for operand 1 means that a reload is necessary.  When a reload is
required, reload makes no guarantees about where the reload instruction will
be emitted.  It may emit an input reload before the asm, or it may emit an
output reload after the asm.  In this case, it is emitting an output reload
after the asm.  This instruction then gets optimized away because reload is
smart enough to know that there aren't any following instructions that
use its value.  This is the right thing to do in general, because it means
that we emit one less instruction, and gcc is after all an optimizing
compiler.

A much better way to write this is:
	retval = val;
	asm volatile ("cmoveq %1, 1, %0\n\t"
		     "ret $31, (%2), 1"	 
		     : "=r" (retval)
		     : "0" (retval), "r" (retpc));
Now, no reloads are necessary, and the pattern will always do what you
expect.  We even get better code this way, because now the move instruction
is explicit, we get the benefit of instruction scheduling.

An even better way to write this is:
  retval = val ? val : 1;
  asm volatile ("ret $31, (%0), 1" : : "r" (retpc), "r" (retval));
This just uses the asm for stuff that can't be written in C.

Jim



More information about the Gcc mailing list