cgccassemblyinline-assembly

When to use earlyclobber constraint in extended GCC inline assembly?


I understand when to use a clobber list (e.g. listing a register which is modified in the assembly so that it doesn't get chosen for use as an input register, etc), but I can't wrap my head around the the earlyclobber constraint &. If you list your outputs, wouldn't that already mean that inputs can't use the selected register (aside from matching digit constraints)?

For example:

asm(
    "movl $1, %0;"
    "addl $3, %0;"
    "addl $4, %1;"   // separate bug: modifies input-only operand
    "addl %1, %0;"
    : "=g"(num_out)
    : "g"(num_in)
    :
);

Would & even be needed for the output variables? The compiler should know the register that was selected for the output, and thus know not to use it for the input.


Solution

  • By default, the compiler assumes all inputs will be consumed before any output registers are written to, so that it's allowed to use the same registers for both. This leads to better code when possible, but if the assumption is wrong, things will fail catastrophically. The "early clobber" marker is a way to tell the compiler that this output will be written before all the input has been consumed, so it cannot share a register with any input.

    GNU C inline asm syntax was designed to wrap a single instruction as efficiently as possible. You can put multiple instructions in an asm template, but the defaults (assuming that all inputs are read before any outputs are written) are designed around wrapping a single instruction.

    It's the same constraint syntax as GCC uses in its machine-description files that teach the compiler what instructions are available in an ISA.