cris.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
authorHans-Peter Nilsson <hp@axis.com>
Sat, 12 Nov 2005 21:09:11 +0000 (21:09 +0000)
committerHans-Peter Nilsson <hp@gcc.gnu.org>
Sat, 12 Nov 2005 21:09:11 +0000 (21:09 +0000)
* config/cris/cris.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
* config/cris/cris.c: Include reload.h.
(cris_initial_elimination_offset): New function.
* config/cris/cris-protos.h: (cris_initial_elimination_offset):
Prototype.

From-SVN: r106835

gcc/ChangeLog
gcc/config/cris/cris-protos.h
gcc/config/cris/cris.c
gcc/config/cris/cris.h

index 760a639..b29bc2a 100644 (file)
@@ -1,3 +1,11 @@
+2005-11-12  Hans-Peter Nilsson  <hp@axis.com>
+
+       * config/cris/cris.h (LEGITIMIZE_RELOAD_ADDRESS): Define.
+       * config/cris/cris.c: Include reload.h.
+       (cris_initial_elimination_offset): New function.
+       * config/cris/cris-protos.h: (cris_initial_elimination_offset):
+       Prototype.
+
 2005-11-12  Richard Guenther  <rguenther@suse.de>
 
        * gcse.c (find_rtx_in_ldst): Handle NULL pre_ldst_table.
index f95a5d1..50673d9 100644 (file)
@@ -31,6 +31,7 @@ extern bool cris_simple_epilogue (void);
 #ifdef RTX_CODE
 extern const char *cris_op_str (rtx);
 extern void cris_notice_update_cc (rtx, rtx);
+extern bool cris_reload_address_legitimized (rtx, enum machine_mode, int, int, int);
 extern void cris_print_operand (FILE *, rtx, int);
 extern void cris_print_operand_address (FILE *, rtx);
 extern int cris_side_effect_mode_ok (enum rtx_code, rtx *, int, int,
index 4ce3c8b..0c41539 100644 (file)
@@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA.  */
 #include "function.h"
 #include "toplev.h"
 #include "recog.h"
+#include "reload.h"
 #include "tm_p.h"
 #include "debug.h"
 #include "output.h"
@@ -1205,6 +1206,81 @@ cris_initial_elimination_offset (int fromreg, int toreg)
   gcc_unreachable ();
 }
 
+/* Worker function for LEGITIMIZE_RELOAD_ADDRESS.  */
+
+bool
+cris_reload_address_legitimized (rtx x,
+                                enum machine_mode mode ATTRIBUTE_UNUSED,
+                                int opnum ATTRIBUTE_UNUSED,
+                                int itype,
+                                int ind_levels ATTRIBUTE_UNUSED)
+{
+  enum reload_type type = itype;
+  rtx op0, op1;
+  rtx *op0p;
+  rtx *op1p;
+
+  if (GET_CODE (x) != PLUS)
+    return false;
+
+  op0 = XEXP (x, 0);
+  op0p = &XEXP (x, 0);
+  op1 = XEXP (x, 1);
+  op1p = &XEXP (x, 1);
+
+  if (!REG_P (op1))
+    return false;
+
+  if (GET_CODE (op0) == SIGN_EXTEND
+      && GET_CODE (XEXP (op0, 0)) == MEM)
+    {
+      rtx op00 = XEXP (op0, 0);
+      rtx op000 = XEXP (op00, 0);
+      rtx *op000p = &XEXP (op00, 0);
+
+      if ((GET_MODE (op00) == HImode || GET_MODE (op00) == QImode)
+         && (REG_P (op000)
+             || (GET_CODE (op000) == POST_INC && REG_P (XEXP (op000, 0)))))
+       {
+         bool something_reloaded = false;
+
+         if (GET_CODE (op000) == POST_INC
+             && REG_P (XEXP (op000, 0))
+             && REGNO (XEXP (op000, 0)) > CRIS_LAST_GENERAL_REGISTER)
+           /* No, this gets too complicated and is too rare to care
+              about trying to improve on the general code Here.
+              As the return-value is an all-or-nothing indicator, we
+              punt on the other register too.  */
+           return false;
+
+         if ((REG_P (op000)
+              && REGNO (op000) > CRIS_LAST_GENERAL_REGISTER))
+           {
+             /* The address of the inner mem is a pseudo or wrong
+                reg: reload that.  */
+             push_reload (op000, NULL_RTX, op000p, NULL, GENERAL_REGS,
+                          GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+             something_reloaded = true;
+           }
+
+         if (REGNO (op1) > CRIS_LAST_GENERAL_REGISTER)
+           {
+             /* Base register is a pseudo or wrong reg: reload it.  */
+             push_reload (op1, NULL_RTX, op1p, NULL, GENERAL_REGS,
+                          GET_MODE (x), VOIDmode, 0, 0,
+                          opnum, type);
+             something_reloaded = true;
+           }
+
+         gcc_assert (something_reloaded);
+
+         return true;
+       }
+    }
+
+  return false;
+}
+
 /*  This function looks into the pattern to see how this insn affects
     condition codes.
 
@@ -2160,7 +2236,7 @@ cris_asm_output_mi_thunk (FILE *stream,
     }
 }
 
-/* Boilerplate emitted at start of file.  
+/* Boilerplate emitted at start of file.
 
    NO_APP *only at file start* means faster assembly.  It also means
    comments are not allowed.  In some cases comments will be output
index 0ca52da..0d1d8af 100644 (file)
@@ -1055,6 +1055,15 @@ struct cum_args {int regs;};
    FIXME: Check and adjust for gcc-2.9x.  */
 #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) {}
 
+/* Fix reloads known to cause suboptimal spilling.  */
+#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN)     \
+  do                                                                   \
+    {                                                                  \
+      if (cris_reload_address_legitimized (X, MODE, OPNUM, TYPE, INDL))        \
+       goto WIN;                                                       \
+    }                                                                  \
+  while (0)
+
 /* In CRIS, only the postincrement address mode depends thus,
    since the increment depends on the size of the operand.  */
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)      \