https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116620

            Bug ID: 116620
           Summary: Feature request: type attribute to control storage
                    size of pointers
           Product: gcc
           Version: 15.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: stephane at syena dot net
  Target Milestone: ---

I'm working specifically with aarch64 but I think this could benefit other
targets.
It is a known fact that having 64 bits pointer is a waste of bits on this
architecture and I found several suggestions to try and use 32 bits pointers
instead in past reports. One problem of the proposed approaches was that they
would likely break ABI and Kernel / lib interfaces, which was probably bringing
more pain than benefits.

The burden of 64 bits pointer mostly impacts storage (which in turn can
manifest performance impacts since cache lines are less efficiently used). I am
also seeing storage size savings as a way to reduce translation tables depth by
working with a smaller virtual space (again, potential performances gain and
also lower VM management complexity).

My proposition lies in defining a data attribute that controls the storage size
of pointers. This attribute would be applicable to both data symbols (global
variables) and fields of complex types (struct, unions).
I expect (but I may be wrong) that impacts would be limited to the generation
of load / store instructions so that the stored 32 bits value is extended as a
64 bit one in the processor register.
Since the attribute would only be applied on data/structures that are declared
with it, control lies fully in the hand of the designer of this structures,
which I expect to be the designer of the relevant kernel API, lib API,
application interface.

possible attribute syntax:
void *ptr __attribute((uptr32)); // stored as an unsigned 32 bit value.
void *ptr __attribute((sptr32)); // stored as a signed 32 bit value.
void *ptr __attribute((storeas(32,unsigned)))
void *ptr __attribute((storeas(32,signed)))

uptr32 can cover addresses in the 4GB lower range.
sptr32 can cover addressed in the 2GB lower range as well as in the upper 2GB
range (using sign overflow). aarch64 have specific virtual spaces from 0 to 2ˆN
and 2^(64-M) to 2^64, where N and M are configurable parameters of the MMU, so
this signed form has its use (it is actually the one I'm invested in the most).

I am currently using casts to turn 32-bit scalars I use for storage into
pointers but there are several downsides to this:
- My code looks slightly less clear.
- My pointers are no longer understood as such in debug because DWARF info has
them as scalars... until the point I cast them in the code.
- The generated code looks like it could lose a few instructions (eg when using
the signed 32 bit version, I see loadw (load 32 bit) instructions, followed by
stxw (sign extend from 32 to 64) ones upon cast. With my data declared as
pointer with a 32 bit storage, I would expect to see loadsw (load of 32 bit
with sign extension to 64).

The concept could be extended to 16 bits pointers or any other size if it make
sense for target architectures, but the space gain may be less tangible.

Reply via email to