avr-gcc-list
[Top][All Lists]
Advanced

[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: Neil Johnson
Subject: Re: [avr-gcc-list] 8 bit bitwise operation promoted to 16 bit values
Date: Sun, 26 Oct 2003 15:57:31 +0000 (GMT)

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 ) )
    {
        ...
    }

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 ) )
    {
        ...
    }

Also looks nicer IMHO :-)

Cheers,
Neil

--
Neil Johnson :: Computer Laboratory :: University of Cambridge ::
http://www.njohnson.co.uk          http://www.cl.cam.ac.uk/~nej22
----  IEE Cambridge Branch: http://www.iee-cambridge.org.uk  ----


reply via email to

[Prev in Thread] Current Thread [Next in Thread]