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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Re: Inline vs. ? : operator


From: David Brown
Subject: [avr-gcc-list] Re: Inline vs. ? : operator
Date: Sat, 27 Mar 2010 20:22:00 +0100
User-agent: Thunderbird 2.0.0.23 (Windows/20090812)

Szikra Istvan wrote:
/**
Category: optimization miss
affects: avr-gcc 4.x.x
'?:' operator bit write generates unnecessary 'in' instruction in
inline functions.

I had a problem with my bit set macro and inline functions (among
other things). Though I found a workaround, I thought I'll share my
experience.

I have this 2 macros:
#define bit_write(p,b,c)        (c ? bit_set(p,b) : bit_clear(p,b))
#define bit_write_fix(p,b,c)    if (c) { bit_set(p,b);}else bit_clear(p,b)

The first works fine with constant parameters, but produces an extra
'in' instruction if called from static inline function.
The second works fine in both cases. Of course the inline functions
are called with constants.

My question is why is that?
It seems to be a bug to me. (It only affects gcc 4.x, good old gcc
3.4.6 works perfectly. )

I'm not a C expert, maybe I'm just missing something.
Any suggestions on the code, or maybe compiler parameters?


You /are/ missing something - gcc 4.x is working correctly and 3.4.6 apparently has a bug. When you write "c ? bit_set(p, b) : bit_clear(p, b)" as a statement, you are really saying "Depending on the value of c, evaluate bit_set(p, b) or bit_clear(p, b). Since I'm not using the result, discard it". Evaluating the result of "p |= BIT(b)" means carrying out the or-assign, then reading the value of p and returning it. Since p is volatile, that means a new "in" instruction to read it. This is required behaviour for a volatile, even if the value is not used.

Hope that makes things clearer for you.

mvh.,

David



--Details:
-environment: WinAVR-20070525, 20080610,20081205,20090313,20100110
(avr-gcc 4.3.x )
(WinAVR-20060421 3.4.6 works)

-build command:
avr-gcc -mmcu=atmega16 -save-temps -Os test.c
or WinAVR Makefile Template

Here is the test code:
*/

#include <avr/io.h>

#define BIT(x) (0x01 << (x))
#define bit_set(p,b) ((p) |= BIT(b))
#define bit_clear(p,b) ((p) &= ~BIT(b))
#define bit_write(p,b,c) (c ? bit_set(p,b) : bit_clear(p,b))
#define bit_write_fix(p,b,c) if (c) { bit_set(p,b);}else bit_clear(p,b)

static inline void t_sw(char bit, char enable)
{
  enable ? bit_set(PORTA,bit) : bit_clear(PORTA,bit);
}
static inline void t_ie(char bit, char enable)
{
  if (enable) {
    bit_set(PORTA,bit);
  }else{
    bit_clear(PORTA,bit);
  }
}

static inline void t_BW(char bit, char enable)
{
  bit_write(PORTA,bit,enable);
}
static inline void t_BWF(char bit, char enable)
{
  bit_write_fix(PORTA,bit,enable);
}

int main (void)
{
  bit_write(PORTA,0,0);         /// cbi 59-32,0
  t_sw(2,0);                    /// cbi 59-32,2
                                /// in r24,59-32
  t_ie(3,0);                    /// cbi 59-32,3
  t_BW(1,0);                    /// cbi 59-32,1
                                /// in r24,59-32
  t_BWF(4,0);                   /// cbi 59-32,4
  bit_write_fix(PORTA,5,0);     /// cbi 59-32,5

  for (;;)  {
  }
}
/*
avr-gcc (WinAVR 20100110) 4.3.3
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=16000000UL
-DBOOTSIZE=1024  -Os -funsigned-char -funsigned-bitfields
-fpack-struct -fshort-enums -fno-strict-aliasing
-fno-inline-small-functions  -save-temps  -Wall -Winline
-Wstrict-prototypes -Wa,-adhlns=test.lst -ID:/Lib/ -std=gnu99 -MD -MP
-MF .dep/test.o.d test.c -o test.o
avr-gcc -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=16000000UL
-DBOOTSIZE=1024  -Os -funsigned-char -funsigned-bitfields
-fpack-struct -fshort-enums -fno-strict-aliasing
-fno-inline-small-functions  -save-temps  -Wall -Winline
-Wstrict-prototypes -Wa,-adhlns=test.o -ID:/Lib/ -std=gnu99 -MD -MP
-MF .dep/test.elf.d test.o --output test.elf -Wl,-Map=test.map,--cref
-lm -Wl,--section-start=.bootloader=0x3800
*/
/*
avr-gcc (GCC) 3.4.6
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

avr-gcc -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=8000000UL -Os
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wundef -Wa,-adhlns=obj/test.lst -std=gnu99
-Wundef -MD -MP -MF .dep/test.elf.d test.c --output test.elf
-Wl,-Map=test.map,--cref -lm
*/
///(I get "../../../../../avr-libc-1.4.4/crt1/gcrt1.S:51: undefined
reference to `main'" error when use -save-temps option with gcc 3.4.6,
anyone has an idea why is that?)







reply via email to

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