9.117 __nop intrinsic

This intrinsic inserts a NOP instruction or an equivalent code sequence into the instruction stream.

The compiler does not optimize away the NOP instructions, except for normal unreachable code elimination. One NOP instruction is generated for each __nop intrinsic in the source.
ARMv6 and previous architectures do not have a NOP instruction, so the compiler generates a MOV r0,r0 instruction instead.
In addition, __nop creates a special sequence point that prevents operations with side effects from moving past it under all circumstances. Normal sequence points allow operations with side effects past if they do not affect program behavior. Operations without side effects are not restricted by the intrinsic, and the compiler can move them past the sequence point. The __schedule_barrier intrinsic also creates this special sequence point, without inserting a NOP instruction.
Section 5.1.2.3 of the C standard defines operations with side effects as those that change the state of the execution environment. These operations:
  • Access volatile objects.
  • Modify a memory location.
  • Modify a file.
  • Call a function that does any of the above.
In the following example, the compiler ensures that the read from the volatile variable x is enclosed between two NOP instructions.
volatile int x;
int z;
int read_variable(int y)
{
    int i;
    int a = 0;
    __nop();
    a = x;
    __nop();
    return z + y;
}
If the __nop intrinsics are removed, and the compilation is performed at -O3 -Otime for --cpu=Cortex-M3, for example, then the compiler can schedule the read of the non-volatile variable z to be before the read of variable x.
In the following example, the compiler ensures that the write to variable z is enclosed between two NOP instructions.
int x;
int z;
int write_variable(int y)
{
    int i;
    for (i = 0; i < 10; i++)
    {
        __nop();
        z = y;
        __nop();
        x += y;
    }
    return z;
}
In this case, if the __nop intrinsics are removed, then with -O3 -Otime --cpu=Cortex-M3, the compiler can fold away the loop.
In the following example, because pure_func has no side effects, the compiler can move the call to it to outside of the loop. Still, the compiler ensures that the call to func is enclosed between two NOP instructions.
int func(int x);
int pure_func(int x) __pure;
int read(int x)
{
    int i;
    int a=0;
    for (i=0; i<10; i++)
    {
        __nop();
        a += pure_func(x) + func(x);
        __nop();
    }
    return a;
}

Note

  • You can use the __schedule_barrier intrinsic to insert a scheduling barrier without generating a NOP instruction.
  • In the examples above, the compiler would treat __schedule_barrier in the same way as __nop.

Syntax

void __nop(void)
Related reference
9.131 __sev intrinsic
9.140 __wfe intrinsic
9.141 __wfi intrinsic
9.142 __yield intrinsic
9.13 __pure
9.129  __schedule_barrier intrinsic
3.4 Generic intrinsics
Related information
NOP
Non-ConfidentialPDF file icon PDF versionARM DUI0375E
Copyright © 2007, 2008, 2011, 2012, 2014 ARM. All rights reserved.