Search code examples
cgccoptimization

Does gcc cache the address of a global array at a static index by default?


Let's say I have the global array char global_array[3] = {33, 17, 6}; and I access global_array[1]. When gcc interprets global_array[1], will it add 1 to the address of global_array at runtime, or change global_array[1] to a static address, assuming -O0? If not, is there a compiler flag to for gcc to make the static index of an array a static pointer?


Solution

  • When gcc interprets global_array[1], will it add 1 to the address of global_array at runtime, or change global_array[1] to a static address, assuming -O0?

    There's no particular guarantees of what gcc does and does not depending on level of optimization. Take your example under gcc 12.2 for x86_64:

    int func (void)
    {
      char global_array[3] = {33, 17, 6};
    
      return global_array[1];
    }
    

    This results in peculiar assembly code under -O0:

    func:
    
      push    rbp
      mov     rbp, rsp
      mov     WORD PTR [rbp-3], 4385
      mov     BYTE PTR [rbp-1], 6
      movzx   eax, BYTE PTR [rbp-2]
      movsx   eax, al
      pop     rbp
      ret
    

    It is storing the array of the stack but it loads the magic number 4385 as a word, then loads a 6 at the end. Now wth is 4385? It is 0x1121 hex. Where the bytes have values 0x11 = 17dec and 0x21 = 33, and since it is a x86 little endian, the byte order for the WORD instruction is reversed vs the order of the array.

    This word write is already some manner of mini-optimization even though I used -O0. So again - no guarantees. Regarding your question, the access part rbp-2 is indeed similar to adding 1 the to the address in runtime. In this case it is subtracting an offset from the stack frame pointer, but that's essentially the same thing (and likely as fast/slow as adding 1 to an address).

    The normal thing when optimizations are enabled would otherwise be to replace the whole thing with the absolute value.

    If not, is there a compiler flag to for gcc to make the static index of an array a static pointer?

    Messing around with compiler options is probably not how. If you wish to have a pointer to a fixed address, then this is the usual steps:

    • Create a custom segment at a fixed address in the linker script for the specific target.
    • Declare your array at file scope and use gcc variable attributes to allocate it inside your custom segment.
    • Now &global_array[1] is always the same address.