hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.

2002-11-04  Aldy Hernandez  <aldyh@redhat.com>

	* hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.

	* config/rs6000/rs6000.h (CLASS_CANNOT_CHANGE_MODE_P): Remove.
	(CLASS_CANNOT_CHANGE_MODE): Remove.
	(CANNOT_CHANGE_MODE_CLASS): New.

	* config/alpha/alpha.h: Same.

	* config/ia64/ia64.h: Same.

	* config/mips/mips.h: Same.

	* config/s390/s390.h: Same.

	* config/sh/sh.h: Same.

	* config/pa/pa64-regs.h: Same.

	* config/sh/sh-protos.h (sh_cannot_change_mode_class): Add prototype.

	* config/sh/sh.c (sh_cannot_change_mode_class): New.

	* config/mips/mips-protos.h (mips_cannot_change_mode_class): Add
	prototype.

	* config/mips/mips.c (mips_cannot_change_mode_class): New.

	* doc/tm.texi (Register Classes): Remove
	CLASS_CANNOT_CHANGE_MODE and CLASS_CANNOT_CHANGE_MODE_P.
	Document CANNOT_CHANGE_MODE_CLASS.

	* reload.c (push_reload): Use CANNOT_CHANGE_MODE_CLASS.
	(push_reload): Same.

	* simplify-rtx.c (simplify_subreg): Same.

	* reload1.c (choose_reload_regs): Same.

	* recog.c (register_operand): Same.

	* regrename.c (mode_change_ok): Change to use new
	CANNOT_CHANGE_MODE_CLASS infrastructure.

	* regclass.c (cannot_change_mode_set_regs): New.
	Declare subregs_of_mode.
	(regclass): Use subregs_of_mode.
	Remove references to reg_changes_mode.
	(init_reg_sets_1): Remove class_can_change_mode and
	reg_changes_mode code.
	(invalid_mode_change_p): New.
	(dump_regclass): Use invalid_mode_change_p instead of
	class_can_change_mode.
	(regclass): Same.
	(record_operand_costs): Do not set reg_changes_mode.

	* local-alloc.c (struct qty): Remove changes_mode field.
	(alloc_qty): Remove changes_mode initialization.
	(update_qty_class): Remove set of changes_mode.
	(find_free_reg): Use subregs_of_mode.

	* global.c (find_reg): Use subregs_of_mode info.

	* rtl.h (cannot_change_mode_set_regs): New prototype.
	(invalid_mode_change_p): Same.
	(REG_CANNOT_CHANGE_MODE_P): New macro.

	* flow.c (mark_used_regs): Calculate subregs_of_mode.  Remove
	REG_CHANGES_MODE.
	(life_analysis): Clear subregs_of_mode.

	* combine.c (subst): Pass class to CLASS_CANNOT_CHANGE_MODE_P.
	Remove use of CLASS_CANNOT_CHANGE_MODE.
	(simplify_set): Same.
	(gen_lowpart_for_combine): Calculate subregs_of_mode.  Remove
	REG_CHANGES_MODE.

	* regs.h: Add extern for subregs_of_mode;
	Include hard-reg-set and basic-block.
	(REG_CHANGES_MODE): Delete.

From-SVN: r58794
This commit is contained in:
Aldy Hernandez 2002-11-04 16:58:39 +00:00 committed by Aldy Hernandez
parent f1c129e309
commit cff9f8d509
26 changed files with 304 additions and 233 deletions

View File

@ -1,3 +1,85 @@
2002-11-04 Aldy Hernandez <aldyh@redhat.com>
* hard-reg-set.h (REG_CANNOT_CHANGE_MODE_P): New.
* config/rs6000/rs6000.h (CLASS_CANNOT_CHANGE_MODE_P): Remove.
(CLASS_CANNOT_CHANGE_MODE): Remove.
(CANNOT_CHANGE_MODE_CLASS): New.
* config/alpha/alpha.h: Same.
* config/ia64/ia64.h: Same.
* config/mips/mips.h: Same.
* config/s390/s390.h: Same.
* config/sh/sh.h: Same.
* config/pa/pa64-regs.h: Same.
* config/sh/sh-protos.h (sh_cannot_change_mode_class): Add prototype.
* config/sh/sh.c (sh_cannot_change_mode_class): New.
* config/mips/mips-protos.h (mips_cannot_change_mode_class): Add
prototype.
* config/mips/mips.c (mips_cannot_change_mode_class): New.
* doc/tm.texi (Register Classes): Remove
CLASS_CANNOT_CHANGE_MODE and CLASS_CANNOT_CHANGE_MODE_P.
Document CANNOT_CHANGE_MODE_CLASS.
* reload.c (push_reload): Use CANNOT_CHANGE_MODE_CLASS.
(push_reload): Same.
* simplify-rtx.c (simplify_subreg): Same.
* reload1.c (choose_reload_regs): Same.
* recog.c (register_operand): Same.
* regrename.c (mode_change_ok): Change to use new
CANNOT_CHANGE_MODE_CLASS infrastructure.
* regclass.c (cannot_change_mode_set_regs): New.
Declare subregs_of_mode.
(regclass): Use subregs_of_mode.
Remove references to reg_changes_mode.
(init_reg_sets_1): Remove class_can_change_mode and
reg_changes_mode code.
(invalid_mode_change_p): New.
(dump_regclass): Use invalid_mode_change_p instead of
class_can_change_mode.
(regclass): Same.
(record_operand_costs): Do not set reg_changes_mode.
* local-alloc.c (struct qty): Remove changes_mode field.
(alloc_qty): Remove changes_mode initialization.
(update_qty_class): Remove set of changes_mode.
(find_free_reg): Use subregs_of_mode.
* global.c (find_reg): Use subregs_of_mode info.
* rtl.h (cannot_change_mode_set_regs): New prototype.
(invalid_mode_change_p): Same.
(REG_CANNOT_CHANGE_MODE_P): New macro.
* flow.c (mark_used_regs): Calculate subregs_of_mode. Remove
REG_CHANGES_MODE.
(life_analysis): Clear subregs_of_mode.
* combine.c (subst): Pass class to CLASS_CANNOT_CHANGE_MODE_P.
Remove use of CLASS_CANNOT_CHANGE_MODE.
(simplify_set): Same.
(gen_lowpart_for_combine): Calculate subregs_of_mode. Remove
REG_CHANGES_MODE.
* regs.h: Add extern for subregs_of_mode;
Include hard-reg-set and basic-block.
(REG_CHANGES_MODE): Delete.
2002-11-03 John David Anglin <dave@hiauly1.hia.nrc.ca>
* jump.c (never_reached_warning): Don't set contains_insn until the

View File

@ -3519,15 +3519,13 @@ subst (x, from, to, in_dest, unique_copy)
)
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
if (code == SUBREG
&& GET_CODE (to) == REG
&& REGNO (to) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (to)))
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
GET_MODE (x)))
&& REG_CANNOT_CHANGE_MODE_P (REGNO (to),
GET_MODE (to),
GET_MODE (x)))
return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
#endif
@ -5198,13 +5196,11 @@ simplify_set (x)
&& (GET_MODE_SIZE (GET_MODE (src))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (dest)))
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
GET_MODE (SUBREG_REG (src))))
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
GET_MODE (src),
GET_MODE (SUBREG_REG (src))))
#endif
&& (GET_CODE (dest) == REG
|| (GET_CODE (dest) == SUBREG
@ -9937,14 +9933,13 @@ gen_lowpart_for_combine (mode, x)
}
result = gen_lowpart_common (mode, x);
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
if (result != 0
&& GET_CODE (result) == SUBREG
&& GET_CODE (SUBREG_REG (result)) == REG
&& REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
GET_MODE (SUBREG_REG (result))))
REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
&& REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (result)],
REGNO (SUBREG_REG (result)));
#endif
if (result)

View File

@ -857,15 +857,10 @@ enum reg_class {
#define CLASS_MAX_NREGS(CLASS, MODE) \
((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. */
/* Return the class of registers that cannot change mode from FROM to TO. */
#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 CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS)
/* Define the cost of moving between registers of various classes. Moving
between FLOAT_REGS and anything else except float regs is expensive.

View File

@ -1008,17 +1008,11 @@ enum reg_class
: ((CLASS) == FR_REGS && (MODE) == TFmode) ? 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.
In FP regs, we can't change FP values to integer values and vice
/* In FP regs, we can't change FP values to integer values and vice
versa, but we can change e.g. DImode to SImode. */
#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
(GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO))
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
(GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) ? FR_REGS : NO_REGS)
/* A C expression that defines the machine-dependent operand constraint
letters (`I', `J', `K', .. 'P') that specify particular ranges of

View File

@ -122,6 +122,8 @@ extern int mips_adjust_insn_length PARAMS ((rtx, int));
extern enum reg_class mips_secondary_reload_class PARAMS ((enum reg_class,
enum machine_mode,
rtx, int));
extern enum reg_class mips_cannot_change_mode_class
PARAMS ((enum machine_mode, enum machine_mode));
extern int mips_class_max_nregs PARAMS ((enum reg_class,
enum machine_mode));
extern int mips_register_move_cost PARAMS ((enum machine_mode,

View File

@ -8399,6 +8399,23 @@ function_arg_pass_by_reference (cum, mode, type, named)
return size == -1 || size > UNITS_PER_WORD;
}
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
enum reg_class
mips_cannot_change_mode_class (from, to)
enum machine_mode from, to;
{
if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
{
if (TARGET_BIG_ENDIAN)
return FP_REGS;
if (TARGET_FLOAT64)
return HI_AND_FP_REGS;
return HI_REG;
}
return NO_REGS;
}
/* This function returns the register class required for a secondary
register when copying between one of the registers in CLASS, and X,
using MODE. If IN_P is nonzero, the copy is going from X to the

View File

@ -2343,14 +2343,8 @@ extern enum reg_class mips_char_to_class[256];
We can't allow 64-bit float registers to change from a 32-bit
mode to a 64-bit mode. */
#define CLASS_CANNOT_CHANGE_MODE \
(TARGET_BIG_ENDIAN ? FP_REGS \
: (TARGET_FLOAT64 ? HI_AND_FP_REGS : HI_REG))
/* 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 CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
mips_cannot_change_mode_class (FROM, TO)
/* Stack layout; function entry, exit and calling. */

View File

@ -232,12 +232,7 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
{0x00000000, 0x10000000}, /* SHIFT_REGS */ \
{0xfffffffe, 0x1fffffff}} /* ALL_REGS */
/* 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 (FP_REGS)
/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.
/* Defines invalid mode changes.
SImode loads to floating-point registers are not zero-extended.
The definition for LOAD_EXTEND_OP specifies that integer loads
@ -245,8 +240,9 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FPUPPER_REGS, FP_REGS,
we inhibit changes from SImode unless they are to a mode that is
identical in size. */
#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
((FROM) == SImode && GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
? FP_REGS : NO_REGS)
/* Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression

View File

@ -1314,16 +1314,14 @@ enum reg_class
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
: ((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 FLOAT_REGS
/* Return a class of registers that cannot change FROM mode to TO mode. */
/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS \
: (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1 ? GENERAL_REGS \
: NO_REGS)
#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
/* Stack layout; function entry, exit and calling. */
/* Enumeration to give which calling sequence to use. */

View File

@ -330,10 +330,8 @@ do \
/* If a 4-byte value is loaded into a FPR, it is placed into the
*upper* half of the register, not the lower. Therefore, we
cannot use SUBREGs to switch between modes in FP registers. */
#define CLASS_CANNOT_CHANGE_MODE FP_REGS
#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FP_REGS : NO_REGS)
/* Register classes. */

View File

@ -126,6 +126,8 @@ extern int sh_pr_n_sets PARAMS ((void));
extern int sh_hard_regno_rename_ok PARAMS ((unsigned int, unsigned int));
extern int sh_cfun_interrupt_handler_p PARAMS ((void));
extern void sh_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern enum reg_class sh_cannot_change_mode_class
PARAMS ((enum machine_mode, enum machine_mode));
#ifdef HARD_CONST
extern void fpscr_set_from_mem PARAMS ((int, HARD_REG_SET));

View File

@ -7733,4 +7733,26 @@ sh_expand_binop_v2sf (code, op0, op1, op2)
emit_insn ((*fn) (op0, op1, op2, op, sel1, sel1, sel1));
}
/* Return the class of registers for which a mode change from FROM to TO
is invalid. */
enum reg_class
sh_cannot_change_mode_class (from, to)
enum machine_mode from, to;
{
if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
{
if (TARGET_LITTLE_ENDIAN)
{
if (GET_MODE_SIZE (to) < 8 || GET_MODE_SIZE (from) < 8)
return DF_REGS;
}
else
{
if (GET_MODE_SIZE (from) < 8)
return DF_HI_REGS;
}
}
return NO_REGS;
}
#include "gt-sh.h"

View File

@ -1372,14 +1372,8 @@ extern const enum reg_class reg_class_from_letter[];
/* ??? We need to renumber the internal numbers for the frnn registers
when in little endian in order to allow mode size changes. */
#define CLASS_CANNOT_CHANGE_MODE (TARGET_LITTLE_ENDIAN ? DF_REGS : DF_HI_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) \
&& ((TARGET_LITTLE_ENDIAN && GET_MODE_SIZE (TO) < 8) \
|| GET_MODE_SIZE (FROM) < 8))
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO) \
sh_cannot_change_mode_class (FROM, TO)
/* Stack layout; function entry, exit and calling. */

View File

@ -2561,25 +2561,22 @@ 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_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 invalid.
@item CANNOT_CHANGE_MODE_CLASS(@var{from}, @var{to})
If defined, a C expression that returns a register class for which
a change from mode @var{from} to mode @var{to} is invalid, otherwise the
macro returns @code{NO_REGS}.
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 @code{CLASS_CANNOT_CHANGE_MODE}
as @code{FLOAT_REGS} and @code{CLASS_CANNOT_CHANGE_MODE_P} restricts
mode changes to same-size modes.
register. Therefore, @file{alpha.h} defines @code{CANNOT_CHANGE_MODE_CLASS}
as below:
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.
@example
#define CANNOT_CHANGE_MODE_CLASS \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) ? FLOAT_REGS : NO_REGS)
@end example
@end table
Three other special macros describe which operands fit which constraint

View File

@ -414,8 +414,8 @@ life_analysis (f, file, flags)
FILE *file;
int flags;
{
#ifdef ELIMINABLE_REGS
int i;
#ifdef ELIMINABLE_REGS
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
@ -431,6 +431,13 @@ life_analysis (f, file, flags)
SET_HARD_REG_BIT (elim_reg_set, FRAME_POINTER_REGNUM);
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
if (flags & PROP_REG_INFO)
for (i=0; i < NUM_MACHINE_MODES; ++i)
INIT_REG_SET (&subregs_of_mode[i]);
#endif
if (! optimize)
flags &= ~(PROP_LOG_LINKS | PROP_AUTOINC | PROP_ALLOW_CFG_CHANGES);
@ -3813,12 +3820,11 @@ mark_used_regs (pbi, x, cond, insn)
break;
case SUBREG:
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (SUBREG_REG (x)) == REG
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (x),
GET_MODE (SUBREG_REG (x))))
REG_CHANGES_MODE (REGNO (SUBREG_REG (x))) = 1;
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (x)],
REGNO (SUBREG_REG (x)));
#endif
/* While we're here, optimize this case. */
@ -3862,13 +3868,12 @@ mark_used_regs (pbi, x, cond, insn)
|| GET_CODE (testreg) == SIGN_EXTRACT
|| GET_CODE (testreg) == SUBREG)
{
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (testreg) == SUBREG
&& GET_CODE (SUBREG_REG (testreg)) == REG
&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (testreg)),
GET_MODE (testreg)))
REG_CHANGES_MODE (REGNO (SUBREG_REG (testreg))) = 1;
&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER)
SET_REGNO_REG_SET (&subregs_of_mode[GET_MODE (testreg)],
REGNO (SUBREG_REG (testreg)));
#endif
/* Modifying a single register in an alternate mode

View File

@ -974,10 +974,7 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
int retrying;
{
int i, best_reg, pass;
#ifdef HARD_REG_SET
register /* Declare it register if it's a scalar. */
#endif
HARD_REG_SET used, used1, used2;
HARD_REG_SET used, used1, used2;
enum reg_class class = (alt_regs_p
? reg_alternate_class (allocno[num].reg)
@ -1001,10 +998,8 @@ 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_MODE
if (REG_CHANGES_MODE (allocno[num].reg))
IOR_HARD_REG_SET (used1,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
#ifdef CANNOT_CHANGE_MODE_CLASS
cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
#endif
/* Try each hard reg to see if it fits. Do this in two passes.
@ -1200,11 +1195,9 @@ find_reg (num, losers, alt_regs_p, accept_call_clobbered, retrying)
&& (allocno[num].calls_crossed == 0
|| accept_call_clobbered
|| ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
#ifdef CLASS_CANNOT_CHANGE_MODE
&& ! (REG_CHANGES_MODE (allocno[num].reg)
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
regno)))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
mode)
#endif
)
{

View File

@ -488,4 +488,11 @@ extern int n_non_fixed_regs;
extern const char * reg_names[FIRST_PSEUDO_REGISTER];
/* Given a hard REGN a FROM mode and a TO mode, return non-zero if
REGN cannot change modes between the specified modes. */
#define REG_CANNOT_CHANGE_MODE_P(REGN, FROM, TO) \
(TEST_HARD_REG_BIT \
(reg_class_contents[(int) CANNOT_CHANGE_MODE_CLASS (FROM, TO)], \
REGN))
#endif /* ! GCC_HARD_REG_SET_H */

View File

@ -61,10 +61,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "hard-reg-set.h"
#include "rtl.h"
#include "tm_p.h"
#include "flags.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "regs.h"
#include "function.h"
@ -144,12 +144,6 @@ struct qty
or -1 if none was found. */
short phys_reg;
/* Nonzero if this quantity has been used in a SUBREG in some
way that is illegal. */
char changes_mode;
};
static struct qty *qty;
@ -328,7 +322,6 @@ alloc_qty (regno, mode, size, birth)
qty[qtyno].alternate_class = reg_alternate_class (regno);
qty[qtyno].n_refs = REG_N_REFS (regno);
qty[qtyno].freq = REG_FREQ (regno);
qty[qtyno].changes_mode = REG_CHANGES_MODE (regno);
}
/* Main entry point of this file. */
@ -2026,9 +2019,6 @@ update_qty_class (qtyno, reg)
rclass = reg_alternate_class (reg);
if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
qty[qtyno].alternate_class = rclass;
if (REG_CHANGES_MODE (reg))
qty[qtyno].changes_mode = 1;
}
/* Handle something which alters the value of an rtx REG.
@ -2182,11 +2172,7 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
int born_index, dead_index;
{
int i, ins;
#ifdef HARD_REG_SET
/* Declare it register if it's a scalar. */
register
#endif
HARD_REG_SET used, first_used;
HARD_REG_SET first_used, used;
#ifdef ELIMINABLE_REGS
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
@ -2234,10 +2220,8 @@ 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_MODE
if (qty[qtyno].changes_mode)
IOR_HARD_REG_SET (used,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
#ifdef CANNOT_CHANGE_MODE_CLASS
cannot_change_mode_set_regs (&used, mode, qty[qtyno].first_reg);
#endif
/* Normally, the registers that can be used for the first register in

View File

@ -1083,13 +1083,10 @@ register_operand (op, mode)
if (! reload_completed && GET_CODE (sub) == MEM)
return general_operand (op, mode);
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (sub) == REG
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (sub)))
&& CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
&& REG_CANNOT_CHANGE_MODE_P (REGNO (sub), mode, GET_MODE (sub))
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
return 0;

View File

@ -26,10 +26,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "hard-reg-set.h"
#include "rtl.h"
#include "expr.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "flags.h"
#include "basic-block.h"
#include "regs.h"
@ -227,20 +227,11 @@ static char *in_inc_dec;
#endif /* FORBIDDEN_INC_DEC_CLASSES */
#ifdef CLASS_CANNOT_CHANGE_MODE
/* These are the classes containing only registers that can be used in
a SUBREG expression that changes the mode of the register in some
way that is illegal. */
static int class_can_change_mode[N_REG_CLASSES];
/* Registers, including pseudos, which change modes in some way that
is illegal. */
static regset reg_changes_mode;
#endif /* CLASS_CANNOT_CHANGE_MODE */
#ifdef CANNOT_CHANGE_MODE_CLASS
/* All registers that have been subreged. Indexed by mode, where each
entry is a regset of registers. */
regset_head subregs_of_mode [NUM_MACHINE_MODES];
#endif
/* Sample MEM values for use by memory_move_secondary_cost. */
@ -549,22 +540,6 @@ init_reg_sets_1 ()
may_move_out_cost[m][i][j] = 65536;
}
}
#ifdef CLASS_CANNOT_CHANGE_MODE
{
HARD_REG_SET c;
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_mode [i] = 0;
continue;
ok_class:
class_can_change_mode [i] = 1;
}
}
#endif /* CLASS_CANNOT_CHANGE_MODE */
}
/* Compute the table of register modes.
@ -952,9 +927,9 @@ dump_regclass (dump)
&& (!in_inc_dec[i]
|| !forbidden_inc_dec_class[(enum reg_class) class])
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (!REGNO_REG_SET_P (reg_changes_mode, i)
|| class_can_change_mode [(enum reg_class) class])
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! invalid_mode_change_p (i, (enum reg_class) class,
PSEUDO_REGNO_MODE (i))
#endif
)
fprintf (dump, " %s:%i", reg_class_names[class],
@ -994,15 +969,7 @@ record_operand_costs (insn, op_costs, reg_pref)
op_costs[i] = init_cost;
if (GET_CODE (recog_data.operand[i]) == SUBREG)
{
rtx inner = SUBREG_REG (recog_data.operand[i]);
#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;
}
recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]);
if (GET_CODE (recog_data.operand[i]) == MEM)
record_address_regs (XEXP (recog_data.operand[i], 0),
@ -1193,10 +1160,6 @@ regclass (f, nregs, dump)
costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
#ifdef CLASS_CANNOT_CHANGE_MODE
reg_changes_mode = BITMAP_XMALLOC ();
#endif
#ifdef FORBIDDEN_INC_DEC_CLASSES
in_inc_dec = (char *) xmalloc (nregs);
@ -1329,9 +1292,9 @@ regclass (f, nregs, dump)
#ifdef FORBIDDEN_INC_DEC_CLASSES
|| (in_inc_dec[i] && forbidden_inc_dec_class[class])
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
|| (REGNO_REG_SET_P (reg_changes_mode, i)
&& ! class_can_change_mode [class])
#ifdef CANNOT_CHANGE_MODE_CLASS
|| invalid_mode_change_p (i, (enum reg_class) class,
PSEUDO_REGNO_MODE (i))
#endif
)
;
@ -1359,9 +1322,9 @@ regclass (f, nregs, dump)
#ifdef FORBIDDEN_INC_DEC_CLASSES
&& ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
&& ! (REGNO_REG_SET_P (reg_changes_mode, i)
&& ! class_can_change_mode [class])
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! invalid_mode_change_p (i, (enum reg_class) class,
PSEUDO_REGNO_MODE (i))
#endif
)
alt = reg_class_subunion[(int) alt][class];
@ -1394,9 +1357,6 @@ regclass (f, nregs, dump)
#ifdef FORBIDDEN_INC_DEC_CLASSES
free (in_inc_dec);
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
BITMAP_XFREE (reg_changes_mode);
#endif
free (costs);
}
@ -2643,4 +2603,46 @@ regset_release_memory ()
bitmap_release_memory ();
}
#ifdef CANNOT_CHANGE_MODE_CLASS
/* Set bits in *USED which correspond to registers which can't change
their mode from FROM to any mode in which REGNO was encountered. */
void
cannot_change_mode_set_regs (used, from, regno)
HARD_REG_SET *used;
enum machine_mode from;
unsigned int regno;
{
enum machine_mode to;
enum reg_class class;
for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
{
class = CANNOT_CHANGE_MODE_CLASS (from, to);
if (class != NO_REGS)
IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]);
}
}
/* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
mode. */
bool
invalid_mode_change_p (regno, class, from_mode)
unsigned int regno;
enum reg_class class;
enum machine_mode from_mode;
{
enum machine_mode to_mode;
for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
&& reg_classes_intersect_p
(class, CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode)))
return 1;
return 0;
}
#endif /* CANNOT_CHANGE_MODE_CLASS */
#include "gt-regclass.h"

View File

@ -1313,10 +1313,8 @@ mode_change_ok (orig_mode, new_mode, regno)
if (GET_MODE_SIZE (orig_mode) < GET_MODE_SIZE (new_mode))
return false;
#ifdef CLASS_CANNOT_CHANGE_MODE
if (TEST_HARD_REG_BIT (reg_class_contents[CLASS_CANNOT_CHANGE_MODE], regno)
&& CLASS_CANNOT_CHANGE_MODE_P (orig_mode, new_mode))
return false;
#ifdef CANNOT_CHANGE_MODE_CLASS
return !REG_CANNOT_CHANGE_MODE_P (regno, orig_mode, new_mode);
#endif
return true;

View File

@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "varray.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
@ -64,6 +66,8 @@ typedef struct reg_info_def
extern varray_type reg_n_info;
extern regset_head subregs_of_mode [NUM_MACHINE_MODES];
/* Indexed by n, gives number of times (REG n) is used or set. */
#define REG_N_REFS(N) (VARRAY_REG (reg_n_info, N)->refs)
@ -104,13 +108,6 @@ 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 mode of the reg in some way
that is illegal for a given class (usually floating-point)
of registers. */
#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. */
#define PSEUDO_REGNO_SIZE(N) \

View File

@ -967,9 +967,10 @@ push_reload (in, out, inloc, outloc, class,
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !reg_classes_intersect_p
(class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)),
inmode))
#endif
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
@ -1016,14 +1017,11 @@ push_reload (in, out, inloc, outloc, class,
SUBREG_REG (in))
== NO_REGS))
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (SUBREG_REG (in))))
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)),
inmode))
&& REG_CANNOT_CHANGE_MODE_P
(REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
#endif
))
{
@ -1081,10 +1079,10 @@ 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_lowpart_p (out) || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
outmode))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !reg_classes_intersect_p
(class, CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)),
outmode))
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
@ -1118,14 +1116,12 @@ push_reload (in, out, inloc, outloc, class,
SUBREG_REG (out))
== NO_REGS))
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (SUBREG_REG (out))))
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
outmode))
&& REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
outmode))
#endif
))
{

View File

@ -5490,16 +5490,15 @@ choose_reload_regs (chain)
GET_MODE_CLASS (mode));
if (
#ifdef CLASS_CANNOT_CHANGE_MODE
(TEST_HARD_REG_BIT
(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 (need_mode)))
#else
#ifdef CANNOT_CHANGE_MODE_CLASS
(!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
need_mode)
||
#endif
(GET_MODE_SIZE (GET_MODE (last_reg))
>= GET_MODE_SIZE (need_mode))
#ifdef CANNOT_CHANGE_MODE_CLASS
)
#endif
&& reg_reloaded_contents[i] == regno
&& TEST_HARD_REG_BIT (reg_reloaded_valid, i)

View File

@ -2092,6 +2092,7 @@ extern int global_alloc PARAMS ((FILE *));
extern void dump_global_regs PARAMS ((FILE *));
#endif
#ifdef HARD_CONST
/* Yes, this ifdef is silly, but HARD_REG_SET is not always defined. */
extern void retry_global_alloc PARAMS ((int, HARD_REG_SET));
#endif
extern void build_insn_chain PARAMS ((rtx));
@ -2109,6 +2110,14 @@ extern void regclass PARAMS ((rtx, int, FILE *));
extern void reg_scan PARAMS ((rtx, unsigned int, int));
extern void reg_scan_update PARAMS ((rtx, rtx, unsigned int));
extern void fix_register PARAMS ((const char *, int, int));
#ifdef HARD_CONST
extern void cannot_change_mode_set_regs PARAMS ((HARD_REG_SET *,
enum machine_mode,
unsigned int));
#endif
extern bool invalid_mode_change_p PARAMS ((unsigned int,
enum reg_class,
enum machine_mode));
extern int delete_null_pointer_checks PARAMS ((rtx));
@ -2269,4 +2278,5 @@ extern void invert_br_probabilities PARAMS ((rtx));
extern bool expensive_function_p PARAMS ((int));
/* In tracer.c */
extern void tracer PARAMS ((void));
#endif /* ! GCC_RTL_H */

View File

@ -2586,15 +2586,12 @@ simplify_subreg (outermode, op, innermode, byte)
if (REG_P (op)
&& (! REG_FUNCTION_VALUE_P (op)
|| ! rtx_equal_function_value_matters)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& ! (CLASS_CANNOT_CHANGE_MODE_P (outermode, innermode)
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (op))))
#endif
&& REGNO (op) < FIRST_PSEUDO_REGISTER
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), outermode, innermode)
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
#endif
&& ((reload_completed && !frame_pointer_needed)
|| (REGNO (op) != FRAME_POINTER_REGNUM
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM