How do I tell GCC that a global variable is immutable after initialization?

Matthias Pfaller leo@marco.de
Wed Jun 22 08:08:00 GMT 2016


On 06/22/2016 09:48 AM, Sebastian Huber wrote:
> On 22/06/16 09:42, Mason wrote:
>> On 22/06/2016 09:00, Sebastian Huber wrote:
>>
>>> is there a way to tell GCC that a global variable is immutable after
>>> initialization? For example
>>>
>>> struct {
>>>       int (*f)(void);
>>> } s;
>>>
>>> int f(void)
>>> {
>>>       int a;
>>>       int b;
>>>
>>>       a = (*s.f)();
>>>       b = (*s.f)();
>>>
>>>       return a + b;
>>> }
>>>
>>> yields on ARMv8 for example
>>>
>>> f:
>>>           push    {r4, r5, r6, lr}
>>>           movw    r4, #:lower16:s
>>>           movt    r4, #:upper16:s
>>>           ldr     r3, [r4]
>>>           blx     r3
>>>           ldr     r3, [r4] <- I would like to get rid of this load here
>>>           mov     r5, r0
>>>           blx     r3
>>>           add     r0, r5, r0
>>>           pop     {r4, r5, r6, pc}
>>>
>>> The
>>>
>>> a = (*s.f)();
>>>
>>> is a call to a global function, so GCC must assume that s might have
>>> changed afterwards. I would like to get rid of the second load of s.f.
>>> Is there a special attribute to tell GCC that s is essentially
>>> immutable? I cannot use the const qualifier, since the structure is
>>> initialized during system start.
>> A simple solution would be storing the function pointer in a local
>> variable.
>> Thus, the compiler "knows" you intended to call the same function twice.
>>
>> typedef int func(void);
>> struct { func *f; } s;
>> int f(void)
>> {
>>       func *g = s.f;
>>       int a = g();
>>       int b = g();
>>       return a + b;
>> }
>>
>>     push    {r3, r4, r5, lr}
>>     movw    r3, #:lower16:s
>>     movt    r3, #:upper16:s
>>     ldr    r4, [r3]
>>     blx    r4
>>     mov    r5, r0
>>     blx    r4
>>     add    r0, r0, r5
>>     pop    {r3, r4, r5, pc}
>>
>> Regards.
> 
> My problem is that the actual (*s.f)() call is an implementation detail.
> I have a function which returns a timestamp via an architecture specific
> way, e.g. on PowerPC this is something like this:
> 
> static inline int timestamp(void)
> {
>   int t;
>    __asm__(... t ...).
>   return t;
> }
> 
> On SPARC this is something like this:
> 
> static inline int timestamp(void)
> {
>   return (*s.f)();
> }
> 
> So, I cannot use a local variable for this particular use case.

So you are saying that your code fragment with the two calls to s.f() is
actually the result of gcc inlining the call to timestamp?
-- 
Matthias Pfaller                          Software Entwicklung
marco Systemanalyse und Entwicklung GmbH  Tel   +49 8131 5161 41
Hans-Böckler-Str. 2, D 85221 Dachau       Fax   +49 8131 5161 66
http://www.marco.de/                      Email leo@marco.de
Geschäftsführer Martin Reuter             HRB 171775 Amtsgericht München

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4349 bytes
Desc: S/MIME Cryptographic Signature
URL: <https://gcc.gnu.org/pipermail/gcc-help/attachments/20160622/3d6ac2c0/attachment.p7s>


More information about the Gcc-help mailing list