diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 29 | ||||
-rw-r--r-- | gcc/hard-reg-set.h | 11 | ||||
-rw-r--r-- | gcc/recog.c | 28 | ||||
-rw-r--r-- | gcc/reginfo.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/mips.exp | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/no-dsp-1.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/soft-float-1.c | 7 | ||||
-rw-r--r-- | gcc/varasm.c | 15 |
10 files changed, 117 insertions, 43 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e49291899eb..8fc34d64d95 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +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> * config/pa/pa-linux.h (TARGET_GAS): Remove comment. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 75e73bda2a1..ea971a91d9c 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -15835,31 +15835,26 @@ mips_conditional_register_usage (void) global_regs[CCDSP_PO_REGNUM] = 1; global_regs[CCDSP_SC_REGNUM] = 1; } - else - { - int regno; + else + AND_COMPL_HARD_REG_SET (accessible_reg_set, + 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) { - int regno; - - for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) - fixed_regs[regno] = call_used_regs[regno] = 1; - for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) - fixed_regs[regno] = call_used_regs[regno] = 1; + AND_COMPL_HARD_REG_SET (accessible_reg_set, + reg_class_contents[(int) FP_REGS]); + AND_COMPL_HARD_REG_SET (accessible_reg_set, + reg_class_contents[(int) ST_REGS]); } - else if (! ISA_HAS_8CC) + else if (!ISA_HAS_8CC) { - int regno; - /* We only have a single condition-code register. We implement this by fixing all the condition-code registers and generating RTL that refers directly to ST_REG_FIRST. */ - for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) - fixed_regs[regno] = call_used_regs[regno] = 1; + AND_COMPL_HARD_REG_SET (accessible_reg_set, + 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 for reload. We prohibit the unused $s registers, since they diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h index 9cd7c8bb962..9823a5b3441 100644 --- a/gcc/hard-reg-set.h +++ b/gcc/hard-reg-set.h @@ -583,6 +583,13 @@ hard_reg_set_iter_next (hard_reg_set_iterator *iter, unsigned *regno) extern char global_regs[FIRST_PSEUDO_REGISTER]; 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 that are fixed use (stack pointer, pc, frame pointer, etc.;. These are the registers that cannot be used to allocate @@ -659,6 +666,10 @@ extern struct target_hard_regs *this_target_hard_regs; #define this_target_hard_regs (&default_target_hard_regs) #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 \ (this_target_hard_regs->x_fixed_regs) #define fixed_reg_set \ diff --git a/gcc/recog.c b/gcc/recog.c index 17cec759905..19f00b176d7 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -925,10 +925,7 @@ next_insn_tests_no_inequality (rtx insn) it has. The main use of this function is as a predicate in match_operand - 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'. */ + expressions in the machine description. */ int general_operand (rtx op, enum machine_mode mode) @@ -998,9 +995,8 @@ general_operand (rtx op, enum machine_mode mode) } if (code == REG) - /* A register whose class is NO_REGS is not a general operand. */ 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) { @@ -1033,15 +1029,7 @@ address_operand (rtx op, enum machine_mode mode) If MODE is VOIDmode, accept a register in any mode. The main use of this function is as a predicate in match_operand - 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. */ + expressions in the machine description. */ int register_operand (rtx op, enum machine_mode mode) @@ -1080,11 +1068,10 @@ register_operand (rtx op, enum machine_mode mode) op = sub; } - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ return (REG_P (op) && (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. */ @@ -1203,11 +1190,10 @@ nonmemory_operand (rtx op, enum machine_mode mode) op = SUBREG_REG (op); } - /* We don't consider registers whose class is NO_REGS - to be a register operand. */ return (REG_P (op) && (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 diff --git a/gcc/reginfo.c b/gcc/reginfo.c index e9bf65f3003..f6f91a9975b 100644 --- a/gcc/reginfo.c +++ b/gcc/reginfo.c @@ -192,6 +192,9 @@ init_reg_sets (void) memcpy (reg_alloc_order, initial_reg_alloc_order, sizeof reg_alloc_order); #endif 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. */ @@ -292,6 +295,8 @@ static char saved_call_used_regs[FIRST_PSEUDO_REGISTER]; static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER]; #endif 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. */ void @@ -315,6 +320,8 @@ save_register_info (void) /* And similarly for reg_names. */ gcc_assert (sizeof reg_names == sizeof saved_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. */ @@ -330,6 +337,8 @@ restore_register_info (void) #endif 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 @@ -459,8 +468,27 @@ init_reg_sets_1 (void) else 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++) { + /* 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. */ gcc_assert (!fixed_regs[i] || call_used_regs[i]); #ifdef CALL_REALLY_USED_REGISTERS diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 56073ab096a..bfb1ac68a59 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +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> PR rtl-optimization/49912 diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp index 9d666fbaca3..55b26f9602d 100644 --- a/gcc/testsuite/gcc.target/mips/mips.exp +++ b/gcc/testsuite/gcc.target/mips/mips.exp @@ -834,6 +834,10 @@ proc mips-dg-finish {} { # | | # -mexplicit-relocs -mno-explicit-relocs # | | +# -mdspr2 -mno-dspr2 +# | | +# -mdsp -mno-dsp +# | | # +-- gp, abi & arch ---------+ # # For these purposes, the "gp", "abi" & "arch" option groups are treated @@ -1136,7 +1140,6 @@ proc mips-dg-options { args } { mips_make_test_option options "-mfp32" } mips_make_test_option options "-mno-dsp" - mips_make_test_option options "-mno-dspr2" } unset arch unset isa @@ -1144,6 +1147,7 @@ proc mips-dg-options { args } { } # 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" switch -- [mips_test_option options small-data] { "" - diff --git a/gcc/testsuite/gcc.target/mips/no-dsp-1.c b/gcc/testsuite/gcc.target/mips/no-dsp-1.c new file mode 100644 index 00000000000..093037579b9 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/no-dsp-1.c @@ -0,0 +1,7 @@ +/* { dg-options "-mno-dsp" } */ + +void +foo (void) +{ + register int x asm ("$ac1hi"); /* { dg-error "cannot be accessed" } */ +} diff --git a/gcc/testsuite/gcc.target/mips/soft-float-1.c b/gcc/testsuite/gcc.target/mips/soft-float-1.c new file mode 100644 index 00000000000..4c456462797 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/soft-float-1.c @@ -0,0 +1,7 @@ +/* { dg-options "-msoft-float" } */ + +void +foo (void) +{ + register float x asm ("$f0"); /* { dg-error "cannot be accessed" } */ +} diff --git a/gcc/varasm.c b/gcc/varasm.c index a01f49af58f..8d555487818 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1198,16 +1198,23 @@ make_decl_rtl (tree decl) else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) { const char *asmspec = name+1; + enum machine_mode mode = DECL_MODE (decl); reg_number = decode_reg_name (asmspec); /* First detect errors in declaring global registers. */ if (reg_number == -1) error ("register name not specified for %q+D", decl); else if (reg_number < 0) 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", 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", decl); /* Now handle properly declared static register variables. */ @@ -1230,7 +1237,7 @@ make_decl_rtl (tree decl) confused with that register and be eliminated. This usage is 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; REG_USERVAR_P (DECL_RTL (decl)) = 1; @@ -1242,7 +1249,7 @@ make_decl_rtl (tree decl) name = IDENTIFIER_POINTER (DECL_NAME (decl)); ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name); #endif - nregs = hard_regno_nregs[reg_number][DECL_MODE (decl)]; + nregs = hard_regno_nregs[reg_number][mode]; while (nregs > 0) globalize_reg (decl, reg_number + --nregs); } |