This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: reload bugfix
On Aug 19, 2000, Alexandre Oliva <aoliva@redhat.com> wrote:
> Basically, I'm trying to fix a SH problem of loading SFmode constants
> to pseudo registers that end up on the stack. GCC fails because it
> needs r0 as a scratch register with earlyclobber, but reload assigns
> the frame-pointer offset to r0 (which is the only index register too),
> and it loses. An example:
> (insn 23 21 24 (parallel[
> (set (subreg:SF (reg/v:DI 87) 0)
> (const_double:SF (cc0) 0 [0x0] 0 [0x0] [0]))
> (use (reg/v:PSI 48 fpscr))
> (clobber (scratch:SI))
> ] ) 91 {movsf_ie} (nil)
> (expr_list:REG_UNUSED (scratch:SI)
> (nil)))
> reload replaces the subreg with
> (mem:SF (plus:SI (reg:SI 14) (const_int 48))), then replaces
> (const_int 48) with (reg:SI r0).
> But then, when it gets to the scratch register, it needs r0 too,
> because the constraint is `&z', and reload aborts.
> Ok, so I introduced a new variant, that accepts a mem as the SET_DEST,
> a floating-point constant as SET_SRC and any register `&r' as scratch,
> then defined a split that copies SET_SRC to the scratch register, then
> stores the scratch register in SET_DEST.
> But GCC still insisted in allocating both the FP offset and the
> scratch register to r0. I seem to have just found a solution. First,
> I had to disable the optimization in find_reloads() that used
> RELOAD_FOR_INSN for scratch earlyclobber registers that are noted as
> unused. Then, I had to add test reload_reg_used_in_op_addr_reload in
> reload_reg_free_p(), for a RELOAD_OTHER reload type.
> Does this make sense for you?
Here's the patch. Ok to install?
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
* config/sh/sh.md (movsf_ie): New alternative that uses any
`r' register as scratch. Split it into two `movsf_i's.
(movsf_i): Don't require ! TARGET_SH3E.
* reload.c (find_reloads): Don't use RELOAD_FOR_INSN for
earlyclobber operands.
* reload1.c (reload_reg_free_p) [RELOAD_OTHER]: Conflict with
reload_reg_used_in_op_addr_reload.
Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.119
diff -u -p -r1.119 reload.c
--- gcc/reload.c 2000/08/16 16:53:02 1.119
+++ gcc/reload.c 2000/08/19 21:02:34
@@ -3534,9 +3534,13 @@ find_reloads (insn, replace, ind_levels,
however they were previously categorized. */
if (goal_alternative_earlyclobber[i] && operand_type[i] != RELOAD_OTHER)
- operand_type[i]
+ operand_type[i] = RELOAD_OTHER;
+#if 0 /* This optimization doesn't seem to be valid. An earlyclobber
+ register conflicts with any other input operand of the insn,
+ even one that is used_in_op_addr_reload. */
= (find_reg_note (insn, REG_UNUSED, recog_data.operand[i])
? RELOAD_FOR_INSN : RELOAD_OTHER);
+#endif
}
/* Any constants that aren't allowed and can't be reloaded
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.221
diff -u -p -r1.221 reload1.c
--- gcc/reload1.c 2000/08/08 23:07:10 1.221
+++ gcc/reload1.c 2000/08/19 21:02:36
@@ -4285,6 +4285,7 @@ reload_reg_free_p (regno, opnum, type)
/* In use for anything means we can't use it for RELOAD_OTHER. */
if (TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno))
return 0;
Index: gcc/config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.md,v
retrieving revision 1.39
diff -u -p -r1.39 sh.md
--- gcc/config/sh/sh.md 2000/08/18 19:10:43 1.39
+++ gcc/config/sh/sh.md 2000/08/19 21:02:38
@@ -2952,13 +2952,8 @@
(define_insn "movsf_i"
[(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
(match_operand:SF 1 "general_movsrc_operand" "r,I,FQ,mr,r,r,l"))]
- "
- (! TARGET_SH3E
- /* ??? We provide some insn so that direct_{load,store}[SFmode] get set */
- || (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 3)
- || (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 3))
- && (arith_reg_operand (operands[0], SFmode)
- || arith_reg_operand (operands[1], SFmode))"
+ "arith_reg_operand (operands[0], SFmode)
+ || arith_reg_operand (operands[1], SFmode)"
"@
mov %1,%0
mov %1,%0
@@ -2974,15 +2969,16 @@
;; when the destination changes mode.
(define_insn "movsf_ie"
[(set (match_operand:SF 0 "general_movdst_operand"
- "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,y")
+ "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,y,m")
(match_operand:SF 1 "general_movsrc_operand"
- "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y"))
- (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
- (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X"))]
+ "f,r,G,H,FQ,mf,f,FQ,mr,r,y,f,>,fr,y,r,y,FQ"))
+ (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c"))
+ (clobber (match_scratch:SI 3 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X,&r"))]
"TARGET_SH3E
&& (arith_reg_operand (operands[0], SFmode)
- || arith_reg_operand (operands[1], SFmode))"
+ || arith_reg_operand (operands[1], SFmode)
+ || arith_reg_operand (operands[3], SImode))"
"@
fmov %1,%0
mov %1,%0
@@ -3000,12 +2996,14 @@
#
sts %1,%0
lds %1,%0
- ! move optimized away"
- [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,nil")
- (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,0")
+ ! move optimized away
+ #"
+ [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,nil,*")
+ (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,4,2,2,0,4")
(set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
(const_string "single")
(const_string "none")))])
+
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "register_operand" ""))
@@ -3020,6 +3018,16 @@
(clobber (scratch:SI))])]
"")
+(define_split
+ [(set (match_operand:SF 0 "memory_operand" "=m")
+ (match_operand:SF 1 "" "FQ"))
+ (use (match_operand:PSI 2 "fpscr_operand" "c"))
+ (clobber (match_operand:SI 3 "register_operand" "=&r"))]
+ ""
+ [(set (match_dup 3) (match_dup 1))
+ (set (match_dup 0) (match_dup 3))]
+ "operands[3] = gen_rtx_REG (SFmode, REGNO (operands[3]));")
+
(define_expand "movsf"
[(set (match_operand:SF 0 "general_movdst_operand" "")
(match_operand:SF 1 "general_movsrc_operand" ""))]
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me