"Promote char to int" revisited

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There have been spirited discussions in the past on when/why/how C compilers do/should automatically widen operations from 8-bit to 16-bit. In tight microcontroller apps with lots of references to 8-bit variables the widening can cause much larger code. This thread has much of the pros-and-cons:
https://www.avrfreaks.net/index.p...

So we find clawson saying:

Quote:
So compilers that generate 8 bit access code without being forced to do so are not adhering to C standards!
(speaking about widening constants) and Dean:
Quote:
C likes to promote pretty much everything and anything to an int.

I was looking up something in my dusty 1989 "ANSI C: A Lexical Guide"/Mark Williams and came across the "as if rule":

Quote:

The Standard does not command implemetors to implement all of its models and standards. Rather, implementors should write their implementations to bring about the same result, as if the model had been implemented directly.

For example, consider the following expression:

char c1, c2, c3;
c2 = c1 + c3;

The Standard states that such an expression must be performed as if c1 and c3 had been promoted to ints before performing the arithmetic. An implementor, however, may choose not to promote the operands to ints if the same result is obtained. It is as if the operands were promoted and integer arithmetic performed, when in fact, the program was optimized by performing character arithmetic.

Now, the referenced thread dealt with widening constants, not variables. I'd assume the same rationale would apply. Also, this was the first "ANSI C" and there have been several standard C releases since then. And this is one author's interpretation.

But according to this, compilers CAN e.g. do 8-bit switch() if they want, or not widen a constant as in the referenced thread, etc. Not widening is not non-conforming according to the as-if rule.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sure, the "as if" rule still applies. It's a general concept of the C
standard. So it's not strictly required to perform the 16-bit expansion,
but the code must behave same as if it were doing so. In the above simple
expression, demonstrating this is trivial. When it comes to more complex
expressions, obeying all the rules might not be that trivial. Usually,
you'll probably have the compiler core expand it as requested, and then
see that the optimizer can detect thos situations where the upper byte
is not needed.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lee,

Sadly I'm unable to back up that statement as the entire post said:

Quote:
By the way, just to stoke the compiler wars a little more, as I Googled it seems the C standard suggests that integer constants are auto-sized according to what they will fit into from the sequence int...long...unsigned long

So if one uses the literal 0x5F then the C compiler *should* interpret it as an int and hold it as 005F (int on AVRis 16 bit). So compilers that generate 8 bit access code without being forced to do so are not adhering to C standards!


and I'm no longer able to remember where Google took me to suggest that "it seems the C standard suggests that integer constants are auto-sized". But this was about auto-sizing of contants, not variables as the piece you quoted seems to relate to.

But as this seems to be a missive in Compiler Wars Round 71 I will point out that in the same thread I also said:

Quote:
If code space is so tight that a number of 16 bit comparisons where 8 would do are adding so much code that it bursts the device size then maybe it's time to look at using one the commercial compilers. On the whole their only selling point over GCC these days seems to be better code density - but in this case that seems to be what you need

and

Quote:
Well the "quick" fix, if speed is an issue, may still be to buy a commercial compiler. Several are available to download and unlock with an emailed key so you could have a full version within 1 day if time is of the essence.

OTOH you could get the source for avr-gcc and "correct" it's behaviour!


Those of us who use GCC *know* that it's optimisation may not be as "tight" as the AVR specific compilers as the AVR port is working on top of a core that generically tries to support far more architectures than any other copiler.

So it isn't perfect. But the last senetence in that last quote is perhaps the most telling. I'm not aware of another AVR compiler where, if you don't like the way it's optimising things, you have the opportunity to re-engineer it yourself!

In it's defence I would also point out that optimisation is known to be one of the weaknesses in the 3.x compiler that was used in that original thread and 4.x is proven to be far "tighter" for AVRs though I'm afraid that without access to a copy myself I'm unable to say whether that 0x5F literal constant in the original thread is promoted to 16 bits by 4.x or not. (I have a sneaking suspicion I may be able to guess the answer though!)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff--I just used that thread as one that I knew I could find. There have been other discussions on this over the years on this, not only in the GCC Forum. And (this time :) ) it wasn't intended to be another Compiler Wars volley--kind of closer to the C vs. ASM battles: "Why should I use C when the unnecessary bloated code in my crafted small app makes it bigger and slower"?

I had never noticed the "as if rule" entry in my book before, and thought it was interesting and pertinent to ongoing AVR discussions. In particular, AFAIK the mainstream AVR C compilers use 8-bit "char" and 16-bit "int"/"short". Many of the "rules" references on widening say something like "short or bigger as needed" which leads to not doing 8-bit in many scenarios. I do a lot of Mega48-class apps, and careful use of 8-bit register (especially) vars for the "main" data items with many, many accesses can reduce code size dramatically. E.G., the main program "state" might have a few dozen states, and I often use a switch() on them. With constant case expressions the generated if/else is a lot tighter & faster with 8-bit.

I'm not a Standard C scholar; I defer to those that know where to find the reference to where it states how things should be done. But I've been doing this C thing for 20 years now on many platforms. I pretty much try to use vanilla C as much as practical, maybe just to make it easier to understand next year when I need to go back to it. There was always the pang in my heart when "forcing" 8-bit work, as with other compiler extensions--am I sinning against the Standard? After reading about the as-if rule I can now continue packing into my Mega48 with a clear conscience.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

In it's defence I would also point out that optimisation is known to be one of the weaknesses in the 3.x compiler that was used in that original thread and 4.x is proven to be far "tighter" for AVRs though I'm afraid that without access to a copy myself I'm unable to say whether that 0x5F literal constant in the original thread is promoted to 16 bits by 4.x or not. (I have a sneaking suspicion I may be able to guess the answer though!)

There's a pre-built WinAVR-friendly version of GCC4.1.x and Binutils avaliable from here - just extract it to your WinAVR directory and overwrite the existing files.

My experience has shown that GCC4.1 produces significantly small code.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Dean, I noticed you mentioned 4.1 in another thread and was wondering where you'd got it from - downloading now.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a "prerelease" version apparently, so don't blame me (or the person who built that) if something goes terribly wrong! I've had zero troubles with it and the code it produces is MUCH better than 3.4; I was seeing a 10%-20% code size reduction.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dean,

Sorry to go off-topic but if I rebuild any of my projects using this 4.1.1 compiler and then try to load the .elf into the simulator I see:

Error loading object file C:\Documents and 
Settings\Cliff\tny26\default\tny26.elf

I guess you presumably aren't seeing this?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm getting that also - but I put it down to a configuration error in my Studio. I didn't realise that it and the new compiler were related; perhaps an email to the person who compiled the package (AtmanAVR) would be in order?

- Dean :twisted:

PS: Curiously, I can still open some ELFs fine - ones build before GCC4.1. Again, didn't realise the two were connected.

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So what we seem to be saying is that the 4.1.1 ELF output format is not compatible with Studio 490. Sadly for me that makes the thing pretty pointless as I either use the compiler output in the simulator or over JTAG/debugwire from Studio. Roll on the next WinAVR where I'd kind of hope the issue would have been resolved.

I wanted to try the original CANGIT & 0x5F thing to see what code 4.1.1 produces for it. Myabe I should just look at the .LSS instead?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Would the problem be in the Binutils or the compiler do you think? Perhaps it would be possible to keep the older compiler named slightly differently, then use that to link the ELF?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well it's the linker that generates the .elf then the other binutils extract various forms of data from this .elf - I guess only the chaps developing Studio can really know what it is in the modified .elf format that their loader doesn't like the look of.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Still OT, but...

My copies of avr-binutils 2.16.1, avr-gcc 4.1.1, and avr-libc 1.4.4, which I built myself from the sources under Cygwin, does produce ELF output that debugs correctly inside the AVR Studio Simulator.

But I only included Jörg's official newdevices, coff, and 0b-constants patches from the freebsd ports system CVS. I didn't include the prerelease patches for ATmega256x support.

abcminiuser wrote:

It's a "prerelease" version apparently

BTW, GCC 4.1.1 is a full release, it's only the AVR portion of the toolchain that is still considered "under development". And from what I can tell, that's mostly because of the ATmega256x.

- Luke

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Would you mind sharing? I lack the know-how to get it all built myself with all the appropriate patches. I don't care about 256x support - all I want is the better optimizations.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe AtmanAVR has (accidentally?) included the 32-bit DWARF-2 patch?
This is supposed to overcome the "can only debug 64 KiB of ROM" problem,
but obviously, it needs an AVR Studio plugin that is aware of the
different debugging format.

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser wrote:
Would you mind sharing? I lack the know-how to get it all built myself with all the appropriate patches. I don't care about 256x support - all I want is the better optimizations.

- Dean :twisted:


No problem. I just have to tidy things up a bit before I can send it to you because right now it is geared to a Cygwin environment inside the Cygwin directory structure. So its paths would likely be messed up on your machine, and there may be some DLL hell with the Cygwin runtime.

I'll look into building it as a native Win32 binary for you.