Am 06.12.24 um 14:53 schrieb Richard Biener:
On Fri, Dec 6, 2024 at 2:17 PM Georg-Johann Lay <a...@gjlay.de> wrote:

Am 06.12.24 um 13:23 schrieb Sam James:
Georg-Johann Lay <a...@gjlay.de> writes:

This patch disables CRC lookup tables which consume quite some RAM.

Given that -foptimize-crc is new, it may be useful to CC the pass
authors in case they have input.

CCing Mariam Arutunian

Ok for trunk?

Johann

The problem is not in the new CRC pass, but because AVR is a very
limited hardware.  Because AVR has no linear address space, .rodata
has to be placed in RAM, and most devices have just a few KiB of RAM,
or even less.

An extension PR49857 to put such lookup tables in flash / program memory
has been rejected by the global maintainers as "too specific", ignoring
most of the constraints imposed by the requirement of using named
address-spaces.

The point is that you cannot just put data in flash, one must also use
the correct instructions to access them, which is achieved by means
of avr specific named address-spaces like __flash.

This would require a new target hook like proposed in PR49857, which
could put lookup-tables into a non-generic address-space provided:

*) All respective data is put in the preferred address-space, and

*) All accesses have to use the same address-space as of 1),
independent of what the rest of the code may look like.

To date, only 3 lookup tables generated by GCC meet these criteria:

1) Lookup tables from tree-switch conversion.

2) Lookup tables from the current CRC work

3) vtables.  Though g++ does not, and probably never will, support
named address spaces.

4) const global data

No. That won't work. Suppose:

foo.c:

const int ii = 1;
int inc (const int*);

int func (void)
{
    return inc (&ii);
}

bar.c:

int inc (const int *p)
{
    return 1 + *p;
}

This works when ii is in generic address-space.  But when you
put ii in a different AS (like e.g. __flash), then inc() will
read from the wrong AS.  You'd need a version of inc() that is

int inc_flash (const __flash int *p)
{
    return 1 + *p;
}

TL;DR You don't have control over *all* accesses, but in foo.c
the pointer to ii may escape.

Notice that in, say, tree-switch-conversion this is different
because that pass knows *all* accesses to the table, and it
could attach an AS from a target hook to all accesses.

Once that pass has finished, there's no more way to retroactively
optimize this, because addresses may escape to other modules
or to inline asm, or there may be copies or the tree var.
You's have to find all tree vars ssa_names.

I think generally this might be a sound optimization - but as you said
it requires generating correct accesses in the first place which also
means once anything takes the address of the data all pointer uses
have to know beforehand.  Thus application is likely quite limited for
4) at least.

Maybe it's possible to perform half of the task by the linker via
relaxation?   Though I can easily guess it's somewhat difficult for AVR.

Richard.

No.  I don't see what the linker has to do with it.  Different ASes
even have different instructions to access them and support different
addressing modes and need different address registers.

Addressing modes are generated by the compiler and
TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P.  The linker cannot fix that.

Johann

Reply via email to