Re: Optimisation mixes up registers in inline assembly

David Brown <[email protected]> Wed, 24 Jul 2019 23:00:07 +0200
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <[email protected]>
On 24/07/2019 21:41, Michael Kwasnicki wrote:
> So the inputs to inline assembly are by value and not by reference, as I 
> thought. Right?

Correct.  The inputs are used to initialise the registers.

> The correlation between my named registers and those C variables was 
> pure coincidence.

No, it is pure optimisation, not coincidence.  And of course you don't 
necessarily get registers for variables in C - certainly not for const 
values.

> And by making the named registers both - input and output - it creates a 
> reference to the original C variable.

Yes, roughly.

The big question here is why you are using assembly at all.  Why not 
just write in C?

void test2(void) {
     uint8_t size = 42;
     const uint8_t start = _BV(WGM02) |  _BV(CS00);
     const uint8_t stop = 0x00;
     TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
     OCR0A = 9;                              // TOP
     const uint8_t zero = 1;                 // 0 < i <= TOP
     const uint8_t one = 7;                        // 0 < i <= TOP

     OCR0B = one;
     TCCR0B = start;

     while (size--) {
         for (uint8_t bits = 0; bits < 8; bits++) {
             OCR0B = one;
         }
         OCR0B = zero;
     }
     TCCR0B = stop;
}

It is simpler, easier to understand, much easier to get right, and gives 
code that is marginally smaller and faster than your hand-written 
assembly.  (It is even better with -O2, which is the optimisation level 
I recommend as usually giving smaller and faster code than -Os.)

mvh.,

David



> 
> Regards,
> 
> Michael K.
> 
> 
> 
>> Am 24.07.2019 um 19:17 schrieb Joseph C. Sible <[email protected] 
>> <mailto:[email protected]>>:
>>
>> Since you intend to modify the inputs, you need to declare them as 
>> outputs as well (with the + constraint). If you don't do this, GCC is 
>> allowed to assume you don't write to them, and can share any that have 
>> the same values.
>>
>> Joseph C. Sible
>>
>>
>> On Wed, Jul 24, 2019, 13:04 Michael Kwasnicki <[email protected] 
>> <mailto:[email protected]>> wrote:
>>
>>     Hello dear list members,
>>
>>     I am new to this list because I need someone to discuss a
>>     potential compiler bug.
>>
>>
>>     I try to mix inline assembly in C code. In the assembly I use
>>     passed in variables which are named:
>>
>>     _https://godbolt.org/z/w8wuJy_
>>     _
>>     _
>>     The register mapping is:
>>     [rZero] -> R20
>>     [rOne] -> R21
>>     [rStart] -> R18
>>     [rStop] -> R19
>>     [rSize] -> R22
>>     [bits] -> R19
>>
>>     If I look at the output assembly I can see the compiler did some
>>     optimisation.
>>     R19 is shared between [bits] and [rStop].
>>     In this case this is okay as the bit count reaches zero at the end
>>     and thus [bits] and [rStop] have the same value then.
>>
>>
>>     But when I change the initial value of `bitcount` in C to 7 all
>>     hell breaks loose.
>>
>>     https://godbolt.org/z/F7rrB_
>>
>>     The register mapping is:
>>     [rZero] -> R20
>>     [rOne] -> R18
>>     [rStart] -> R19
>>     [rStop] -> R21
>>     [rSize] -> R22
>>     [bits] -> R18
>>
>>     This time the compiler optimisation corrupted the program.
>>     R18 is shared between [rOne] and [bits]. [rOne] was supposed to be
>>     a constant that is cached in a register. But [bits] gets decremented.
>>     Thus the value passed to OCR0B varies and is not constant any more
>>     changing the logic of the inline assembly.
>>
>>     I am not experienced with inline assembly so I might have missed
>>     something but my general expectation for assembly is that if I
>>     name things differently, they are different things (registers in
>>     this case).
>>
>>     The issue does not show up with -O0 but anything above.
>>     Locally I am running avr-gcc (GCC) 9.1.0. Not sure what the exact
>>     version at godbolt is.
>>
>>     Cheers,
>>
>>     Michael
>>     _______________________________________________
>>     AVR-GCC-list mailing list
>>     [email protected] <mailto:[email protected]>
>>     https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
>>
> 
> 
> _______________________________________________
> AVR-GCC-list mailing list
> [email protected]
> https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
> 


_______________________________________________
AVR-GCC-list mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list