c - When would the compiler be conservative regarding pointer dereferencing optimization, if at all? -


so, took interest in how compiler (gcc (gcc) 4.8.3 being 1 in question) in optimizing pointers , pointers.

initially created simple integer , integer pointer , realized operations on print out. expected, operations hard coded optmized, through dereferenced pointer or not.

call    __main leaq    .lc0(%rip), %rcx movl    $1, %edx call    printf 

and after creating function takes in int pointer, dereferences , changes it still optmized.

call    __main leaq    .lc0(%rip), %rcx movl    $-1, %edx call    printf 

now, when treated pointer void , made changes casting char , dereferencing it, still optmized (an 'extra' mov call since treated 8 byte value, , 1 byte value pointer dereferencing)

call    __main movl    $4, 44(%rsp) movb    $2, 44(%rsp) leaq    .lc0(%rip), %rcx movl    44(%rsp), %eax leal    1(%rax), %edx call    printf 

so onto question(s):

  1. how consistent compiler optimization regarding pointer dereferencing? cases chose conservative?

  2. if of pointers in project declared restrict keyword, trust optimized if 'no pointers being used @ all'?

(assuming there no volatile cases )

ps¹.: aware compiler enough job, , programmer worrying aiding compiler in minor optimizations is, in general, unproductive (as many point out in stackoverflow answers questions regarding optimization). yet still have curiosity regarding matter.

ps².: gcc -o3 -s -c main.c command used generate assembly code

c code: (as requested)

1:

#include <stdio.h>  int main (void) {     int = 4;     int *ap = &a;      *ap = 0;     += 1;      printf("%d\n", a);     return 0; } 

2:

#include <stdio.h>  void change(int *p) {     *p -= 2; }  int main (void) {     int = 4;     int *ap = &a;      *ap = 0;     change(ap);     += 1;      printf("%d\n", a);     return 0; } 

3:

#include <stdio.h>  void change(void *p) {     *((char*)p) += 2; }  int main (void) {     int = 4;     void *ap = (void*) &a;      *((char*)(ap)) = 0;     change(ap);     += 1;      printf("%d\n", a);     return 0; } 

llvm , gcc both emit static-single-assigment form code part of optimization analysis. 1 of useful properties of ssa code precisely shows flow of influence assignment -- is, knows assignments lead other assignments , can detect values can influence others.

the first influence chain looks like

a1 -> constant(0) -> ap -> a2

the second: a1 -> constant(0) - > ap -> p -> a2

the third being pretty similar second. (sorry, notation pretty made-up hope illustrates point.)

because simple prove influence of on ap deterministic, feel free dereference 'early' , combine instructions 1 (though in first 2 cases isn't accurate statement since constant overwrites original reference , lets compiler prove original assignment not flow end of code.

causing compiler more conservative dereferencing involve getting complicated enough escape compiler's understanding (difficult in static program think) or more causing compiler invoke phi function in process of ssa (in laymen's terms, cause assignment influenced multiple previous assignments) in nondeterministic way.

the restrict keyword has purpose of hinting compiler 2 pointers different. wouldn't restrict use of dereference @ runtime if code produced pointer still had nondeterministic source (for example, if runtime-created data influenced choice of pointer value dereferenced- think happen if serialized pointer sent program external source?)


Comments