Non-Confidential | ![]() | ARM DUI0472J | ||
| ||||
Home > Compiler-specific Features > __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-A8
, 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-A8
, 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; }
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
.
void __nop(void)