https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89497
--- Comment #15 from Martin Liška <marxin at gcc dot gnu.org> --- There's a more readable test-case: $ echo =1= && cat 1.i && echo =2= && cat 2.i && echo =3= && cat 3.i && echo =4= && cat 4.i =1= int guard; int cupsArraySave() { if (guard) return 0; else return 1; } =2= int *get_null() { return 0; } =3= unsigned long _cups_strlcpy(char *, char *, long); typedef struct { char array[81]; } container; container *get(); container *get_null(); container c; void d() { container *a = get(); for (; a; a = get_null()) { cupsArraySave(); _cups_strlcpy(a->array, c.array, sizeof(c.array)); } } =4= unsigned long _cups_strlcpy(char *dest, char *src, long len) { unsigned long len2 = __builtin_strlen(src); if (len2 > len) len2 = len; __builtin_memmove(dest, src, len2); } We ICE in tree-vrp where: SSA form after inserting ASSERT_EXPRs d () { int D.4365; long unsigned int len2; int * D.4357; struct container * a; char[81] * _1; int _18; int _19; <bb 2> [local count: 118111600]: a_6 = get (); goto <bb 9>; [100.00%] <bb 3> [local count: 955630223]: a_10 = ASSERT_EXPR <a_2, a_2 != 0B>; _18 = guard; if (_18 != 0) goto <bb 5>; [50.00%] else goto <bb 4>; [50.00%] <bb 4> [local count: 477815111]: <bb 5> [local count: 955630223]: # _19 = PHI <0(3), 1(4)> _1 = &a_10->array; len2_15 = __builtin_strlen (&c.array); if (len2_15 > 81) goto <bb 6>; [50.00%] else goto <bb 11>; [50.00%] <bb 11> [local count: 477815112]: len2_23 = ASSERT_EXPR <len2_15, len2_15 <= 81>; goto <bb 7>; [100.00%] <bb 6> [local count: 477815111]: len2_14 = ASSERT_EXPR <len2_15, len2_15 > 81>; <bb 7> [local count: 955630223]: # len2_17 = PHI <81(6), len2_23(11)> __builtin_memmove (_1, &c.array, len2_17); <bb 8> [local count: 955630223]: # a_20 = PHI <0B(7)> goto <bb 10>; [100.00%] <bb 9> [local count: 118111601]: # a_2 = PHI <a_6(2)> if (a_2 != 0B) goto <bb 3>; [97.00%] else goto <bb 10>; [3.00%] <bb 10> [local count: 118111601]: return; } ... Visiting statement: _1 = &a_2->array; LKUP STMT len2_15 = __builtin_strlen (&c.array) with .MEM_11 <<<< COPY _19 = 0 Registering jump thread: (3, 5) incoming edge; (5, 11) normal; <<<< STMT 0 = a_2 eq_expr 0B <<<< STMT 1 = a_2 ne_expr 0B <<<< COPY a_10 = a_2 Threaded jump 4 --> 5 to 12 Threaded jump 3 --> 5 to 12 Removing basic block 5 ;; basic block 5, loop depth 0 ;; pred: # _19 = PHI <> _1 = &a_2->array; len2_15 = __builtin_strlen (&c.array); if (0 != 0) goto <bb 6>; [100.00%] else goto <bb 11>; [0.00%] ;; succ: 6 ;; 11 ... after the BB removal we end up with: (gdb) p debug_function(cfun->decl, 0) d () { int D.4365; long unsigned int len2; int * D.4357; struct container * a; char[81] * _1; int _18; int _19; int _24; char[81] * _25; <bb 2> [local count: 118111601]: a_6 = get (); if (a_6 != 0B) goto <bb 3>; [97.00%] else goto <bb 10>; [3.00%] <bb 3> [local count: 955630223]: _18 = guard; if (_18 != 0) goto <bb 12>; [50.00%] else goto <bb 4>; [50.00%] <bb 4> [local count: 477815111]: goto <bb 12>; [100.00%] <bb 11> [local count: 477815112]: <bb 7> [local count: 955630223]: # len2_17 = PHI <len2_15(12)> __builtin_memmove (_1, &c.array, len2_17); <bb 8> [local count: 955630223]: <bb 10> [local count: 118111601]: return; <bb 12> [local count: 477815112]: # _24 = PHI <1(4), 0(3)> _25 = &a_6->array; len2_26 = __builtin_strlen (&c.array); goto <bb 7>; [100.00%] } Note that _1 has missing definition. And we segfault in cleanup_tree_cfg_bb where we're trying to fold __builtin_memmove (_1, &c.array, len2_17); Am I correct that the bb removal should propagate _1 into the __builtin_memmove? Maybe a broken DEF-USE chain?