From: Richard Biener Date: Thu, 21 Jun 2018 07:24:06 +0000 (+0000) Subject: backport: [multiple changes] X-Git-Tag: releases/gcc-6.5.0~264 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7bc1b51043443440180870422f708dc43aa9c4a9;p=thirdparty%2Fgcc.git backport: [multiple changes] 2018-06-21 Richard Biener Backport from mainline 2017-08-21 Richard Biener PR middle-end/81884 * tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses at struct end conservatively when comparing common bases. * g++.dg/torture/pr81884.C: New testcase. 2017-05-04 Richard Biener * tree.c (array_at_struct_end_p): Handle arrays at struct end with flexarrays more conservatively. Refactor and treat arrays of arrays or aggregates more strict. Fix VIEW_CONVERT_EXPR handling. 2018-04-06 Richard Biener PR middle-end/85244 * tree-dfa.c (get_ref_base_and_extent): Reset seen_variable_array_ref after seeing a component reference with an adjacent field. Treat refs to arrays at struct end of external decls similar to refs to unconstrained commons. * gcc.dg/torture/pr85244-1.c: New testcase. * gcc.dg/torture/pr85244-2.c: Likewise. * gcc.dg/tree-prof/pr66295.c: Remove unsupported dg-error scanning. From-SVN: r261833 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0da795e96588..0ad4c907ac7a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2018-06-21 Richard Biener + + Backport from mainline + 2017-08-21 Richard Biener + + PR middle-end/81884 + * tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses + at struct end conservatively when comparing common bases. + + 2017-05-04 Richard Biener + + * tree.c (array_at_struct_end_p): Handle arrays at struct + end with flexarrays more conservatively. Refactor and treat + arrays of arrays or aggregates more strict. Fix + VIEW_CONVERT_EXPR handling. + + 2018-04-06 Richard Biener + + PR middle-end/85244 + * tree-dfa.c (get_ref_base_and_extent): Reset seen_variable_array_ref + after seeing a component reference with an adjacent field. Treat + refs to arrays at struct end of external decls similar to + refs to unconstrained commons. + 2018-06-20 Richard Biener * tree-ssa-alias.c (stmt_kills_ref_p): Revert accidentially diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 67095b8a5146..bc02092f8bfc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2018-06-21 Richard Biener + + Backport from mainline + 2017-08-21 Richard Biener + + PR middle-end/81884 + * g++.dg/torture/pr81884.C: New testcase. + + 2018-04-06 Richard Biener + + PR middle-end/85244 + * gcc.dg/torture/pr85244-1.c: New testcase. + * gcc.dg/torture/pr85244-2.c: Likewise. + + * gcc.dg/tree-prof/pr66295.c: Remove unsupported dg-error scanning. + 2018-06-20 Richard Biener Backport from mainline diff --git a/gcc/testsuite/g++.dg/torture/pr81884.C b/gcc/testsuite/g++.dg/torture/pr81884.C new file mode 100644 index 000000000000..f545355ce352 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr81884.C @@ -0,0 +1,39 @@ +/* { dg-do run } */ + +typedef unsigned long uint64_t; + +struct value_t { + uint64_t _count; + value_t(uint64_t c) : _count(c) {} +}; + +struct X { + value_t eventTime; + uint64_t arr[0]; +}; + +X* x; + +__attribute__((noclone, noinline)) +void initialize() +{ + x->arr[0] = 11; + x->arr[1] = 12; + x->eventTime = value_t(10); + x->arr[2] = 13; + x->arr[3] = 14; +} + +int main() +{ + char buffer[sizeof(X) + sizeof(uint64_t)*4]; + x = (X*)buffer; + x->eventTime = value_t(999); + x->arr[0] = 1; + x->arr[1] = 2; + x->arr[2] = 3; + x->arr[3] = 4; + initialize(); + if (x->arr[0] != 11 || x->arr[1] != 12 || x->arr[2] != 13 || x->arr[3] != 14) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr85244-1.c b/gcc/testsuite/gcc.dg/torture/pr85244-1.c new file mode 100644 index 000000000000..44716aa9e04d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr85244-1.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-additional-sources "pr85244-2.c" } */ + +struct s { + long a; + int b; + int tab[]; +}; + +extern const struct s val; +extern int idx; +extern void abort (void); + +int main() +{ + if (val.tab[0] != 42 || val.tab[1] != 1337 || val.tab[idx] != 1337) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr85244-2.c b/gcc/testsuite/gcc.dg/torture/pr85244-2.c new file mode 100644 index 000000000000..d57cb7124202 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr85244-2.c @@ -0,0 +1,8 @@ +struct s { + long a; + int b; + int tab[]; +}; + +int idx = 1; +const struct s val = { 0, 0, { 42, 1337 } }; diff --git a/gcc/testsuite/gcc.dg/tree-prof/pr66295.c b/gcc/testsuite/gcc.dg/tree-prof/pr66295.c index e83e821387ff..d7d64c41b075 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/pr66295.c +++ b/gcc/testsuite/gcc.dg/tree-prof/pr66295.c @@ -12,7 +12,7 @@ foo (double *__restrict a, double *__restrict b, int n) } double -bar (double *__restrict a, double *__restrict b, int n) /* { dg-error "attribute\[^\n\r]*foo\[^\n\r]* is unknown" } */ +bar (double *__restrict a, double *__restrict b, int n) { double s; int i; diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index f133abc79bda..2ebd974baf8f 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -433,7 +433,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, referenced the last field of a struct or a union member then we have to adjust maxsize by the padding at the end of our field. */ - if (seen_variable_array_ref && maxsize != -1) + if (seen_variable_array_ref) { tree stype = TREE_TYPE (TREE_OPERAND (exp, 0)); tree next = DECL_CHAIN (field); @@ -449,7 +449,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, || ssize == NULL || TREE_CODE (ssize) != INTEGER_CST) maxsize = -1; - else + else if (maxsize != -1) { offset_int tem = (wi::to_offset (ssize) - wi::to_offset (fsize)); @@ -458,6 +458,11 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, maxsize += tem; } } + /* An component ref with an adjacent field up in the + structure hierarchy constrains the size of any variable + array ref lower in the access hierarchy. */ + else + seen_variable_array_ref = false; } } else @@ -612,8 +617,9 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, if (DECL_P (exp)) { - if (flag_unconstrained_commons - && TREE_CODE (exp) == VAR_DECL && DECL_COMMON (exp)) + if (VAR_P (exp) + && ((flag_unconstrained_commons && DECL_COMMON (exp)) + || (DECL_EXTERNAL (exp) && seen_variable_array_ref))) { tree sz_tree = TYPE_SIZE (TREE_TYPE (exp)); /* If size is unknown, or we have read to the end, assume there diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 08f10e5248b5..3f0011f3d100 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -2235,6 +2235,7 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref) if (ref->ref) { tree base = ref->ref; + tree innermost_dropped_array_ref = NULL_TREE; if (handled_component_p (base)) { tree saved_lhs0 = NULL_TREE; @@ -2254,6 +2255,11 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref) TREE_OPERAND (base, 0) = saved_base0; if (res) break; + /* Remember if we drop an array-ref that we need to + double-check not being at struct end. */ + if (TREE_CODE (base) == ARRAY_REF + || TREE_CODE (base) == ARRAY_RANGE_REF) + innermost_dropped_array_ref = base; /* Otherwise drop handled components of the access. */ base = saved_base0; } @@ -2262,15 +2268,22 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref) TREE_OPERAND (lhs, 0) = saved_lhs0; } /* Finally check if the lhs has the same address and size as the - base candidate of the access. */ - if (lhs == base - || (((TYPE_SIZE (TREE_TYPE (lhs)) - == TYPE_SIZE (TREE_TYPE (base))) - || (TYPE_SIZE (TREE_TYPE (lhs)) - && TYPE_SIZE (TREE_TYPE (base)) - && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)), - TYPE_SIZE (TREE_TYPE (base)), 0))) - && operand_equal_p (lhs, base, OEP_ADDRESS_OF))) + base candidate of the access. Watch out if we have dropped + an array-ref that was at struct end, this means ref->ref may + be outside of the TYPE_SIZE of its base. */ + if ((! innermost_dropped_array_ref + || ! array_at_struct_end_p (innermost_dropped_array_ref)) + && (lhs == base + || (((TYPE_SIZE (TREE_TYPE (lhs)) + == TYPE_SIZE (TREE_TYPE (base))) + || (TYPE_SIZE (TREE_TYPE (lhs)) + && TYPE_SIZE (TREE_TYPE (base)) + && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)), + TYPE_SIZE (TREE_TYPE (base)), + 0))) + && operand_equal_p (lhs, base, + OEP_ADDRESS_OF + | OEP_MATCH_SIDE_EFFECTS)))) return true; } diff --git a/gcc/tree.c b/gcc/tree.c index 84f324f03f10..e25cbb700c2e 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12944,15 +12944,26 @@ array_ref_up_bound (tree exp) return NULL_TREE; } -/* Returns true if REF is an array reference to an array at the end of - a structure. If this is the case, the array may be allocated larger +/* Returns true if REF is an array reference or a component reference + to an array at the end of a structure. + If this is the case, the array may be allocated larger than its upper bound implies. */ bool array_at_struct_end_p (tree ref) { - if (TREE_CODE (ref) != ARRAY_REF - && TREE_CODE (ref) != ARRAY_RANGE_REF) + tree atype; + + if (TREE_CODE (ref) == ARRAY_REF + || TREE_CODE (ref) == ARRAY_RANGE_REF) + { + atype = TREE_TYPE (TREE_OPERAND (ref, 0)); + ref = TREE_OPERAND (ref, 0); + } + else if (TREE_CODE (ref) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE) + atype = TREE_TYPE (TREE_OPERAND (ref, 1)); + else return false; while (handled_component_p (ref)) @@ -12960,24 +12971,47 @@ array_at_struct_end_p (tree ref) /* If the reference chain contains a component reference to a non-union type and there follows another field the reference is not at the end of a structure. */ - if (TREE_CODE (ref) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE) + if (TREE_CODE (ref) == COMPONENT_REF) { - tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1)); - while (nextf && TREE_CODE (nextf) != FIELD_DECL) - nextf = DECL_CHAIN (nextf); - if (nextf) - return false; + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE) + { + tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1)); + while (nextf && TREE_CODE (nextf) != FIELD_DECL) + nextf = DECL_CHAIN (nextf); + if (nextf) + return false; + } } + /* If we have a multi-dimensional array we do not consider + a non-innermost dimension as flex array if the whole + multi-dimensional array is at struct end. + Same for an array of aggregates with a trailing array + member. */ + else if (TREE_CODE (ref) == ARRAY_REF) + return false; + else if (TREE_CODE (ref) == ARRAY_RANGE_REF) + ; + /* If we view an underlying object as sth else then what we + gathered up to now is what we have to rely on. */ + else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR) + break; + else + gcc_unreachable (); ref = TREE_OPERAND (ref, 0); } + /* The array now is at struct end. Treat flexible arrays as + always subject to extend, even into just padding constrained by + an underlying decl. */ + if (! TYPE_SIZE (atype)) + return true; + /* If the reference is based on a declared entity, the size of the array is constrained by its given domain. (Do not trust commons PR/69368). */ if (DECL_P (ref) && !(flag_unconstrained_commons - && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref))) + && VAR_P (ref) && DECL_COMMON (ref))) return false; return true;