4

From GCC documentation regarding Extended ASM - Clobbers and Scratch Registers I find it difficult to understand the following explanation and example:

Here is a fictitious sum of squares instruction, that takes two pointers to floating point values in memory and produces a floating point register output. Notice that x, and y both appear twice in the asm parameters, once to specify memory accessed, and once to specify a base register used by the asm.

Ok, first part understood, now the sentence continues:

You won’t normally be wasting a register by doing this as GCC can use the same register for both purposes. However, it would be foolish to use both %1 and %3 for x in this asm and expect them to be the same. In fact, %3 may well not be a register. It might be a symbolic memory reference to the object pointed to by x.

Lost me.

The example:

asm ("sumsq %0, %1, %2"
     : "+f" (result)
     : "r" (x), "r" (y), "m" (*x), "m" (*y));

What does the example and the second part of the sentence tells us? whats is the added value of this code in compare to another? does this code will result in a more efficient memory flush (as explained earlier in the chapter)?

Jester
  • 56,577
  • 4
  • 81
  • 125
izac89
  • 3,790
  • 7
  • 30
  • 46

1 Answers1

3

Whats is the added value of this code in compare to another?

Which "another"? The way I see it, if you have this kind of instruction, you pretty much have to use this code (the only alternative being a generic memory clobber).

The situation is, you need to pass in registers to the instruction but the actual operands are in memory. Hence you need to ensure two separate things, namely:

  1. That your instruction gets the operands in registers. This is what the r constraints do.
  2. That the compiler knows your asm block reads memory so the values of *x and *y have to be flushed prior to the block. This is what the m constraints are used for.

You can't use %3 instead of %1, because the m constraint uses memory reference syntax. E.g. while %1 may be something like %r0 or %eax, %3 may be (%r0), (%eax) or even just some_symbol. Unfortunately your hypothetical instruction doesn't accept these kinds of operands.

Jester
  • 56,577
  • 4
  • 81
  • 125
  • Worth mentioning that the main use-case for this kind of thing is when you want to construct an addressing-mode yourself, although in that case instead of `*x` you need to tell the compiler you reference the whole array, not just the first element. See https://stackoverflow.com/questions/1956379/att-asm-inline-c-problem/47358313?noredirect=1#comment81680441_47358313 for discussion on that. – Peter Cordes Mar 02 '18 at 15:23
  • And BTW, it often *does* use up another register for the dummy memory operand if you tell the compiler you will modify the pointer register and use an early-clobber. (`"+&r"(buffer), "m" (*(const char (*)[]) *buffer)`.) You can avoid that if you lie to the compiler and leave out the early-clobber, but then you have a potential bug if any other operand has the same value as that pointer. – Peter Cordes Mar 02 '18 at 15:28