OSDN Git Service

gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 27 Nov 2011 10:09:15 +0000 (10:09 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 27 Nov 2011 10:09:15 +0000 (10:09 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181760 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/hard-reg-set.h
gcc/recog.c
gcc/reginfo.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/mips.exp
gcc/testsuite/gcc.target/mips/no-dsp-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/soft-float-1.c [new file with mode: 0644]
gcc/varasm.c

index e492918..8fc34d6 100644 (file)
@@ -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.
index 75e73bd..ea971a9 100644 (file)
@@ -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
index 9cd7c8b..9823a5b 100644 (file)
@@ -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 \
index 17cec75..19f00b1 100644 (file)
@@ -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
index e9bf65f..f6f91a9 100644 (file)
@@ -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
index 56073ab..bfb1ac6 100644 (file)
@@ -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
index 9d666fb..55b26f9 100644 (file)
@@ -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 (file)
index 0000000..0930375
--- /dev/null
@@ -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 (file)
index 0000000..4c45646
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-options "-msoft-float" } */
+
+void
+foo (void)
+{
+  register float x asm ("$f0"); /* { dg-error "cannot be accessed" } */
+}
index a01f49a..8d55548 100644 (file)
@@ -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);
            }