mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-23 01:20:31 +08:00
combine.c (subst): Use CLASS_CANNOT_CHANGE_MODE and CLASS_CANNOT_CHANGE_MODE_P instead of...
* 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. From-SVN: r34526
This commit is contained in:
parent
d805809112
commit
02188693ed
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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: \
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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
|
||||
|
16
gcc/flow.c
16
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
|
||||
|
12
gcc/global.c
12
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
|
||||
)
|
||||
|
@ -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
|
||||
|
10
gcc/recog.c
10
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
10
gcc/regs.h
10
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. */
|
||||
|
||||
|
24
gcc/reload.c
24
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
|
||||
))
|
||||
{
|
||||
|
@ -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)
|
||||
|
20
gcc/tm.texi
20
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user