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