https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110503
--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> --- I noticed there is a missing optimization here (during VRP1): _29 = _11 == 0; _30 = (unsigned int) _29; _14 = -_30; if (_14 > 2) That is just: if (_14 != 0) or: if (_29 != 0) or rather: if (_11 == 0) Oh the difference between GCC 12 and GCC 13 is that completely unroll does not happen. GCC 13: size: 13-6, last_iteration: 13-6 Loop size: 13 Estimated size after unrolling: 14 Not unrolling loop 1: contains call and code would grow. Not peeling: upper bound is known so can unroll completely GCC 12: size: 13-6, last_iteration: 13-6 Loop size: 13 Estimated size after unrolling: 14 Making edge 11->7 impossible by redistributing probability to other edges. Making edge 15->7 impossible by redistributing probability to other edges. Making edge 6->8 impossible by redistributing probability to other edges. /app/example.cpp:17:14: optimized: loop with 2 iterations completely unrolled (header execution count 1073741833) Exit condition of peeled iterations was eliminated. Basically the comparatively size would increase too much ... So this was just by accident I think.