--- /dev/null
+/* { dg-do compile } */
+
+typedef struct { double re, im; } dcmlx_t;
+typedef struct { double re[4], im[4]; } dcmlx4_t;
+
+void foo_i2(dcmlx4_t dst[], const dcmlx_t src[], int n)
+{
+ for (int i = 0; i < n; ++i) {
+ dcmlx_t s00 = src[i*4+0];
+ dcmlx_t s01 = src[i*4+1];
+ dcmlx_t s02 = src[i*4+2];
+ dcmlx_t s03 = src[i*4+3];
+
+ dcmlx_t s10 = src[i*4+0+n];
+ dcmlx_t s11 = src[i*4+1+n];
+ dcmlx_t s12 = src[i*4+2+n];
+ dcmlx_t s13 = src[i*4+3+n];
+
+ dst[i*2+0].re[0] = s00.re;
+ dst[i*2+0].re[1] = s01.re;
+ dst[i*2+0].re[2] = s02.re;
+ dst[i*2+0].re[3] = s03.re;
+ dst[i*2+0].im[0] = s00.im;
+ dst[i*2+0].im[1] = s01.im;
+ dst[i*2+0].im[2] = s02.im;
+ dst[i*2+0].im[3] = s03.im;
+
+ dst[i*2+1].re[0] = s10.re;
+ dst[i*2+1].re[1] = s11.re;
+ dst[i*2+1].re[2] = s12.re;
+ dst[i*2+1].re[3] = s13.re;
+ dst[i*2+1].im[0] = s10.im;
+ dst[i*2+1].im[1] = s11.im;
+ dst[i*2+1].im[2] = s12.im;
+ dst[i*2+1].im[3] = s13.im;
+ }
+}
+
+/* The first step to produce optimal code is to appropriately detect the
+ load and store groups. */
+/* { dg-final { scan-tree-dump "Detected interleaving load of size 8" "vect" } } */
+/* { dg-final { scan-tree-dump "Detected interleaving store of size 16" "vect" } } */
+/* { dg-final { scan-tree-dump-not "gap of 6 elements" "vect" } } */
&& TYPE_PRECISION (type) >= TYPE_PRECISION (itype)
&& (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)))
{
- if (INTEGRAL_TYPE_P (itype) && TYPE_OVERFLOW_WRAPS (itype))
+ if (INTEGRAL_TYPE_P (itype) && TYPE_OVERFLOW_WRAPS (itype)
+ && (TYPE_PRECISION (type) > TYPE_PRECISION (itype)
+ || TYPE_UNSIGNED (itype) != TYPE_UNSIGNED (type)))
{
/* Split the unconverted operand and try to prove that
wrapping isn't a problem. */