re PR tree-optimization/92618 (error: type mismatch in binary expression in reassoc...
authorJakub Jelinek <jakub@redhat.com>
Fri, 22 Nov 2019 18:17:04 +0000 (19:17 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 22 Nov 2019 18:17:04 +0000 (19:17 +0100)
PR tree-optimization/92618
* tree-ssa-reassoc.c (v_info): Change from auto_vec to a struct
containing the auto_vec and a tree.
(undistribute_bitref_for_vector): Handle the case when element type
of vec is not the same as type of the BIT_FIELD_REF.  Formatting
fixes.

* gcc.c-torture/compile/pr92618.c: New test.
* gcc.c-torture/execute/pr92618.c: New test.

From-SVN: r278626

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr92618.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr92618.c [new file with mode: 0644]
gcc/tree-ssa-reassoc.c

index 0b3b47714eac85b13712b47aa9d43d6405706360..7f7dd0006f2d4663b16982d4cb57a8f59e08b43b 100644 (file)
@@ -1,3 +1,12 @@
+2019-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/92618
+       * tree-ssa-reassoc.c (v_info): Change from auto_vec to a struct
+       containing the auto_vec and a tree.
+       (undistribute_bitref_for_vector): Handle the case when element type
+       of vec is not the same as type of the BIT_FIELD_REF.  Formatting
+       fixes.
+
 2019-11-22  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/83859
index b9d86958376859d5bde803ac06a26edc7837b61e..b3ff86843ee6e1f7cd9a82f18959654a78da1dad 100644 (file)
@@ -1,3 +1,9 @@
+2019-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/92618
+       * gcc.c-torture/compile/pr92618.c: New test.
+       * gcc.c-torture/execute/pr92618.c: New test.
+
 2019-11-22  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/83859
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr92618.c b/gcc/testsuite/gcc.c-torture/compile/pr92618.c
new file mode 100644 (file)
index 0000000..b2a2eea
--- /dev/null
@@ -0,0 +1,67 @@
+/* PR tree-optimization/92618 */
+
+typedef long long __m128i __attribute__((__may_alias__, __vector_size__(2 * sizeof (long long))));
+typedef long long __m256i __attribute__((__may_alias__, __vector_size__(4 * sizeof (long long))));
+typedef long long __m512i __attribute__((__may_alias__, __vector_size__(8 * sizeof (long long))));
+
+double a[32];
+unsigned long long b[32];
+__m128i bar (void);
+__m256i qux (void);
+__m512i corge (void);
+
+void
+foo (unsigned long long *x)
+{
+  __m128i c = bar ();
+  __m128i d = bar ();
+  __m256i e = qux ();
+  __m256i f = qux ();
+  __m256i g = qux ();
+  __m512i h = corge ();
+  __m512i i = corge ();
+  *(__m128i *) &b[0] = c;
+  *(__m128i *) &b[2] = d;
+  *(__m256i *) &b[4] = e;
+  *(__m256i *) &b[8] = f;
+  *(__m256i *) &b[12] = g;
+  *(__m512i *) &b[16] = h;
+  *(__m512i *) &b[24] = i;
+  *x = b[0] + b[1] + b[2] + b[3]
+     + b[4] + b[5] + b[6] + b[7]
+     + b[8] + b[9] + b[10] + b[11]
+     + b[12] + b[13] + b[14] + b[15]
+     + b[16] + b[17] + b[18] + b[19]
+     + b[20] + b[21] + b[22] + b[23]
+     + b[24] + b[25] + b[26] + b[27]
+     + b[28] + b[29] + b[30] + b[31];
+}
+
+void
+baz (double *x)
+{
+#if __SIZEOF_LONG_LONG__ == __SIZEOF_DOUBLE__
+  __m128i c = bar ();
+  __m128i d = bar ();
+  __m256i e = qux ();
+  __m256i f = qux ();
+  __m256i g = qux ();
+  __m512i h = corge ();
+  __m512i i = corge ();
+  *(__m128i *) &a[0] = c;
+  *(__m128i *) &a[2] = d;
+  *(__m256i *) &a[4] = e;
+  *(__m256i *) &a[8] = f;
+  *(__m256i *) &a[12] = g;
+  *(__m512i *) &a[16] = h;
+  *(__m512i *) &a[24] = i;
+  *x = a[0] + a[1] + a[2] + a[3]
+     + a[4] + a[5] + a[6] + a[7]
+     + a[8] + a[9] + a[10] + a[11]
+     + a[12] + a[13] + a[14] + a[15]
+     + a[16] + a[17] + a[18] + a[19]
+     + a[20] + a[21] + a[22] + a[23]
+     + a[24] + a[25] + a[26] + a[27]
+     + a[28] + a[29] + a[30] + a[31];
+#endif
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr92618.c b/gcc/testsuite/gcc.c-torture/execute/pr92618.c
new file mode 100644 (file)
index 0000000..2a5e565
--- /dev/null
@@ -0,0 +1,63 @@
+/* PR tree-optimization/92618 */
+
+typedef long long __m128i __attribute__((__may_alias__, __vector_size__(2 * sizeof (long long))));
+
+double a[4];
+unsigned long long b[4];
+
+__attribute__((noipa)) __m128i
+bar (void)
+{
+  static int cnt;
+  cnt += 2;
+  return (__m128i) { cnt, cnt + 1 };
+}
+
+#if __SIZEOF_LONG_LONG__ == __SIZEOF_DOUBLE__
+typedef double __m128d __attribute__((__may_alias__, __vector_size__(2 * sizeof (double))));
+
+__attribute__((noipa)) __m128i
+qux (void)
+{
+  static double cnt;
+  cnt += 2.0;
+  return (__m128i) (__m128d) { cnt, cnt + 1.0 };
+}
+#endif
+
+void
+foo (unsigned long long *x)
+{
+  __m128i c = bar ();
+  __m128i d = bar ();
+  *(__m128i *) &b[0] = c;
+  *(__m128i *) &b[2] = d;
+  *x = b[0] + b[1] + b[2] + b[3];
+}
+
+void
+baz (double *x)
+{
+#if __SIZEOF_LONG_LONG__ == __SIZEOF_DOUBLE__
+  __m128i c = qux ();
+  __m128i d = qux ();
+  *(__m128i *) &a[0] = c;
+  *(__m128i *) &a[2] = d;
+  *x = a[0] + a[1] + a[2] + a[3];
+#endif
+}
+
+int
+main ()
+{
+  unsigned long long c = 0;
+  foo (&c);
+  if (c != 2 + 3 + 4 + 5)
+    __builtin_abort ();
+#if __SIZEOF_LONG_LONG__ == __SIZEOF_DOUBLE__
+  double d = 0.0;
+  baz (&d);
+  if (d != 2.0 + 3.0 + 4.0 + 5.0)
+    __builtin_abort ();
+#endif
+}
index ed14b6b4e7a385a704bc1004f8a6eeb3dca626e4..3479591366136b0cb3bd8bbbaf49864cf7124b74 100644 (file)
@@ -1775,7 +1775,10 @@ undistribute_ops_list (enum tree_code opcode,
    first: element index for each relevant BIT_FIELD_REF.
    second: the index of vec ops* for each relevant BIT_FIELD_REF.  */
 typedef std::pair<unsigned, unsigned> v_info_elem;
-typedef auto_vec<v_info_elem, 32> v_info;
+struct v_info {
+  tree vec_type;
+  auto_vec<v_info_elem, 32> vec;
+};
 typedef v_info *v_info_ptr;
 
 /* Comparison function for qsort on VECTOR SSA_NAME trees by machine mode.  */
@@ -1840,8 +1843,11 @@ undistribute_bitref_for_vector (enum tree_code opcode,
   if (ops->length () <= 1)
     return false;
 
-  if (opcode != PLUS_EXPR && opcode != MULT_EXPR && opcode != BIT_XOR_EXPR
-      && opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
+  if (opcode != PLUS_EXPR
+      && opcode != MULT_EXPR
+      && opcode != BIT_XOR_EXPR
+      && opcode != BIT_IOR_EXPR
+      && opcode != BIT_AND_EXPR)
     return false;
 
   hash_map<tree, v_info_ptr> v_info_map;
@@ -1879,9 +1885,45 @@ undistribute_bitref_for_vector (enum tree_code opcode,
       if (!TYPE_VECTOR_SUBPARTS (vec_type).is_constant ())
        continue;
 
+      if (VECTOR_TYPE_P (TREE_TYPE (rhs))
+         || !is_a <scalar_mode> (TYPE_MODE (TREE_TYPE (rhs))))
+       continue;
+
+      /* The type of BIT_FIELD_REF might not be equal to the element type of
+        the vector.  We want to use a vector type with element type the
+        same as the BIT_FIELD_REF and size the same as TREE_TYPE (vec).  */
+      if (!useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (vec_type)))
+       {
+         machine_mode simd_mode;
+         unsigned HOST_WIDE_INT size, nunits;
+         unsigned HOST_WIDE_INT elem_size
+           = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (rhs)));
+         if (!GET_MODE_BITSIZE (TYPE_MODE (vec_type)).is_constant (&size))
+           continue;
+         if (size <= elem_size || (size % elem_size) != 0)
+           continue;
+         nunits = size / elem_size;
+         if (!mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (rhs)),
+                               nunits).exists (&simd_mode))
+           continue;
+         vec_type = build_vector_type_for_mode (TREE_TYPE (rhs), simd_mode);
+
+         /* Ignore it if target machine can't support this VECTOR type.  */
+         if (!VECTOR_MODE_P (TYPE_MODE (vec_type)))
+           continue;
+
+         /* Check const vector type, constrain BIT_FIELD_REF offset and
+            size.  */
+         if (!TYPE_VECTOR_SUBPARTS (vec_type).is_constant ())
+           continue;
+
+         if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (vec_type)),
+                       GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (vec)))))
+           continue;
+       }
+
       tree elem_type = TREE_TYPE (vec_type);
-      unsigned HOST_WIDE_INT elem_size
-       = TREE_INT_CST_LOW (TYPE_SIZE (elem_type));
+      unsigned HOST_WIDE_INT elem_size = tree_to_uhwi (TYPE_SIZE (elem_type));
       if (maybe_ne (bit_field_size (rhs), elem_size))
        continue;
 
@@ -1898,8 +1940,13 @@ undistribute_bitref_for_vector (enum tree_code opcode,
       bool existed;
       v_info_ptr &info = v_info_map.get_or_insert (vec, &existed);
       if (!existed)
-       info = new v_info;
-      info->safe_push (std::make_pair (idx, i));
+       {
+         info = new v_info;
+         info->vec_type = vec_type;
+       }
+      else if (!types_compatible_p (vec_type, info->vec_type))
+       continue;
+      info->vec.safe_push (std::make_pair (idx, i));
     }
 
   /* At least two VECTOR to combine.  */
@@ -1919,14 +1966,15 @@ undistribute_bitref_for_vector (enum tree_code opcode,
     {
       tree cand_vec = (*it).first;
       v_info_ptr cand_info = (*it).second;
-      unsigned int num_elems = VECTOR_CST_NELTS (cand_vec).to_constant ();
-      if (cand_info->length () != num_elems)
+      unsigned int num_elems
+       = TYPE_VECTOR_SUBPARTS (cand_info->vec_type).to_constant ();
+      if (cand_info->vec.length () != num_elems)
        continue;
       sbitmap holes = sbitmap_alloc (num_elems);
       bitmap_ones (holes);
       bool valid = true;
       v_info_elem *curr;
-      FOR_EACH_VEC_ELT (*cand_info, i, curr)
+      FOR_EACH_VEC_ELT (cand_info->vec, i, curr)
        {
          if (!bitmap_bit_p (holes, curr->first))
            {
@@ -1962,25 +2010,53 @@ undistribute_bitref_for_vector (enum tree_code opcode,
 
       unsigned int idx, j;
       gimple *sum = NULL;
-      v_info_ptr info_ptr;
       tree sum_vec = tvec;
+      v_info_ptr info_ptr = *(v_info_map.get (tvec));
       v_info_elem *elem;
+      tree vec_type = info_ptr->vec_type;
 
       /* Build the sum for all candidates with same mode.  */
       do
        {
-         sum = build_and_add_sum (TREE_TYPE (sum_vec), sum_vec,
+         sum = build_and_add_sum (vec_type, sum_vec,
                                   valid_vecs[i + 1], opcode);
+         if (!useless_type_conversion_p (vec_type,
+                                         TREE_TYPE (valid_vecs[i + 1])))
+           {
+             /* Update the operands only after build_and_add_sum,
+                so that we don't have to repeat the placement algorithm
+                of build_and_add_sum.  */
+             gimple_stmt_iterator gsi = gsi_for_stmt (sum);
+             tree vce = build1 (VIEW_CONVERT_EXPR, vec_type,
+                                valid_vecs[i + 1]);
+             tree lhs = make_ssa_name (vec_type);
+             gimple *g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR, vce);
+             gimple_set_uid (g, gimple_uid (sum));
+             gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+             gimple_assign_set_rhs2 (sum, lhs);
+             if (sum_vec == tvec)
+               {
+                 vce = build1 (VIEW_CONVERT_EXPR, vec_type, sum_vec);
+                 lhs = make_ssa_name (vec_type);
+                 g = gimple_build_assign (lhs, VIEW_CONVERT_EXPR, vce);
+                 gimple_set_uid (g, gimple_uid (sum));
+                 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+                 gimple_assign_set_rhs1 (sum, lhs);
+               }
+             update_stmt (sum);
+           }
          sum_vec = gimple_get_lhs (sum);
          info_ptr = *(v_info_map.get (valid_vecs[i + 1]));
+         gcc_assert (types_compatible_p (vec_type, info_ptr->vec_type));
          /* Update those related ops of current candidate VECTOR.  */
-         FOR_EACH_VEC_ELT (*info_ptr, j, elem)
+         FOR_EACH_VEC_ELT (info_ptr->vec, j, elem)
            {
              idx = elem->second;
              gimple *def = SSA_NAME_DEF_STMT ((*ops)[idx]->op);
              /* Set this then op definition will get DCEd later.  */
              gimple_set_visited (def, true);
-             if (opcode == PLUS_EXPR || opcode == BIT_XOR_EXPR
+             if (opcode == PLUS_EXPR
+                 || opcode == BIT_XOR_EXPR
                  || opcode == BIT_IOR_EXPR)
                (*ops)[idx]->op = build_zero_cst (TREE_TYPE ((*ops)[idx]->op));
              else if (opcode == MULT_EXPR)
@@ -2007,16 +2083,16 @@ undistribute_bitref_for_vector (enum tree_code opcode,
          BIT_FIELD_REF statements accordingly.  */
       info_ptr = *(v_info_map.get (tvec));
       gcc_assert (sum);
-      tree elem_type = TREE_TYPE (TREE_TYPE (tvec));
-      FOR_EACH_VEC_ELT (*info_ptr, j, elem)
+      tree elem_type = TREE_TYPE (vec_type);
+      FOR_EACH_VEC_ELT (info_ptr->vec, j, elem)
        {
          idx = elem->second;
          tree dst = make_ssa_name (elem_type);
-         gimple *gs = gimple_build_assign (
-           dst, BIT_FIELD_REF,
-           build3 (BIT_FIELD_REF, elem_type, sum_vec, TYPE_SIZE (elem_type),
-                   bitsize_int (elem->first
-                                * tree_to_uhwi (TYPE_SIZE (elem_type)))));
+         tree pos = bitsize_int (elem->first
+                                 * tree_to_uhwi (TYPE_SIZE (elem_type)));
+         tree bfr = build3 (BIT_FIELD_REF, elem_type, sum_vec,
+                            TYPE_SIZE (elem_type), pos);
+         gimple *gs = gimple_build_assign (dst, BIT_FIELD_REF, bfr);
          insert_stmt_after (gs, sum);
          gimple *def = SSA_NAME_DEF_STMT ((*ops)[idx]->op);
          /* Set this then op definition will get DCEd later.  */