From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by sourceware.org (Postfix) with ESMTP id 310AE3858426 for ; Wed, 28 Jun 2023 16:49:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 310AE3858426 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A13C6C14; Wed, 28 Jun 2023 09:50:19 -0700 (PDT) Received: from [10.2.78.54] (e120077-lin.cambridge.arm.com [10.2.78.54]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3AC583F64C; Wed, 28 Jun 2023 09:49:35 -0700 (PDT) Message-ID: <7d5c5921-634c-7fdd-b219-e8034a5a0a9c@arm.com> Date: Wed, 28 Jun 2023 17:49:33 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Subject: Re: wishlist: support for shorter pointers Content-Language: en-GB To: Martin Uecker , =?UTF-8?Q?Rafa=c5=82_Pietrak?= , "gcc@gcc.gnu.org" References: <439affd4-11fe-de80-94c8-6fc64cbf76ec@ztk-rp.eu> <112e711791835d56cca38654f83a009cb46707d4.camel@gwdg.de> From: "Richard Earnshaw (lists)" In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-3492.8 required=5.0 tests=BAYES_00,KAM_DMARC_NONE,KAM_DMARC_STATUS,KAM_LAZY_DOMAIN_SECURITY,KAM_SHORT,NICE_REPLY_A,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On 28/06/2023 17:07, Martin Uecker wrote: > Am Mittwoch, dem 28.06.2023 um 16:44 +0100 schrieb Richard Earnshaw (lists): >> On 28/06/2023 15:51, Rafał Pietrak via Gcc wrote: >>> Hi Martin, >>> >>> W dniu 28.06.2023 o 15:00, Martin Uecker pisze: >>>> >>>> Sounds like named address spaces to me: >>>> https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html >>> >>> Only to same extend, and only in x86 case. >>> >>> The goal of the wish-item I've describe is to shorten pointers. I may be >>> wrong and have misread the specs, but the "address spaces" >>> implementation you've pointed out don't look like doing that. In >>> particular the AVR variant applies to devices that have a "native int" >>> of 16-bits, and those devices (most of them) have address space no >>> larger. So there is no gain. Their pointers cover all their address >>> space and if one wanted to have shorter pointers ... like 12-bits - >>> those wouldn't "nicely fit into register", or 8-bits - those would >>> reduce the "addressable" space to 256 bytes, which is VERY tight for any >>> practical application. >>> >>> Additionally, the AVR case is explained as "only for rodata" - this >>> completely dismisses it from my use. >>> >>> To explain a little more: the functionality I'm looking for is something >>> like x86 implementation of that "address spaces". The key functionality >>> here is the additional register like fs/gs (an address offset register). >>> IMHO the feature/implementation in question would HAVE TO use additional >>> register instead of letting linker adjust them at link time, because >>> those "short" pointers would need to be load-and-stored dynamically and >>> changed dynamically at runtime. That's why I've put an example of ARM >>> instruction that does this. Again IMHO the only "syntactic" feature,that >>> is required for a compiler to do "the right thing" is to make compiler >>> consider segment (segment name, ordinary linker segment name) where a >>> particular pointer target resides. Then if that segment where data (of >>> that pointer) reside is declared "short pointers", then compiler loads >>> and uses additional register pointing to the base of that segment. Quite >>> like intel segments work in hardware. >>> >>> Naturally, although I have hints on such mechanism behavior, I have no >>> skills to even imagine where to tweak the sources to achieve that. >> >> >> I think I understand what you're asking for but: >> 1) You'd need a new ABI specification to handle this, probably involving >> register assignments (for the 'segment' addresses), the initialization >> of those at startup, assembler and linker extensions to allow for >> relocations describing the symbols, etc. >> 2) Implementations for all of the above (it would be a lot of work - >> weeks to months, not days). Little existing code, including most of the >> hand-written assembly routines is likely to be compatible with the >> register conventions you'd need to define, so all that code would need >> auditing and alternatives developed. >> 3) I doubt it would be an overall win in the end. >> >> I base the last assertion on the fact that you'd now have three values >> in many addresses, the base (segment), the pointer and then a final >> offset. This means quite a bit more code being generated, so you trade >> smaller pointers in your data section for more code in your code >> section. For example, >> >> struct f >> { >>    int a; >>    int b; >> }; >> >> int func (struct f *p) >> { >>    return p->b; >> } >> >> would currently compile to something like >> >> ldr r0, [r0, #4] >> bx lr >> >> but with the new, shorter, pointer you'd end up with >> >> add r0, r_seg, r0 >> ldr r0, [r0, #4] >> bx lr >> >> In some cases it might be even worse as you'd end up with >> zero-extensions of the pointer values as well. >> > > I do not quite understand why this wouldn't work with > named address spaces? > > __near struct { > int x; > int y; > }; > > int func (__near struct f *p) > { > return p->b; > } > > could produce exactly such code? If you need multiple > such segments one could have __near0, ..., __near9. > > Such a pointer could also be converted to a regular > pointer, which could reduce code overhead. > > Martin Named address spaces, as they exist today, don't really do anything (at least, in the Arm port). A pointer is still 32-bits in size, so they become just syntactic sugar. If you're going to use them as 'bases', then you still have to define how the base address is accessed - it doesn't just happen by magic. R. > > > >> R. >> >>> -R >>> >>>> >>>> Best, >>>> Martin >>>> >>>> Am Dienstag, dem 27.06.2023 um 14:26 +0200 schrieb Rafał Pietrak via Gcc: >>>>> Hello everybody, >>>>> >>>>> I'm not quite sure if this is correct mailbox for this suggestion (may >>>>> be "embedded" would be better), but let me present it first (and while >>>>> the examples is from ARM stm32 environment, the issue would equally >>>>> apply to i386 or even amd64). So: >>>>> >>>>> 1. Small MPU (like stm32f103) would normally have small amount of RAM, >>>>> and even somewhat larger variant do have its memory "partitioned/ >>>>> dedicated" to various subsystems (like CloseCoupledMemory, Ethernet >>>>> buffers, USB buffs, etc). >>>>> >>>>> 2. to address any location within those sections of that memory (or >>>>> their entire RAM) it would suffice to use 16-bit pointers. >>>>> >>>>> 3. still, declaring a pointer in GCC always allocate "natural" size of a >>>>> pointer in given architecture. In case of ARM stm32 it would be 32-bits. >>>>> >>>>> 4. programs using pointers do keep them around in structures. So >>>>> programs with heavy use of pointers have those structures like 2 times >>>>> larger then necessary .... if only pointers were 16-bit. And memory in >>>>> those devices is scarce. >>>>> >>>>> 5. the same thing applies to 64-bit world. Programs that don't require >>>>> huge memories but do use pointers excessively, MUST take up 64-bit for a >>>>> pointer no matter what. >>>>> >>>>> So I was wondering if it would be feasible for GCC to allow SEGMENT to >>>>> be declared as "small" (like 16-bit addressable in 32-bit CPU, or 32-bit >>>>> addressable in 64-bit CPU), and ANY pointer declared to reference >>>>> location within them would then be appropriately reduced. >>>>> >>>>> In ARM world, the use of such pointers would require the use of an >>>>> additional register (functionally being a "segment base address") to >>>>> allow for data access using instructions like: "LD Rx, [Ry, Rz]" - >>>>> meaning register index reference. Here Ry is the base of the SEGMENT in >>>>> question. Or if (like inside a loop) the structure "pointed to" by Rz >>>>> must be often used, just one operation "ADD Rz, Ry" will prep Rz for >>>>> subsequent "ordinary" offset operations like: "LD Ra, [Rz, #member]" ... >>>>> and reentering the loop by "LDH Rz, [Rz, #next]" does what's required by >>>>> "x = x->next". >>>>> >>>>> Not having any experience in compiler implementations I have no idea if >>>>> this is a big or a small change to compiler design. >>>>> >>>>> -R >>>> >>>> >> > >