http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22553
--- Comment #26 from Oleg Endo <olegendo at gcc dot gnu.org> 2012-11-09 21:44:16 UTC --- I've tried enabling sched1 on rev 193341 and ran the test suite with make -k -j4 check RUNTESTFLAGS="--target_board=sh-sim\{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" I got one failure for -m2a, -m4 -m4a (both, -ml and -mb): FAIL: gcc.dg/pr42475.c (internal compiler error) The error is: sh_tmp.cpp: In function 'baz': sh_tmp.cpp:25:1: error: unable to find a register to spill in class 'R0_REGS' } ^ sh_tmp.cpp:25:1: error: this is the insn: (insn 18 31 42 2 (parallel [ (set (subreg:SF (reg:SI 1 r1 [orig:174 D.1383+4 ] [174]) 0) (mult:SF (reg:SF 171) (reg:SF 65 fr1 [orig:170 p.c.z ] [170]))) (use (reg/v:PSI 151 )) ]) sh_tmp.cpp:24 426 {mulsf3_i} (expr_list:REG_DEAD (reg:SF 171) (expr_list:REG_DEAD (reg:SF 65 fr1 [orig:170 p.c.z ] [170]) (expr_list:REG_DEAD (reg/v:PSI 151 ) (nil))))) sh_tmp.cpp:25:1: internal compiler error: in spill_failure, at reload1.c:2124 A GP reg is supposed to receive the result of an FP operation, which the SH actually can't do. It has to go through FPUL. The error occurs because sched1 hoists a load of r0 (part of the return value) before the failing insn: (insn 31 15 18 2 (set (reg:SI 0 r0) (const_int 0 [0])) sh_tmp.cpp:25 244 {movsi_ie} (nil)) (insn 18 31 42 2 (parallel [ (set (subreg:SF (reg:SI 174 [ D.1383+4 ]) 0) (mult:SF (reg:SF 170 [ p.c.z ]) (reg:SF 171))) .... The result value transfer from FP reg to GP reg (through FPUL) seems to go a long way during reload, and one the insns that reload checks has a R0 clobber (not sure which one, but there are a couple of reload insns with a =&z constraint). On option to fix this is to split such insns. The patch below fixes the test case failure, but I haven't re-tested it completely. Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 193342) +++ gcc/config/sh/sh.md (working copy) @@ -12077,6 +12077,32 @@ [(set_attr "type" "fp") (set_attr "fp_mode" "single")]) +;; If the output of a floating-point operation is to be stored in a GP reg +;; the target GP output reg might be propagated as a subreg into floating- +;; point insns. If we split the operation and the GP reg store +;; (through FPUL) into separate insns before reload some trouble can be +;; avoided during reload. +(define_split + [(set (match_operand:SF 0 "fp_arith_reg_operand") + (match_operator:SF 1 "float_operator" + [(match_operand:SF 2 "fp_arith_reg_operand") + (match_operand:SF 3 "fp_arith_reg_operand")])) + (use (match_operand:PSI 4 "fpscr_operand"))] + "TARGET_SH2E + && can_create_pseudo_p () && GET_CODE (operands[0]) == SUBREG + && REG_P (SUBREG_REG (operands[0])) + && GET_MODE (SUBREG_REG (operands[0])) != SFmode" + [(parallel [(set (match_dup 5) (match_dup 6)) + (use (match_dup 4))]) + (parallel [(set (match_dup 0) (match_dup 5)) + (use (match_dup 4)) + (clobber (reg:SI FPUL_REG))])] +{ + operands[5] = gen_reg_rtx (SFmode); + operands[6] = gen_rtx_fmt_ee (GET_CODE (operands[1]), SFmode, operands[2], + operands[3]); +}) + ;; FMA (fused multiply-add) patterns (define_expand "fmasf4" [(set (match_operand:SF 0 "fp_arith_reg_operand" "") Index: gcc/config/sh/predicates.md =================================================================== --- gcc/config/sh/predicates.md (revision 193342) +++ gcc/config/sh/predicates.md (working copy) @@ -1156,3 +1156,9 @@ return false; }) + +(define_predicate "float_operator" + (ior (match_operand 0 "binary_float_operator") + (match_operand 0 "commutative_float_operator") + (match_operand 0 "noncommutative_float_operator") + (match_operand 0 "unary_float_operator"))) Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 193342) +++ gcc/config/sh/sh.c (working copy) @@ -877,6 +877,7 @@ || (TARGET_SHMEDIA && !TARGET_PT_FIXED)) flag_no_function_cse = 1; +#if 0 if (targetm.small_register_classes_for_mode_p (VOIDmode)) \ { /* Never run scheduling before reload, since that can @@ -903,6 +904,7 @@ && !global_options_set.x_flag_schedule_insns) flag_schedule_insns = 0; } +#endif /* Unwind info is not correct around the CFG unless either a frame pointer is present or M_A_O_A is set. Fixing this requires rewriting