http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54429
--- Comment #5 from Oleg Endo <olegendo at gcc dot gnu.org> 2012-11-14 09:45:22 UTC --- (In reply to comment #4) > > makes the unwanted subreg propagation go away, but ends up in another reload > trouble: > > sh_tmp.cpp:92:1: error: unable to find a register to spill in class > 'TARGET_REGS' > } > ^ > sh_tmp.cpp:92:1: error: this is the insn: > (insn 7 4 8 2 (set (reg:SI 1 r1 [165]) > (subreg:SI (reg:DF 70 fr6 [ y ]) 0)) sh_tmp.cpp:91 244 {movsi_ie} > (expr_list:REG_DEAD (reg:DF 70 fr6 [ y ]) > (nil))) > The test case I was using for tracking this: extern double copysign(double,double); double test1(double x, double y) { return copysign(-x,y); } Interestingly, without any patches applied, compiling the function above with -O2 -m4 -ml results in: _test1: fmov.s fr6,@-r15 ! 49 movsf_ie/7 [length = 2] fmov.s fr7,@-r15 ! 50 movsf_ie/7 [length = 2] mov.l .L8,r1 ! 43 movsi_ie/1 [length = 2] mov.l @r15+,r2 ! 51 movdf_k/3 [length = 4] mov.l @r15+,r3 tst r3,r1 ! 10 tstsi_t/2 [length = 2] fmov fr4,fr0 ! 52 movsf_ie/1 [length = 2] fmov fr5,fr1 ! 53 movsf_ie/1 [length = 2] bt/s .L6 ! 11 *cbranch_t [length = 2] fabs dr0 ! 9 absdf2_i [length = 2] fneg dr0 ! 12 negdf2_i [length = 2] .L6: rts nop ! 56 *return_i [length = 4] .L9: .align 2 .L8: .long -2147483648 and -O2 -m4 -mb is: _test1: flds fr6,fpul ! 46 movsi_ie/22 [length = 2] sts fpul,r1 ! 47 movsi_ie/20 [length = 2] fmov fr4,fr0 ! 48 movsf_ie/1 [length = 2] fmov fr5,fr1 ! 49 movsf_ie/1 [length = 2] cmp/pz r1 ! 10 cmpgesi_t/1 [length = 2] bt/s .L6 ! 11 *cbranch_t [length = 2] fabs dr0 ! 9 absdf2_i [length = 2] fneg dr0 ! 12 negdf2_i [length = 2] .L6: rts nop ! 52 *return_i [length = 4] This is probably due to the 'sh_cannot_change_mode_class'. On big endian the DFmode reg can be accessed as SImode, but not on little endian because of the subreg ordering. Maybe it would be better to not do all the GP <-> FPUL <-> FP reg transfers during reload but emit the necessary insn sequences before reload.