This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Committed: revival of LEGITIMIZE_RELOAD_ADDRESS for CRIS.
- From: Hans-Peter Nilsson <hans-peter dot nilsson at axis dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 12 Nov 2005 22:14:01 +0100
- Subject: Committed: revival of LEGITIMIZE_RELOAD_ADDRESS for CRIS.
Oh my, was this ever needed... not. I thought I'd fix those
suboptimalities I saw from the generic address reload support
when fixing PR middle-end/24750. But for all assembled code in
gcc, this only triggers for the specific test-cases in
gcc.target/cris/*. Anyway, it fixes... a code quality regression
from gcc-4.0.2... which however SEGV:s on rld-legit2.c anyway
because of a braino in the old LEGITIMIZE_RELOAD_ADDRESS
implementation. I like full code coverage.
gcc/:
* 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.
gcc/testsuite/:
* gcc.target/cris/cris.exp: New file.
* gcc.target/cris/rld-legit1.c: New test.
* gcc.target/cris/rld-legit2.c: New test.
Index: cris.c
===================================================================
--- cris.c (revision 106481)
+++ cris.c (working copy)
@@ -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 fro
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: cris.h
===================================================================
--- cris.h (revision 106481)
+++ cris.h (working copy)
@@ -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) \
Index: cris-protos.h
===================================================================
--- cris-protos.h (revision 106481)
+++ cris-protos.h (working copy)
@@ -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: rld-legit1.c
===================================================================
--- rld-legit1.c (revision 0)
+++ rld-legit1.c (revision 0)
@@ -0,0 +1,21 @@
+/* Check that we don't get unnecessary insns due to reload using more
+ insns than needed due to reloading of more locations than
+ needed. */
+/* { dg-options -O2 } */
+/* { dg-final { scan-assembler-not "movs.w" } } */
+/* { dg-final { scan-assembler-not "move.w" } } */
+
+/* As torture/pr24750-2.c, except we need to clobber R8 for thorough
+ testing and know we can do, since we replace the frame-pointer. */
+
+int
+f (short *a, char *y)
+{
+ __asm__ ("" : : :
+#ifndef __PIC__
+ "r0",
+#endif
+ "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
+ "r9", "r10", "r11", "r12", "r13");
+ return y[*a];
+}
Index: rld-legit2.c
===================================================================
--- rld-legit2.c (revision 0)
+++ rld-legit2.c (revision 0)
@@ -0,0 +1,16 @@
+/* A variant of rld-legit1.c only for full code coverage of the
+ initial version of cris_reload_address_legitimized. */
+/* { dg-options -O2 } */
+
+short *
+g (short *a, char *y)
+{
+ __asm__ ("" : : :
+#ifndef __PIC__
+ "r0",
+#endif
+ "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8",
+ "r9", "r10", "r11", "r12", "r13");
+ y[*a++] = 0;
+ return a;
+}
Index: cris.exp
===================================================================
--- cris.exp (revision 0)
+++ cris.exp (revision 0)
@@ -0,0 +1,41 @@
+# Copyright (C) 2005 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# GCC testsuite that uses the `gcc-dg.exp' driver, just a single option, no
+# looping over tests.
+
+# Exit immediately if this isn't a CRIS target.
+if ![istarget cris-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish