Discussion:
[avr-gcc-list] foo++, subi vs inc?
Sparr
2008-11-11 23:24:09 UTC
Permalink
Why does "foo++;" compile to "subi Rd,lo8(-(1))" instead of "inc Rd"? I am
keeping global register variables in registers below 16, which are not valid
for subi so they get duplicated to perform the increment. I am preparing to
check out the machine description for the avr target, but thought I would
ask here before I go that deep.
Weddington, Eric
2008-11-12 00:00:53 UTC
Permalink
-----Original Message-----
org] On Behalf Of Sparr
Sent: Tuesday, November 11, 2008 4:24 PM
Subject: [avr-gcc-list] foo++, subi vs inc?
Why does "foo++;" compile to "subi Rd,lo8(-(1))" instead of
"inc Rd"? I am keeping global register variables in
registers below 16, which are not valid for subi so they get
duplicated to perform the increment. I am preparing to check
out the machine description for the avr target, but thought I
would ask here before I go that deep.
What is the type of foo?
Gre7g Luterman
2008-11-12 00:03:44 UTC
Permalink
Does it really matter which instruction the compiler chooses? Both constructs consume the same amount of memory and execution time.

I understand your concern that potentially more time and memory could be used if the compiler resisted the use of inc and the register was below R16, but unless you've seen evidence of it doing this... Is it an issue or just an idle curiousity?

Gre7g



________________________________
From: Sparr <***@gmail.com>
To: avr-gcc-***@nongnu.org
Sent: Tuesday, November 11, 2008 4:24:09 PM
Subject: [avr-gcc-list] foo++, subi vs inc?

Why does "foo++;" compile to "subi Rd,lo8(-(1))" instead of "inc Rd"?  I am keeping global register variables in registers below 16, which are not valid for subi so they get duplicated to perform the increment.  I am preparing to check out the machine description for the avr target, but thought I would ask here before I go that deep.
Sparr
2008-11-12 00:52:42 UTC
Permalink
On Tue, Nov 11, 2008 at 7:00 PM, Weddington, Eric
Post by Weddington, Eric
What is the type of foo?
register unsigned char foo asm("r5");
Post by Weddington, Eric
Does it really matter which instruction the compiler chooses? Both
constructs consume the same amount of memory and execution time.
I understand your concern that potentially more time and memory could be
used if the compiler resisted the use of inc and the register was below R16,
but unless you've seen evidence of it doing this... Is it an issue or just
an idle curiousity?
Gre7g
It is an issue. See above for the declaration of foo. If r5 was used
instead of copying to r21 it would save two instructions, which is not
as trivial as it sounds since I am doing it inside a timer interrupt
and my current goal is to shrink the code as much as possible. I know
I will eventually have to do optimizations in asm, but for now I'd
like my C code to be compiled optimally.
Weddington, Eric
2008-11-12 01:33:47 UTC
Permalink
-----Original Message-----
org] On Behalf Of Sparr
Sent: Tuesday, November 11, 2008 5:53 PM
Subject: Re: [avr-gcc-list] foo++, subi vs inc?
On Tue, Nov 11, 2008 at 7:00 PM, Weddington, Eric
Post by Weddington, Eric
What is the type of foo?
register unsigned char foo asm("r5");
On Tue, Nov 11, 2008 at 7:03 PM, Gre7g Luterman
Post by Weddington, Eric
Does it really matter which instruction the compiler chooses? Both
constructs consume the same amount of memory and execution time.
I understand your concern that potentially more time and
memory could be
Post by Weddington, Eric
used if the compiler resisted the use of inc and the
register was below R16,
Post by Weddington, Eric
but unless you've seen evidence of it doing this... Is it
an issue or just
Post by Weddington, Eric
an idle curiousity?
Gre7g
It is an issue. See above for the declaration of foo. If r5 was used
instead of copying to r21 it would save two instructions, which is not
as trivial as it sounds since I am doing it inside a timer interrupt
and my current goal is to shrink the code as much as possible. I know
I will eventually have to do optimizations in asm, but for now I'd
like my C code to be compiled optimally.
If you want your C code to be compiled optimally, then don't reserve a specific register for a global variable. But then again, the AVR backend hasn't been tuned to generate optimal code either.

The issue could be very well in the AVR target machine description. You'll have to bite the bullet and go look at the code.
Joerg Wunsch
2008-11-12 20:35:43 UTC
Permalink
Post by Sparr
Why does "foo++;" compile to "subi Rd,lo8(-(1))" instead of "inc
Rd"?
As I already wrote you on avrfreaks.net, the use of fixed registers is
such a minor issue that nobody bothered to special-case peephole
optimizations for it in AVR-GCC.

If you want an optimal ISR, *and* you already do know which assembly
code to use for that, then just go ahead, and write your entire
charlieplexing ISR in assembly. This is for sure the most optimal
method just in this case.

The global register variables inside the C code could still prove
useful in that case anyway (provided you compile all your C
compilation units with consistent declarations about them), since that
way, you can ask the compiler to effectively treat these registers as
reserved locations, and not use them. Of course, you always have to
be careful with library functions in that case, unless you recompile
the library with the same set of global register declarations.
--
cheers, J"org .-.-. --... ...-- -.. . DL8DTL

http://www.sax.de/~joerg/ NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)
Sparr
2008-11-12 20:57:13 UTC
Permalink
Post by Joerg Wunsch
Post by Sparr
Why does "foo++;" compile to "subi Rd,lo8(-(1))" instead of "inc
Rd"?
As I already wrote you on avrfreaks.net, the use of fixed registers is
such a minor issue that nobody bothered to special-case peephole
optimizations for it in AVR-GCC.
Fixed registers just make this problem much easier to spot. If you
have a block of code with 20+ "normal" local variables being
manipulated then this mis-implementation of the simple ++ (and, i
presume, --) operator may cause non-optimal code generation due to a
variable that could otherwise live in r<16 being moved to r>=16 just
for the increment, displacing another variable that later has to be
moved back there. I can produce a test case for this if you insist,
but the implications should be obvious.
Joerg Wunsch
2008-11-12 21:01:09 UTC
Permalink
Post by Sparr
Fixed registers just make this problem much easier to spot.
Sure, but there's "bigger fish to fry", i. e. there are so many more
not-quite-optimal parts in the code generation that I'd see this one
as being really a low-priority item.

Of course, if you've got a fix for it, go ahead, and file a bug report
together with the suggested fix. However, if you don't have a patch,
I'm afraid the available "human resources" won't make it very likely
that anyone would deal with the issue within a reasonable timeframe.
--
cheers, J"org .-.-. --... ...-- -.. . DL8DTL

http://www.sax.de/~joerg/ NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)
Marek Michalkiewicz
2008-11-12 21:51:35 UTC
Permalink
Post by Sparr
Why does "foo++;" compile to "subi Rd,lo8(-(1))" instead of "inc Rd"? I
am keeping global register variables in registers below 16, which are not
valid for subi so they get duplicated to perform the increment. I am
preparing to check out the machine description for the avr target, but
thought I would ask here before I go that deep.
The addqi3 pattern already has alternatives that use inc/dec - listed
after the one using subi. You could try to change the order so that
"subi" is the last one and inc/dec is preferred, all else being equal.
Not sure why this doesn't already work as expected in your case though,
despite this paragraph from gccint.info:

If all the operands fit any one alternative, the instruction is valid.
Otherwise, for each alternative, the compiler counts how many
instructions must be added to copy the operands so that that
alternative applies. The alternative requiring the least copying is
chosen. If two alternatives need the same amount of copying, the one
that comes first is chosen. These choices can be altered with the `?'
and `!' characters:

Based on the above, it seems GCC thinks the two alternatives require the
same amount of copying, even though subi may need more as it only works
with r16-r31. You could also experiment with putting `?' in the second
alternative, to disparage "subi" slightly.

Hope this helps,
Marek
Sparr
2008-11-12 22:38:38 UTC
Permalink
An ubuntu bug is keeping me from [easily] working with the gcc source,
having that information when i finally do get started will save some
time. I will experiment with finding out why it is picking subi
instead of inc, but I think inc should come ahead of subi in general,
so that's at least one thing I can put in a patch.

PS: is gccint.info a typo?

On Wed, Nov 12, 2008 at 4:51 PM, Marek Michalkiewicz
Post by Marek Michalkiewicz
The addqi3 pattern already has alternatives that use inc/dec - listed
after the one using subi. You could try to change the order so that
"subi" is the last one and inc/dec is preferred, all else being equal.
Not sure why this doesn't already work as expected in your case though,
If all the operands fit any one alternative, the instruction is valid.
Otherwise, for each alternative, the compiler counts how many
instructions must be added to copy the operands so that that
alternative applies. The alternative requiring the least copying is
chosen. If two alternatives need the same amount of copying, the one
that comes first is chosen. These choices can be altered with the `?'
Based on the above, it seems GCC thinks the two alternatives require the
same amount of copying, even though subi may need more as it only works
with r16-r31. You could also experiment with putting `?' in the second
alternative, to disparage "subi" slightly.
Hope this helps,
Marek
Weddington, Eric
2008-11-12 22:55:15 UTC
Permalink
-----Original Message-----
org] On Behalf Of Sparr
Sent: Wednesday, November 12, 2008 3:39 PM
To: Marek Michalkiewicz
Subject: Re: [avr-gcc-list] foo++, subi vs inc?
An ubuntu bug is keeping me from [easily] working with the gcc source,
having that information when i finally do get started will save some
time. I will experiment with finding out why it is picking subi
instead of inc, but I think inc should come ahead of subi in general,
so that's at least one thing I can put in a patch.
Keep in mind that SUBI will set the carry flag. INC does not set the carry flag. I don't know if that is important in this particular case, but it might be useful info so you don't introduce regressions. Speaking of which, if you develop a patch, you need to be sure to run the GCC Regression Test Suite.
PS: is gccint.info a typo?
gccint.info is the GCC Internals documentation in the 'info' format.
Loading...