I can not understand why GCC compiler cutting out part of my code while it preserve absolutely the same one in the neighborhood?
The C code:
#define setb_SYNCO do{(PORTA|= (1<<0));} while(0);
ISR(INT0_vect){
unsigned char i;
i = 10;
while(i>0)i--; // first pause - omitted
setb_SYNCO;
setb_GATE;
i=30;
clrb_SYNCO;
while(i>0)i--; // second pause - preserved
clrb_GATE;
}
The corresponding part of LSS (assembler file, created by the compiler):
ISR(INT0_vect){
a4: 1f 92 push r1
a6: 0f 92 push r0
a8: 0f b6 in r0, 0x3f ; 63
aa: 0f 92 push r0
ac: 11 24 eor r1, r1
ae: 8f 93 push r24
unsigned char i;
i = 10;
while(i>0)i--;
setb_SYNCO;
b0: d8 9a sbi 0x1b, 0 ; 27
setb_GATE;
b2: d9 9a sbi 0x1b, 1 ; 27
i=30;
clrb_SYNCO;
b4: d8 98 cbi 0x1b, 0 ; 27
b6: 8e e1 ldi r24, 0x1E ; 30
b8: 81 50 subi r24, 0x01 ; 1
while(i>0)i--;
ba: f1 f7 brne .-4 ; 0xb8 <__vector_1+0x14>
clrb_GATE;
bc: d9 98 cbi 0x1b, 1 ; 27
}
be: 8f 91 pop r24
c0: 0f 90 pop r0
c2: 0f be out 0x3f, r0 ; 63
c4: 0f 90 pop r0
c6: 1f 90 pop r1
c8: 18 95 reti
I could assume that compiler figure out that such code is dummy and cuts it out but why is it preserve the same one in the end of the code?
Is there any compiler instructions to prevent from such optimization?
Best Answer
Since in one comment you state that "each CPU tick is worthy" I suggest using some inline assembly to make your delays loop just as you want. This solution is superior to the various
volatile
or-O0
because it makes clear what your intent is.That should do the trick. The volatile thing is there to tell the compiler "I know this does not do anything, just keep it and trust me". The three asm "statements" are quite self explanatory, you can use any register instead of r24, I believe the compiler likes lower registers so you might want to use a high one. After the first
:
you should list output (read and write) c variables, and there's none, after the second:
you should list input (ronly) c variables, again, there is none, and the third parameter is a comma separated list of modified registers, in this case r24. I am not sure if you should include also the status register since theZERO
flag changes of course, I did not include it.edit edited answer as OP requested. Some notes.
The
"+rm"
before(i)
means that you are letting the compiler decide to place i in memory or in a register. That's a good thing in most cases since the compiler can optimize better if it's free. In your case I believe you want to keep only the r constraint to force i to be a register.