On Wednesday 12 April 2006 15:43, Rask Ingemann Lambertsen wrote:
> On Wed, Apr 12, 2006 at 07:47:32AM +0200, Frank Riese wrote:
> > On Monday 10 April 2006 19:48, you wrote:
> > > Can it at least add (small) immediates to registers?
> >
> > Nope, sry. The only instructions that take other arguments than registers
> > are the aforementioned LDL/LDH (load low/high), branch instructions (they
> > take a memory address) and four bit operations which can mask, invert,
> > set or delete a bit in a register.
>
> This will increase the probability of reload failures when storing through
> a pointer, because of the need for an extra register to hold the offset in
> some cases. For example
>
>       int x, *p;
>       p[15] = x;
>       /* p not used after this */
>
>       LDL     R[4], 30
>       LDH     R[4], 0
>       ADD     R[3], R[3], R[4]
>       STO     R[3], R[2]
>
> > > #define GO_IF_LEGITIMATE_ADDRESS(XMODE, X, LABEL)     \
> > >       if (REG_P (X))                                  \
> > >               goto LABEL;
> >
> > I tried that out today. I wasn't sure about the exact contexts in which
> > this macro is used. It seems to work fine, though.
>

Rask, Dave, thanks for your answers so far!

Sry for not answering for some time but the last two weeks were pretty busy 
for me and I wans't able to try out all of your suggestions until yesterday. I 
also tried to read up on compilers and GCC internals the best I could before 
requesting your help again - hope I don't ask any redundant questions.

I moved my code to mainline and the segmentation faults I had before 
disappeared. Not making BP fixed seems to have helped with a lot of code, too.

However, I'm still having problems with reloading/register spilling:

-------------------------------------------------------------------------------------
/usr/local/src/gcc/objdir/./gcc/xgcc -B/usr/local/src/gcc/objdir/./gcc/ 
-B/usr/local/zykluno-none/bin/ -B/usr/local/zykluno-none/lib/ 
-isystem /usr/local/zykluno-none/include -isystem 
/usr/local/zykluno-none/sys-include 
-O2  -O2 -g -O2   -DIN_GCC -DCROSS_COMPILE   -W -Wall -Wwrite-strings 
-Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  
-isystem ./include   -g  -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED 
-Dinhibit_libc -I. -I. -I../../gcc -I../../gcc/. -I../../gcc/../include 
-I../../gcc/../libcpp/include  -I../../gcc/../libdecnumber 
-I../libdecnumber -DL_muldi3 -c ../../gcc/libgcc2.c -o libgcc/./_muldi3.o

cc1: warning: target system does not support debug output
cc1: warning: target system does not support debug output
../../gcc/libgcc2.c: In function '__muldi3':
../../gcc/libgcc2.c:520: error: unable to find a register to spill in 
class 'GENERAL_REGS'
../../gcc/libgcc2.c:520: error: this is the insn:
(insn 436 435 442 6 ../../gcc/libgcc2.c:520 (set (reg/f:HI 5 R[5] [+6 ])
        (mem/s/c:HI (reg/f:HI 198) [0+2 S2 A16])) 17 {movhi} (nil)
    (expr_list:REG_DEAD (reg/f:HI 198)
        (nil)))
../../gcc/libgcc2.c:520: internal compiler error: in spill_failure, at 
reload1.c:1912
-------------------------------------------------------------------------------------

I looked at the offending lines in libgcc2.c and it seems to me that the only 
problem with that code is that the compiler needs a lot of registers for the 
structures and members and thus runs out of registers.

I followed your suggestion and dumped the *.greg of libgcc2.c 
(-fdump-rtl-greg-details):

-------------------------------------------------------------------------------------
[...]
Using reg 2 for reload 0
Using reg 3 for reload 1
Spilling for insn 425.
Using reg 2 for reload 0
Using reg 3 for reload 1
Spilling for insn 426.
Using reg 2 for reload 0
Using reg 3 for reload 1
Spilling for insn 433.
Using reg 3 for reload 0
Spilling for insn 434.
Using reg 4 for reload 0
Spilling for insn 435.
Using reg 5 for reload 0
Spilling for insn 436.
reload failure for reload 0

Reloads for insn # 436
Reload 0: reload_in (HI) = (reg/f:HI 198)
        GENERAL_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 1)
        reload_in_reg: (reg/f:HI 198)
-------------------------------------------------------------------------------------

With my limited experience I would say that this tells me that the compiler 
gradually uses up all available registers and then, instead of freeing one, 
it complains that it hasn't any left (as a reminder: registers 3-7 are my 
GENERAL_REGS with BP being number 6 and SP number 7). 

If that helps, here are the last few instructions before the compiler fails:

-------------------------------------------------------------------------------------
[...]
(note 430 426 431 6 NOTE_INSN_FUNCTION_END)
(note 431 430 433 6 ("../../gcc/libgcc2.c") 520)
(insn 433 431 434 6 ../../gcc/libgcc2.c:520 (set (reg:HI 2 R[2] [ <result> ])
        (subreg:HI (reg:DI 30 [ <result> ]) 0)) 17 {movhi} 
(insn_list:REG_DEP_TRUE 426 (nil))
    (nil))
(insn 434 433 435 6 ../../gcc/libgcc2.c:520 (set (reg:HI 3 R[3] [+2 ])
        (subreg:HI (reg:DI 30 [ <result> ]) 2)) 17 {movhi} (nil)
    (nil))
(insn 435 434 436 6 ../../gcc/libgcc2.c:520 (set (reg:HI 4 R[4] [+4 ])
        (subreg:HI (reg:DI 30 [ <result> ]) 4)) 17 {movhi} (nil)
    (expr_list:REG_DEAD (reg:DI 30 [ <result> ])
        (nil)))
(insn 436 435 442 6 ../../gcc/libgcc2.c:520 (set (reg/f:HI 5 R[5] [+6 ])
        (mem/s/c:HI (reg/f:HI 198) [0+2 S2 A16])) 17 {movhi} (nil)
    (expr_list:REG_DEAD (reg/f:HI 198)
        (nil)))
(insn 442 436 0 6 ../../gcc/libgcc2.c:520 (use (reg/i:DI 2 R[2])) -1 
(insn_list:REG_DEP_TRUE 433 (nil))
    (nil))
;; End of basic block 6, registers live:
 2 [R[2]] 3 [R[3]] 4 [R[4]] 5 [R[5]] 6 [BP] 7 [SP]
-------------------------------------------------------------------------------------

The problem is that he does know how to spill registers (= move the contents 
of a register to a temporary storage place to free up a register) in 
GENERAL_REGS, right? 

So, IMHO I need to provide him with a way to free up a register: e.g. by 
pushing the contents of a register onto the stack and restoring it 
afterwards - or somewhere else in memory. 

Perhaps I'm just missing an instruction in the machine defintion so that he 
does not know how to do that? Would he do this with a movm instruction? Or 
with a pushm? I tried to provide him with scratch registers via 
reload_[in/out] instructions but he does not seem to use those instructions 
at all. 

I think that my constraints for my move instructions are correct, too:

-------------------------------------------------------------------------------------
(define_insn "movhi"
  [(set (match_operand:HI 0 "general_operand" "=r,r,m,r,X")
        (match_operand:HI 1 "general_operand" " r,m,r,i,X"))]
  ""
  "@ OR \t%0, R[0], %1
     LDD \t%0, %1
     STO \t%0, %1
     LDH \t%0, %H1\n\tLDL \t%0, %L1
     XXX"
)
-------------------------------------------------------------------------------------

I inserted the last pair of constraints to see if the compiler's trying to do 
anything he normally can't.

I also provided a push instruction, so I think GCC should be able to save away 
a register:

-------------------------------------------------------------------------------------
(define_insn "pushhi1"
  [(match_operand:HI 0 "register_operand" "")]
  ""
  {
  zykluno_output_push(operands[0]);
  }    
)
-------------------------------------------------------------------------------------

I read the GCC internals section about target macros for register classes 
again (SECONDARY_RELOAD_CLASS, SECONDARY_MEMORY_NEEDED, 
CLASS_LIKELY_SPILLED_P, SMALL_REGISTER_CLASSES, etc.), but those don't seem to 
help as most of them seem to tell the compiler that he is always supposed to 
copy the contents of certain registers in a special way and not how to free 
some when he runs out of registers.

I might be wrong, but I guess I'm missing something very basic. To sum up, I 
think the problem is that I just didn't provide GCC with a way to save away a 
register. However, I've run out of ideas how to enable GCC to do so. 

Your suggestions have been very helpful so far and I hope to hear from you 
again. 

Cheers,
Frank





Reply via email to