diff options
author | Richard Guenther <rguenther@suse.de> | 2010-02-07 13:42:52 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2010-02-07 13:42:52 +0000 |
commit | cb6b911a63724d5efd5b48b9ae0dac09c3060e85 (patch) | |
tree | 0fbca980303c232d16d4c5e497733ca6ff9c94ae | |
parent | f41e0f10464c060e928927c5272a360c31a48093 (diff) | |
download | gcc-cb6b911a63724d5efd5b48b9ae0dac09c3060e85.zip gcc-cb6b911a63724d5efd5b48b9ae0dac09c3060e85.tar.gz gcc-cb6b911a63724d5efd5b48b9ae0dac09c3060e85.tar.bz2 |
re PR tree-optimization/42956 (internal compiler error: Segmentation fault with -O1)
2010-02-07 Richard Guenther <rguenther@suse.de>
PR middle-end/42956
* gimplify.c (gimple_fold_indirect_ref): Avoid generating
new ARRAY_REFs on variable size element or minimal index arrays.
Complete.
* tree-ssa-loop-ivopts.c (find_interesting_uses_address): Use
gimple_fold_indirect_ref.
* gcc.c-torture/compile/pr42956.c: New testcase.
From-SVN: r156571
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/gimplify.c | 69 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr42956.c | 33 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 6 |
5 files changed, 118 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1b5fd3..c05b658 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-02-07 Richard Guenther <rguenther@suse.de> + + PR middle-end/42956 + * gimplify.c (gimple_fold_indirect_ref): Avoid generating + new ARRAY_REFs on variable size element or minimal index arrays. + Complete. + * tree-ssa-loop-ivopts.c (find_interesting_uses_address): Use + gimple_fold_indirect_ref. + 2010-02-06 Richard Earnshaw <rearnsha@arm.com> PR target/42957 diff --git a/gcc/gimplify.c b/gcc/gimplify.c index fac3fda..91dabd1 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3935,7 +3935,7 @@ gimple_fold_indirect_ref (tree t) tree sub = t; tree subtype; - STRIP_USELESS_TYPE_CONVERSION (sub); + STRIP_NOPS (sub); subtype = TREE_TYPE (sub); if (!POINTER_TYPE_P (subtype)) return NULL_TREE; @@ -3950,18 +3950,80 @@ gimple_fold_indirect_ref (tree t) /* *(foo *)&fooarray => fooarray[0] */ if (TREE_CODE (optype) == ARRAY_TYPE + && TREE_CODE (TYPE_SIZE (TREE_TYPE (optype))) == INTEGER_CST && useless_type_conversion_p (type, TREE_TYPE (optype))) { tree type_domain = TYPE_DOMAIN (optype); tree min_val = size_zero_node; if (type_domain && TYPE_MIN_VALUE (type_domain)) min_val = TYPE_MIN_VALUE (type_domain); - return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE); + if (TREE_CODE (min_val) == INTEGER_CST) + return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE); } + /* *(foo *)&complexfoo => __real__ complexfoo */ + else if (TREE_CODE (optype) == COMPLEX_TYPE + && useless_type_conversion_p (type, TREE_TYPE (optype))) + return fold_build1 (REALPART_EXPR, type, op); + /* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */ + else if (TREE_CODE (optype) == VECTOR_TYPE + && useless_type_conversion_p (type, TREE_TYPE (optype))) + { + tree part_width = TYPE_SIZE (type); + tree index = bitsize_int (0); + return fold_build3 (BIT_FIELD_REF, type, op, part_width, index); + } + } + + /* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */ + if (TREE_CODE (sub) == POINTER_PLUS_EXPR + && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) + { + tree op00 = TREE_OPERAND (sub, 0); + tree op01 = TREE_OPERAND (sub, 1); + tree op00type; + + STRIP_NOPS (op00); + op00type = TREE_TYPE (op00); + if (TREE_CODE (op00) == ADDR_EXPR + && TREE_CODE (TREE_TYPE (op00type)) == VECTOR_TYPE + && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type)))) + { + HOST_WIDE_INT offset = tree_low_cst (op01, 0); + tree part_width = TYPE_SIZE (type); + unsigned HOST_WIDE_INT part_widthi + = tree_low_cst (part_width, 0) / BITS_PER_UNIT; + unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; + tree index = bitsize_int (indexi); + if (offset / part_widthi + <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (op00type))) + return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (op00, 0), + part_width, index); + } + } + + /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ + if (TREE_CODE (sub) == POINTER_PLUS_EXPR + && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST) + { + tree op00 = TREE_OPERAND (sub, 0); + tree op01 = TREE_OPERAND (sub, 1); + tree op00type; + + STRIP_NOPS (op00); + op00type = TREE_TYPE (op00); + if (TREE_CODE (op00) == ADDR_EXPR + && TREE_CODE (TREE_TYPE (op00type)) == COMPLEX_TYPE + && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (op00type)))) + { + tree size = TYPE_SIZE_UNIT (type); + if (tree_int_cst_equal (size, op01)) + return fold_build1 (IMAGPART_EXPR, type, TREE_OPERAND (op00, 0)); + } } /* *(foo *)fooarrptr => (*fooarrptr)[0] */ if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE + && TREE_CODE (TYPE_SIZE (TREE_TYPE (TREE_TYPE (subtype)))) == INTEGER_CST && useless_type_conversion_p (type, TREE_TYPE (TREE_TYPE (subtype)))) { tree type_domain; @@ -3973,7 +4035,8 @@ gimple_fold_indirect_ref (tree t) type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); if (type_domain && TYPE_MIN_VALUE (type_domain)) min_val = TYPE_MIN_VALUE (type_domain); - return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE); + if (TREE_CODE (min_val) == INTEGER_CST) + return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE); } return NULL_TREE; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d50b950..f9508f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-02-07 Richard Guenther <rguenther@suse.de> + + PR middle-end/42956 + * gcc.c-torture/compile/pr42956.c: New testcase. + 2010-02-06 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libfortran/42742 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr42956.c b/gcc/testsuite/gcc.c-torture/compile/pr42956.c new file mode 100644 index 0000000..f592d4b --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr42956.c @@ -0,0 +1,33 @@ +typedef const int cint; +typedef struct { +} Bounds; +int ndim_, ncomp_, selectedcomp_, nregions_; +void *voidregion_; +typedef struct { + double diff, err, spread; +} Errors; +typedef const Errors cErrors; +void Split(int iregion, int depth, int xregion) +{ + typedef struct { + double avg, err, spread, chisq; + double xmin[ndim_], xmax[ndim_]; + } Result; + typedef struct region { + Result result[ncomp_]; + } Region; + Errors errors[ncomp_]; + int comp, ireg, xreg; + for( ireg = iregion, xreg = xregion; ireg < nregions_; ireg = xreg++ ) + { + Result *result = ((Region *)voidregion_)[ireg].result; + for( comp = 0; comp < ncomp_; ++comp ) + { + Result *r = &result[comp]; + cErrors *e = &errors[comp]; + double c = e->diff; + if( r->err > 0 ) r->err = r->err*e->err + c; + } + } +} + diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 759edb1..436e6ce 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1686,7 +1686,11 @@ find_interesting_uses_address (struct ivopts_data *data, gimple stmt, tree *op_p while (handled_component_p (*ref)) ref = &TREE_OPERAND (*ref, 0); if (TREE_CODE (*ref) == INDIRECT_REF) - *ref = fold_indirect_ref (*ref); + { + tree tem = gimple_fold_indirect_ref (TREE_OPERAND (*ref, 0)); + if (tem) + *ref = tem; + } } } |