/* { dg-additional-options "-O3" } */
/* { dg-require-effective-target vect_double } */
/* { dg-additional-options "-mprefer-vector-width=128" { target x86_64-*-* i?86-*-* } } */

#include "tree-vect.h"

extern void abort (void);
extern void *malloc (__SIZE_TYPE__);

struct site {
    struct {
	struct {
	    double real;
	    double imag;
	} e[3][3];
    } link[32];
    double phase[32];
} *lattice;
int sites_on_node;

void rephase (void)
{
  int i,j,k,dir;
  struct site *s;
  for(i=0,s=lattice;i<sites_on_node;i++,s++)
    for(dir=0;dir<32;dir++)
      {
	for(j=0;j<3;j++)
	  for(k=0;k<3;k++)
	    {
	      s->link[dir].e[j][k].real *= s->phase[dir];
	      s->link[dir].e[j][k].imag *= s->phase[dir];
	    }
	/* Avoid loop vectorizing the outer loop after unrolling
	   the inners.  */
	__asm__ volatile ("" : : : "memory");
      }
}

int main()
{
  int i,j,k;
  check_vect ();
  sites_on_node = 1;
  lattice = malloc (sizeof (struct site) * sites_on_node);
  for (i = 0; i < 32; ++i)
    {
      lattice->phase[i] = i;
      for (j = 0; j < 3; ++j)
	for (k = 0; k < 3; ++k)
	  {
	    lattice->link[i].e[j][k].real = 1.0;
	    lattice->link[i].e[j][k].imag = 1.0;
	    __asm__ volatile ("" : : : "memory");
	  }
    }
  rephase ();
#pragma GCC novector
  for (i = 0; i < 32; ++i)
#pragma GCC novector
    for (j = 0; j < 3; ++j)
#pragma GCC novector
      for (k = 0; k < 3; ++k)
	if (lattice->link[i].e[j][k].real != i
	    || lattice->link[i].e[j][k].imag != i)
	  abort ();
  return 0;
}

/* We should also be able to use 2-lane SLP to initialize the real and
   imaginary components in the first loop of main.  */
/* { dg-final { scan-tree-dump-times "optimized: basic block" 10 "slp1" { target {! { vect1024 } } } } } */
/* { dg-final { scan-tree-dump-times "optimized: basic block" 11 "slp1" { target { { vect1024 } } } } } */
/* We should see the s->phase[dir] operand splatted and no other operand built
   from scalars.  See PR97334.  */
/* { dg-final { scan-tree-dump "Using a splat" "slp1" } } */
/* { dg-final { scan-tree-dump-times "Building vector operands from scalars" 0 "slp1" } } */
