[Bug tree-optimization/67705] New: incorrect restrict interpretation
vries at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Thu Sep 24 08:09:00 GMT 2015
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67705
Bug ID: 67705
Summary: incorrect restrict interpretation
Product: gcc
Version: 6.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: vries at gcc dot gnu.org
Target Milestone: ---
I think I found an example for which the compiler misinterprets restrict.
Consider test-case test.c:
...
void
f (int *__restrict__ &__restrict__ fp,
int *__restrict__ &__restrict__ fp2)
{
*fp = 1;
*fp2 = 2;
}
void
g (int *__restrict__ gp)
{
f (gp, gp);
}
void
h (void)
{
int ha;
g (&ha);
}
...
At the ealias dump we see that the two stores are disambiguated, due to the
fact that they're in the same clique (1) but have different bases (base 2 and
base 4):
...
void f(int* __restrict__&, int* __restrict__&) (intD.9 * restrict & restrict
fpD.2252, intD.9 * restrict & restrict fp2D.2253)
{
intD.9 * _3;
intD.9 * _6;
# VUSE <.MEM_1(D)>
# PT = { D.2269 } (nonlocal)
_3 = MEM[(intD.9 * restrict &)fp_2(D) clique 1 base 1];
# .MEM_4 = VDEF <.MEM_1(D)>
MEM[(intD.9 *)_3 clique 1 base 2] = 1;
# VUSE <.MEM_4>
# PT = { D.2271 } (nonlocal)
_6 = MEM[(intD.9 * restrict &)fp2_5(D) clique 1 base 3];
# .MEM_7 = VDEF <.MEM_4>
MEM[(intD.9 *)_6 clique 1 base 4] = 2;
...
>From the example, it's obvious that the stores in fact alias, because we call f
with the two arguments being identical.
The question is if this is a valid example, in other words, doesn't passing
identical arguments violate the second restrict in both "int *__restrict__
&__restrict__ fp" and "int *__restrict__ &__restrict__ fp2"?
I think the example is valid, due to the "modified" wording in the restrict
definition.
In the case of the second restrict, the object being referenced is gp. And gp
is not modified during execution of f, so the restrict has no impact.
This link has an explanation of the "modified" wording:
http://www.lysator.liu.se/%28nobg%29/c/restrict.html at "Aliasing of unmodified
objects".
It's to allow a call "f10(x, y, y)" to this function:
...
void
f10 (int n, float *restrict a, float *restrict b, float *restrict c)
{
int i;
for ( i=0; i<n; i++ )
a[i] = b[i] + c[i];
}
...
The object pointed to by y is not modified in f10, so we're allowed to mark
both b and c restrict. And marking b and c restrict helps compilers which only
disambiguate is both pointers are restrict (PR48885), in other words, it allows
those compilers to disambiguate between first a[i] and b[i], and second a[i]
and c[i].
The downside of the "modified" wording is: "... allow aliasing through two
restrict-qualified pointers provided the referenced objects are not modified.
Unfortunately, if those objects are themselves pointers (i.e., there are two
levels of indirection), this aliasing can inhibit optimization, even if the
secondary pointers are also restrict-qualified and used to modify the objects
to which they, in turn, refer. See X3J11.1/93-040 for examples."
I think test.c above is such an example (I have no access to X3J11.1/93-040
though).
More information about the Gcc-bugs
mailing list