On 06/22/2016 10:21 AM, Sebastian Huber wrote: > > > 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. In that case your options are very limited :-( Its ugly, but the only way I can see: #if defined(PLATFORM_SPARC) #define timestamp (*s.f) #endif now you can use the suggested work around using a local variable: func *g = timestamp; Be aware that in the powerpc case gcc will treat the __asm__ as __attribute__((const)) when it has no inputs. Thus it will emit the code in __asm__ only once and multiply by two... -- 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@xxxxxxxx Geschäftsführer Martin Reuter HRB 171775 Amtsgericht München
Attachment:
smime.p7s
Description: S/MIME Cryptographic Signature