Yes, signed types always have such issues. That is a big reason why I started by saying you should /never/ be using "char" for arithmetic - always use int8_t or uint8_t (or int_fast8_t, uint_least8_t, etc., or application-specific typedefs of these). Leave "char" for holding characters - ASCII letters and elements of an ASCII string.
On a chip like the AVR, don't use signed types for arithmetic unless you actually need negative values, as they are less efficient in some circumstances. mvh., David On 31/12/2020 18:18, Jochen Barth wrote: > Thanks. Did forget to mention that *16/256 instead of >>4 does insert > some code to add ((2^n) -1) on negative values (because /16 and >>4 is > not the same). > > So a direct optimization on shr would be better. > > Kind regards, Jochen > > > Am 30.12.20 um 12:19 schrieb David Brown: >> Hi, >> >> As a general point, never use "char" like this - use either uint8_t or >> int8_t depending on whether you want signed or unsigned. Usually if you >> are doing shifts, it's uint8_t you want. >> >> The AVR compiler has trouble with some of these kinds of expressions. I >> think it has something to do with the way gcc handles them (most cpus >> have instructions for multiple shifts or rotates) combined with the >> integer promotion. The AVR gcc port has 16-bit int (it's the smallest >> size allowed by C and C++), which means everything has to be done with >> double registers, then there are peepholes and other optimisation passes >> that try to remove the redundant code. A lot of that is manual work >> added to the compiler, and so there are bound to be combinations that >> have not been included. Each suboptimal combination has to be spotted, >> then added to the compiler. >> >> The different rearrangements done earlier in the compile process can >> also mean that the internal code passed to the backend optimiser can >> vary substantially. For example, with most gcc ports, you can split >> expressions into multiple local variables without it affecting the >> (optimised) results. For the AVR, that does not always apply. >> >> This all means it is not easy to guess the source code to use to get the >> optimal results. These three versions all give the same code for both C >> and C++, with shorter and faster code than 5 shifts (it has one >> nibble-swap, one shift and one mask). >> >> uint8_t u; >> >> void fooa(void) { >> u = ((u & 0xe0) >> 5); >> } >> >> void foob(void) { >> u = u / (1u << 5); >> } >> >> void fooc(void) { >> u = (u >> 5) & 0x07; >> } >> >> >> You can also consider using the "-mint8" flag. That breaks C >> compatibility but it can be useful for small programs, and can often >> result in better code. Be very careful to stick to <stdint.h> types >> rather than "int" and "long" if you are trying this! >> >> David >> >> >> >> On 29/12/2020 21:00, Jochen Barth wrote: >>> I'm using Arduino 1.8.13 with avr-g++ (GCC) 7.3.0. >>> >>> char x; >>> x >>= 5 generates asm (promoted to 16 bit signed) with 5* asr+ror; >>> x = x * (1<<(8-5)) / 256 >>> generates 5* asr (without type promotion). >>> >>> Kind regards, >>> Jochen >>> >>> >>> Weddington, Eric Mon, 08 Nov 2010 04:25:48 -0800 >>>> -----Original Message----- >>>> From: >>>> avr-gcc-list-bounces+eric.weddington=atmel....@nongnu.org >>>> [mailto:avr-gcc-list-bounces+eric.weddington=atmel....@nongnu. >>>> org] On Behalf Of William "Chops" Westfield >>>> Sent: Sunday, November 07, 2010 9:58 PM >>>> To: avr-gcc-list@nongnu.org >>>> Subject: [avr-gcc-list] odd optimization differences of shift >>>> between C andC++ >>>> >>>> >>>> >>>> Is this expected? Is it bug-worthy ? >>>> >>> I would say that it's bug-worthy, as a missed optimization bug. FYI, >>> there are >>> more bugs with the C++ compiler for the AVR than for the C compiler. >>> So I'm not >>> totally surprised that this is happening. >>> >>> BTW, could you please subscribe to the mailing list? That way your >>> posts do not >>> have to be approved by hand. >>> >>> _______________________________________________ >>> AVR-GCC-list mailing list >>> AVR-GCC-list@nongnu.org >>> http://lists.nongnu.org/mailman/listinfo/avr-gcc-list >>>