asm("") and register optimisation

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

Just for interest, what is going on if I include in my code the line

asm("")

Why does it cause register re-allocation?

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

I don't know( you're not telling the MCU to do ANYTHING ), but WHY would you do that ? Just for grins try this: asm( "" :: ) and let me know what happens, if you don't mind. But what you're doing buys you NOTHING even if it DIDN'T reallocate.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Quote:

Why does it cause register re-allocation?

I believe it's what's known as a "code barrier". It does seem curious that, with nothing listed in the "clobber list", that the C compiler would think it needed to make any change to its register allocation because of it?

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

Cliff!

I believe the 'correct' term is actually "memory barrier". See e.g. http://en.wikipedia.org/wiki/Mem... .

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

OK so let's call it a "code memory barrier" then? ;-)

BTW your article further links to:

http://en.wikipedia.org/wiki/Mem...

But in both it's the application of "volatile" to the "asm("")" that is the "trick" that forces it. The OP didn't mention the use of volatile?

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

Quote:

OK so let's call it a "code memory barrier" then?

You could pose as a Swede anytime, Cliff :wink: Consensus, and all that..

I believe the memory referred to in this barrier thing is actually the data memory. I might be wrong, though..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:

I believe the memory referred to in this barrier thing is actually the data memory. I might be wrong, though..

Apart from LPM that's generally what any pointer/index values held in registers may be pointing at ;-)

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

From my past life doing compiler work, I always thought it was a "sequence point".
http://en.wikipedia.org/wiki/Seq...

[I don't have the "Dragon book" here right now. It would seem that many posters just kind of dive in, without any background in the basics. I suppose Donald Knuth is too old and old fashioned, but his volumes especially on sorting and searching have the classical primitives well covered. The first Dragon book by Aho and Ullman on "Principles of Compiler Design" and following volumes will lay out all the basics. (And yes, the underlying principles still apply to Java or whatever nowadays.) Fundamentals of Interactive Computer Graphics by Foley and van Dam, and follow-on editions.

There are other references that have aged quite well. For sparkies and would-bes, The Art of Electronics. Numerical Recipes has a lot of information. PID often comes up here, but it seems that posters have never gone through any of the Astrom books.]

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:

It would seem that many posters just kind of dive in, without any background in the basics.

Somewhat guilty as accused. While I have never worked with compiler design and implementation professionally, I have dabbled with it over the years. Mainly for writing parsers and lexers, not at all doing code-generating back ends.

Yes, perhaps I was to quick on the trigger above. You post now forces me to get my issue of the Dragon book out (2nd ed?) to read up on this. Oh well, that is a good excuse to make a nice pot of Lapsang!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

No, it's not a memory barrier, that would be:

asm(""::"memory");

Volatile is implied as no outputs are declared, this means the resulting program must execute the statement as the source says. For example:

for(int i = 0; i < 1000; ++i) asm("");

can not be removed.

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

melbourne wrote:
Just for interest, what is going on if I include in my code the line
asm("")

Why does it cause register re-allocation?

This line does not cause register re-allocation (in the sense register allocation is used in gcc).

However, this line may hinder some optimization passes an thus result in code change. I observed that

asm (""::)

is an even stronger barrier (I used it once to avoid some common subexpression elimination in an older version of avr-gcc).

But I do not see any documentation/specification of this, so I guess it's just a byproduct of asm insns being present avoiding some optimization because the compiler does not analyse the content of inline asm (except for %-operands and number of lines).

As already said, gcc must emit corresponding code. You will see in the assembler output that

asm ("")

is not printed while

asm (" ")

is.

Also note that in code like

for (int i=0; i < 100; i++)
   asm ("");

the loop might be unrolled eventually resulting in /no/ loop, just 100 nothings in sequence.

avrfreaks does not support Opera. Profile inactive.

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

melbourne wrote:
Just for interest, what is going on if I include in my code the line
asm("")

Why does it cause register re-allocation?

Perhaps because R0 is always implicitly clobbered.
Other than that,
the code requires nothing else of the compiler.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

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

OP, why don't YOU just TELL us what the code's intent is and even post that section of code ?

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

The documentation on effects of asm() with, without volatile or "memory" clobber, is inadequate, to put it very mildly, and have changed through the versions of gcc, as undoubtedly has changed also the behaviour of gcc. My impression is, that the developers of gcc don't have a clear idea what all these options are supposed to do "barrier-wise", and that every developer puts in his own creative ideas into this field.

We have discussed this quite extensively in the past, for example here.

JW

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

wek wrote:
The documentation on effects of asm() with, without volatile or "memory" clobber, is inadequate, to put it very mildly, and have changed through the versions of gcc, as undoubtedly has changed also the behaviour of gcc. My impression is, that the developers of gcc don't have a clear idea what all these options are supposed to do "barrier-wise", and that every developer puts in his own creative ideas into this field.

GCC ist just a complex piece of software. If some (new) optimization misses to test volatile and volatile-correctnes in gcc is broken, this is worth a bug report.

Besides that, from time to time, in the gcc developer's mailing lists the question comes up what the meaning of unspec volatile is (or should be).
IMHO the backend should be able to influence the decision, e.g. is some hard reg or pseudo reg must/may/must not survive an unspec volatile. However, gcc has not an infra structure that is capable of doing that.

Newer or patched versions of avr-gcc support builtins for sei, cli, nop, delay loops, etc. which have some advantage over C resp. inline asm. In particular, they are implemented as unspec volatile which is somehow stronger than asm volatile.

Quote:
We have discussed this quite extensively in the past, for example here

I do not see anything wrong with the code generated there. Yes, the IRQ latency is greater than it could be. But as already mentioned there, C doesn't say anything about IRQ latency, and the result of the division may commute with the asm volatile. Just as a memory access (volatile or not) not depending on the quotient may commute with the computation of the quotient. In a backend that makes the division explicit to the compiler, the memory access could even happen somewhere during the computation, e.g. by means of some scheduling pass and provided the division takes more than one instruction.

The trouble with the post referred above looks rather like this: guys look at the code which gcc produces and deduce some specefic behaviour of gcc from it, and blame gcc if the behaviour changes as sourrounding code changes, or version or options of gcc change.

Then note: Discussing such stuff here won't change anything. Maybe you can bring up such topics in one of gcc's mls, see http://gcc.gnu.org/ml like gcc or gcc-help, in order to have it clarified, better documented, fixed or whatever is helpful or enlightning.

avr-gcc development is veeery slow, but topics like this are common to other architectures. I once had a bad optimization which could be reproduced on some wide spread hardware, and the itch was fixed within minutes.

avrfreaks does not support Opera. Profile inactive.

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

I also tried asm(""::) and __asm__ __volatile__.

Repeating the line sometimes has an effect where one invocation has no apparent effect.

I am not using asm("") for anything, I asked this question because it is an interesting question.

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

And now you know that it makes sense to use CODE tags here even for short one-liners... :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

SprinterSB wrote:

Newer or patched versions of avr-gcc support builtins for sei, cli, nop, delay loops, etc. which have some advantage over C resp. inline asm. In particular, they are implemented as unspec volatile which is somehow stronger than asm volatile.

Where in the documentation can I find the list of supported builtins?

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

skeeve wrote:
Perhaps because R0 is always implicitly clobbered.

Is that a guess, or an informed guess or a fact? There is no reason why there shouldn't be an implicit clobber list, but I haven't seen any discussion of it before.

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

melbourne wrote:
skeeve wrote:
Perhaps because R0 is always implicitly clobbered.

Is that a guess, or an informed guess or a fact? There is no reason why there shouldn't be an implicit clobber list, but I haven't seen any discussion of it before.

It's not phrased that way,
but it's in the av-libc inline assembler cookbook.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods

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

skeeve wrote:
melbourne wrote:
skeeve wrote:
Perhaps because R0 is always implicitly clobbered.

Is that a guess, or an informed guess or a fact? There is no reason why there shouldn't be an implicit clobber list, but I haven't seen any discussion of it before.

It's not phrased that way,
but it's in the av-libc inline assembler cookbook.

GCC knows two kind of hard registers: fixed regs and non-fixed regs (there are many other views on registers).

Non-fixed regs are regs the compiler can work with, it can put values in these regs and knows about the value, it can reload such a reg to another reg or register class or can temporarily save it to the stack.

Fixed regs will never be used by the compiler itself. Fixed regs are just used -- if at all -- implicitely by backend writers. For avr-gcc this are the regs R0 and R1. R0 is aka. __tmp_reg__ and R1 is aka. __zero_reg__. Between insns, the latter always contains the value 0 which is put there in startup code (.init0 or .init1) or in ISR prologue, so a backend guy can rely on that and use this value in the output string of the insn which prints the asm representation of the insn.

An implicit use of R1 can be seen in the "neghi2" insn (negating half an int, i.e. a 16-bit value):

com %B0 
neg %A0
sbc %B0,__zero_reg__
inc %B0 

The above code handles the case x = -x where x is some reg of class "r" (R2-R31). The compiler decides which reg it actually it. For R1 there is no choice and no one tells gcc that R1 = 0.

As both R0 and R1 are fixed, they are treated the same way by gcc's algorithms. The difference between R0 and R1 is just the way they are initialized and the way some output strings rely on that: R1 = 0 and R0 is scratch.

As R1 is fixed, it is useless to clobber it in inline asm, e.g. in an asm that uses some mul instruction: this reg is fixed and the compiler won't emit code for it. That's the reason why clobbering R1 in inline asm won't work as expected (you will have to type the CLR R1 by hand).

So there is no mechanism like an "implicit clobber" if we use "clobber" the way it is used in inline asm or in gcc internals.

avrfreaks does not support Opera. Profile inactive.