On Thu, Sep 23, 2021 at 8:32 AM Richard Biener via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On Thu, 23 Sep 2021, Hongtao Liu wrote:
>
> > On Thu, Sep 23, 2021 at 9:48 AM Hongtao Liu <crazy...@gmail.com> wrote:
> > >
> > > On Wed, Sep 22, 2021 at 10:21 PM Martin Sebor <mse...@gmail.com> wrote:
> > > >
> > > > On 9/21/21 7:38 PM, Hongtao Liu wrote:
> > > > > On Mon, Sep 20, 2021 at 4:13 AM Martin Sebor <mse...@gmail.com> wrote:
> > > > ...
> > > > >>>>> diff --git a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c 
> > > > >>>>> b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> > > > >>>>> index 1d79930cd58..9351f7e7a1a 100644
> > > > >>>>> --- a/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> > > > >>>>> +++ b/gcc/testsuite/c-c++-common/Wstringop-overflow-2.c
> > > > >>>>> @@ -1,7 +1,7 @@
> > > > >>>>>    /* PR middle-end/91458 - inconsistent warning for writing past 
> > > > >>>>> the end
> > > > >>>>>       of an array member
> > > > >>>>>       { dg-do compile }
> > > > >>>>> -   { dg-options "-O2 -Wall -Wno-array-bounds -fno-ipa-icf" } */
> > > > >>>>> +   { dg-options "-O2 -Wall -Wno-array-bounds -fno-ipa-icf 
> > > > >>>>> -fno-tree-vectorize" } */
> > > > >>>>
> > > > >>>> The testcase is large - what part requires this change?  Given the
> > > > >>>> testcase was added for inconsistent warnings do they now become
> > > > >>>> inconsistent again as we enable vectorization at -O2?
> > > > >>>>
> > > > >>>> That said, the testcase adjustments need some explaining - I 
> > > > >>>> suppose
> > > > >>>> you didn't just slap -fno-tree-vectorize to all of those changing
> > > > >>>> behavior?
> > > > >>>>
> > > > >>> void ga1_ (void)
> > > > >>> {
> > > > >>>     a1_.a[0] = 0;
> > > > >>>     a1_.a[1] = 1;                 // { dg-warning 
> > > > >>> "\\\[-Wstringop-overflow" }
> > > > >>>     a1_.a[2] = 2;                 // { dg-warning 
> > > > >>> "\\\[-Wstringop-overflow" }
> > > > >>>
> > > > >>>     struct A1 a;
> > > > >>>     a.a[0] = 0;
> > > > >>>     a.a[1] = 1;                   // { dg-warning 
> > > > >>> "\\\[-Wstringop-overflow" }
> > > > >>>     a.a[2] = 2;                   // { dg-warning 
> > > > >>> "\\\[-Wstringop-overflow" }
> > > > >>>     sink (&a);
> > > > >>> }
> > > > >>>
> > > > >>> It's supposed to be 2 warning for a.a[1] = 1 and a.a[2] = 1 since
> > > > >>> there are 2 accesses, but after enabling vectorization, there's only
> > > > >>> one access, so one warning is missing which causes the failure.
> > > >
> > > > With the stores vectorized, is the warning on the correct line or
> > > > does it point to the first store, the one that's in bounds, as
> > > > it does with -O3?  The latter would be a regression at -O2.
> > > For the upper case, It points to the second store which is out of
> > > bounds, the third store warning is missing.
> > > >
> > > > >>
> > > > >> I would find it preferable to change the test code over disabling
> > > > >> optimizations that are on by default.  My concern is that the test
> > > > >> would no longer exercise the default behavior.  (The same goes for
> > > > >> the -fno-ipa-icf option.)
> > > > > Hmm, it's a middle-end test, for some backend, it may not do
> > > > > vectorization(it depends on TARGET_VECTOR_MODE_SUPPORTED_P and
> > > > > relative cost model).
> > > >
> > > > Yes, there are quite a few warning tests like that.  Their main
> > > > purpose is to verify that in common GCC invocations (i.e., without
> > > > any special options) warnings are a) issued when expected and b)
> > > > not issued when not expected.  Otherwise, middle end warnings are
> > > > known to have both false positives and false negatives in some
> > > > invocations, depending on what optimizations are in effect.
> > > > Indiscriminately disabling common optimizations for these large
> > > > tests and invoking them under artificial conditions would
> > > > compromise this goal and hide the problems.
> > > >
> > > > If enabling vectorization at -O2 causes regressions in the quality
> > > > of diagnostics (as the test failure above indicates seems to be
> > > > happening) we should investigate these and open bugs for them so
> > > > they can be fixed.  We can then tweak the specific failing test
> > > > cases to avoid the failures until they are fixed.
> > > There are indeed cases of false positives and false negatives
> > > .i.e.
> > > // Verify warning for access to a definition with an initializer that
> > > // initializes the one-element array member.
> > > struct A1 a1i_1 = { 0, { 1 } };
> > >
> > > void ga1i_1 (void)
> > > {
> > >   a1i_1.a[0] = 0;
> > >   a1i_1.a[1] = 1;               // { dg-warning "\\\[-Wstringop-overflow" 
> > > }
> > >   a1i_1.a[2] = 2;               // { dg-warning "\\\[-Wstringop-overflow" 
> > > }
> > >
> > >   struct A1 a = { 0, { 1 } }; --- false positive here.
> > >   a.a[0] = 1;
> > >   a.a[1] = 2;                   // { dg-warning
> > > "\\\[-Wstringop-overflow" } false negative here.
> > >   a.a[2] = 3;                   // { dg-warning
> > > "\\\[-Wstringop-overflow" } false negative here.
> > >   sink (&a);
> > > }
> > Similar for
> > * gcc.dg/Warray-bounds-51.c.
> > * gcc.dg/Warray-parameter-3.c
> > * gcc.dg/Wstringop-overflow-14.c
> > * gcc.dg/Wstringop-overflow-21.c
> >
> > So there're 3 situations.
> > 1. All accesses are out of bound, and after vectorization, there are
> > some warnings missing.
> > 2. Part of accesses are inbound, part of accesses are out of bound,
> > and after vectorization, the warning goes from out of bound line to
> > inbound line.
> > 3. All access are out of bound, and after vectoriation, all warning
> > are missing, and goes to a false-positive line.
>
> I remember some of the warning code explicitely excuses itself from
> even trying to deal with vectorized loads/stores, that might need to
> be revisited.  It would also be useful to verify whether the line
> info on the vectorized loads/stores is sensible (if you dump with
> -lineno you get stmts with line numbers).
>
> It is of course impossible to preserve the location of all original
> scalar accesses exactly - it _might_ be possible to create a new
> location range (not sure how they are exactly represented), but then
> if we vectorize say
>
>   a[0] = b[0];
>   a[1] = b[1];
>
> we'd somehow get a multi-line location range that covers unrelated
> bits (the intermediate load or store).
>
> So currently the vectorizer simply chooses the location of one of
> the scalar loads or stores for the vectorized access (and it might do
> so quite randomly).
>
> Note I don't think it's feasible to not vectorize out-of-bound loads
> or stores for the same reason that you'll say you can't do the
> warnings all before vectorizing because the might expose themselves
> only later.
>
> So we simply have to cope with the reality that GCC is optimizing and
> that the later we perform analysis for warnings the more the original
> code is mangled.  As we moved array-bound warnings before unrolling
> so we should move this particular warning to before vectorization
> [loop optimization].

Sorry I'm late to the party here...

Couldn't we run warnings earlier?

A while back, I converted the array bounds checker to the generic
range_query API, so it could be used either with the vr_values object
from the VRP pass, or with a ranger.  There's no reason it should be
tied to VRP.  We could make it its own pass and move it somewhere more
sensible.

Aldy

Reply via email to