https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120608
--- Comment #19 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Why are you using the attribute at -O0?
In any case, this boils down to roughly -O0 -fsanitize=address
[[gnu::noipa]] int
foo (int x)
{
return x;
}
[[gnu::noipa]] void
bar (int *x, int *y, int *z)
{
(void) x;
(void) y;
(void) z;
}
[[gnu::noipa]] int
baz (int x)
{
int a = 4;
{
int b = 8;
{
int c = 10;
bar (&a, &b, &c);
if (a + b + c == 22)
[[gnu::musttail]] return foo (x);
bar (&a, &b, &c);
}
bar (&a, &b, &a);
}
bar (&a, &a, &a);
return 42;
}
During gimplification, .ASAN_MARK (POISON, ...); calls are added as try ...
finally.
So we get something like:
try
{
.ASAN_MARK (UNPOISON, &a, 4);
a = 4;
{
int b;
try
{
.ASAN_MARK (UNPOISON, &b, 4);
b = 8;
{
int c;
try
{
.ASAN_MARK (UNPOISON, &c, 4);
c = 10;
...
D.3414 = foo (x); [must tail call]
// predicted unlikely by early return (on trees) predictor.
return D.3414;
...
}
finally
{
.ASAN_MARK (POISON, &c, 4);
}
...
}
finally
{
.ASAN_MARK (POISON, &b, 4);
}
...
}
finally
{
.ASAN_MARK (POISON, &a, 4);
}
Now, the eh pass turns those into
D.3414 = foo (x); [must tail call]
// predicted unlikely by early return (on trees) predictor.
finally_tmp.3 = 0;
goto <D.3417>;
...
<D.3417>:
.ASAN_MARK (POISON, &c, 4);
switch (finally_tmp.3) <default: <D.3420>, case 1: <D.3418>>
<D.3418>:
goto <D.3419>;
<D.3420>:
finally_tmp.4 = 0;
goto <D.3422>;
...
<D.3422>:
.ASAN_MARK (POISON, &b, 4);
switch (finally_tmp.4) <default: <D.3425>, case 1: <D.3423>>
<D.3423>:
goto <D.3424>;
<D.3425>:
goto <D.3426>;
...
<D.3426>:
.ASAN_MARK (POISON, &a, 4);
goto <D.3415>;
<D.3415>:
return D.3414;
And note we've been asked not to optimize anything and so we don't.
Before sanopt0 pass we still have
_26 = foo (x_24(D)); [must tail call]
// predicted unlikely by early return (on trees) predictor.
finally_tmp.3_27 = 0;
goto <bb 5>; [INV]
...
<bb 5> :
# _6 = PHI <_26(3), _23(D)(4)>
# finally_tmp.3_8 = PHI <finally_tmp.3_27(3), finally_tmp.3_22(4)>
.ASAN_MARK (POISON, &c, 4);
if (finally_tmp.3_8 == 1)
goto <bb 7>; [INV]
else
goto <bb 6>; [INV]
<bb 6> :
<L4>:
finally_tmp.4_31 = 0;
goto <bb 8>; [INV]
...
<bb 8> :
# finally_tmp.4_9 = PHI <finally_tmp.4_31(6), finally_tmp.4_30(7)>
.ASAN_MARK (POISON, &b, 4);
if (finally_tmp.4_9 == 1)
goto <bb 9>; [INV]
else
goto <bb 10>; [INV]
...
<bb 10> :
# _7 = PHI <_6(8), _34(9)>
.ASAN_MARK (POISON, &a, 4);
<bb 11> :
<L11>:
return _7;
And then sanopt0 actually comes before musttail pass (the -O0 special copy of
that), so .ASAN_MARK calls
are lowered into something musttail pass has no easy way to match.
So, in order to deal with this, we'd need to do something with pass ordering:
NEXT_PASS (pass_sanopt);
NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_musttail);
We want the musttail pass before sanopt, but am not sure if we still rely on
cleanup_eh or not (I think tailc/musttail
pass has workarounds for that), so maybe simply moving pass_musttail 2 lines up
would work.
And another problem is the lack of forward propagation of the finally_tmp.*
SSA_NAMEs into PHI nodes and whether
tailc/musttail will be able to deal with the GIMPLE_CONDs in there. If we
track through which edges we go from the
musttail call to the return path and we see GIMPLE_CONDs on that path, we could
look it up; e.g. for the
if (finally_tmp.3_8 == 1) case, see it defined in # finally_tmp.3_8 = PHI
<finally_tmp.3_27(3), finally_tmp.3_22(4)>
and because we came to bb 5 through the 3->5 edge, look at finally_tmp.3_27
SSA_NAME_DEF_STMT and because it is 0,
figure out the condition is false, etc.