This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: RFA: reload infrastructure to fix PR target/21623
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: Bernd Schmidt <bernds_cb1 at t-online dot de>
- Cc: Ian Lance Taylor <ian at airs dot com>, gcc-patches at gcc dot gnu dot org, Kaz Kojima <kkojima at rr dot iij4u dot or dot jp>, aoliva at redhat dot com
- Date: Mon, 03 Oct 2005 23:52:35 +0100
- Subject: Re: RFA: reload infrastructure to fix PR target/21623
- References: <20050927.103622.26298462.kkojima@rr.iij4u.or.jp> <20050927.160054.68062105.kkojima@rr.iij4u.or.jp> <43392D3B.6020905@st.com> <20050927.231900.34738606.kkojima@rr.iij4u.or.jp> <433B0E9A.2000103@st.com> <433CF482.1080201@t-online.de> <433D40E1.5080109@st.com> <433D4227.4090004@st.com> <433D6009.7000002@st.com> <m3mzluxr1w.fsf@gossamer.airs.com> <433DAECA.1010902@st.com> <433E5537.6060402@t-online.de> <43412904.3070404@st.com> <43413BD5.6040107@t-online.de> <434157EA.4060008@st.com> <4341708A.3000602@t-online.de>
Here is a heads up of what I have so far; I don't know if it compiles.
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/rs6000: .rs6000.md.swp
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .predicates.md.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.c 2005-09-05 13:45:22.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.c 2005-10-03 22:14:50.000000000 +0100
@@ -500,6 +500,9 @@ static int hard_regs_intersect_p (HARD_R
#define TARGET_ADJUST_UNROLL_MAX sh_adjust_unroll_max
#endif
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD sh_secondary_reload
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Implement TARGET_HANDLE_OPTION. */
@@ -10619,6 +10622,107 @@ shmedia_prepare_call_address (rtx fnaddr
return fnaddr;
}
+enum reg_class
+sh_secondary_reload (int in_p, rtx x, enum reg_class class,
+ enum machine_mode mode, secondary_reload_info *)
+{
+ if (in_p)
+ {
+ if (REGCLASS_HAS_FP_REG (class)
+ && ! TARGET_SHMEDIA
+ && immediate_operand ((x), mode)
+ && ! ((fp_zero_operand (x) || fp_one_operand (x))
+ && mode == SFmode && fldi_ok ()))
+ switch (mode)
+ {
+ case SFmode:
+ sri->icode = CODE_FOR_reload_insf__frn;
+ return NO_REGS;
+ case DFmode:
+ sri->icode = CODE_FOR_reload_indf__frn;
+ return NO_REGS;
+ case SImode:
+ sri->icode = CODE_FOR_reload_insi__i_fpul;
+ return FPUL_REGS;
+ default:
+ abort ();
+ }
+ if (class == FPUL_REGS
+ && ((GET_CODE (x) == REG
+ && (REGNO (x) == MACL_REG || REGNO (x) == MACH_REG
+ || REGNO (x) == T_REG))
+ || GET_CODE (x) == PLUS))
+ return GENERAL_REGS;
+ if (class == FPUL_REGS && immediate_operand (x, mode))
+ {
+ if (GET_CODE (x) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (x)))
+ return GENERAL_REGS;
+ sri->icode = CODE_FOR_reload_insi__i_fpul;
+ return NO_REGS;
+ }
+ if (class == FPSCR_REGS
+ && ((GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER)
+ || (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS)))
+ return GENERAL_REGS;
+ if (REGCLASS_HAS_FP_REG (class)
+ && TARGET_SHMEDIA
+ && immediate_operand (x, mode)
+ && x != CONST0_RTX (GET_MODE (x))
+ && GET_MODE (x) != V4SFmode)
+ return GENERAL_REGS;
+ if ((mode == QImode || mode == HImode)
+ && TARGET_SHMEDIA && inqhi_operand (x, mode))
+ {
+ sri->icode = ((mode == QImode)
+ ? CODE_FOR_reload_inqi : CODE_FOR_reload_inhi);
+ return NO_REGS;
+ }
+ if (TARGET_SHMEDIA && class == GENERAL_REGS
+ && (GET_CODE (x) == LABEL_REF || PIC_DIRECT_ADDR_P (x)))
+ return TARGET_REGS;
+ } /* end of input-only processing. */
+
+ if (((REGCLASS_HAS_FP_REG (class)
+ && (GET_CODE (x) == REG
+ && (GENERAL_OR_AP_REGISTER_P (REGNO (x))
+ || (FP_REGISTER_P (REGNO (x)) && mode == SImode
+ && TARGET_FMOVD))))
+ || (REGCLASS_HAS_GENERAL_REG (class)
+ && GET_CODE (x) == REG
+ && FP_REGISTER_P (REGNO (x))))
+ && ! TARGET_SHMEDIA
+ && (mode == SFmode || mode == SImode))
+ return FPUL_REGS;
+ if ((class == FPUL_REGS
+ || (REGCLASS_HAS_FP_REG (class)
+ && ! TARGET_SHMEDIA && mode == SImode))
+ && (GET_CODE (x) == MEM
+ || (GET_CODE (x) == REG
+ && (REGNO (x) >= FIRST_PSEUDO_REGISTER
+ || REGNO (x) == T_REG
+ || system_reg_operand (x, VOIDmode)))))
+ {
+ if (class == FPUL_REGS)
+ return GENERAL_REGS;
+ sri->icode = (in_p ? CODE_FOR_reload_insi__r_fpul
+ : CODE_FOR_reload_outsi__fpul_r);
+ return FPUL_REGS;
+ }
+ if ((class == TARGET_REGS
+ || (TARGET_SHMEDIA && class == SIBCALL_REGS))
+ && !EXTRA_CONSTRAINT_Csy (x)
+ && (GET_CODE (x) != REG || ! GENERAL_REGISTER_P (REGNO (x))))
+ return GENERAL_REGS;
+ if ((class == MAC_REGS || class == PR_REGS)
+ && GET_CODE (x) == REG && ! GENERAL_REGISTER_P (REGNO (x))
+ && class != REGNO_REG_CLASS (REGNO (x)))
+ return GENERAL_REGS;
+ if (class != GENERAL_REGS && GET_CODE (x) == REG
+ && TARGET_REGISTER_P (REGNO (x)))
+ return GENERAL_REGS;
+ return NO_REGS;
+}
+
enum sh_divide_strategy_e sh_div_strategy = SH_DIV_STRATEGY_DEFAULT;
/* This defines the storage for the variable part of a -mboard= option.
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.h 2005-09-12 14:23:10.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.h 2005-10-03 22:52:22.000000000 +0100
@@ -1581,6 +1581,7 @@ extern enum reg_class reg_class_from_let
: (C) == 'H' ? (fp_one_operand (VALUE) && fldi_ok ()) \
: (C) == 'F')
+#if 0
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
@@ -1665,6 +1666,9 @@ extern enum reg_class reg_class_from_let
&& (GET_CODE (X) == LABEL_REF || PIC_DIRECT_ADDR_P (X))) \
? TARGET_REGS \
: SECONDARY_INOUT_RELOAD_CLASS((CLASS),(MODE),(X), NO_REGS))
+#else
+#define HAVE_SECONDARY_RELOADS
+#endif
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .sh.h.swo
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .sh.h.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.md /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.md
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh.md 2005-09-13 23:03:18.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh.md 2005-09-30 21:38:02.000000000 +0100
@@ -5845,15 +5845,15 @@ label:
(clobber (scratch:SI))])]
"")
-(define_expand "reload_indf"
- [(parallel [(set (match_operand:DF 0 "register_operand" "=f")
+(define_expand "reload_indf__frn"
+ [(parallel [(set (match_operand:DF 0 "register_operand" "=a")
(match_operand:DF 1 "immediate_operand" "FQ"))
(use (reg:PSI FPSCR_REG))
(clobber (match_operand:SI 2 "register_operand" "=&z"))])]
"TARGET_SH1"
"")
-(define_expand "reload_outdf"
+(define_expand "reload_outdf__RnFRm"
[(parallel [(set (match_operand:DF 0 "register_operand" "=r,f")
(match_operand:DF 1 "register_operand" "af,r"))
(clobber (match_operand:SI 2 "register_operand" "=&y,y"))])]
@@ -6475,7 +6475,7 @@ label:
[(set_attr "length" "0")
(set_attr "type" "nil")])
-(define_expand "reload_insf"
+(define_expand "reload_insf__frn"
[(parallel [(set (match_operand:SF 0 "register_operand" "=a")
(match_operand:SF 1 "immediate_operand" "FQ"))
(use (reg:PSI FPSCR_REG))
@@ -6483,13 +6483,25 @@ label:
"TARGET_SH1"
"")
-(define_expand "reload_insi"
+(define_expand "reload_insi__i_fpul"
[(parallel [(set (match_operand:SI 0 "fpul_operand" "=y")
(match_operand:SI 1 "immediate_operand" "i"))
(clobber (match_operand:SI 2 "register_operand" "=&z"))])]
"TARGET_SH1"
"")
+(define_expand "reload_insi__r_fpul"
+ [(set (match_operand:SI 2 "" "=r") (match_operand:SI 1 "" ""))
+ (set (match_operand:SI 0 "" "=y") (match_dup 2))]
+ "TARGET_SH1"
+ "")
+
+(define_expand "reload_outsi__fpul_r"
+ [(set (match_operand:SI 2 "" "=r") (match_operand:SI 1 "" "y"))
+ (set (match_operand:SI 0 "" "") (match_dup 2))]
+ "TARGET_SH1"
+ "")
+
(define_expand "ptabs"
[(set (match_operand 0 "" "=b") (match_operand 1 "" "r"))]
"TARGET_SHMEDIA"
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh: .sh.md.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh-protos.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh-protos.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/config/sh/sh-protos.h 2005-06-29 02:24:25.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/config/sh/sh-protos.h 2005-09-30 19:40:31.000000000 +0100
@@ -165,6 +165,7 @@ extern int shmedia_cleanup_truncate (rtx
extern int sh_contains_memref_p (rtx);
extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall);
+extern int sh_reload_icode (int, rtx, enum reg_class, enum machine_mode);
#endif /* ! GCC_SH_PROTOS_H */
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/doc: .md.texi.swp
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/gencodes.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/gencodes.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/gencodes.c 2005-06-25 03:00:13.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/gencodes.c 2005-09-30 19:17:15.000000000 +0100
@@ -52,6 +52,8 @@ int
main (int argc, char **argv)
{
rtx desc;
+ int i;
+ const char * reg_class_names[] = REG_CLASS_NAMES;
progname = "gencodes";
@@ -86,7 +88,11 @@ enum insn_code {");
gen_insn (desc, insn_code_number);
}
- puts (" CODE_FOR_nothing\n\
+ puts (" CODE_FOR_nothing,");
+ for (i = 0; i < N_REG_CLASSES; i++)
+ printf (" CODE_FOR_reload__%s,\n", reg_class_names[i]);
+
+ puts (" CODE_FOR_reload__end\n\
};\n\
\n\
#endif /* GCC_INSN_CODES_H */");
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/regclass.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/regclass.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/regclass.c 2005-06-25 03:00:52.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/regclass.c 2005-09-30 22:04:28.000000000 +0100
@@ -54,11 +54,9 @@ static void init_reg_autoinc (void);
reloads, we are not allowed to use classes requiring secondary
reloads for pseudos auto-incremented since reload can't handle it. */
-#ifdef AUTO_INC_DEC
-#if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)
+#if defined(AUTO_INC_DEC) && defined(HAVE_SECONDARY_RELOADS)
#define FORBIDDEN_INC_DEC_CLASSES
#endif
-#endif
/* Register tables used by many passes. */
@@ -622,22 +620,7 @@ memory_move_secondary_cost (enum machine
rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode];
- if (in)
- {
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- altclass = SECONDARY_INPUT_RELOAD_CLASS (class, mode, mem);
-#else
- altclass = NO_REGS;
-#endif
- }
- else
- {
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- altclass = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, mem);
-#else
- altclass = NO_REGS;
-#endif
- }
+ altclass = secondary_reload_class (in ? 1 : 0, class, mode, mem);
if (altclass == NO_REGS)
return 0;
@@ -1175,6 +1158,8 @@ init_reg_autoinc (void)
m = (enum machine_mode) ((int) m + 1))
if (HARD_REGNO_MODE_OK (j, m))
{
+ enum reg_class base_class = MODE_BASE_REG_CLASS (VOIDmode);
+
PUT_MODE (r, m);
/* If a register is not directly suitable for an
@@ -1182,21 +1167,8 @@ init_reg_autoinc (void)
requires secondary reloads, disallow its class from
being used in such addresses. */
- if ((0
-#ifdef SECONDARY_RELOAD_CLASS
- || (SECONDARY_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
- != NO_REGS)
-#else
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- || (SECONDARY_INPUT_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
- != NO_REGS)
-#endif
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- || (SECONDARY_OUTPUT_RELOAD_CLASS (MODE_BASE_REG_CLASS (VOIDmode), m, r)
- != NO_REGS)
-#endif
-#endif
- )
+ if ((secondary_reload_class (1, base_class, m, r)
+ || secondary_reload_class (1, base_class, m, r))
&& ! auto_inc_dec_reg_p (r, m))
forbidden_inc_dec_class[i] = 1;
}
@@ -1900,15 +1872,8 @@ copy_cost (rtx x, enum machine_mode mode
cost is that to load the input into the intermediate register, then
to copy them. We use a special value of TO_P to avoid recursion. */
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- if (to_p == 1)
- secondary_class = SECONDARY_INPUT_RELOAD_CLASS (class, mode, x);
-#endif
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- if (! to_p)
- secondary_class = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, x);
-#endif
+ if (to_p == 1 || ! to_p)
+ secondary_class = secondary_reload_class (to_p, class, mode, x);
if (secondary_class != NO_REGS)
return (move_cost[mode][(int) secondary_class][(int) class]
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload1.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload1.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload1.c 2005-09-07 08:52:48.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload1.c 2005-10-03 23:48:28.000000000 +0100
@@ -43,6 +43,7 @@ Software Foundation, 51 Franklin Street,
#include "toplev.h"
#include "except.h"
#include "tree.h"
+#include "target.h"
/* This file contains the reload pass of the compiler, which is
run after register allocation has been done. It checks that
@@ -5496,9 +5497,9 @@ choose_reload_regs (struct insn_chain *c
enough. */
|| ((REGISTER_MOVE_COST (mode, last_class, class)
< MEMORY_MOVE_COST (mode, class, 1))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- && (SECONDARY_INPUT_RELOAD_CLASS (class, mode,
- last_reg)
+#ifdef HAVE_SECONDARY_RELOADS
+ && (secondary_reload_class (1, class, mode,
+ last_reg)
== NO_REGS)
#endif
#ifdef SECONDARY_MEMORY_NEEDED
@@ -6209,7 +6210,7 @@ emit_input_reload_insns (struct insn_cha
if (mode == VOIDmode)
mode = rl->inmode;
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
/* If we need a secondary register for this operation, see if
the value is already in a register in that class. Don't
do this if the secondary register will be used as a scratch
@@ -6259,9 +6260,8 @@ emit_input_reload_insns (struct insn_cha
&& (REGISTER_MOVE_COST (mode, REGNO_REG_CLASS (regno),
rl->class)
>= MEMORY_MOVE_COST (mode, rl->class, 1)))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- || (SECONDARY_INPUT_RELOAD_CLASS (rl->class,
- mode, oldequiv)
+#ifdef HAVE_SECONDARY_RELOADS
+ || (secondary_reload_class (1, rl->class, mode, oldequiv)
!= NO_REGS)
#endif
#ifdef SECONDARY_MEMORY_NEEDED
@@ -6449,7 +6449,7 @@ emit_input_reload_insns (struct insn_cha
/* We can't do that, so output an insn to load RELOADREG. */
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
/* If we have a secondary reload, pick up the secondary register
and icode, if any. If OLDEQUIV and OLD are different or
if this is an in-out reload, recompute whether or not we
@@ -6521,24 +6521,52 @@ emit_input_reload_insns (struct insn_cha
if ((old != oldequiv && ! rtx_equal_p (old, oldequiv))
|| (rl->in != 0 && rl->out != 0))
{
- enum reg_class new_class
- = SECONDARY_INPUT_RELOAD_CLASS (rl->class,
- mode, real_oldequiv);
+ secondary_reload_info sri;
+ enum reg_class new_class;
- if (new_class == NO_REGS)
+ sri.icode = CODE_FOR_nothing;
+ new_class = targetm.secondary_reload (1, real_oldequiv, rl->class,
+ mode, &sri);
+
+ if (new_class == NO_REGS && sri.icode == CODE_FOR_nothing)
second_reload_reg = 0;
else
{
- enum insn_code new_icode;
+ enum insn_code new_icode = sri.icode;
enum machine_mode new_mode;
+ const char *constraint;
+ char letter;
+
+ /* ??? The old code incorrectly assumed that the
+ SECONDARY_RELOAD_CLASS will always return the scratch
+ register, and that there was no problem with matching the
+ constraint of operand[0]. */
+ if (insn_data[(int) icode].n_operands != 3)
+ goto failure;
+ constraint = &insn_data[(int) new_icode].operand[0].constraint[1];
+ if (*constraint == '&')
+ constraint++;
+ new_class = (t_letter == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
+ constraint));
+ if (! TEST_HARD_REG_BIT (reg_class_contents[(int) new_class],
+ REGNO (rl->reg_rtx)))
+ constraint = &insn_data[(int) new_icode].operand[2].constraint[1];
+ if (*constraint == '&')
+ constraint++;
+ letter = *constraint;
+ new_class = (t_letter == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
+ constraint));
if (! TEST_HARD_REG_BIT (reg_class_contents[(int) new_class],
REGNO (second_reload_reg)))
+ failure:
oldequiv = old, real_oldequiv = real_old;
else
{
- new_icode = reload_in_optab[(int) mode];
if (new_icode != CODE_FOR_nothing
+ /* ??? md.texi says this does not exist. */
&& ((insn_data[(int) new_icode].operand[0].predicate
&& ! ((*insn_data[(int) new_icode].operand[0].predicate)
(reloadreg, mode)))
@@ -6554,6 +6582,8 @@ emit_input_reload_insns (struct insn_cha
if (GET_MODE (second_reload_reg) != new_mode)
{
+ /* ??? should check HARD_REGNO_NREGS if NEW_MODE will
+ need more hard registers than we have. */
if (!HARD_REGNO_MODE_OK (REGNO (second_reload_reg),
new_mode))
oldequiv = old, real_oldequiv = real_old;
@@ -6682,7 +6712,7 @@ emit_output_reload_insns (struct insn_ch
if (GET_MODE (reloadreg) != mode)
reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
/* If we need two reload regs, set RELOADREG to the intermediate
one, since it will be stored into OLD. We might need a secondary
@@ -6696,9 +6726,7 @@ emit_output_reload_insns (struct insn_ch
&& reg_equiv_mem[REGNO (old)] != 0)
real_old = reg_equiv_mem[REGNO (old)];
- if ((SECONDARY_OUTPUT_RELOAD_CLASS (rl->class,
- mode, real_old)
- != NO_REGS))
+ if (secondary_reload_class (0, rl->class, mode, real_old) != NO_REGS)
{
rtx second_reloadreg = reloadreg;
reloadreg = rld[rl->secondary_out_reload].reg_rtx;
Only in /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc: reload1.c-20050930-2225
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.c 2005-08-05 17:06:35.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.c 2005-10-03 23:02:11.000000000 +0100
@@ -301,6 +301,7 @@ push_secondary_reload (int in_p, rtx x,
enum insn_code *picode)
{
enum reg_class class = NO_REGS;
+ enum reg_class scratch_class;
enum machine_mode mode = reload_mode;
enum insn_code icode = CODE_FOR_nothing;
enum reg_class t_class = NO_REGS;
@@ -308,6 +309,9 @@ push_secondary_reload (int in_p, rtx x,
enum insn_code t_icode = CODE_FOR_nothing;
enum reload_type secondary_type;
int s_reload, t_reload = -1;
+ const char *insn_constraint;
+ char insn_letter;
+ secondary_reload_info sri;
if (type == RELOAD_FOR_INPUT_ADDRESS
|| type == RELOAD_FOR_OUTPUT_ADDRESS
@@ -339,31 +343,14 @@ push_secondary_reload (int in_p, rtx x,
&& reg_equiv_mem[REGNO (x)] != 0)
x = reg_equiv_mem[REGNO (x)];
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- if (in_p)
- class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
-#endif
-
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- if (! in_p)
- class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);
-#endif
+ sri.icode == CODE_FOR_nothing;
+ class = targetm.secondary_reload (in_p, x, reload_class, reload_mode, &sri);
+ icode = sri.icode;
/* If we don't need any secondary registers, done. */
- if (class == NO_REGS)
+ if (class == NO_REGS && icode == CODE_FOR_nothing)
return -1;
- /* Get a possible insn to use. If the predicate doesn't accept X, don't
- use the insn. */
-
- icode = (in_p ? reload_in_optab[(int) reload_mode]
- : reload_out_optab[(int) reload_mode]);
-
- if (icode != CODE_FOR_nothing
- && insn_data[(int) icode].operand[in_p].predicate
- && (! (insn_data[(int) icode].operand[in_p].predicate) (x, reload_mode)))
- icode = CODE_FOR_nothing;
-
/* If we will be using an insn, see if it can directly handle the reload
register we will be using. If it can, the secondary reload is for a
scratch register. If it can't, we will use the secondary reload for
@@ -379,40 +366,60 @@ push_secondary_reload (int in_p, rtx x,
enum reg_class insn_class;
- if (insn_data[(int) icode].operand[!in_p].constraint[0] == 0)
+ /* ??? It would be useful to be able to handle only two, or more than
+ three, operands, but for now we can only handle the case of having
+ exactly three: output, input and one temp/scratch. */
+ gcc_assert (insn_data[(int) icode].n_operands == 3);
+
+ insn_constraint = insn_data[(int) icode].operand[!in_p].constraint;
+ if (!*insn_constraint)
insn_class = ALL_REGS;
else
{
- const char *insn_constraint
- = &insn_data[(int) icode].operand[!in_p].constraint[in_p];
- char insn_letter = *insn_constraint;
+ if (in_p)
+ {
+ gcc_assert (*insn_constraint == '=');
+ insn_constraint++;
+ }
+ insn_letter = *insn_constraint;
insn_class
= (insn_letter == 'r' ? GENERAL_REGS
: REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
insn_constraint));
gcc_assert (insn_class != NO_REGS);
- gcc_assert (!in_p
- || insn_data[(int) icode].operand[!in_p].constraint[0]
- == '=');
}
- /* The scratch register's constraint must start with "=&". */
- gcc_assert (insn_data[(int) icode].operand[2].constraint[0] == '='
- && insn_data[(int) icode].operand[2].constraint[1] == '&');
+ insn_constraint = insn_data[(int) icode].operand[2].constraint;
+ gcc_assert (*insn_constraint == '=');
+ insn_constraint++;
+ if (*insn_constraint == '&')
+ insn_constraint++;
+ insn_letter = *insn_constraint;
+ scratch_class = (insn_letter == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+ insn_constraint));
- if (reg_class_subset_p (reload_class, insn_class))
- mode = insn_data[(int) icode].operand[2].mode;
+ /* ??? If insn_data[(int) icode].operand[!in_p].constraint denotes a
+ register class, and X doesn't match that class, we should recurse. */
+
+ if (class == NO_REGS && reg_class_subset_p (reload_class, insn_class))
+ {
+ class = scratch_class;
+ mode = insn_data[(int) icode].operand[2].mode;
+ }
else
{
- const char *t_constraint
- = &insn_data[(int) icode].operand[2].constraint[2];
- char t_letter = *t_constraint;
- class = insn_class;
+ if (class == NO_REGS)
+ class = insn_class;
+ else
+ {
+ /* ??? We should push another reload if the classes
+ don't match. */
+ gcc_assert (reg_class_subset_p (class, insn_class));
+ }
t_mode = insn_data[(int) icode].operand[2].mode;
- t_class = (t_letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) t_letter,
- t_constraint));
+ t_class = scratch_class;
t_icode = icode;
icode = CODE_FOR_nothing;
}
@@ -581,6 +588,35 @@ push_secondary_reload (int in_p, rtx x,
*picode = icode;
return s_reload;
}
+
+enum reg_class
+secondary_reload_class (int in_p, enum reg_class class,
+ enum machine_mode mode, rtx x)
+{
+ enum insn_code icode;
+ const char *insn_constraint;
+ char insn_letter;
+ secondary_reload_info sri;
+
+ sri.icode = CODE_FOR_nothing;
+ class = targetm.secondary_reload (in_p, x, class, mode, &sri);
+ icode = sri.icode;
+
+ if (icode == CODE_FOR_nothing || class != NO_REGS)
+ return class;
+
+ gcc_assert (insn_data[(int) icode].n_operands >= 3);
+ insn_constraint = insn_data[(int) icode].operand[2].constraint;
+ gcc_assert (*insn_constraint == '=');
+ insn_constraint++;
+ if (*insn_constraint == '&')
+ insn_constraint++;
+ insn_letter = *insn_constraint;
+ if (insn_letter == 'r')
+ return GENERAL_REGS;
+ return REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+ insn_constraint);
+}
#endif /* HAVE_SECONDARY_RELOADS */
#ifdef SECONDARY_MEMORY_NEEDED
@@ -1058,11 +1094,10 @@ push_reload (rtx in, rtx out, rtx *inloc
!= (int) hard_regno_nregs[REGNO (SUBREG_REG (in))]
[GET_MODE (SUBREG_REG (in))]))
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
- || (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
- && (SECONDARY_INPUT_RELOAD_CLASS (class,
- GET_MODE (SUBREG_REG (in)),
- SUBREG_REG (in))
+#ifdef HAVE_SECONDARY_RELOADS
+ || (secondary_reload_class (1, class, inmode, in) != NO_REGS
+ && (secondary_reload_class (1, class, GET_MODE (SUBREG_REG (in)),
+ SUBREG_REG (in))
== NO_REGS))
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1154,11 +1189,10 @@ push_reload (rtx in, rtx out, rtx *inloc
!= (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
[GET_MODE (SUBREG_REG (out))]))
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- || (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
- && (SECONDARY_OUTPUT_RELOAD_CLASS (class,
- GET_MODE (SUBREG_REG (out)),
- SUBREG_REG (out))
+#ifdef HAVE_SECONDARY_RELOADS
+ || (secondary_reload_class (0, class, outmode, out) != NO_REGS
+ && (secondary_reload_class (0, class, GET_MODE (SUBREG_REG (out)),
+ SUBREG_REG (out))
== NO_REGS))
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1310,14 +1344,14 @@ push_reload (rtx in, rtx out, rtx *inloc
and IN or CLASS and OUT. Get the icode and push any required reloads
needed for each of them if so. */
-#ifdef SECONDARY_INPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
if (in != 0)
secondary_in_reload
= push_secondary_reload (1, in, opnum, optional, class, inmode, type,
&secondary_in_icode);
#endif
-#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+#ifdef HAVE_SECONDARY_RELOADS
if (out != 0 && GET_CODE (out) != SCRATCH)
secondary_out_reload
= push_secondary_reload (0, out, opnum, optional, class, outmode,
Binary files /mnt/scratch/nightly/2005-09-28/gcc/gcc/.reload.c.swp and /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/.reload.c.swp differ
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/reload.h 2005-06-25 03:00:54.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/reload.h 2005-10-03 21:14:51.000000000 +0100
@@ -247,11 +247,20 @@ extern struct insn_chain *reload_insn_ch
/* Allocate a new insn_chain structure. */
extern struct insn_chain *new_insn_chain (void);
+/* The struct used by the secondary_reload target hook. */
+struct secondary_reload_info
+{
+ enum machine_mode *icode;
+} secondary_reload_info;
+
extern void compute_use_by_pseudos (HARD_REG_SET *, regset);
#endif
/* Functions from reload.c: */
+extern enum reg_class secondary_reload_class (int, enum reg_class,
+ enum machine_mode, rtx);
+
/* Return a memory location that will be used to copy X in mode MODE.
If we haven't already made a location for this mode in this insn,
call find_reloads_address on the location being returned. */
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/target-def.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target-def.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/target-def.h 2005-08-24 08:13:07.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target-def.h 2005-10-03 21:11:53.000000000 +0100
@@ -474,6 +474,10 @@ Foundation, 51 Franklin Street, Fifth Fl
#define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 0
#endif
+#ifndef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD default_secondary_reload
+#endif
+
/* C++ specific. */
#ifndef TARGET_CXX_GUARD_TYPE
@@ -597,6 +601,7 @@ Foundation, 51 Franklin Street, Fifth Fl
TARGET_INVALID_CONVERSION, \
TARGET_INVALID_UNARY_OP, \
TARGET_INVALID_BINARY_OP, \
+ TARGET_SECONDARY_RELOAD, \
TARGET_CXX, \
TARGET_UNWIND_TABLES_DEFAULT, \
TARGET_HAVE_NAMED_SECTIONS, \
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/target.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/target.h 2005-07-14 08:39:55.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/target.h 2005-10-03 21:12:51.000000000 +0100
@@ -622,6 +622,11 @@ struct gcc_target
is not permitted on TYPE1 and TYPE2, NULL otherwise. */
const char *(*invalid_binary_op) (int op, tree type1, tree type2);
+ /* Return the class for a secondary reload, and fill in extra information. */
+ enum reg_class (*secondary_reload) (int, rtx, enum reg_class,
+ enum machine_mode,
+ struct secondary_reload_info *);
+
/* Functions specific to the C++ frontend. */
struct cxx {
/* Return the integer type used for guard variables. */
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.c /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.c
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.c 2005-07-14 08:39:55.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.c 2005-10-03 22:34:57.000000000 +0100
@@ -62,6 +62,8 @@ Software Foundation, 51 Franklin Street,
#include "tm_p.h"
#include "target-def.h"
#include "ggc.h"
+#include "reload.h"
+#include "insn-codes.h"
void
@@ -439,4 +441,78 @@ default_function_value (tree ret_type AT
#endif
}
+enum reg_class
+default_secondary_reload (int in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
+ enum reg_class reload_class ATTRIBUTE_UNUSED,
+ enum machine_mode reload_mode ATTRIBUTE_UNUSED
+ secondary_reload_info *sri)
+{
+ enum reg_class class = NO_REGS;
+
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+ if (in_p)
+ class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
+#endif
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+ if (! in_p)
+ class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x);
+#endif
+ if (class != NO_REGS)
+ {
+ enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode]
+ : reload_out_optab[(int) reload_mode]);
+
+ if (icode != CODE_FOR_nothing
+ && insn_data[(int) icode].operand[in_p].predicate
+ && ! insn_data[(int) icode].operand[in_p].predicate (x, reload_mode))
+ icode = CODE_FOR_nothing;
+ else if (icode != CODE_FOR_nothing)
+ {
+ const char *insn_constraint;
+ char insn_letter;
+ enum reg_class insn_class, scratch_class;
+
+ gcc_assert (insn_data[(int) icode].n_operands == 3);
+ sri->icode = icode;
+ insn_constraint = insn_data[(int) icode].operand[2].constraint;
+ if (!*insn_constraint)
+ insn_class = ALL_REGS;
+ else
+ {
+ if (in_p)
+ {
+ gcc_assert (*insn_constraint == '=');
+ insn_constraint++;
+ }
+ insn_letter = *insn_constraint;
+ insn_class
+ = (insn_letter == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+ insn_constraint));
+ gcc_assert (insn_class != NO_REGS);
+ }
+
+ insn_constraint = insn_data[(int) icode].operand[2].constraint;
+ /* The scratch register's constraint must start with "=&". */
+ gcc_assert (insn_constraint[0] == '=' && insn_constraint[1] == '&');
+ insn_constraint += 2;
+ insn_letter = *insn_constraint;
+ scratch_class
+ = (insn_letter == 'r' ? GENERAL_REGS
+ : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter,
+ insn_constraint));
+
+ if (reg_class_subset_p (reload_class, insn_class))
+ {
+ gcc_assert (scratch_class == class);
+ class = NO_REGS;
+ }
+ else
+ class = insn_class;
+
+ }
+ }
+ return class;
+}
+
#include "gt-targhooks.h"
diff -pur /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.h /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.h
--- /mnt/scratch/nightly/2005-09-28/gcc/gcc/targhooks.h 2005-07-14 08:39:56.000000000 +0100
+++ /mnt/scratch/nightly/2005-09-28-2nd-reload/gcc/gcc/targhooks.h 2005-10-03 21:16:17.000000000 +0100
@@ -68,4 +68,7 @@ extern const char *hook_invalid_arg_for_
(tree, tree, tree);
extern bool hook_bool_rtx_commutative_p (rtx, int);
extern rtx default_function_value (tree, tree, bool);
+extern enum reg_class default_secondary_reload (int, rtx, enum reg_class,
+ enum machine_mode,
+ secondary_reload_info *);