------- Additional Comments From uweigand at gcc dot gnu dot org 2004-11-24 14:50 ------- We have here the following situation before reload: (insn 27 46 28 7 (set (reg:DI 118 [ D.1118 ]) (const_int 4294967295 [0xffffffff])) 313 {*movdi_internal32} (nil) (nil)) where reg 118 gets assigned a stack slot, and due to the large stack frame size this slot is not directly addressable.
Now, when reverting my patch, what happens is that LEGITIMIZE_RELOAD_ADDRESS finds a way to construct the stack slot address, and the constant is reloaded into a register (pair): (insn 67 46 66 7 (set (reg:DI 2 r2) (const_int 4294967295 [0xffffffff])) 313 {*movdi_internal32} (nil) (nil)) (insn 66 67 27 7 (set (reg:SI 9 r9) (plus:SI (reg/f:SI 30 r30) (const_int 131072 [0x20000]))) 64 {*addsi3_internal1} (nil) (nil)) (insn 27 66 28 7 (set (mem:DI (plus:SI (reg:SI 9 r9) (const_int 40 [0x28])) [0 D.1118+0 S8 A8]) (reg:DI 2 r2)) 313 {*movdi_internal32} (nil) (nil)) Note that insn 27 now uses the r -> o alternative of *movdi_internal32; this is allowed only if the address is offsettable. Now, that address is the one that was constructed by LEGITIMIZE_RELOAD_ADDRESS. Unfortunately, reload common code has no way to actually look at what LEGITIMIZE_RELOAD_ADDRESS does, so that it could decide whether or not the address constructed is in fact an offsettable one or not. Before my 2004-08-22 patch, reload simply always assumed the address is offsettable, due to an apparent bug in LEGITIMIZE_RELOAD_ADDRESS handling: reload assumed that L_R_A would always completely replace the address by a single base register (which of course implies the address is offsettable). This bug caused problems on s390. My patch removed this erroneous assumption that L_R_A always completly replaces the address; as we don't know anything further we then have to make the conservative assumption that addresses constructed by L_R_A are never offsettable. Thus reload doesn't accept the r -> o alternative of *movdi_internal32 any more; the one it chooses instead is f -> m. This implies reloading the constant into a floating point register, and that's what reload goes ahead and does: (insn 67 46 66 7 (set (reg:DI 32 f0) (const_int 4294967295 [0xffffffff])) 313 {*movdi_internal32} (nil) (nil)) (insn 66 67 27 7 (set (reg:SI 2 r2) (plus:SI (reg/f:SI 30 r30) (const_int 131072 [0x20000]))) 64 {*addsi3_internal1} (nil) (nil)) (insn 27 66 28 7 (set (mem:DI (plus:SI (reg:SI 2 r2) (const_int 40 [0x28])) [0 D.1118+0 S8 A8]) (reg:DI 32 f0)) 313 {*movdi_internal32} (nil) (nil)) However, the insn 67 emitted thus is not actually implemented by any of the alternatives or splitters; thus the crash later on. This would appear to be a latent bug in the rs6000 back end. Reload insns generated during the gen_reload phase *must* be implemented by the backend. I'm not familiar enough with the platform to suggested the best way to do so; one obvious option would be force the constant to memory using either from within the movdi expander or via a secondary input reload. The next question is whether the new code, if implemented correctly, is better or worse than the old code -- again this is a rs6000 back-end issue. However, one middle-end question remains: while it is obviously wrong for reload to assume that L_R_A always results in a simple base register, at least on rs6000 is appears to be the case that L_R_A always results in an *offsettable* address. If this is true, we might be missing optimizations by not exploiting that knowledge in reload any more. One way might be to extend the L_R_A interface in a way that would allow the back end to inform the middle end about properties of the address is has constructed; I'm not sure how this interface should look in detail. The other option would be to simply go back to having the middle end assume the L_R_A constructed addresses are always offsettable. This could be implemented by something like the following patch: Index: reload.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/reload.c,v retrieving revision 1.258 diff -c -p -r1.258 reload.c *** reload.c 9 Nov 2004 17:29:02 -0000 1.258 --- reload.c 24 Nov 2004 14:49:04 -0000 *************** find_reloads (rtx insn, int replace, int *** 3189,3196 **** && ((ind_levels ? offsettable_memref_p (operand) : offsettable_nonstrict_memref_p (operand)) /* A reloaded address is offsettable because it is now ! just a simple register indirect. */ ! || address_reloaded[i] == 1)) || (REG_P (operand) && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (operand)] < 0 --- 3189,3198 ---- && ((ind_levels ? offsettable_memref_p (operand) : offsettable_nonstrict_memref_p (operand)) /* A reloaded address is offsettable because it is now ! just a simple register indirect. Addresses built ! via LEGITIMIZE_RELOAD_ADDRESS must always be ! offsettable as well. */ ! || address_reloaded[i])) || (REG_P (operand) && REGNO (operand) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (operand)] < 0 (This requirement should then be documented in the L_R_A docs as well.) -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18641