[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values
From: |
Theodore A. Roth |
Subject: |
Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values |
Date: |
Sun, 26 Oct 2003 09:17:17 -0800 (PST) |
On Sun, 26 Oct 2003, Neil Johnson wrote:
> Alex,
>
> > I was surprised a while ago to learn that the compiler can promote 8 bit
> > bitwise operations to 16 bit sometimes, so I had a look through some of
> > my code and looked at the LST files and sure enough there were some.
>
> Well, its more a case of the compiler must behave as if they are always
> promoted (this is defined in the language standard), but can optimize the
> code where the compiler can determine that such optimization is safe (i.e.
> will produce code that behaves exactly *as if* the expression was computed
> all in ints).
>
> > if( RxByte & 0x80 )
>
> Here the optimizer can determine that 0x80 will fit into an 8-bit unsigned
> char, so the result will be either 0x00 or 0x80 and thus can be optimized
> to 8-bit ops.
>
> > if( ( ( LN_TX_PORT >> LN_TX_BIT ) & 0x01 ) == ( ( LN_RX_PORT >>
> > LN_RX_BIT ) & 0x01 ) )
>
> Why do it this way? Seems a tad silly to pay the cost of two runtime
> shifts. Why not do:
>
> if ( LN_TX_PORT & ( 0x01 << LN_TX_BIT ) ==
> LN_RX_PORT & ( 0x01 << LN_RX_BIT ) )
> {
> ...
> }
Won't this always evaluate to false unless (LN_TX_BIT == LN_RX_BIT)?
The only way I can see this working is like this:
if ( LN_TX_PORT & ( 0x01 << LN_TX_BIT ) &&
LN_RX_PORT & ( 0x01 << LN_RX_BIT ) )
{
...
}
>
> In this code the two shifts should be folded by the compiler into
> constants (this is mandated by the standard), reducing the expression to
> two 8-bit bitwise ANDs and a compare. The optimizer should be able to
> convert this into 8-bit ops.
>
> > if( ( ( LN_TX_PORT >> LN_TX_BIT ) & (byte)0x01 ) == ( ( LN_RX_PORT >>
> > LN_RX_BIT ) & (byte)0x01 ) )
>
> Unlikely to help, and the shift will still cause a promotion to int.
>
> > register byte Mask ;
> > Mask = 0x01 ;
> > if( ( ( LN_TX_PORT >> LN_TX_BIT ) & Mask ) == ( ( LN_RX_PORT >>
> > LN_RX_BIT ) & Mask ) )
>
> A nasty trick to force the optimizer to spot something which can be
> avoided with a bit of careful code (see above). Even better might be to
> use the bit test macros that are, I believe, in the libs somewhere.
> E.g. use the "bit_is_set" macro, the code becomes:
>
> if ( bit_is_set( LN_TX_PORT, LN_TX_BIT ) ==
> bit_is_set( LN_RX_PORT, LN_RX_BIT ) )
> {
> ...
> }
Likewise here since bit_is_set() is defined by avr-libc thusly:
#define bit_is_set(sfr, bit) (sfr & _BV(bit))
Again, I think replacing '==' with '&&' will correct the code.
Other than those logical errors, I think Neil's comments ring true.
Ted Roth
- [avr-gcc-list] RE: eeprom section and ld scripts, Bill Somerville, 2003/10/25
- [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Alex Shepherd, 2003/10/26
- Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Neil Johnson, 2003/10/26
- Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values,
Theodore A. Roth <=
- Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Neil Johnson, 2003/10/26
- RE: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Alex Shepherd, 2003/10/26
- Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, David Brown, 2003/10/27
- RE: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Alex Shepherd, 2003/10/27
- Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Neil Johnson, 2003/10/27
- RE: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values, Neil Johnson, 2003/10/27