https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117243
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hubicka at gcc dot gnu.org, | |jakub at gcc dot gnu.org, | |pinskia at gcc dot gnu.org, | |rguenth at gcc dot gnu.org --- Comment #10 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Cleaned up #c7: void foo (unsigned int a, unsigned char b) { lbl: for (b = 0; b <= 7; b++) { unsigned char c[1][1]; int i, j; for (i = 0; i < 1; i++) for (j = 0; j < 1; j++) c[i][j] = 1; if (b) goto lbl; } } int main () { foo (1, 2); } The crash is because at cunroll time we decide to replace the loop by __builtin_unreachable (). And we do so because it sees clearly endless loop which has in loop structures as upper bound of the number of iterations 8. >From what I can see, starting with the end of ch2 pass, we have <bb 2> [local count: 2657777]: <bb 3> [local count: 268435456]: lbl: <bb 4> [local count: 536870912]: # b_1 = PHI <0(3), 1(4)> if (b_1 != 0) goto <bb 3>; [50.00%] else goto <bb 4>; [50.00%] where the innermost loop is just bb 4 and has 8 as upper bound (it comes originally from the b = 0; b <= 7; b++ loop) and then there is an outer loop with bb3 and bb4 which doesn't have bounded iterations. Before phiopt3 it is still: Loops in function: foo loop_0 (header = 0, latch = 1) { bb_2 (preds = {bb_0 }, succs = {bb_3 }) { <bb 2> [local count: 2657777]: } loop_1 (header = 3, latch = 4 iterations by profile: 99.999992 (unreliable, maybe flat) entry count:2657777 (estimated locally, freq 1.0000)) { bb_3 (preds = {bb_2 bb_4 }, succs = {bb_4 }) { <bb 3> [local count: 268435456]: lbl: } loop_2 (header = 4, latch = 4, finite_p upper_bound 8 likely_upper_bound 8 iterations by profile: 1.000000 (unreliable, maybe flat) entry count:268435456 (estimated locally, freq 101.0000)) { bb_4 (preds = {bb_3 bb_4 }, succs = {bb_3 bb_4 }) { <bb 4> [local count: 536870912]: # b_1 = PHI <0(3), 1(4)> if (b_1 != 0) goto <bb 3>; [50.00%] else goto <bb 4>; [50.00%] } } } } which looks correct to me (8 is way too large, that loop loops just once). Phiopt itself then just changes that # b_1 = PHI <0(3), 1(4)> if (b_1 != 0) to # b_1 = PHI <0(3), _5(4)> _5 = b_1 ^ 1; if (0 != 0) Then phiopt (well, seems TODO_cleanup_cfg at the end of it) decides to merge the 2 blocks: <bb 2> [local count: 2657777]: <bb 3> [local count: 536870912]: # b_1 = PHI <0(2), _5(3)> _5 = b_1 ^ 1; goto <bb 3>; [100.00%] but doesn't adjust appropriately the loop structures: Loops in function: foo loop_0 (header = 0, latch = 1) { bb_2 (preds = {bb_0 }, succs = {bb_3 }) { <bb 2> [local count: 2657777]: } loop_2 (header = 3, latch = 3, finite_p upper_bound 8 likely_upper_bound 8 iterations by profile: 200.999984 (unreliable) entry count:2657777 (estimated locally, freq 1.0000)) { bb_3 (preds = {bb_2 bb_3 }, succs = {bb_3 }) { <bb 3> [local count: 536870912]: # b_1 = PHI <0(2), _5(3)> _5 = b_1 ^ 1; goto <bb 3>; [100.00%] } } } which is wrong, because the inner loop is infinite, not finite_p and doesn't have upper_bound of 8. Though, I'm afraid I have no idea what should adjust the loop structures here, whether already phiopt itself which turns the conditional branch into unconditional, or the following cfgcleanup.