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]

reload patch to fix compile/20000804-1.c on powerpc


We started with:

(insn 35 34 37 (set (concat:CDI (reg:DI 88)
            (reg:DI 89))
        (asm_operands ("") ("=r") 0[ 
                (reg:SI 90)
                (reg:SI 91)
                (concat:CDI (reg:DI 88)
                    (reg:DI 89))
            ] 
            [ 
                (asm_input:SI ("r"))
                (asm_input:SI ("r"))
                (asm_input:CDI ("0"))
            ]  ("/home/geoffk/cygnus/co/egcs-mainline/egcs/gcc/testsuite/gcc.c-t
orture/compile/20000804-1.c") 8)) -1 (nil)
    (expr_list:REG_DEAD (reg:SI 91)
        (expr_list:REG_DEAD (reg:SI 90)
            (nil))))

and global-alloc decided to put the CONCAT into 

(concat:CDI (reg:DI 32 f0) (reg:DI 45 f13))

[this is probably a bug in regclass, or something]
and then reload had to deal with the resulting mess, which it did by
generating a reload:

Reload 0: reload_in (CDI) = (concat:CDI (reg:DI 32 f0)
                                                    (reg:DI 45 f13))
        reload_out (CDI) = (concat:CDI (reg:DI 32 f0)
                                                    (reg:DI 45 f13))
        GENERAL_REGS, RELOAD_OTHER (opnum = 0)
        reload_in_reg: (concat:CDI (reg:DI 32 f0)
                                                    (reg:DI 45 f13))
        reload_out_reg: (concat:CDI (reg:DI 32 f0)
                                                    (reg:DI 45 f13))
        reload_reg_rtx: (reg:CDI 5 r5)


very cool, but unfortunately it needs secondary memory to
copy between int and FP registers, and it wasn't allocating it
(or using it).

I'll commit this when it finishes a bootstrap and test on
powerpc-linux.  I believe that in the absence of CONCAT it is
equivalent to the existing code.

There are some interesting bugs in the whole SECONDARY_MEMORY_NEEDED
thing, mostly related to matching push_reload and gen_reload.  IMHO,
it's a bug that gen_reload looks at SECONDARY_MEMORY_NEEDED at all;
instead, push_reload should do the work and only generate reloads
that are valid.  One day I may even fix it :-).
-- 
- Geoffrey Keating <geoffk@cygnus.com>

===File ~/patches/cygnus/rs6000-cmplxLLreload.patch=========
2000-08-10  Geoff Keating  <geoffk@cygnus.com>

	* reload1.c (rtx_reg_class): New function.
	(gen_reload): Use rtx_reg_class to determine the class
	of hard registers, even if they are inside a CONCAT.
	* reload.c (push_reload): Change to match above change to
	gen_reload.
	* reload.h: Prototype rtx_reg_class.

Index: gcc/reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.117
diff -p -u -u -p -r1.117 reload.c
--- reload.c	2000/08/04 20:28:05	1.117
+++ reload.c	2000/08/10 07:44:16
@@ -1218,6 +1218,9 @@ push_reload (in, out, inloc, outloc, cla
 
   if (i == n_reloads)
     {
+#ifdef SECONDARY_MEMORY_NEEDED
+      enum reg_class inclass, outclass;
+#endif
       /* See if we need a secondary reload register to move between CLASS
 	 and IN or CLASS and OUT.  Get the icode and push any required reloads
 	 needed for each of them if so.  */
@@ -1241,10 +1244,9 @@ push_reload (in, out, inloc, outloc, cla
 
 #ifdef SECONDARY_MEMORY_NEEDED
       /* If a memory location is needed for the copy, make one.  */
-      if (in != 0 && GET_CODE (in) == REG
-	  && REGNO (in) < FIRST_PSEUDO_REGISTER
-	  && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
-				      class, inmode))
+      if (in != 0 
+	  && (inclass = rtx_reg_class (in)) != NO_REGS
+	  && SECONDARY_MEMORY_NEEDED (inclass, class, inmode))
 	get_secondary_mem (in, inmode, opnum, type);
 #endif
 
@@ -1271,10 +1273,9 @@ push_reload (in, out, inloc, outloc, cla
       n_reloads++;
 
 #ifdef SECONDARY_MEMORY_NEEDED
-      if (out != 0 && GET_CODE (out) == REG
-	  && REGNO (out) < FIRST_PSEUDO_REGISTER
-	  && SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),
-				      outmode))
+      if (out != 0
+	  && (outclass = rtx_reg_class (out)) != NO_REGS
+	  && SECONDARY_MEMORY_NEEDED (class, outclass, outmode))
 	get_secondary_mem (out, outmode, opnum, type);
 #endif
     }
Index: gcc/reload.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.h,v
retrieving revision 1.29
diff -p -u -u -p -r1.29 reload.h
--- reload.h	2000/07/28 17:46:17	1.29
+++ reload.h	2000/08/10 07:44:17
@@ -358,6 +358,9 @@ extern void mark_home_live PARAMS ((int)
    replacement (such as sp), plus an offset.  */
 extern rtx eliminate_regs PARAMS ((rtx, enum machine_mode, rtx));
 
+/* Determine the class of the hard register(s) R is stored in, if any.  */
+extern enum reg_class rtx_reg_class PARAMS ((rtx r));
+
 /* Emit code to perform a reload from IN (which may be a reload register) to
    OUT (which may also be a reload register).  IN or OUT is from operand
    OPNUM with reload type TYPE.  */
Index: gcc/reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.221
diff -p -u -u -p -r1.221 reload1.c
--- reload1.c	2000/08/08 23:07:10	1.221
+++ reload1.c	2000/08/10 07:44:42
@@ -7143,6 +7143,29 @@ emit_reload_insns (chain)
   IOR_HARD_REG_SET (reg_reloaded_dead, reg_reloaded_died);
 }
 
+/* Given a RTX R, determine the class of the hard register(s) it is
+   stored in, or return NO_REGS if it is not necessarily stored in a
+   hard register.
+*/
+enum reg_class
+rtx_reg_class (r)
+     rtx r;
+{
+  /* We need not deal with SUBREGs here because there shouldn't
+     be any SUBREGs of hard regs.  */
+
+  if (GET_CODE (r) == REG && REGNO (r) < FIRST_PSEUDO_REGISTER)
+    return REGNO_REG_CLASS (REGNO (r));
+
+  else if (GET_CODE (r) == CONCAT)
+    return (reg_class_superunion
+	    [rtx_reg_class (XEXP (r, 0))]
+	    [rtx_reg_class (XEXP (r, 1))]);
+
+  else 
+    return NO_REGS;
+}
+
 /* Emit code to perform a reload from IN (which may be a reload register) to
    OUT (which may also be a reload register).  IN or OUT is from operand
    OPNUM with reload type TYPE.
@@ -7158,6 +7181,9 @@ gen_reload (out, in, opnum, type)
 {
   rtx last = get_last_insn ();
   rtx tem;
+#ifdef SECONDARY_MEMORY_NEEDED
+  enum reg_class inclass, outclass;
+#endif
 
   /* If IN is a paradoxical SUBREG, remove it and try to put the
      opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
@@ -7320,10 +7346,9 @@ gen_reload (out, in, opnum, type)
 
 #ifdef SECONDARY_MEMORY_NEEDED
   /* If we need a memory location to do the move, do it that way.  */
-  else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
-	   && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
-	   && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
-				       REGNO_REG_CLASS (REGNO (out)),
+  else if ((inclass = rtx_reg_class (in)) != NO_REGS
+	   && (outclass = rtx_reg_class (out)) != NO_REGS
+	   && SECONDARY_MEMORY_NEEDED (inclass, outclass,
 				       GET_MODE (out)))
     {
       /* Get the memory to use and rewrite both registers to its mode.  */
============================================================

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