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

Sebastian Huber sebastian.huber@embedded-brains.de
Wed Jun 22 08:21:00 GMT 2016



On 22/06/16 10:08, Matthias Pfaller wrote:
> 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?

Yes.

-- 
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.



More information about the Gcc-help mailing list