I'm interested, why for Cortex M3 microcontroller (stm32f103) compiler sometimes generates a NOP instruction after branch. And why it sometimes doesn't.
0x08000496 2400 MOVS r4,#0x00 0x08000498 4625 MOV r5,r4 0x0800049A E006 B 0x080004AA 64: res=res+a[i]; 65: } 0x0800049C F85A0034 LDR r0,[r10,r4,LSL #3] // No NOP after B 0x080004A0 EB100808 ADDS r8,r0,r8 0x080004A4 1C64 ADDS r4,r4,#1 0x080004A6 F1450500 ADC r5,r5,#0x00 0x080004AA 1BA0 SUBS r0,r4,r6 0x080004AC EB750007 SBCS r0,r5,r7 0x080004B0 DBF4 BLT 0x0800049C 66: int64_t avg=res/x; 0x080004B2 BF00 NOP // <------------------- NOP after BLT 69: int v=countbits1(5); 0x080004B4 2005 MOVS r0,#0x05 0x080004B6 F7FFFFA2 BL.W countbits1 (0x080003FE) 0x080004BA 9001 STR r0,[sp,#0x04] // No NOP after BL.W 72: unsigned int b=countLeadingZeros(5); 73: 0x080004BC 2005 MOVS r0,#0x05
My initial guess was that long instruction needs word-alignment but BL.W after NOP actually doesn't have it.
If this NOP is related to pipeline somehow than why there are branches without nop's after them?
It turns out that branch may be not relevant at all. I tried to moving declaration of unused local variable int64_t avg – and NOP moved along with it.
So I beleive pjc50 comment is right and this NOP is there just to let debugger put a breakpoint on this line.
Try moving the int64_t line of C up or down a bit. The first two are clearly part of a for loop; but line 66 has generated no code at all. My guess is that the NOP is for the benefit of the debugger so that every line of C generates at least one instruction.
(Not all debuggers do this on all platforms; Visual Studio will simply move your breakpoint to the nearest line that has code associated with it.)