1  /* { dg-require-effective-target size32plus } */
       2  /* { dg-additional-options "-O2 -fopenmp -fdump-tree-vect-details" } */
       3  /* { dg-additional-options "-msse2" { target sse2_runtime } } */
       4  /* { dg-additional-options "-mavx" { target avx_runtime } } */
       5  /* { dg-final { scan-tree-dump-times "vectorized \[2-6] loops" 2 "vect" { target sse2_runtime } } } */
       6  
       7  extern void abort (void);
       8  int r, a[1024], b[1024];
       9  
      10  #pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0)
      11  
      12  __attribute__((noipa)) void
      13  foo (int *a, int *b)
      14  {
      15    #pragma omp for simd reduction (inscan, foo:r) simdlen (1)
      16    for (int i = 0; i < 1024; i++)
      17      {
      18        r += a[i];
      19        #pragma omp scan inclusive(r)
      20        b[i] = r;
      21      }
      22  }
      23  
      24  __attribute__((noipa)) int
      25  bar (void)
      26  {
      27    int s = 0;
      28    #pragma omp parallel
      29    #pragma omp for simd reduction (inscan, foo:s)
      30    for (int i = 0; i < 1024; i++)
      31      {
      32        s += 2 * a[i];
      33        #pragma omp scan inclusive(s)
      34        b[i] = s;
      35      }
      36    return s;
      37  }
      38  
      39  __attribute__((noipa)) void
      40  baz (int *a, int *b)
      41  {
      42    #pragma omp parallel for simd reduction (inscan, foo:r)
      43    for (int i = 0; i < 1024; i++)
      44      {
      45        r += a[i];
      46        #pragma omp scan inclusive(r)
      47        b[i] = r;
      48      }
      49  }
      50  
      51  __attribute__((noipa)) int
      52  qux (void)
      53  {
      54    int s = 0;
      55    #pragma omp parallel for simd if (simd: 0) reduction (inscan, foo:s)
      56    for (int i = 0; i < 1024; i++)
      57      {
      58        s += 2 * a[i];
      59        #pragma omp scan inclusive(s)
      60        b[i] = s;
      61      }
      62    return s;
      63  }
      64  
      65  int
      66  main ()
      67  {
      68    int s = 0;
      69    for (int i = 0; i < 1024; ++i)
      70      {
      71        a[i] = i;
      72        b[i] = -1;
      73        asm ("" : "+g" (i));
      74      }
      75    #pragma omp parallel
      76    foo (a, b);
      77    if (r != 1024 * 1023 / 2)
      78      abort ();
      79    for (int i = 0; i < 1024; ++i)
      80      {
      81        s += i;
      82        if (b[i] != s)
      83  	abort ();
      84        else
      85  	b[i] = 25;
      86      }
      87    if (bar () != 1024 * 1023)
      88      abort ();
      89    s = 0;
      90    for (int i = 0; i < 1024; ++i)
      91      {
      92        s += 2 * i;
      93        if (b[i] != s)
      94  	abort ();
      95        else
      96  	b[i] = -1;
      97      }
      98    r = 0;
      99    baz (a, b);
     100    if (r != 1024 * 1023 / 2)
     101      abort ();
     102    s = 0;
     103    for (int i = 0; i < 1024; ++i)
     104      {
     105        s += i;
     106        if (b[i] != s)
     107  	abort ();
     108        else
     109  	b[i] = -25;
     110      }
     111    if (qux () != 1024 * 1023)
     112      abort ();
     113    s = 0;
     114    for (int i = 0; i < 1024; ++i)
     115      {
     116        s += 2 * i;
     117        if (b[i] != s)
     118  	abort ();
     119      }
     120    return 0;
     121  }