From 204b0bebee5343b5bd07e2a7be6fd74d6698b937 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 22 Nov 2019 19:17:04 +0100 Subject: [PATCH] re PR tree-optimization/92618 (error: type mismatch in binary expression in reassoc since r273490) 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 | 9 ++ gcc/testsuite/ChangeLog | 6 + gcc/testsuite/gcc.c-torture/compile/pr92618.c | 67 ++++++++++ gcc/testsuite/gcc.c-torture/execute/pr92618.c | 63 ++++++++++ gcc/tree-ssa-reassoc.c | 118 ++++++++++++++---- 5 files changed, 242 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr92618.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr92618.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0b3b47714ea..7f7dd0006f2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-11-22 Jakub Jelinek + + 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 PR middle-end/83859 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b9d86958376..b3ff86843ee 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-11-22 Jakub Jelinek + + 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 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 index 00000000000..b2a2eeadab3 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr92618.c @@ -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 index 00000000000..2a5e565559f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr92618.c @@ -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 +} diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index ed14b6b4e7a..34795913661 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -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 v_info_elem; -typedef auto_vec v_info; +struct v_info { + tree vec_type; + auto_vec 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 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 (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. */ -- 2.30.2