In the "Register Classes" chapter, gccint states the following regarding
REGNO_REG_CLASS:

  " REGNO_REG_CLASS (regno) [Macro]
    A C expression whose value is a register class containing hard register
    regno.  In general there is more than one such class; choose a class
    which is minimal, meaning that no smaller class also contains the
    register. "
                                -- 19.8 Register Classes, gccint (the latest)

This patch adds code to the end of the function specified by the
TARGET_CONDITIONAL_REGISTER_USAGE macro to generate a regno-to-"minimal"
regclass mapping, and ensures that this mapping is subsequently referenced
via REGNO_REG_CLASS().

gcc/ChangeLog:

        * config/xtensa/xtensa-protos.h (xtensa_regno_to_class):
        Remove.
        * config/xtensa/xtensa.h (xtensa_regno_to_class):
        Declaration of a new global array.
        (REGNO_REG_CLASS):
        Change to reference the xtensa_regno_to_class array.
        * config/xtensa/xtensa.cc (xtensa_regno_to_class):
        Remove the original function definition and define it as a new global
        array.
        (xtensa_conditional_register_usage):
        Append code to the end that records a map in xtensa_regno_to_class
        showing which of the current regclass definitions each hardware
        register belongs to.
---
 gcc/config/xtensa/xtensa-protos.h |  1 -
 gcc/config/xtensa/xtensa.cc       | 39 +++++++++++++------------------
 gcc/config/xtensa/xtensa.h        |  3 ++-
 3 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/gcc/config/xtensa/xtensa-protos.h 
b/gcc/config/xtensa/xtensa-protos.h
index d729b488397..f3387dd3177 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -81,7 +81,6 @@ extern long compute_frame_size (poly_int64);
 extern void xtensa_expand_prologue (void);
 extern void xtensa_expand_epilogue (void);
 extern void xtensa_adjust_reg_alloc_order (void);
-extern enum reg_class xtensa_regno_to_class (int regno);
 extern HOST_WIDE_INT xtensa_initial_elimination_offset (int from, int to);
 extern const char **xtensa_get_config_strings (void);
 extern rtl_opt_pass *make_pass_xtensa_largeconst1 (gcc::context *);
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index af1e027f53d..400703208b1 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -112,6 +112,9 @@ struct GTY(()) machine_function
   bool postreload_completed;
 };
+/* Referenced by the REGNO_REG_CLASS() macro. */
+enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
+
 static void xtensa_option_override (void);
 static void xtensa_option_override_after_change (void);
 static enum internal_test map_test_to_internal_test (enum rtx_code);
@@ -5365,7 +5368,7 @@ xtensa_reorg (void)
 static void
 xtensa_conditional_register_usage (void)
 {
-  unsigned i, c_mask;
+  unsigned int i, c_mask, cl;
c_mask = TARGET_WINDOWED_ABI ? (1 << 1) : (1 << 2); @@ -5391,30 +5394,20 @@ xtensa_conditional_register_usage (void)
     fixed_regs[A0_REG] = 0;
   else
     CLEAR_HARD_REG_BIT (reg_class_contents[RL_REGS], A0_REG);
-}
-
-/* Map hard register number to register class */
-enum reg_class xtensa_regno_to_class (int regno)
-{
-  static const enum reg_class regno_to_class[FIRST_PSEUDO_REGISTER] =
-    {
-      RL_REGS, SP_REG,         RL_REGS,        RL_REGS,
-      RL_REGS, RL_REGS,        RL_REGS,        RL_REGS,
-      RL_REGS, RL_REGS,        RL_REGS,        RL_REGS,
-      RL_REGS, RL_REGS,        RL_REGS,        RL_REGS,
-      AR_REGS, AR_REGS,        BR_REGS,
-      FP_REGS, FP_REGS,        FP_REGS,        FP_REGS,
-      FP_REGS, FP_REGS,        FP_REGS,        FP_REGS,
-      FP_REGS, FP_REGS,        FP_REGS,        FP_REGS,
-      FP_REGS, FP_REGS,        FP_REGS,        FP_REGS,
-      ACC_REG,
-    };
+  /* Generate the contents of the reverse-lookup array from the currently
+     active register class definitions.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+    for (cl = NO_REGS + 1; cl < ALL_REGS; ++cl)
+      if (TEST_HARD_REG_BIT (reg_class_contents[cl], i))
+       {
+         xtensa_regno_to_class[i] = (enum reg_class)cl;
+         break;
+       }
- if (regno == HARD_FRAME_POINTER_REGNUM)
-    return GR_REGS;
-  else
-    return regno_to_class[regno];
+  /* Verify the generated mapping for any omissions.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+    gcc_assert (xtensa_regno_to_class[i] != NO_REGS);
 }
/* Implement TARGET_CONSTANT_ALIGNMENT. Align string constants and
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 4fab1e055a1..eea7323b326 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -408,7 +408,8 @@ enum reg_class
    register REGNO.  In general there is more that one such class;
    choose a class which is "minimal", meaning that no smaller class
    also contains the register.  */
-#define REGNO_REG_CLASS(REGNO) xtensa_regno_to_class (REGNO)
+extern enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
+#define REGNO_REG_CLASS(REGNO) xtensa_regno_to_class[REGNO]
/* Use the Xtensa AR register file for base registers.
    No index registers.  */
--
2.39.5

Reply via email to