For the avr.cc part, the __flashx named address space has been approved,
which means that the natural choice in the target hook would be
ADDR_SPACE_FLASHX instead of ADDR_SPACE_MEMX:

+/* 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;
+}
+

Johann

Am 09.12.24 um 15:13 schrieb Georg-Johann Lay:
This patch adds a new target hook that allows to chose
a non-generic named address-space for compiler generated
lookup tables.

The purpose is that there are cases (on avr namely) where
the generic address space is sub-optimal because it must
put .rodata in RAM.  With this hook it is possible to
chose an address space that's better suited, like the
__flash address space that allocates to .progmem.data which
resides in flash.

The patch passes without regressions on avr.

On x86_64, it bootstraps and tests without regressions.

Ok for trunk?

Johann

p.s.  The feature has been discussed in the lists before,
and in all discussions I failed in getting across why a
different address space is needed.  Some background:

1) On AVR, you cannot just put data in a different section
without also using different instructions to access it.
In general a different section also requires different
address registers and different addressing modes and
different instructions.

2) It is *not* possible to do this during linker relaxation.
You cannot just change register allocation and address registers
in the linker.  You cannot just replace a 16-bit register like
X or Y by a 24-bit address that lives in Z (lower 16 bits) and
in some SFR (upper 8 bits).

3) You cannot just put all static storage read-only data into
a different address space.  For example, it is perfectly fine
for a C/C++ code to define a variable in static storage and
access it in assembly code.  The assembly code must know the
address space of the symbol, or otherwise the code is wrong.

4) From 3) it follows that you can only change the address space
of an object when it is hidden from the user, i.e. the compiler
is building the object and has control over all accesses, and
there's no way the user can get a reference to the object.

To date, there are only 2 lookup tables generated by GCC that
fit these criteria:

A) CSWTCH tables from tree-switch-conversion.cc.

B) crc_table_for_* tables from gimple-crc-optimization.cc.

Though B) may increase the code size by quite a lot.  For example,
size of gcc.dg/torture/crc-2.c will increase by more than 1500%
(and even more when a 24-bit address-space is required).  The
CRC optimizations uses some builtin magic, so it's unclear where
and how to introduce a different address space.

--

Allow target to chose address-space for artificial rodata.

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.

Reply via email to