@@ -119,6 +119,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'. */
@@ -254,6 +273,31 @@ avr_tolower (char *lo, const char *up)
}
+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. */
@@ -11123,6 +11167,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_MEMX : 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
@@ -11396,49 +11452,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'. */
@@ -16013,6 +16026,10 @@ avr_use_lra_p ()
#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
@@ -340,6 +340,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
@@ -11399,6 +11399,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
@@ -7332,6 +7332,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
@@ -3504,6 +3504,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
@@ -1783,6 +1783,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
@@ -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);
@@ -1007,6 +1007,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;