https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64119
Andrew Pinski <pinskia at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> --- (In reply to Adam Warner from comment #3) > Seriously Andrew? Here's an opportunity to reconsider your closing of the > bug report. Did you read the documentation I pointed out? Because it is obvious you did not. > > //asm triggers local register variable data corruption > #include <stdio.h> > > __attribute__((noinline)) void fn(int inputa, int inputb, int inputc) { > register int a asm ("rax"); > register int b asm ("rbx"); > register int c asm ("rcx"); > > a = inputa; b = inputb; c = inputc; > printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, > c); > > a = inputa; b = inputb; c = inputc; > printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, > c); > > a = inputa; b = inputb; c = inputc; > asm volatile ("mov %0, %0; mov %1, %1; mov %2, %2" : "+r" (a), "+r" (b), > "+r" (c)); > printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, > c); > > a = inputa; b = inputb; c = inputc; > printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, > c); > } > > int main(void) { > fn(1, 2, 3); > return 0; > } > > $ clang-3.6 -O3 gcc-asm-reg-var-data-corruption_b.c && ./a.out > The values of a, b and c are 1, 2 and 3 respectively > The values of a, b and c are 1, 2 and 3 respectively > The values of a, b and c are 1, 2 and 3 respectively > The values of a, b and c are 1, 2 and 3 respectively > > $ gcc-4.9 -O3 gcc-asm-reg-var-data-corruption_b.c && ./a.out > The values of a, b and c are 1, 2 and 3 respectively > The values of a, b and c are 1, 2 and 3 respectively > The values of a, b and c are 53, 2 and 39 respectively > The values of a, b and c are 1, 2 and 3 respectively What GCC is optimizing it to: #include <stdio.h> __attribute__((noinline)) void fn(int inputa, int inputb, int inputc) { register int a asm ("rax"); register int b asm ("rbx"); register int c asm ("rcx"); a = inputa; b = inputb; c = inputc; printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, c); printf("The values of a, b and c are %d, %d and %d respectively\n", inputa, inputb, inputc); asm volatile ("mov %0, %0; mov %1, %1; mov %2, %2" : "+r" (a), "+r" (b), "+r" (c)); printf("The values of a, b and c are %d, %d and %d respectively\n", a, b, c); printf("The values of a, b and c are %d, %d and %d respectively\n", inputa, inputb, inputc); } Aka it is treating the local register variables as normal variables except for inline-asm. > > Do you claim that one may not assign values to explicit register variables? > (which clearly appears to be happening when a, b and c are again set to a = > inputa; b = inputb; c = inputc; as evidenced by the output of the fourth > printf statement) No you can assign them, except they got optimized like normal variables in most cases that means the assignments might be optimized away if there is already an assignment. > > GCC is ignoring the variable assignments in the presence of a harmless asm > statement. No it is not see above on how GCC optimizes it and read the documentation again about what is going on. > > At this stage I cannot accept your justification for the compiler output. > What is your computational model? It is standard C one. ... clang output which is not useful this for discussion because this is about the documentation of GCC and use in GCC .... > > I've only used features supported by both gcc and clang. clang's output is > sensible and fits my mental model of the C virtual machine. gcc's output is > really surprising and I've had a lot of experience manipulating gcc via > inline asm. Are you sure gcc's output is justified? Yes re-read the documentation. I explicitly put it here for you to understand what GCC is doing. I will again copy and paste the most important part of the documentation for you to understand what is going on here: References to local register variables may be deleted or moved or simplified. --- CUT --- They are being moved and simplified to only assigned before the first printf. If you don't like that then create a new local register variable each time and GCC won't optimize them away.