This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH PR71734] Add missed check that reference defined inside loop.


Hi Yuri,

I saw this test case runs on arm platforms, and maybe other platforms as well.

testsuite/g++.dg/vect/pr70729.cc:7:10: fatal error: xmmintrin.h: No such file or directory

Before the change here, it's gated by vect_simd_clones target selector, which limit it to i?86/x86_64 platform only.

Regards,
Renlin Li



On 08/07/16 15:07, Yuri Rumyantsev wrote:
Hi Richard,

Thanks for your help - your patch looks much better.
Here is new patch in which additional argument was added to determine
source loop of reference.

Bootstrap and regression testing did not show any new failures.

Is it OK for trunk?
ChangeLog:
2016-07-08  Yuri Rumyantsev  <ysrumyan@gmail.com>

PR tree-optimization/71734
* tree-ssa-loop-im.c (ref_indep_loop_p_1): Add REF_LOOP argument which
contains REF, use it to check safelen, assume that safelen value
must be greater 1, fix style.
(ref_indep_loop_p_2): Add REF_LOOP argument.
(ref_indep_loop_p): Pass LOOP as additional argument to
ref_indep_loop_p_2.
gcc/testsuite/ChangeLog:
         * g++.dg/vect/pr70729.cc: Delete redundant dg options, fix style.

2016-07-08 11:18 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Thu, Jul 7, 2016 at 5:38 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
I checked simd3.f90 and found out that my additional check reject
independence of references

REF is independent in loop#3
.istart0.19, .iend0.20
which are defined in loop#1 which is outer for loop#3.
Note that these references are defined by
_103 = __builtin_GOMP_loop_dynamic_next (&.istart0.19, &.iend0.20);
which is in loop#1.
It is clear that both these references can not be independent for loop#3.

Ok, so we end up calling ref_indep_loop for ref in LOOP also for inner loops
of LOOP to catch memory references in those as well.  So the issue is really
that we look at the wrong loop for safelen and we _do_ want to apply safelen
to inner loops as well.

So better track the loop we are ultimately asking the question for, like in the
attached patch (fixes the testcase for me).

Richard.



2016-07-07 17:11 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Thu, Jul 7, 2016 at 4:04 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
I Added this check because of new failures in libgomp.fortran suite.
Here is copy of Jakub message:
--- Comment #29 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The #c27 r237844 change looks bogus to me.
First of all, IMNSHO you can argue this way only if ref is a reference seen in
loop LOOP,

or inner loops of LOOP I guess.  I _think_ we never call ref_indep_loop_p_1 with
a REF whose loop is not a sub-loop of LOOP or LOOP itself (as it would not make
sense to do that, it would be a waste of time).

So only if "or inner loops of LOOP" is not correct the check would be needed
but then my issue with unrolling an inner loop and turning a ref that safelen
does not apply to into a ref that it now applies to arises.

I don't fully get what Jakub is hinting at.

Can you install the safelen > 0 -> safelen > 1 fix please?  Jakub, can you
explain that bitmap check with a simple testcase?

Thanks,
Richard.

which is the case of e.g. *.omp_data_i_23(D).a ref in simd3.f90 -O2
-fopenmp -msse2, but not the D.3815[0] case tested during can_sm_ref_p - the
D.3815[0] = 0; as well as something = D.3815[0]; stmt found in the outer loop
obviously can be dependent on many of the loads and/or stores in the loop, be
it "omp simd array" or not.
Say for
void
foo (int *p, int *q)
{
   #pragma omp simd
   for (int i = 0; i < 1024; i++)
     p[i] += q[0];
}
sure, q[0] can't alias p[0] ... p[1022], the earlier iterations could write
something that changes its value, and then it would behave differently from
using VF = 1024, where everything is performed in parallel.
Though, actually, it can alias, just it would have to write the same value as
was there.  So, if this is used to determine if it is safe to hoist the load
before the loop, it is fine, if it is used to determine if &q[0] >= &p[0] &&
&q[0] <= &p[1023], then it is not fine.

For aliasing of q[0] and p[1023], I don't see why they couldn't alias in a
valid program.  #pragma omp simd I think guarantees that the last iteration is
executed last, it isn't necessarily executed last alone, it could be, or
together with one before last iteration, or (for simdlen INT_MAX) even all
iterations can be done concurrently, in hw or sw, so it is fine if it is
transformed into:
   int temp[1024], temp2[1024], temp3[1024];
   for (int i = 0; i < 1024; i++)
     temp[i] = p[i];
   for (int i = 0; i < 1024; i++)
     temp2[i] = q[0];
   /* The above two loops can be also swapped, or intermixed.  */
   for (int i = 0; i < 1024; i++)
     temp3[i] = temp[i] + temp2[i];
   for (int i = 0; i < 1024; i++)
     p[i] = temp3[i];
   /* Or the above loop reversed etc. */

If you have:
int
bar (int *p, int *q)
{
   q[0] = 0;
   #pragma omp simd
   for (int i = 0; i < 1024; i++)
     p[i]++;
   return q[0];
}
i.e. something similar to what misbehaves in simd3.f90 with the change, then
the answer is that q[0] isn't guaranteed to be independent of any references in
the simd loop.

2016-07-07 16:57 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Thu, Jul 7, 2016 at 3:24 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
Richard,

Did you meas the following check enhancement:

   outer = loop_outer (loop);
   /* We consider REF defined in LOOP as independent if at least 2 loop
      iterations are not dependent.  */
   if ((loop->safelen > 1
        || (outer && outer->safelen > 1))
       && bitmap_bit_p (&memory_accesses.refs_in_loop[loop->num], ref->id))
     return true;
which allows us to consider reference x[0] as invariant for the test
#pragma omp simd
   for (i = 0; i< 100; i++)
     {
       y[i] = i * 2;
       for (j = 0; j < 100; j++)
z[j] += x[0];
     }

Moving statement
_9 = *x_19(D);
(cost 20) out of loop 1.

outer loops will be automatically considered by outermost_indep_loop
which eventually
calls the function you are patching.

I was questioning the added test

        && bitmap_bit_p (&memory_accesses.refs_in_loop[loop->num], ref->id))

and still do not understand why you need that.  It makes us only consider the
loop of ref itself when looking at safelen (but not refs that belong
to inner loops
of loop).

Richard.


2016-07-07 11:46 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Wed, Jul 6, 2016 at 4:42 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
Richard,

I don't understand your question and how it is related to proposed patch.

2016-07-06 16:55 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Wed, Jul 6, 2016 at 3:50 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
See for example Jakub comments for 70729.

But how can the check be valid given a

#pragma omp simd
   for (;;)
     {
        for (;;)
          ...ref in question...
     }

can be transformed to

#pragma omp simd
    for (;;)
      {
         ...ref in question...
         ...ref in question..
         ...
      }

by means of unrolling?

The bitmap check would return false for the not unrolled inner loop
and true for the inner unrolled loop.
So it cannot be correct.

(not sure why this is all off-list btw)

Richard.

Richard.

2016-07-06 16:25 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Wed, Jul 6, 2016 at 1:43 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
I did not learn LIM detailed but I see on the following example
#pragma omp simd
   for (i = 0; i< 100; i++)
     {
       y[i] = i * 2;
       for (j = 0; j < 100; j++)
z[j] += x[0];
     }
that only inner,ost loop is handled:

Memory reference in loop#2 1: *_7
Memory reference in loop#2 2: *x_19(D)
Memory reference in loop#1 3: *_3
Basic block 3 (loop 1 -- depth 1):

Basic block 4 (loop 2 -- depth 2):

Loop#2 is innermost
Querying dependency of refs 2 and 1: dependent.
Querying dependencies of ref 2 in loop 2: dependent

well, LIM doesn't bother to check against refs in an outer loop if
refs in the inner loop are already dependent.

Loop unroll of inner loop does not invalidate 'safelen' of outer one
accordingly with safelen definition.

So why do you need the bitmap_bit_p check then?

Richard.

2016-07-06 14:23 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Wed, Jul 6, 2016 at 1:17 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
Richard,

LIM phase considers only innermost loops and does not handle loop
nests, so in your case the innermost loop (j) does not have non-zero
safelen.

Huh?  LIM considers loop nests just fine.  And yes, the innermost loop
does not have safelen but shouldn't it?  Consider the inner loop being unrolled
by GCC so it is removed - should that then invalidate the outer loop safelen
because innermost loop refs now appear in the outer loop?

Richard.


2016-07-06 13:34 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Wed, Jul 6, 2016 at 11:50 AM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
Richard,

I pointed out in the commentary that REF is defined inside loop and
this check is related to this statement. Should I clarify it?

+  /* We consider REF defined in LOOP as independent if at least 2 loop
+     iterations are not dependent.  */

Yes, I fail to see why x[0] should not be disambiguated against y[i] in

#pragma GCC loop ivdep
   for (i...)
     {
       y[i] = ...;
       for (j...)
         ... = x[0];
     }

REF is always inside the loop nest with LOOP being the outermost loop.

Richard.


2016-07-06 12:38 GMT+03:00 Richard Biener <richard.guenther@gmail.com>:
On Tue, Jul 5, 2016 at 4:56 PM, Yuri Rumyantsev <ysrumyan@gmail.com> wrote:
Hi All,

Here is a simple fix to cure regressions introduced by my fix for
70729. Patch also contains minor changes in test found by Jakub.

Bootstrapping and regression testing did not show any new failures.

Is it OK for trunk?

+      && bitmap_bit_p (&memory_accesses.refs_in_loop[loop->num], ref->id))

So safelen does not apply to refs in nested loops?  The added comment only
explains the safelen check change but this also requires explanation.

Richard.

ChangeLog:
2016-07-05  Yuri Rumyantsev  <ysrumyan@gmail.com>

PR tree-optimization/71734
* tree-ssa-loop-im.c (ref_indep_loop_p_1): Consider REF defined in
LOOP as independent if at least two loop iterations are not dependent.
gcc/testsuite/ChangeLog:
         * g++.dg/vect/pr70729.cc: Delete redundant dg options, fix style.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]