title: gcc for ARM does a compare with zero after a subtraction
body: <p>I am currently trying to check, what C code does generate the best/efficient code for ARM Cortex-M processors. Especially for loops: I wanted to know how I need to write a loop to be able to omit any compare statements in assembly and make use of the Zero flag.</p>
  <p>For that, I set up a demo project with a loop. The loop counts down to zero, as seen here:</p>
  <pre><code>sum = 0;
  
      for(int i=ADC_BUFFER_LENGTH-1; i!=0; i--)
      {
        sum += adc_data_buffer[i];
      }
  </code></pre>
  <p>The disassembly of the code did among other things:</p>
  <pre><code>...
  3b01        subs    r3, #1
  2b00        cmp     r3, #0
  d1f5        bne.n   14 &lt;main+0x14&gt;
  ...
  </code></pre>
  <p>As one can see, the counter value in the register 3 will be decremented, then compared to &quot;0&quot; and it will branch if it is not equal (= Zero-flag is not set).</p>
  <p>The usage for the compare statement here puzzles me greatly as the subtraction statement also has an influence on the Zero-flag of course.</p>
  <p>It is compiled with the -Og optimization option. When I used -O3, then the subtraction did not occur right before the branch and so it needed a compare for that. As the register 3 is not used anywhere else, the assembly could even be further optimized by rearranging the statements a little.</p>
  <p>It puzzles me because I have read multiple times that the optimizer/compiler now days is so good, it is not possible to be better by writing you own assembly... Can somebody shed some light on this?</p>
  <p>The target is a STM32F030, compiled with arm-none-eabi-gcc 10.3.1-2.3.1 on Windows 10 (STM32-for-VSCode)</p>