https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101769
--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> --- free_all2_r loses it during CDDCE1 which elides the original while loop. Then tail-recursion discovers a new loop from the following IL void free_all2_r (struct Node * n_) { struct Node * t; struct Node * _1; <bb 2> : _1 = n__6(D)->right; if (_1 != 0B) goto <bb 3>; [INV] else goto <bb 4>; [INV] <bb 3> : free_all2_r (_1); <bb 4> : return; which leaves loop fixup to discover the created loop which is then not marked as finite (I don't think we can technically say it is?): fix_loop_structure: fixing up loops for function flow_loops_find: discovered new loop 2 with header 2 that then gets inlined into free_all2. free_all suffers from exactly the same issue. The info doesn't get lost - it's simply that tail recursion added loops are not marked finite. I guess since it's recursion we know it will eventually terminate (blow the stack). But the tail-recursion pass doesn't bother to create the loop structure where it could set ->finite_p. if (changed) { /* We may have created new loops. Make them magically appear. */ loops_state_set (LOOPS_NEED_FIXUP); free_dominance_info (CDI_DOMINATORS); } I have a patch that tries to fix that. With this all functions end up empty.