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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





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@xxxxxxxxxxxxxxxxxx
PGP     : Public key available on request.

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





[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux