diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-06-13 21:47:44 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-06-13 21:47:44 +0000 |
commit | c5af420ec97dd94ae5687cdba874f25f64cd6660 (patch) | |
tree | 18a58d10aaf4181b83524ed496b484df5ceed88e /gcc | |
parent | d2a6ef1c68ee7ca2c078facde9bf04ec194f12a4 (diff) | |
download | gcc-c5af420ec97dd94ae5687cdba874f25f64cd6660.tar.gz |
* combine.c (subst): Use CLASS_CANNOT_CHANGE_MODE and
CLASS_CANNOT_CHANGE_MODE_P instead of CLASS_CANNOT_CHANGE_SIZE
and hard-coded tests.
(simplify_set): Likewise.
(gen_lowpart_for_combine): Likewise.
* emit-rtl.c (gen_lowpart_common): Likewise.
* global.c (find_reg): Likewise.
* local-alloc.c (find_free_reg): Likewise.
* recog.c (register_operand): Likewise.
* regclass.c (init_reg_sets_1): Likewise.
(record_operand_costs, regclass): Likewise.
* reload.c (push_reload): Likewise.
* reload1.c (choose_reload_regs): Likewise.
* flow.c (mark_used_regs): Conditionally set REG_CHANGES_MODE.
* local-alloc.c (struct qty): Rename changes_size to changes_mode.
Update all references.
* regs.h (struct reg_info_def): Likewise.
(REG_CHANGES_MODE): Rename from REG_CHANGES_SIZE.
* tm.texi (CLASS_CANNOT_CHANGE_MODE): Document.
(CLASS_CANNOT_CHANGE_MODE_P): Likewise.
* config/alpha/alpha.h (CLASS_CANNOT_CHANGE_MODE): Rename.
(CLASS_CANNOT_CHANGE_MODE_P): New.
* config/mips/mips.h: Likewise.
* config/pa/pa32-regs.h: Likewise.
* config/pa/pa64-regs.h: Likewise.
* config/rs6000/rs6000.h: Likewise.
* config/sh/sh.h: Likewise.
* config/ia64/ia64.h (CLASS_CANNOT_CHANGE_MODE): New.
(CLASS_CANNOT_CHANGE_MODE_P): New.
* config/avr/avr.h (CLASS_CANNOT_CHANGE_SIZE): Remove dead code.
* config/d30v/d30v.h: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34526 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/combine.c | 24 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 9 | ||||
-rw-r--r-- | gcc/config/avr/avr.h | 16 | ||||
-rw-r--r-- | gcc/config/d30v/d30v.h | 11 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 9 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 9 | ||||
-rw-r--r-- | gcc/config/pa/pa32-regs.h | 6 | ||||
-rw-r--r-- | gcc/config/pa/pa64-regs.h | 10 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 9 | ||||
-rw-r--r-- | gcc/config/sh/sh.h | 9 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 6 | ||||
-rw-r--r-- | gcc/flow.c | 16 | ||||
-rw-r--r-- | gcc/global.c | 12 | ||||
-rw-r--r-- | gcc/local-alloc.c | 18 | ||||
-rw-r--r-- | gcc/recog.c | 10 | ||||
-rw-r--r-- | gcc/regclass.c | 52 | ||||
-rw-r--r-- | gcc/regs.h | 10 | ||||
-rw-r--r-- | gcc/reload.c | 24 | ||||
-rw-r--r-- | gcc/reload1.c | 17 | ||||
-rw-r--r-- | gcc/tm.texi | 20 |
21 files changed, 201 insertions, 131 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6d1decfffa8..d91bbe864a2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2000-06-13 Richard Henderson <rth@cygnus.com> + + * combine.c (subst): Use CLASS_CANNOT_CHANGE_MODE and + CLASS_CANNOT_CHANGE_MODE_P instead of CLASS_CANNOT_CHANGE_SIZE + and hard-coded tests. + (simplify_set): Likewise. + (gen_lowpart_for_combine): Likewise. + * emit-rtl.c (gen_lowpart_common): Likewise. + * global.c (find_reg): Likewise. + * local-alloc.c (find_free_reg): Likewise. + * recog.c (register_operand): Likewise. + * regclass.c (init_reg_sets_1): Likewise. + (record_operand_costs, regclass): Likewise. + * reload.c (push_reload): Likewise. + * reload1.c (choose_reload_regs): Likewise. + * flow.c (mark_used_regs): Conditionally set REG_CHANGES_MODE. + * local-alloc.c (struct qty): Rename changes_size to changes_mode. + Update all references. + * regs.h (struct reg_info_def): Likewise. + (REG_CHANGES_MODE): Rename from REG_CHANGES_SIZE. + * tm.texi (CLASS_CANNOT_CHANGE_MODE): Document. + (CLASS_CANNOT_CHANGE_MODE_P): Likewise. + + * config/alpha/alpha.h (CLASS_CANNOT_CHANGE_MODE): Rename. + (CLASS_CANNOT_CHANGE_MODE_P): New. + * config/mips/mips.h: Likewise. + * config/pa/pa32-regs.h: Likewise. + * config/pa/pa64-regs.h: Likewise. + * config/rs6000/rs6000.h: Likewise. + * config/sh/sh.h: Likewise. + * config/ia64/ia64.h (CLASS_CANNOT_CHANGE_MODE): New. + (CLASS_CANNOT_CHANGE_MODE_P): New. + * config/avr/avr.h (CLASS_CANNOT_CHANGE_SIZE): Remove dead code. + * config/d30v/d30v.h: Likewise. + 2000-06-13 J. David Anglin <dave@hiauly1.hia.nrc.ca> * configure.in: Add AC_TYPE_GETGROUPS test. diff --git a/gcc/combine.c b/gcc/combine.c index 8d7cadccbb7..6010cb7905c 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -3400,15 +3400,15 @@ subst (x, from, to, in_dest, unique_copy) ) return gen_rtx_CLOBBER (VOIDmode, const0_rtx); -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE if (code == SUBREG && GET_CODE (to) == REG && REGNO (to) < FIRST_PSEUDO_REGISTER && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], REGNO (to))) - && (GET_MODE_BITSIZE (GET_MODE (to)) - != GET_MODE_BITSIZE (GET_MODE (x)))) + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to), + GET_MODE (x))) return gen_rtx_CLOBBER (VOIDmode, const0_rtx); #endif @@ -5036,13 +5036,13 @@ simplify_set (x) && (GET_MODE_SIZE (GET_MODE (src)) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))) #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], REGNO (dest))) - && (GET_MODE_SIZE (GET_MODE (src)) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))) + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src), + GET_MODE (SUBREG_REG (src)))) #endif && (GET_CODE (dest) == REG || (GET_CODE (dest) == SUBREG @@ -9680,13 +9680,15 @@ gen_lowpart_for_combine (mode, x) } result = gen_lowpart_common (mode, x); +#ifdef CLASS_CANNOT_CHANGE_MODE if (result != 0 && GET_CODE (result) == SUBREG && GET_CODE (SUBREG_REG (result)) == REG && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER - && (GET_MODE_SIZE (GET_MODE (result)) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (result))))) - REG_CHANGES_SIZE (REGNO (SUBREG_REG (result))) = 1; + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result), + GET_MODE (SUBREG_REG (result)))) + REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1; +#endif if (result) return result; diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 45ebbd83f3f..0721392fcea 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -860,9 +860,14 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS, ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) /* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the size of the object. */ + operand of a SUBREG that changes the mode of the object illegally. */ -#define CLASS_CANNOT_CHANGE_SIZE FLOAT_REGS +#define CLASS_CANNOT_CHANGE_MODE FLOAT_REGS + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ + +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) /* Define the cost of moving between registers of various classes. Moving between FLOAT_REGS and anything else except float regs is expensive. diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index f459bc038da..b357af5372b 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -848,22 +848,6 @@ enum reg_class { This macro helps control the handling of multiple-word values in the reload pass. */ -#undef CLASS_CANNOT_CHANGE_SIZE -/* `CLASS_CANNOT_CHANGE_SIZE' - If defined, a C expression for a class that contains registers - which the compiler must always access in a mode that is the same - size as the mode in which it loaded the register. - - For the example, loading 32-bit integer or floating-point objects - into floating-point registers on the Alpha extends them to 64-bits. - Therefore loading a 64-bit object and then storing it as a 32-bit - object does not store the low-order 32-bits, as would be the case - for a normal register. Therefore, `alpha.h' defines this macro as - `FLOAT_REGS'. - - Three other special macros describe which operands fit which - constraint letters. */ - #define CONST_OK_FOR_LETTER_P(VALUE, C) \ ((C) == 'I' ? (VALUE) >= 0 && (VALUE) <= 63 : \ (C) == 'J' ? (VALUE) <= 0 && (VALUE) >= -63: \ diff --git a/gcc/config/d30v/d30v.h b/gcc/config/d30v/d30v.h index c97ff98032b..d4556293499 100644 --- a/gcc/config/d30v/d30v.h +++ b/gcc/config/d30v/d30v.h @@ -1759,17 +1759,6 @@ extern enum reg_class reg_class_from_letter[]; ? ((GET_MODE_SIZE (MODE) + 8 - 1) / 8) \ : ((GET_MODE_SIZE (MODE) + 4 - 1) / 4)) -/* If defined, a C expression for a class that contains registers which the - compiler must always access in a mode that is the same size as the mode in - which it loaded the register. - - For the example, loading 32-bit integer or floating-point objects into - floating-point registers on the Alpha extends them to 64-bits. Therefore - loading a 64-bit object and then storing it as a 32-bit object does not - store the low-order 32-bits, as would be the case for a normal register. - Therefore, `alpha.h' defines this macro as `FLOAT_REGS'. */ -/* #define CLASS_CANNOT_CHANGE_SIZE */ - /* A C expression that defines the machine-dependent operand constraint letters (`I', `J', `K', .. 'P') that specify particular ranges of integer values. If C is one of those letters, the expression should check that VALUE, an diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index cc5ba5b214d..522c9c7ba80 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -1046,6 +1046,15 @@ enum reg_class || (CLASS) == FR_INT_REGS) && (MODE) == XFmode) ? 1 \ : (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) +/* If defined, gives a class of registers that cannot be used as the + operand of a SUBREG that changes the mode of the object illegally. */ + +#define CLASS_CANNOT_CHANGE_MODE FR_REGS + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ + +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) 1 + /* A C expression that defines the machine-dependent operand constraint letters (`I', `J', `K', .. 'P') that specify particular ranges of integer values. */ diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 1ff81cbb2cd..e723dfc2a70 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2043,10 +2043,15 @@ extern enum reg_class mips_char_to_class[]; : CLASS_UNITS (MODE, UNITS_PER_WORD)) /* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the size of the object. */ + operand of a SUBREG that changes the mode of the object illegally. */ -#define CLASS_CANNOT_CHANGE_SIZE \ +#define CLASS_CANNOT_CHANGE_MODE \ (TARGET_FLOAT64 && ! TARGET_64BIT ? FP_REGS : NO_REGS) + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ + +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/config/pa/pa32-regs.h b/gcc/config/pa/pa32-regs.h index d201f0e009a..21442dbc234 100644 --- a/gcc/config/pa/pa32-regs.h +++ b/gcc/config/pa/pa32-regs.h @@ -243,7 +243,11 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS, /* This may not actually be necessary anymore. But until I can prove otherwise it will stay. */ -#define CLASS_CANNOT_CHANGE_SIZE NO_REGS +#define CLASS_CANNOT_CHANGE_MODE NO_REGS + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) /* The same information, inverted: Return the class number of the smallest class containing diff --git a/gcc/config/pa/pa64-regs.h b/gcc/config/pa/pa64-regs.h index 9d53adce920..a061d2f045c 100644 --- a/gcc/config/pa/pa64-regs.h +++ b/gcc/config/pa/pa64-regs.h @@ -229,9 +229,15 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS, {0x00000000, 0x10000000}, /* SHIFT_REGS */ \ {0xfffffffe, 0x1fffffff}} /* ALL_REGS */ -/* This may not actually be necessary anymore. But until I can prove +/* If defined, gives a class of registers that cannot be used as the + operand of a SUBREG that changes the mode of the object illegally. */ +/* ??? This may not actually be necessary anymore. But until I can prove otherwise it will stay. */ -#define CLASS_CANNOT_CHANGE_SIZE (FP_REGS) +#define CLASS_CANNOT_CHANGE_MODE (FP_REGS) + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) /* The same information, inverted: Return the class number of the smallest class containing diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 94f6c10fa68..fdbcb977dc9 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1134,9 +1134,14 @@ enum reg_class : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) /* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the size of the object. */ + operand of a SUBREG that changes the mode of the object illegally. */ -#define CLASS_CANNOT_CHANGE_SIZE FLOAT_REGS +#define CLASS_CANNOT_CHANGE_MODE FLOAT_REGS + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ + +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 6f14d3c5bed..981a802baa7 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -825,9 +825,14 @@ extern enum reg_class reg_class_from_letter[]; ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) /* If defined, gives a class of registers that cannot be used as the - operand of a SUBREG that changes the size of the object. */ + operand of a SUBREG that changes the mode of the object illegally. */ -#define CLASS_CANNOT_CHANGE_SIZE DF_REGS +#define CLASS_CANNOT_CHANGE_MODE DF_REGS + +/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */ + +#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \ + (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO)) /* Stack layout; function entry, exit and calling. */ diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index fcabed2e528..18a016ae041 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -737,12 +737,12 @@ gen_lowpart_common (mode, x) /* integrate.c can't handle parts of a return value register. */ && (! REG_FUNCTION_VALUE_P (x) || ! rtx_equal_function_value_matters) -#ifdef CLASS_CANNOT_CHANGE_SIZE - && ! (GET_MODE_SIZE (mode) != GET_MODE_SIZE (GET_MODE (x)) +#ifdef CLASS_CANNOT_CHANGE_MODE + && ! (CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (x)) && GET_MODE_CLASS (GET_MODE (x)) != MODE_COMPLEX_INT && GET_MODE_CLASS (GET_MODE (x)) != MODE_COMPLEX_FLOAT && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], REGNO (x)))) #endif /* We want to keep the stack, frame, and arg pointers diff --git a/gcc/flow.c b/gcc/flow.c index 0b6e78fecbf..2e2a79d42e8 100644 --- a/gcc/flow.c +++ b/gcc/flow.c @@ -5263,11 +5263,13 @@ mark_used_regs (pbi, x, cond, insn) break; case SUBREG: +#ifdef CLASS_CANNOT_CHANGE_MODE if (GET_CODE (SUBREG_REG (x)) == REG && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER - && (GET_MODE_SIZE (GET_MODE (x)) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) - REG_CHANGES_SIZE (REGNO (SUBREG_REG (x))) = 1; + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x), + GET_MODE (SUBREG_REG (x)))) + REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1; +#endif /* While we're here, optimize this case. */ x = SUBREG_REG (x); @@ -5310,12 +5312,14 @@ mark_used_regs (pbi, x, cond, insn) || GET_CODE (testreg) == SIGN_EXTRACT || GET_CODE (testreg) == SUBREG) { +#ifdef CLASS_CANNOT_CHANGE_MODE if (GET_CODE (testreg) == SUBREG && GET_CODE (SUBREG_REG (testreg)) == REG && REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER - && (GET_MODE_SIZE (GET_MODE (testreg)) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (testreg))))) - REG_CHANGES_SIZE (REGNO (SUBREG_REG (testreg))) = 1; + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)), + GET_MODE (testreg))) + REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1; +#endif /* Modifying a single register in an alternate mode does not use any of the old value. But these other diff --git a/gcc/global.c b/gcc/global.c index 3c615538643..4ad1e1967fb 100644 --- a/gcc/global.c +++ b/gcc/global.c @@ -999,10 +999,10 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying) IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts); -#ifdef CLASS_CANNOT_CHANGE_SIZE - if (REG_CHANGES_SIZE (allocno[num].reg)) +#ifdef CLASS_CANNOT_CHANGE_MODE + if (REG_CHANGES_MODE (allocno[num].reg)) IOR_HARD_REG_SET (used1, - reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]); + reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]); #endif /* Try each hard reg to see if it fits. Do this in two passes. @@ -1189,10 +1189,10 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying) /* Don't use a reg no good for this pseudo. */ && ! TEST_HARD_REG_BIT (used2, regno) && HARD_REGNO_MODE_OK (regno, mode) -#ifdef CLASS_CANNOT_CHANGE_SIZE - && ! (REG_CHANGES_SIZE (allocno[num].reg) +#ifdef CLASS_CANNOT_CHANGE_MODE + && ! (REG_CHANGES_MODE (allocno[num].reg) && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], regno))) #endif ) diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index bd6492980ea..e2c00bf8dec 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -140,10 +140,10 @@ struct qty short phys_reg; - /* Nonzero if this quantity has been used in a SUBREG that changes - its size. */ + /* Nonzero if this quantity has been used in a SUBREG in some + way that is illegal. */ - char changes_size; + char changes_mode; }; @@ -301,7 +301,7 @@ alloc_qty (regno, mode, size, birth) qty[qtyno].min_class = reg_preferred_class (regno); qty[qtyno].alternate_class = reg_alternate_class (regno); qty[qtyno].n_refs = REG_N_REFS (regno); - qty[qtyno].changes_size = REG_CHANGES_SIZE (regno); + qty[qtyno].changes_mode = REG_CHANGES_MODE (regno); } /* Main entry point of this file. */ @@ -1795,8 +1795,8 @@ update_qty_class (qtyno, reg) if (reg_class_subset_p (rclass, qty[qtyno].alternate_class)) qty[qtyno].alternate_class = rclass; - if (REG_CHANGES_SIZE (reg)) - qty[qtyno].changes_size = 1; + if (REG_CHANGES_MODE (reg)) + qty[qtyno].changes_mode = 1; } /* Handle something which alters the value of an rtx REG. @@ -1997,10 +1997,10 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested, SET_HARD_REG_BIT (used, FRAME_POINTER_REGNUM); #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE - if (qty[qtyno].changes_size) +#ifdef CLASS_CANNOT_CHANGE_MODE + if (qty[qtyno].changes_mode) IOR_HARD_REG_SET (used, - reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]); + reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]); #endif /* Normally, the registers that can be used for the first register in diff --git a/gcc/recog.c b/gcc/recog.c index 556f9f98b29..3b7dab35ff2 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1003,13 +1003,13 @@ register_operand (op, mode) if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM) return general_operand (op, mode); -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE if (GET_CODE (SUBREG_REG (op)) == REG && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER - && TEST_HARD_REG_BIT (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], - REGNO (SUBREG_REG (op))) - && (GET_MODE_SIZE (mode) - != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))) + && (TEST_HARD_REG_BIT + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], + REGNO (SUBREG_REG (op)))) + && CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (SUBREG_REG (op))) && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT) return 0; diff --git a/gcc/regclass.c b/gcc/regclass.c index a0781833c67..eb909d195a5 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -203,18 +203,20 @@ static char *in_inc_dec; #endif /* FORBIDDEN_INC_DEC_CLASSES */ -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE /* These are the classes containing only registers that can be used in - a SUBREG expression that changes the size of the register. */ + a SUBREG expression that changes the mode of the register in some + way that is illegal. */ -static int class_can_change_size[N_REG_CLASSES]; +static int class_can_change_mode[N_REG_CLASSES]; -/* Registers, including pseudos, which change size. */ +/* Registers, including pseudos, which change modes in some way that + is illegal. */ -static regset reg_changes_size; +static regset reg_changes_mode; -#endif /* CLASS_CANNOT_CHANGE_SIZE */ +#endif /* CLASS_CANNOT_CHANGE_MODE */ #ifdef HAVE_SECONDARY_RELOADS @@ -458,21 +460,21 @@ init_reg_sets_1 () may_move_out_cost[i][j] = cost; } -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE { HARD_REG_SET c; - COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_SIZE]); + COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]); for (i = 0; i < N_REG_CLASSES; i++) { GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class); - class_can_change_size [i] = 0; + class_can_change_mode [i] = 0; continue; ok_class: - class_can_change_size [i] = 1; + class_can_change_mode [i] = 1; } } -#endif /* CLASS_CANNOT_CHANGE_SIZE */ +#endif /* CLASS_CANNOT_CHANGE_MODE */ } /* Compute the table of register modes. @@ -860,10 +862,10 @@ record_operand_costs (insn, op_costs, reg_pref) if (GET_CODE (recog_data.operand[i]) == SUBREG) { rtx inner = SUBREG_REG (recog_data.operand[i]); -#ifdef CLASS_CANNOT_CHANGE_SIZE - if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)) - && GET_CODE (inner) == REG) - SET_REGNO_REG_SET (reg_changes_size, REGNO (inner)); +#ifdef CLASS_CANNOT_CHANGE_MODE + if (GET_CODE (inner) == REG + && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner))) + SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner)); #endif recog_data.operand[i] = inner; } @@ -1048,8 +1050,8 @@ regclass (f, nregs, dump) costs = (struct costs *) xmalloc (nregs * sizeof (struct costs)); -#ifdef CLASS_CANNOT_CHANGE_SIZE - reg_changes_size = BITMAP_XMALLOC(); +#ifdef CLASS_CANNOT_CHANGE_MODE + reg_changes_mode = BITMAP_XMALLOC(); #endif #ifdef FORBIDDEN_INC_DEC_CLASSES @@ -1190,9 +1192,9 @@ regclass (f, nregs, dump) #ifdef FORBIDDEN_INC_DEC_CLASSES || (in_inc_dec[i] && forbidden_inc_dec_class[class]) #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE - || (REGNO_REG_SET_P (reg_changes_size, i) - && ! class_can_change_size [class]) +#ifdef CLASS_CANNOT_CHANGE_MODE + || (REGNO_REG_SET_P (reg_changes_mode, i) + && ! class_can_change_mode [class]) #endif ) ; @@ -1220,9 +1222,9 @@ regclass (f, nregs, dump) #ifdef FORBIDDEN_INC_DEC_CLASSES && ! (in_inc_dec[i] && forbidden_inc_dec_class[class]) #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE - && ! (REGNO_REG_SET_P (reg_changes_size, i) - && ! class_can_change_size [class]) +#ifdef CLASS_CANNOT_CHANGE_MODE + && ! (REGNO_REG_SET_P (reg_changes_mode, i) + && ! class_can_change_mode [class]) #endif ) alt = reg_class_subunion[(int) alt][class]; @@ -1256,8 +1258,8 @@ regclass (f, nregs, dump) #ifdef FORBIDDEN_INC_DEC_CLASSES free (in_inc_dec); #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE - BITMAP_XFREE (reg_changes_size); +#ifdef CLASS_CANNOT_CHANGE_MODE + BITMAP_XFREE (reg_changes_mode); #endif free (costs); } diff --git a/gcc/regs.h b/gcc/regs.h index 9c1b886d864..c219ecc4e20 100644 --- a/gcc/regs.h +++ b/gcc/regs.h @@ -55,7 +55,8 @@ typedef struct reg_info_def int live_length; /* # of instructions (REG n) is live */ int calls_crossed; /* # of calls (REG n) is live across */ int basic_block; /* # of basic blocks (REG n) is used in */ - char changes_size; /* whether (SUBREG (REG n)) changes size */ + char changes_mode; /* whether (SUBREG (REG n)) exists and + is illegal. */ } reg_info; extern varray_type reg_n_info; @@ -80,10 +81,11 @@ extern varray_type reg_n_info; #define REG_N_DEATHS(N) (VARRAY_REG (reg_n_info, N)->deaths) /* Indexed by N; says whether a pseudo register N was ever used - within a SUBREG that changes the size of the reg. Some machines prohibit - such objects to be in certain (usually floating-point) registers. */ + within a SUBREG that changes the mode of the reg in some way + that is illegal for a given class (usually floating-point) + of registers. */ -#define REG_CHANGES_SIZE(N) (VARRAY_REG (reg_n_info, N)->changes_size) +#define REG_CHANGES_MODE(N) (VARRAY_REG (reg_n_info, N)->changes_mode) /* Get the number of consecutive words required to hold pseudo-reg N. */ diff --git a/gcc/reload.c b/gcc/reload.c index 0a6d14cd7e5..ce4811a7b40 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -908,8 +908,8 @@ push_reload (in, out, inloc, outloc, class, if (in != 0 && GET_CODE (in) == SUBREG && (SUBREG_WORD (in) == 0 || strict_low) -#ifdef CLASS_CANNOT_CHANGE_SIZE - && class != CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE + && class != CLASS_CANNOT_CHANGE_MODE #endif && (CONSTANT_P (SUBREG_REG (in)) || GET_CODE (SUBREG_REG (in)) == PLUS @@ -958,14 +958,14 @@ push_reload (in, out, inloc, outloc, class, SUBREG_REG (in)) == NO_REGS)) #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE || (GET_CODE (SUBREG_REG (in)) == REG && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], REGNO (SUBREG_REG (in)))) - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - != GET_MODE_SIZE (inmode))) + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), + inmode)) #endif )) { @@ -1026,8 +1026,8 @@ push_reload (in, out, inloc, outloc, class, and in that case the constraint should label it input-output.) */ if (out != 0 && GET_CODE (out) == SUBREG && (SUBREG_WORD (out) == 0 || strict_low) -#ifdef CLASS_CANNOT_CHANGE_SIZE - && class != CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE + && class != CLASS_CANNOT_CHANGE_MODE #endif && (CONSTANT_P (SUBREG_REG (out)) || strict_low @@ -1063,14 +1063,14 @@ push_reload (in, out, inloc, outloc, class, SUBREG_REG (out)) == NO_REGS)) #endif -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE || (GET_CODE (SUBREG_REG (out)) == REG && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER && (TEST_HARD_REG_BIT - (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE], + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], REGNO (SUBREG_REG (out)))) - && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - != GET_MODE_SIZE (outmode))) + && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)), + outmode)) #endif )) { diff --git a/gcc/reload1.c b/gcc/reload1.c index 6f73aeaf13a..4949b89362f 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -5305,20 +5305,25 @@ choose_reload_regs (chain) { enum reg_class class = rld[r].class, last_class; rtx last_reg = reg_last_reload_reg[regno]; + enum machine_mode need_mode; i = REGNO (last_reg) + word; last_class = REGNO_REG_CLASS (i); + + need_mode = smallest_mode_for_size ((word+1) * UNITS_PER_WORD, + GET_MODE_CLASS (mode)); + if ( -#ifdef CLASS_CANNOT_CHANGE_SIZE +#ifdef CLASS_CANNOT_CHANGE_MODE (TEST_HARD_REG_BIT - (reg_class_contents[CLASS_CANNOT_CHANGE_SIZE], i) - ? (GET_MODE_SIZE (GET_MODE (last_reg)) - == GET_MODE_SIZE (mode) + word * UNITS_PER_WORD) + (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i) + ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg), + need_mode) : (GET_MODE_SIZE (GET_MODE (last_reg)) - >= GET_MODE_SIZE (mode) + word * UNITS_PER_WORD)) + >= GET_MODE_SIZE (need_mode))) #else (GET_MODE_SIZE (GET_MODE (last_reg)) - >= GET_MODE_SIZE (mode) + word * UNITS_PER_WORD) + >= GET_MODE_SIZE (need_mode)) #endif && reg_reloaded_contents[i] == regno && TEST_HARD_REG_BIT (reg_reloaded_valid, i) diff --git a/gcc/tm.texi b/gcc/tm.texi index 4648778daf9..90e5e908fee 100644 --- a/gcc/tm.texi +++ b/gcc/tm.texi @@ -2088,17 +2088,25 @@ should be the maximum value of @code{HARD_REGNO_NREGS (@var{regno}, This macro helps control the handling of multiple-word values in the reload pass. -@item CLASS_CANNOT_CHANGE_SIZE -If defined, a C expression for a class that contains registers which the -compiler must always access in a mode that is the same size as the mode -in which it loaded the register. +@item CLASS_CANNOT_CHANGE_MODE +If defined, a C expression for a class that contains registers for +which the compiler may not change modes arbitrarily. + +@item CLASS_CANNOT_CHANGE_MODE_P(@var{from}, @var{to}) +A C expression that is true if, for a register in +@code{CLASS_CANNOT_CHANGE_MODE}, the requested mode punning is illegal. For the example, loading 32-bit integer or floating-point objects into floating-point registers on the Alpha extends them to 64-bits. Therefore loading a 64-bit object and then storing it as a 32-bit object does not store the low-order 32-bits, as would be the case for a normal -register. Therefore, @file{alpha.h} defines this macro as -@code{FLOAT_REGS}. +register. Therefore, @file{alpha.h} defines @code{CLASS_CANNOT_CHANGE_MODE} +as @code{FLOAT_REGS} and @code{CLASS_CANNOT_CHANGE_MODE_P} restricts +mode changes to same-size modes. + +Compare this to IA-64, which extends floating-point values to 82-bits, +and stores 64-bit integers in a different format than 64-bit doubles. +Therefore @code{CLASS_CANNOT_CHANGE_MODE_P} is always true. @end table Three other special macros describe which operands fit which constraint |