https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121258
Bug ID: 121258 Summary: Missed optimization with 'while' loop that can be converted to 'do-while' Product: gcc Version: 15.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: Explorer09 at gmail dot com Target Milestone: --- GCC missed an optimization like this: When the loop body contains only counter increments (or decrements), and the loop condition is determined externally, a 'while' loop construct can be converted to a 'do-while' with a small change in the counter's initial value. This can save an unconditional 'jmp' instruction at the end of the loop. Example code: ```c #include <stdbool.h> #include <stdint.h> extern bool cond(uint32_t x); uint32_t func_a(uint32_t x) { uint32_t i = 10; while (cond(i)) { i++; } return i; } uint32_t func_b(uint32_t x) { uint32_t i = 9; do { i++; } while (cond(i)); return i; } ``` x86-64 gcc 15.1 with '-Os' option produces this (I tested this in Compiler Explorer): ```x86asm func_a: pushq %rbx movl $10, %ebx .L2: movl %ebx, %edi call cond testb %al, %al je .L6 incl %ebx jmp .L2 .L6: movl %ebx, %eax popq %rbx ret func_b: pushq %rbx movl $9, %ebx .L8: incl %ebx movl %ebx, %edi call cond testb %al, %al jne .L8 movl %ebx, %eax popq %rbx ret ``` The expected result is `func_a` optimizes to `func_b`. The two functions should be equivalent. Clang 20.1.0 does perform such an optimization. Note that such optimization opportunity is not limited to additions and subtractions. Below is an example that the counter multiplies by 2 instead (Clang 20.1.0 currently missed this one): ```c uint32_t func2_a(uint32_t x) { uint32_t i = 10; while (cond(i)) { i *= 2; } return i; } uint32_t func2_b(uint32_t x) { uint32_t i = 5; do { i *= 2; } while (cond(i)); return i; } ```