https://gcc.gnu.org/g:e347e2b81ac7daa7382c611a62d54ec0b761bee8

commit r16-4379-ge347e2b81ac7daa7382c611a62d54ec0b761bee8
Author: Georg-Johann Lay <[email protected]>
Date:   Wed Dec 11 11:57:46 2024 +0100

    Allow target to chose address-space for artificial rodata.
    
    This patch adds a new target hook TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA
    that allows the backend to chose an address space other than the generic 
one.
    
    This hook is only invoked when the compiler can make sure that:
    
    -  The object for which the hooks is being invoked will be located
       in the desired address space, and
    
    -  All accesses to that object will be accesses appropriate for
       that address space, and
    
    -  The object is read-only and is initialized at load time, and
    
    -  The hook invokations are independent of each other.  This means
       that this hook can be used to optimize code / data consumption.
       (Rather than introducing an ABI change, which would be the case
       when C++'s vtables were put in a different AS).
    
    To date, there are only two candidates for such compiler generated
    lookup tables:  CSWTCH tables as generated by tree-switch-conversion.cc,
    and CRC lookup tables generated by gimple-crc-optimization.cc.
    
    gcc/
            * coretypes.h (enum artificial_rodata): New enum type.
            * doc/tm.texi: Rebuild.
            * doc/tm.texi.in (TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA):
            New hook.
            * target.def (addr_sapce.for_artificial_rodata): New DEFHOOK.
            * targhooks.cc (default_addr_space_convert): New function.
            * targhooks.h (default_addr_space_convert): New prototype.
            * tree-switch-conversion.cc (build_one_array) <value_type>:
            Set type_quals address-space according to
            targetm.addr_space.for_artificial_rodata().
    
            * config/avr/avr.cc (avr_rodata_in_flash_p): Move up.
            (TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA): Define to...
            (avr_addr_space_for_artificial_rodata): ...this new function.
            * common/config/avr/avr-common.cc (avr_option_optimization_table):
            Adjust -ftree-switch-conversion comment.

Diff:
---
 gcc/common/config/avr/avr-common.cc |  11 ++--
 gcc/config/avr/avr.cc               | 108 ++++++++++++++++++++++--------------
 gcc/coretypes.h                     |  13 +++++
 gcc/doc/tm.texi                     |  25 +++++++++
 gcc/doc/tm.texi.in                  |   2 +
 gcc/target.def                      |  29 ++++++++++
 gcc/targhooks.cc                    |  10 ++++
 gcc/targhooks.h                     |   2 +
 gcc/tree-switch-conversion.cc       |  10 ++++
 9 files changed, 161 insertions(+), 49 deletions(-)

diff --git a/gcc/common/config/avr/avr-common.cc 
b/gcc/common/config/avr/avr-common.cc
index 914b7417fdad..5b642345a0aa 100644
--- a/gcc/common/config/avr/avr-common.cc
+++ b/gcc/common/config/avr/avr-common.cc
@@ -29,12 +29,11 @@
 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
 static const struct default_options avr_option_optimization_table[] =
   {
-    // The lookup table from tree-swicth-conversion.cc lives in .rodata
-    // and hence consumes RAM on almost all devices.  As PR49857 has
-    // been rejected several times for non-technical reasons, just
-    // disable -ftree-switch-conversion by default.  But even with PR49857
-    // in place there remains PR81540, which cannot be filtered out since
-    // the pass has no way to hook in.
+    // There is no way to filter out unwanted cswtch transformations:
+    // - Code bload as mentioned in PR81540.
+    // - When tree-switch-conversion.cc::build_one_array() finds a
+    //   linear function, it will use a formula that involves a
+    //   multiplication without even trying to work out the costs.
     { OPT_LEVELS_ALL, OPT_ftree_switch_conversion, NULL, 0 },
     // The only effect of -fcaller-saves might be that it triggers
     // a frame without need when it tries to be smart around calls.
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index 033bd09e7bfc..0cee92565777 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -120,6 +120,25 @@ const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
 };
 
 
+#ifdef HAVE_LD_AVR_AVRXMEGA2_FLMAP
+static const bool have_avrxmega2_flmap = true;
+#else
+static const bool have_avrxmega2_flmap = false;
+#endif
+
+#ifdef HAVE_LD_AVR_AVRXMEGA4_FLMAP
+static const bool have_avrxmega4_flmap = true;
+#else
+static const bool have_avrxmega4_flmap = false;
+#endif
+
+#ifdef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
+static const bool have_avrxmega3_rodata_in_flash = true;
+#else
+static const bool have_avrxmega3_rodata_in_flash = false;
+#endif
+
+
 /* Holding RAM addresses of some SFRs used by the compiler and that
    are unique over all devices in an architecture like 'avr4'.  */
 
@@ -287,6 +306,36 @@ avr_tolower (char *lo, const char *up)
 }
 
 
+/* Return TRUE when the .rodata sections are located in program memory (flash).
+   Otherwise, the .rodata input sections are located in RAM and FALSE is
+   returned.  Note that the FLMAP cases are a bit wonky since the libs are
+   compiled with the default but -mrodata-in-ram is not a multilib option.  */
+
+static bool
+avr_rodata_in_flash_p ()
+{
+  switch (avr_arch_index)
+    {
+    default:
+      break;
+
+    case ARCH_AVRTINY:
+      return true;
+
+    case ARCH_AVRXMEGA3:
+      return have_avrxmega3_rodata_in_flash;
+
+    case ARCH_AVRXMEGA2:
+      return avropt_flmap && have_avrxmega2_flmap && avropt_rodata_in_ram != 1;
+
+    case ARCH_AVRXMEGA4:
+      return avropt_flmap && have_avrxmega4_flmap && avropt_rodata_in_ram != 1;
+    }
+
+  return false;
+}
+
+
 /* Return chunk of mode MODE of X as an rtx.  N specifies the subreg
    byte at which the chunk starts.  N must be an integral multiple
    of the mode size.  */
@@ -11482,6 +11531,18 @@ avr_addr_space_diagnose_usage (addr_space_t as, 
location_t loc)
 }
 
 
+/* Implement `TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA'.  */
+
+static addr_space_t
+avr_addr_space_for_artificial_rodata (tree /*type*/,
+                                     artificial_rodata /*kind*/)
+{
+  return avr_rodata_in_flash_p ()
+    ? ADDR_SPACE_GENERIC
+    : avropt_n_flash > 1 ? ADDR_SPACE_FLASHX : ADDR_SPACE_FLASH;
+}
+
+
 /* Implement `TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID'.  Zero is a valid
    address in all address spaces. Even in ADDR_SPACE_FLASH1 etc..,
    a zero address is valid and means 0x<RAMPZ val>0000, where RAMPZ is
@@ -11823,49 +11884,6 @@ avr_insert_attributes (tree node, tree *attributes)
     }
 }
 
-#ifdef HAVE_LD_AVR_AVRXMEGA2_FLMAP
-static const bool have_avrxmega2_flmap = true;
-#else
-static const bool have_avrxmega2_flmap = false;
-#endif
-
-#ifdef HAVE_LD_AVR_AVRXMEGA4_FLMAP
-static const bool have_avrxmega4_flmap = true;
-#else
-static const bool have_avrxmega4_flmap = false;
-#endif
-
-#ifdef HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
-static const bool have_avrxmega3_rodata_in_flash = true;
-#else
-static const bool have_avrxmega3_rodata_in_flash = false;
-#endif
-
-
-static bool
-avr_rodata_in_flash_p ()
-{
-  switch (avr_arch_index)
-    {
-    default:
-      break;
-
-    case ARCH_AVRTINY:
-      return true;
-
-    case ARCH_AVRXMEGA3:
-      return have_avrxmega3_rodata_in_flash;
-
-    case ARCH_AVRXMEGA2:
-      return avropt_flmap && have_avrxmega2_flmap && avropt_rodata_in_ram != 1;
-
-    case ARCH_AVRXMEGA4:
-      return avropt_flmap && have_avrxmega4_flmap && avropt_rodata_in_ram != 1;
-    }
-
-  return false;
-}
-
 
 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'.  */
 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'.  */
@@ -16811,6 +16829,10 @@ avr_unwind_word_mode ()
 #undef  TARGET_ADDR_SPACE_DIAGNOSE_USAGE
 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
 
+#undef  TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA
+#define TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA \
+  avr_addr_space_for_artificial_rodata
+
 #undef  TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
 #define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID avr_addr_space_zero_address_valid
 
diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index b6a922a506c3..8c3633b96771 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -342,6 +342,19 @@ enum warn_strict_overflow_code
   WARN_STRICT_OVERFLOW_MAGNITUDE = 5
 };
 
+/* Kind of artificial, compiler-generated lookup table.  Type of the
+   second argument of TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA resp.
+   targetm.addr_space.for_artificial_rodata.  */
+enum artificial_rodata
+{
+  /* Generated by tree-switch-conversion.cc: Lowered GIMPLE_SWITCH expressions
+     to something more efficient than a jump table.  */
+  ARTIFICIAL_RODATA_CSWITCH,
+
+  /* Generated by gimple-crc-optimization.cc:  CRC optimization.  */
+  ARTIFICIAL_RODATA_CRC
+};
+
 /* The type of an alias set.  Code currently assumes that variables of
    this type can take the values 0 (the alias set which aliases
    everything) and -1 (sometimes indicating that the alias set is
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 930003725378..fd208f53844a 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -11532,6 +11532,31 @@ the address space as registered with 
@code{c_register_addr_space}.
 The default implementation does nothing.
 @end deftypefn
 
+@deftypefn {Target Hook} addr_space_t TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA 
(tree @var{type}, enum artificial_rodata @var{purpose})
+Define this hook to return a named address space to be used for
+@var{type}, usually the type of an artificial lookup-table that would
+reside in @code{.rodata} and in the generic address space.
+
+The hook can be used to put compiler-generated, artificial lookup tables in
+static storage into a non-generic address space when it is better suited
+than the generic address space.
+The compiler will generate all accesses to the respective data
+so that all associated accesses will also use the specified address space
+and pointer mode.
+
+@var{type} is the type of the lookup table. @var{purpose} specifies
+the purpose of the lookup table.  It is one of:
+@table @code
+@item ARTIFICIAL_RODATA_CSWITCH
+@file{tree-switch-conversion.cc} lowered a GIMPLE_SWITCH expressions
+to something more efficient than a jump table.
+@item ARTIFICIAL_RODATA_CRC
+@file{gimple-crc-optimization.cc} optimized a CRC computation by
+using a polynomial lookup table.
+@end table
+The default implementation of the hook returns @code{ADDR_SPACE_GENERIC}.
+@end deftypefn
+
 @node Misc
 @section Miscellaneous Parameters
 @cindex parameters, miscellaneous
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 4838af8c0da9..14315dd50805 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -7375,6 +7375,8 @@ c_register_addr_space ("__ea", ADDR_SPACE_EA);
 
 @hook TARGET_ADDR_SPACE_DIAGNOSE_USAGE
 
+@hook TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA
+
 @node Misc
 @section Miscellaneous Parameters
 @cindex parameters, miscellaneous
diff --git a/gcc/target.def b/gcc/target.def
index 31c7af1f8bcc..f288329ffcab 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3540,6 +3540,35 @@ The default implementation does nothing.",
  void, (addr_space_t as, location_t loc),
  default_addr_space_diagnose_usage)
 
+/* Function to patch the address space of some compiler-generated
+   read-only data.  Used for optimization purposes only.  */
+DEFHOOK
+(for_artificial_rodata,
+ "Define this hook to return a named address space to be used for\n\
+@var{type}, usually the type of an artificial lookup-table that would\n\
+reside in @code{.rodata} and in the generic address space.\n\
+\n\
+The hook can be used to put compiler-generated, artificial lookup tables in\n\
+static storage into a non-generic address space when it is better suited\n\
+than the generic address space.\n\
+The compiler will generate all accesses to the respective data\n\
+so that all associated accesses will also use the specified address space\n\
+and pointer mode.\n\
+\n\
+@var{type} is the type of the lookup table. @var{purpose} specifies\n\
+the purpose of the lookup table.  It is one of:\n\
+@table @code\n\
+@item ARTIFICIAL_RODATA_CSWITCH\n\
+@file{tree-switch-conversion.cc} lowered a GIMPLE_SWITCH expressions\n\
+to something more efficient than a jump table.\n\
+@item ARTIFICIAL_RODATA_CRC\n\
+@file{gimple-crc-optimization.cc} optimized a CRC computation by\n\
+using a polynomial lookup table.\n\
+@end table\n\
+The default implementation of the hook returns @code{ADDR_SPACE_GENERIC}.",
+ addr_space_t, (tree type, enum artificial_rodata purpose),
+ default_addr_space_for_artificial_rodata)
+
 HOOK_VECTOR_END (addr_space)
 
 #undef HOOK_PREFIX
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index dfd46eeb8af8..1873d572ba3f 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -1791,6 +1791,16 @@ default_addr_space_convert (rtx op ATTRIBUTE_UNUSED,
   gcc_unreachable ();
 }
 
+
+/* The default hook for TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA.  */
+
+addr_space_t
+default_addr_space_for_artificial_rodata (tree, artificial_rodata)
+{
+  return ADDR_SPACE_GENERIC;
+}
+
+
 /* The defualt implementation of TARGET_HARD_REGNO_NREGS.  */
 
 unsigned int
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 441206763451..92e7a4cb10f1 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -214,6 +214,8 @@ extern bool default_addr_space_subset_p (addr_space_t, 
addr_space_t);
 extern bool default_addr_space_zero_address_valid (addr_space_t);
 extern int default_addr_space_debug (addr_space_t);
 extern void default_addr_space_diagnose_usage (addr_space_t, location_t);
+extern addr_space_t default_addr_space_for_artificial_rodata (tree,
+                                                             
artificial_rodata);
 extern rtx default_addr_space_convert (rtx, tree, tree);
 extern unsigned int default_case_values_threshold (void);
 extern bool default_have_conditional_execution (void);
diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc
index 62eddcd95d31..4bd8ed750511 100644
--- a/gcc/tree-switch-conversion.cc
+++ b/gcc/tree-switch-conversion.cc
@@ -1008,6 +1008,16 @@ switch_conversion::build_one_array (int num, tree 
arr_index_type,
       default_type = TREE_TYPE (m_default_values[num]);
       value_type = array_value_type (default_type, num);
       array_type = build_array_type (value_type, arr_index_type);
+      addr_space_t as
+       = targetm.addr_space.for_artificial_rodata (array_type,
+                                                   ARTIFICIAL_RODATA_CSWITCH);
+      if (!ADDR_SPACE_GENERIC_P (as))
+       {
+         int quals = (TYPE_QUALS_NO_ADDR_SPACE (value_type)
+                      | ENCODE_QUAL_ADDR_SPACE (as));
+         value_type = build_qualified_type (value_type, quals);
+         array_type = build_array_type (value_type, arr_index_type);
+       }
       if (default_type != value_type)
        {
          unsigned int i;

Reply via email to