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?