diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-11-22 19:17:04 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-11-22 19:17:04 +0100 |
commit | 204b0bebee5343b5bd07e2a7be6fd74d6698b937 (patch) | |
tree | 052293e4a3a5094dff1140f32ce16b304bf224ef /gcc/tree-ssa-reassoc.c | |
parent | 54aa6b58fe2fe73bbe67e0485777e0c410a18673 (diff) | |
download | gcc-204b0bebee5343b5bd07e2a7be6fd74d6698b937.zip gcc-204b0bebee5343b5bd07e2a7be6fd74d6698b937.tar.gz gcc-204b0bebee5343b5bd07e2a7be6fd74d6698b937.tar.bz2 |
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
Diffstat (limited to 'gcc/tree-ssa-reassoc.c')
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 118 |
1 files changed, 97 insertions, 21 deletions
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index ed14b6b..3479591 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<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. */ |