From ebe4bf41d2b96a6b2f1de6a184eb0a7f5c2e5d00 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Fri, 9 Feb 2018 05:46:18 +0000 Subject: [PATCH] re PR c++/83659 (ICE on compilable C++ code: in tree_to_shwi, at tree.c:6821) PR c++/83659 * fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro. Formatting fixes. Verify first that tree_fits_poly_int64_p (op01). Sync some changes from cxx_fold_indirect_ref. * constexpr.c (cxx_fold_indirect_ref): Sync some changes from fold_indirect_ref_1, including poly_*int64. Verify first that tree_fits_poly_int64_p (op01). Formatting fixes. * g++.dg/torture/pr83659.C: New test. Co-Authored-By: Jakub Jelinek From-SVN: r257512 --- gcc/ChangeLog | 8 ++++ gcc/cp/ChangeLog | 8 ++++ gcc/cp/constexpr.c | 51 ++++++++++++++++---------- gcc/fold-const.c | 27 ++++++++++---- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/torture/pr83659.C | 18 +++++++++ 6 files changed, 90 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr83659.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5e19ed8f5b..d9c544387fc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2018-02-09 Marek Polacek + Jakub Jelinek + + PR c++/83659 + * fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro. + Formatting fixes. Verify first that tree_fits_poly_int64_p (op01). + Sync some changes from cxx_fold_indirect_ref. + 2018-02-09 Alexandre Oliva * cfgexpand.c (expand_gimple_basic_block): Handle inline entry diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index be4db4b789a..ac53a74d35f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2018-02-09 Marek Polacek + Jakub Jelinek + + PR c++/83659 + * constexpr.c (cxx_fold_indirect_ref): Sync some changes from + fold_indirect_ref_1, including poly_*int64. Verify first that + tree_fits_poly_int64_p (op01). Formatting fixes. + 2018-02-08 Paolo Carlini * constexpr.c (cxx_eval_component_reference): Use INDIRECT_REF_P. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 39a2e1ab578..72924412706 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3025,9 +3025,10 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, static tree cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) { - tree sub, subtype; + tree sub = op0; + tree subtype; + poly_uint64 const_op01; - sub = op0; STRIP_NOPS (sub); subtype = TREE_TYPE (sub); if (!POINTER_TYPE_P (subtype)) @@ -3082,7 +3083,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) { tree part_width = TYPE_SIZE (type); tree index = bitsize_int (0); - return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index); + return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, + index); } /* Also handle conversion to an empty base class, which is represented with a NOP_EXPR. */ @@ -3107,7 +3109,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) } } else if (TREE_CODE (sub) == POINTER_PLUS_EXPR - && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) + && poly_int_tree_p (TREE_OPERAND (sub, 1), &const_op01)) { tree op00 = TREE_OPERAND (sub, 0); tree op01 = TREE_OPERAND (sub, 1); @@ -3121,29 +3123,37 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF */ if (VECTOR_TYPE_P (op00type) - && (same_type_ignoring_top_level_qualifiers_p - (type, TREE_TYPE (op00type)))) + && same_type_ignoring_top_level_qualifiers_p + (type, TREE_TYPE (op00type)) + /* POINTER_PLUS_EXPR second operand is sizetype, unsigned, + but we want to treat offsets with MSB set as negative. + For the code below negative offsets are invalid and + TYPE_SIZE of the element is something unsigned, so + check whether op01 fits into poly_int64, which implies + it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and + then just use poly_uint64 because we want to treat the + value as unsigned. */ + && tree_fits_poly_int64_p (op01)) { - HOST_WIDE_INT offset = tree_to_shwi (op01); tree part_width = TYPE_SIZE (type); - unsigned HOST_WIDE_INT part_widthi = tree_to_shwi (part_width)/BITS_PER_UNIT; - unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; - tree index = bitsize_int (indexi); - - if (known_lt (offset / part_widthi, - TYPE_VECTOR_SUBPARTS (op00type))) - return fold_build3_loc (loc, - BIT_FIELD_REF, type, op00, - part_width, index); - + poly_uint64 max_offset + = (tree_to_uhwi (part_width) / BITS_PER_UNIT + * TYPE_VECTOR_SUBPARTS (op00type)); + if (known_lt (const_op01, max_offset)) + { + tree index = bitsize_int (const_op01 * BITS_PER_UNIT); + return fold_build3_loc (loc, + BIT_FIELD_REF, type, op00, + part_width, index); + } } /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ else if (TREE_CODE (op00type) == COMPLEX_TYPE && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (op00type)))) { - tree size = TYPE_SIZE_UNIT (type); - if (tree_int_cst_equal (size, op01)) + if (known_eq (wi::to_poly_offset (TYPE_SIZE_UNIT (type)), + const_op01)) return fold_build1_loc (loc, IMAGPART_EXPR, type, op00); } /* ((foo *)&fooarray)[1] => fooarray[1] */ @@ -3198,7 +3208,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) { tree type_domain; tree min_val = size_zero_node; - tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); + tree newsub + = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); if (newsub) sub = newsub; else diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c86c3f9b44d..87d00a57476 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -14115,6 +14115,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) { tree op = TREE_OPERAND (sub, 0); tree optype = TREE_TYPE (op); + /* *&CONST_DECL -> to the value of the const decl. */ if (TREE_CODE (op) == CONST_DECL) return DECL_INITIAL (op); @@ -14148,12 +14149,13 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) && type == TREE_TYPE (optype)) return fold_build1_loc (loc, REALPART_EXPR, type, op); /* *(foo *)&vectorfoo => BIT_FIELD_REF */ - else if (TREE_CODE (optype) == VECTOR_TYPE + else if (VECTOR_TYPE_P (optype) && type == TREE_TYPE (optype)) { tree part_width = TYPE_SIZE (type); tree index = bitsize_int (0); - return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index); + return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, + index); } } @@ -14171,8 +14173,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) op00type = TREE_TYPE (op00); /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF */ - if (TREE_CODE (op00type) == VECTOR_TYPE - && type == TREE_TYPE (op00type)) + if (VECTOR_TYPE_P (op00type) + && type == TREE_TYPE (op00type) + /* POINTER_PLUS_EXPR second operand is sizetype, unsigned, + but we want to treat offsets with MSB set as negative. + For the code below negative offsets are invalid and + TYPE_SIZE of the element is something unsigned, so + check whether op01 fits into poly_int64, which implies + it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and + then just use poly_uint64 because we want to treat the + value as unsigned. */ + && tree_fits_poly_int64_p (op01)) { tree part_width = TYPE_SIZE (type); poly_uint64 max_offset @@ -14199,16 +14210,16 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) && type == TREE_TYPE (op00type)) { tree type_domain = TYPE_DOMAIN (op00type); - tree min = size_zero_node; + tree min_val = size_zero_node; if (type_domain && TYPE_MIN_VALUE (type_domain)) - min = TYPE_MIN_VALUE (type_domain); + min_val = TYPE_MIN_VALUE (type_domain); offset_int off = wi::to_offset (op01); offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type)); offset_int remainder; off = wi::divmod_trunc (off, el_sz, SIGNED, &remainder); - if (remainder == 0 && TREE_CODE (min) == INTEGER_CST) + if (remainder == 0 && TREE_CODE (min_val) == INTEGER_CST) { - off = off + wi::to_offset (min); + off = off + wi::to_offset (min_val); op01 = wide_int_to_tree (sizetype, off); return build4_loc (loc, ARRAY_REF, type, op00, op01, NULL_TREE, NULL_TREE); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dfa8cb87d93..49a2275c732 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-02-09 Marek Polacek + Jakub Jelinek + + PR c++/83659 + * g++.dg/torture/pr83659.C: New test. + 2018-02-08 David Malcolm PR tree-optimization/84136 diff --git a/gcc/testsuite/g++.dg/torture/pr83659.C b/gcc/testsuite/g++.dg/torture/pr83659.C new file mode 100644 index 00000000000..bdcdca230ec --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr83659.C @@ -0,0 +1,18 @@ +// PR c++/83659 +// { dg-do compile } + +typedef int V __attribute__ ((__vector_size__ (16))); +V a; +V b[2]; + +int +foo () +{ + return reinterpret_cast (&a)[-1] += 1; +} + +int +bar () +{ + return reinterpret_cast (&a[1])[-1]; +} -- 2.30.2