You copied the Doc URL to your clipboard.

Duplication of labels in inline assembly statements

You can use labels inside inline assembly, for example as the targets of branches or PC-relative load instructions. However, you must ensure that the labels that you create are valid if the compiler removes or duplicates an inline assembly statement.

Duplication can happen when a function containing an inline assembly statement is inlined in multiple locations. Removal can happen if an inline assembly statement is not reachable, or its result is unused and it has no side-effects.

If regular labels are used inside inline assembly, then duplication of the assembly could lead to multiple definitions of the same symbol, which is invalid. Multiple definitions can be avoided either by using numeric local labels, or using the %= template string. The %= template string is expanded to a number that is unique to each instance of an inline assembly statement. Duplicated statements have different numbers. All uses of %= in an instance of the inline assembly statement have the same value. You can therefore create label names that can be referenced in the same inline assembly statement, but which do not conflict with other copies of the same statement.


Unique numbers from the %= template string might still result in the creation of duplicate labels. For example, label names loop%= and loop1%= can result in duplicate labels. The label for instance number 0 of loop1%= evaluates to loop10. The label for instance number 10 of loop%= also evaluates to loop10.

To avoid such duplicate labels, choose the label names carefully.


void memcpy_words(int *src, int *dst, int len) {
	assert((len % 4) == 0);
	int tmp;
	// This uses the "%=" template string to create a label which can be used
	// elsewhere inside the assembly block, but which will not conflict with
	// inlined copies of it.
	// R is a C++11 raw string literal. See the example in File-scope inline assembly.
			ldr %[tmp], %[src], #4
			str %[tmp], %[dst], #4
			subs %[len], #4
			bne .Lloop%=)"
		: [dst] "=&m" (*dst),
			[tmp] "=&r" (tmp),
			[len] "+r" (len)
		: [src] "m" (*src));