Eliminated function return values in retarget

2014-10-14 Thread Jamie Iles
Hi folks,

I'm retargetting GCC to a custom architecture 
(https://github.com/jamieiles/gcc-oldland is the retarget) and have an 
odd problem with function return values near the end of a function being 
eliminated.  For example:

extern int getreturn(void);

int foo(void)
{
if (getreturn() != 0)
return -1;

return 0;
}

I see that with optimization (-O1 or greater) that this gets compiled 
into a call to getreturn() and then unconditionally sets the return 
value to -1 (with a one_cmpl + eor + ior).  Inserting a call to another 
function inbetween the 'return -1' and 'return 0' is enough to cause 
working code to be generated.

works fine at -O0 generating

 :
   0:   f0 ce ff 93 str32   $lr, [$sp, 0x1ffc]
   4:   d0 8e ff 93 str32   $fp, [$sp, 0x1ff8]
   8:   0d 8e 00 08 sub $fp, $sp, 0x8
   c:   0e 8e 00 08 sub $sp, $sp, 0x8
  10:   fb ff ff 40 call0 
10: R_OLDLAND_PC24  getreturn-0x4
  14:   01 00 00 3e mov $r1, $r0
  18:   00 00 00 3c mov $r0, 0x0
  1c:   00 01 00 32 cmp $r1, $r0
  20:   03 00 00 58 beq 30 
  24:   00 fc ff ef movhi   $r0, 0x
  28:   00 fc ff f7 orlo$r0, $r0, 0x
  2c:   01 00 00 50 b   34 
  30:   00 00 00 3c mov $r0, 0x0
  34:   0e 8e 00 00 add $sp, $sp, 0x8
  38:   0d 8e 00 00 add $fp, $sp, 0x8
  3c:   0d 8e ff 83 ldr32   $fp, [$sp, 0x1ff8]
  40:   0f ce ff 83 ldr32   $lr, [$sp, 0x1ffc]
  44:   f0 00 00 46 ret 

but at -O1 I get

 :
   0:   f0 ce ff 93 str32   $lr, [$sp, 0x1ffc]
   4:   d0 8e ff 93 str32   $fp, [$sp, 0x1ff8]
   8:   0d 8e 00 08 sub $fp, $sp, 0x8
   c:   0e 8e 00 08 sub $sp, $sp, 0x8
  10:   fb ff ff 40 call0 
10: R_OLDLAND_PC24  getreturn-0x4
  14:   01 00 00 3c mov $r1, 0x0
  18:   01 01 00 0a sub $r1, $r1, $r0
  1c:   00 01 00 2a or  $r0, $r1, $r0
  20:   00 f0 01 38 asr $r0, $r0, 0x1f
  24:   0e 8e 00 00 add $sp, $sp, 0x8
  28:   0d 8e 00 00 add $fp, $sp, 0x8
  2c:   0d 8e ff 83 ldr32   $fp, [$sp, 0x1ff8]
  30:   0f ce ff 83 ldr32   $lr, [$sp, 0x1ffc]
  34:   f0 00 00 46 ret 

I have $r0-$r5 as call used registers and my TARGET_FUNCTION_VALUE and 
TARGET_FUNCTION_VALUE_REGNO_P using $r0.

Any pointers would be greatfully received.

Regards,

Jamie


Re: Eliminated function return values in retarget

2014-10-14 Thread Jamie Iles
Hi Michael,

On Tue, Oct 14, 2014 at 04:24:13PM +0200, Michael Matz wrote:
> Hi,
> 
> On Tue, 14 Oct 2014, Jamie Iles wrote:
> 
> > int foo(void)
> > {
> > if (getreturn() != 0)
> > return -1;
> > 
> > return 0;
> > }
> 
> So if getreturn() returns zero it can simply reuse that return value ...
> 
> > but at -O1 I get
> > 
> >   10:   fb ff ff 40 call0 
> > 10: R_OLDLAND_PC24  getreturn-0x4
> >   14:   01 00 00 3c mov $r1, 0x0
> >   18:   01 01 00 0a sub $r1, $r1, $r0
> >   1c:   00 01 00 2a or  $r0, $r1, $r0
> >   20:   00 f0 01 38 asr $r0, $r0, 0x1f
> 
> ... and if I'm interpreting the mnemonics correctly that is what seems to 
> happen here.  If $r0 is zero, then:
> 
>  mov $r1, 0x0  $r1 = 0
>  sub $r1, $r1, $r0 $r1 = 0 - 0 = 0
>  or  $r0, $r1, $r0 $r0 = 0 | 0 = 0
>  asr $r0, $r0, 0x1f$r0 = 0 >> 31 = 0
> 
> Voila, zero is correctly returned.  Any non-zero value will be transformed 
> into -1 (if positive the high bit will be set due to subtraction, if 
> negative the high bit will be set due to the 'or', and the shift 
> replicates the high bit into the lower ones, yielding -1).

Thanks, this definitely put me in the right direction, I'd been staring 
at it for too long!  It turns out that the problem was that I'd 
previously been testing with one_cmplsi2 defined which *was* wrong and I 
thought I'd reduced it to this.  It turns out that the actual problem 
was that I had one_cmplsi2 defined with

(define_insn "one_cmplsi2"
  [(set (match_operand:SI 0 "register_operand" "=r")
  (neg:SI (match_operand:SI 1 "register_operand" "r")))]
  ""
  "xor%0, %1, -1")

and had operand 1 as neg:SI rather than not:SI.  Fixing that gives me 
the correct code at all optimization levels.

Thanks again for looking at this, much appreciated!

Jamie