Commit 006b72bf by Richard Sandiford Committed by Richard Sandiford

hard-reg-set.h (target_hard_regs): Add x_accessible_reg_set and x_operand_reg_set.

gcc/
	* hard-reg-set.h (target_hard_regs): Add x_accessible_reg_set
	and x_operand_reg_set.
	(accessible_reg_set, operand_reg_set): New macros.
	* reginfo.c (init_reg_sets): Initialize accessible_reg_set and
	operand_reg_set.
	(saved_accessible_reg_set, saved_operand_reg_set): New variables.
	(save_register_info): Save them.
	(restore_register_info): Restore them.
	(init_reg_sets_1): Limit operand_reg_set to accessible_reg_set.
	Remove NO_REGS registers from operand_reg_set.  Treat members
	of operand_reg_set as fixed.
	* recog.c (general_operand): Check operand_reg_set rather than
	NO_REGS.
	(register_operand, nonmemory_operand): Likewise.
	* varasm.c (make_decl_rtl): Always use DECL_MODE as the mode of
	register variables.  Check accessible_reg_set and operand_reg_set.
	* config/mips/mips.c (mips_conditional_register_usage): Remove
	inaccessible register from accessible_reg_set, rather than just
	making them fixed.

gcc/testsuite/
	* gcc.target/mips/mips.exp (mips-dg-options): Make -mno-dsp
	imply -mno-dspr2.
	* gcc.target/mips/no-dsp-1.c: New test.
	* gcc.target/mips/soft-float-1.c: Likewise.

From-SVN: r181760
parent a58371f3
2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
* hard-reg-set.h (target_hard_regs): Add x_accessible_reg_set
and x_operand_reg_set.
(accessible_reg_set, operand_reg_set): New macros.
* reginfo.c (init_reg_sets): Initialize accessible_reg_set and
operand_reg_set.
(saved_accessible_reg_set, saved_operand_reg_set): New variables.
(save_register_info): Save them.
(restore_register_info): Restore them.
(init_reg_sets_1): Limit operand_reg_set to accessible_reg_set.
Remove NO_REGS registers from operand_reg_set. Treat members
of operand_reg_set as fixed.
* recog.c (general_operand): Check operand_reg_set rather than
NO_REGS.
(register_operand, nonmemory_operand): Likewise.
* varasm.c (make_decl_rtl): Always use DECL_MODE as the mode of
register variables. Check accessible_reg_set and operand_reg_set.
* config/mips/mips.c (mips_conditional_register_usage): Remove
inaccessible register from accessible_reg_set, rather than just
making them fixed.
2011-11-27 Gerald Pfeifer <gerald@pfeifer.com> 2011-11-27 Gerald Pfeifer <gerald@pfeifer.com>
* config/pa/pa-linux.h (TARGET_GAS): Remove comment. * config/pa/pa-linux.h (TARGET_GAS): Remove comment.
...@@ -15836,30 +15836,25 @@ mips_conditional_register_usage (void) ...@@ -15836,30 +15836,25 @@ mips_conditional_register_usage (void)
global_regs[CCDSP_SC_REGNUM] = 1; global_regs[CCDSP_SC_REGNUM] = 1;
} }
else else
{ AND_COMPL_HARD_REG_SET (accessible_reg_set,
int regno; reg_class_contents[(int) DSP_ACC_REGS]);
for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
fixed_regs[regno] = call_used_regs[regno] = 1;
}
if (!TARGET_HARD_FLOAT) if (!TARGET_HARD_FLOAT)
{ {
int regno; AND_COMPL_HARD_REG_SET (accessible_reg_set,
reg_class_contents[(int) FP_REGS]);
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) AND_COMPL_HARD_REG_SET (accessible_reg_set,
fixed_regs[regno] = call_used_regs[regno] = 1; reg_class_contents[(int) ST_REGS]);
for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
fixed_regs[regno] = call_used_regs[regno] = 1;
} }
else if (! ISA_HAS_8CC) else if (!ISA_HAS_8CC)
{ {
int regno;
/* We only have a single condition-code register. We implement /* We only have a single condition-code register. We implement
this by fixing all the condition-code registers and generating this by fixing all the condition-code registers and generating
RTL that refers directly to ST_REG_FIRST. */ RTL that refers directly to ST_REG_FIRST. */
for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) AND_COMPL_HARD_REG_SET (accessible_reg_set,
fixed_regs[regno] = call_used_regs[regno] = 1; reg_class_contents[(int) ST_REGS]);
SET_HARD_REG_BIT (accessible_reg_set, FPSW_REGNUM);
fixed_regs[FPSW_REGNUM] = call_used_regs[FPSW_REGNUM] = 1;
} }
/* In MIPS16 mode, we permit the $t temporary registers to be used /* In MIPS16 mode, we permit the $t temporary registers to be used
for reload. We prohibit the unused $s registers, since they for reload. We prohibit the unused $s registers, since they
......
...@@ -583,6 +583,13 @@ hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno) ...@@ -583,6 +583,13 @@ hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno)
extern char global_regs[FIRST_PSEUDO_REGISTER]; extern char global_regs[FIRST_PSEUDO_REGISTER];
struct target_hard_regs { struct target_hard_regs {
/* The set of registers that actually exist on the current target. */
HARD_REG_SET x_accessible_reg_set;
/* The set of registers that should be considered to be register
operands. It is a subset of x_accessible_reg_set. */
HARD_REG_SET x_operand_reg_set;
/* Indexed by hard register number, contains 1 for registers /* Indexed by hard register number, contains 1 for registers
that are fixed use (stack pointer, pc, frame pointer, etc.;. that are fixed use (stack pointer, pc, frame pointer, etc.;.
These are the registers that cannot be used to allocate These are the registers that cannot be used to allocate
...@@ -659,6 +666,10 @@ extern struct target_hard_regs *this_target_hard_regs; ...@@ -659,6 +666,10 @@ extern struct target_hard_regs *this_target_hard_regs;
#define this_target_hard_regs (&default_target_hard_regs) #define this_target_hard_regs (&default_target_hard_regs)
#endif #endif
#define accessible_reg_set \
(this_target_hard_regs->x_accessible_reg_set)
#define operand_reg_set \
(this_target_hard_regs->x_operand_reg_set)
#define fixed_regs \ #define fixed_regs \
(this_target_hard_regs->x_fixed_regs) (this_target_hard_regs->x_fixed_regs)
#define fixed_reg_set \ #define fixed_reg_set \
......
...@@ -925,10 +925,7 @@ next_insn_tests_no_inequality (rtx insn) ...@@ -925,10 +925,7 @@ next_insn_tests_no_inequality (rtx insn)
it has. it has.
The main use of this function is as a predicate in match_operand The main use of this function is as a predicate in match_operand
expressions in the machine description. expressions in the machine description. */
For an explanation of this function's behavior for registers of
class NO_REGS, see the comment for `register_operand'. */
int int
general_operand (rtx op, enum machine_mode mode) general_operand (rtx op, enum machine_mode mode)
...@@ -998,9 +995,8 @@ general_operand (rtx op, enum machine_mode mode) ...@@ -998,9 +995,8 @@ general_operand (rtx op, enum machine_mode mode)
} }
if (code == REG) if (code == REG)
/* A register whose class is NO_REGS is not a general operand. */
return (REGNO (op) >= FIRST_PSEUDO_REGISTER return (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS); || in_hard_reg_set_p (operand_reg_set, GET_MODE (op), REGNO (op)));
if (code == MEM) if (code == MEM)
{ {
...@@ -1033,15 +1029,7 @@ address_operand (rtx op, enum machine_mode mode) ...@@ -1033,15 +1029,7 @@ address_operand (rtx op, enum machine_mode mode)
If MODE is VOIDmode, accept a register in any mode. If MODE is VOIDmode, accept a register in any mode.
The main use of this function is as a predicate in match_operand The main use of this function is as a predicate in match_operand
expressions in the machine description. expressions in the machine description. */
As a special exception, registers whose class is NO_REGS are
not accepted by `register_operand'. The reason for this change
is to allow the representation of special architecture artifacts
(such as a condition code register) without extending the rtl
definitions. Since registers of class NO_REGS cannot be used
as registers in any case where register classes are examined,
it is most consistent to keep this function from accepting them. */
int int
register_operand (rtx op, enum machine_mode mode) register_operand (rtx op, enum machine_mode mode)
...@@ -1080,11 +1068,10 @@ register_operand (rtx op, enum machine_mode mode) ...@@ -1080,11 +1068,10 @@ register_operand (rtx op, enum machine_mode mode)
op = sub; op = sub;
} }
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
return (REG_P (op) return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER && (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); || in_hard_reg_set_p (operand_reg_set,
GET_MODE (op), REGNO (op))));
} }
/* Return 1 for a register in Pmode; ignore the tested mode. */ /* Return 1 for a register in Pmode; ignore the tested mode. */
...@@ -1203,11 +1190,10 @@ nonmemory_operand (rtx op, enum machine_mode mode) ...@@ -1203,11 +1190,10 @@ nonmemory_operand (rtx op, enum machine_mode mode)
op = SUBREG_REG (op); op = SUBREG_REG (op);
} }
/* We don't consider registers whose class is NO_REGS
to be a register operand. */
return (REG_P (op) return (REG_P (op)
&& (REGNO (op) >= FIRST_PSEUDO_REGISTER && (REGNO (op) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (op)) != NO_REGS)); || in_hard_reg_set_p (operand_reg_set,
GET_MODE (op), REGNO (op))));
} }
/* Return 1 if OP is a valid operand that stands for pushing a /* Return 1 if OP is a valid operand that stands for pushing a
......
...@@ -192,6 +192,9 @@ init_reg_sets (void) ...@@ -192,6 +192,9 @@ init_reg_sets (void)
memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order); memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order);
#endif #endif
memcpy (reg_names, initial_reg_names, sizeof reg_names); memcpy (reg_names, initial_reg_names, sizeof reg_names);
SET_HARD_REG_SET (accessible_reg_set);
SET_HARD_REG_SET (operand_reg_set);
} }
/* Initialize may_move_cost and friends for mode M. */ /* Initialize may_move_cost and friends for mode M. */
...@@ -292,6 +295,8 @@ static char saved_call_used_regs[FIRST_PSEUDO_REGISTER]; ...@@ -292,6 +295,8 @@ static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER]; static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER];
#endif #endif
static const char *saved_reg_names[FIRST_PSEUDO_REGISTER]; static const char *saved_reg_names[FIRST_PSEUDO_REGISTER];
static HARD_REG_SET saved_accessible_reg_set;
static HARD_REG_SET saved_operand_reg_set;
/* Save the register information. */ /* Save the register information. */
void void
...@@ -315,6 +320,8 @@ save_register_info (void) ...@@ -315,6 +320,8 @@ save_register_info (void)
/* And similarly for reg_names. */ /* And similarly for reg_names. */
gcc_assert (sizeof reg_names == sizeof saved_reg_names); gcc_assert (sizeof reg_names == sizeof saved_reg_names);
memcpy (saved_reg_names, reg_names, sizeof reg_names); memcpy (saved_reg_names, reg_names, sizeof reg_names);
COPY_HARD_REG_SET (saved_accessible_reg_set, accessible_reg_set);
COPY_HARD_REG_SET (saved_operand_reg_set, operand_reg_set);
} }
/* Restore the register information. */ /* Restore the register information. */
...@@ -330,6 +337,8 @@ restore_register_info (void) ...@@ -330,6 +337,8 @@ restore_register_info (void)
#endif #endif
memcpy (reg_names, saved_reg_names, sizeof reg_names); memcpy (reg_names, saved_reg_names, sizeof reg_names);
COPY_HARD_REG_SET (accessible_reg_set, saved_accessible_reg_set);
COPY_HARD_REG_SET (operand_reg_set, saved_operand_reg_set);
} }
/* After switches have been processed, which perhaps alter /* After switches have been processed, which perhaps alter
...@@ -459,8 +468,27 @@ init_reg_sets_1 (void) ...@@ -459,8 +468,27 @@ init_reg_sets_1 (void)
else else
CLEAR_REG_SET (fixed_reg_set_regset); CLEAR_REG_SET (fixed_reg_set_regset);
AND_HARD_REG_SET (operand_reg_set, accessible_reg_set);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{ {
/* As a special exception, registers whose class is NO_REGS are
not accepted by `register_operand'. The reason for this change
is to allow the representation of special architecture artifacts
(such as a condition code register) without extending the rtl
definitions. Since registers of class NO_REGS cannot be used
as registers in any case where register classes are examined,
it is better to apply this exception in a target-independent way. */
if (REGNO_REG_CLASS (i) == NO_REGS)
CLEAR_HARD_REG_BIT (operand_reg_set, i);
/* If a register is too limited to be treated as a register operand,
then it should never be allocated to a pseudo. */
if (!TEST_HARD_REG_BIT (operand_reg_set, i))
{
fixed_regs[i] = 1;
call_used_regs[i] = 1;
}
/* call_used_regs must include fixed_regs. */ /* call_used_regs must include fixed_regs. */
gcc_assert (!fixed_regs[i] || call_used_regs[i]); gcc_assert (!fixed_regs[i] || call_used_regs[i]);
#ifdef CALL_REALLY_USED_REGISTERS #ifdef CALL_REALLY_USED_REGISTERS
......
2011-11-27 Richard Sandiford <rdsandiford@googlemail.com>
* gcc.target/mips/mips.exp (mips-dg-options): Make -mno-dsp
imply -mno-dspr2.
* gcc.target/mips/no-dsp-1.c: New test.
* gcc.target/mips/soft-float-1.c: Likewise.
2011-11-26 Jakub Jelinek <jakub@redhat.com> 2011-11-26 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/49912 PR rtl-optimization/49912
......
...@@ -834,6 +834,10 @@ proc mips-dg-finish {} { ...@@ -834,6 +834,10 @@ proc mips-dg-finish {} {
# | | # | |
# -mexplicit-relocs -mno-explicit-relocs # -mexplicit-relocs -mno-explicit-relocs
# | | # | |
# -mdspr2 -mno-dspr2
# | |
# -mdsp -mno-dsp
# | |
# +-- gp, abi & arch ---------+ # +-- gp, abi & arch ---------+
# #
# For these purposes, the "gp", "abi" & "arch" option groups are treated # For these purposes, the "gp", "abi" & "arch" option groups are treated
...@@ -1136,7 +1140,6 @@ proc mips-dg-options { args } { ...@@ -1136,7 +1140,6 @@ proc mips-dg-options { args } {
mips_make_test_option options "-mfp32" mips_make_test_option options "-mfp32"
} }
mips_make_test_option options "-mno-dsp" mips_make_test_option options "-mno-dsp"
mips_make_test_option options "-mno-dspr2"
} }
unset arch unset arch
unset isa unset isa
...@@ -1144,6 +1147,7 @@ proc mips-dg-options { args } { ...@@ -1144,6 +1147,7 @@ proc mips-dg-options { args } {
} }
# Handle dependencies between options on the right of the diagram. # Handle dependencies between options on the right of the diagram.
mips_option_dependency options "-mno-dsp" "-mno-dspr2"
mips_option_dependency options "-mno-explicit-relocs" "-mgpopt" mips_option_dependency options "-mno-explicit-relocs" "-mgpopt"
switch -- [mips_test_option options small-data] { switch -- [mips_test_option options small-data] {
"" - "" -
......
/* { dg-options "-mno-dsp" } */
void
foo (void)
{
register int x asm ("$ac1hi"); /* { dg-error "cannot be accessed" } */
}
/* { dg-options "-msoft-float" } */
void
foo (void)
{
register float x asm ("$f0"); /* { dg-error "cannot be accessed" } */
}
...@@ -1198,16 +1198,23 @@ make_decl_rtl (tree decl) ...@@ -1198,16 +1198,23 @@ make_decl_rtl (tree decl)
else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{ {
const char *asmspec = name+1; const char *asmspec = name+1;
enum machine_mode mode = DECL_MODE (decl);
reg_number = decode_reg_name (asmspec); reg_number = decode_reg_name (asmspec);
/* First detect errors in declaring global registers. */ /* First detect errors in declaring global registers. */
if (reg_number == -1) if (reg_number == -1)
error ("register name not specified for %q+D", decl); error ("register name not specified for %q+D", decl);
else if (reg_number < 0) else if (reg_number < 0)
error ("invalid register name for %q+D", decl); error ("invalid register name for %q+D", decl);
else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode) else if (mode == BLKmode)
error ("data type of %q+D isn%'t suitable for a register", error ("data type of %q+D isn%'t suitable for a register",
decl); decl);
else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl)))) else if (!in_hard_reg_set_p (accessible_reg_set, mode, reg_number))
error ("the register specified for %q+D cannot be accessed"
" by the current target", decl);
else if (!in_hard_reg_set_p (operand_reg_set, mode, reg_number))
error ("the register specified for %q+D is not general enough"
" to be used as a register variable", decl);
else if (!HARD_REGNO_MODE_OK (reg_number, mode))
error ("register specified for %q+D isn%'t suitable for data type", error ("register specified for %q+D isn%'t suitable for data type",
decl); decl);
/* Now handle properly declared static register variables. */ /* Now handle properly declared static register variables. */
...@@ -1230,7 +1237,7 @@ make_decl_rtl (tree decl) ...@@ -1230,7 +1237,7 @@ make_decl_rtl (tree decl)
confused with that register and be eliminated. This usage is confused with that register and be eliminated. This usage is
somewhat suspect... */ somewhat suspect... */
SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number)); SET_DECL_RTL (decl, gen_rtx_raw_REG (mode, reg_number));
ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number; ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
REG_USERVAR_P (DECL_RTL (decl)) = 1; REG_USERVAR_P (DECL_RTL (decl)) = 1;
...@@ -1242,7 +1249,7 @@ make_decl_rtl (tree decl) ...@@ -1242,7 +1249,7 @@ make_decl_rtl (tree decl)
name = IDENTIFIER_POINTER (DECL_NAME (decl)); name = IDENTIFIER_POINTER (DECL_NAME (decl));
ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name); ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name);
#endif #endif
nregs = hard_regno_nregs[reg_number][DECL_MODE (decl)]; nregs = hard_regno_nregs[reg_number][mode];
while (nregs > 0) while (nregs > 0)
globalize_reg (decl, reg_number + --nregs); globalize_reg (decl, reg_number + --nregs);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment