This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]