summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2017-08-28 12:16:06 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2017-08-28 12:16:06 +0000
commit8b79a42b60386d2e4fb9af7ed4690858b2ff843d (patch)
tree50a977659dbfc3537fbef189641630a9dc36b188
parentea7f72c88eb978522e416f152537f285c47870ff (diff)
downloadgcc-8b79a42b60386d2e4fb9af7ed4690858b2ff843d.tar.gz
2017-08-28 Richard Biener <rguenther@suse.de>
Backport from mainline 2017-08-21 Richard Biener <rguenther@suse.de> 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 <rguenther@suse.de> * 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. Remove allow_compref argument. * tree.h (array_at_struct_end_p): Adjust prototype. * gimple-fold.c (get_range_strlen): Likewise. * tree-chkp.c (chkp_may_narrow_to_field): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branch@251379 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/gimple-fold.c2
-rw-r--r--gcc/testsuite/ChangeLog26
-rw-r--r--gcc/testsuite/g++.dg/torture/pr81884.C39
-rw-r--r--gcc/tree-chkp.c2
-rw-r--r--gcc/tree-ssa-alias.c31
-rw-r--r--gcc/tree.c63
-rw-r--r--gcc/tree.h10
8 files changed, 159 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7e4fb5e1fbf..c335097134d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,25 @@
2017-08-28 Richard Biener <rguenther@suse.de>
Backport from mainline
+ 2017-08-21 Richard Biener <rguenther@suse.de>
+
+ 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 <rguenther@suse.de>
+
+ * 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. Remove allow_compref argument.
+ * tree.h (array_at_struct_end_p): Adjust prototype.
+ * gimple-fold.c (get_range_strlen): Likewise.
+ * tree-chkp.c (chkp_may_narrow_to_field): Likewise.
+
+2017-08-28 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
2017-08-01 Richard Biener <rguenther@suse.de>
PR tree-optimization/81181
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 0f3227da4f4..bb993c28239 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -1236,7 +1236,7 @@ get_range_strlen (tree arg, tree length[2], bitmap *visited, int type,
the NUL.
Set *FLEXP to true if the array whose bound is being
used is at the end of a struct. */
- if (array_at_struct_end_p (arg, true))
+ if (array_at_struct_end_p (arg))
*flexp = true;
arg = TREE_OPERAND (arg, 1);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 53cef0bd22f..739c10dc691 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,29 @@
+2017-08-28 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2017-08-21 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/81884
+ * g++.dg/torture/pr81884.C: New testcase.
+
+2017-08-28 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2017-08-01 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81181
+ * gcc.dg/torture/pr81181.c: New testcase.
+
+ 2017-08-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/81723
+ * gfortran.dg/pr81723.f: New testcase.
+
+ 2017-08-24 Richard Biener <rguenther@suse.de>
+
+ PR target/81921
+ * gcc/testsuite/gcc.target/i386/pr81921.c: New testcase.
+
2017-05-19 Uros Bizjak <ubizjak@gmail.com>
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 00000000000..f545355ce35
--- /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/tree-chkp.c b/gcc/tree-chkp.c
index b1ff21851c6..23f5af98ae3 100644
--- a/gcc/tree-chkp.c
+++ b/gcc/tree-chkp.c
@@ -3277,7 +3277,7 @@ chkp_may_narrow_to_field (tree ref, tree field)
return DECL_SIZE (field) && TREE_CODE (DECL_SIZE (field)) == INTEGER_CST
&& tree_to_uhwi (DECL_SIZE (field)) != 0
&& !(flag_chkp_flexible_struct_trailing_arrays
- && array_at_struct_end_p (ref, true))
+ && array_at_struct_end_p (ref))
&& (!DECL_FIELD_OFFSET (field)
|| TREE_CODE (DECL_FIELD_OFFSET (field)) == INTEGER_CST)
&& (!DECL_FIELD_BIT_OFFSET (field)
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 3f0c650475d..4cedcb2392f 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2415,6 +2415,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;
@@ -2434,6 +2435,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;
}
@@ -2442,15 +2448,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 ef9b292d773..d7d01bb4e52 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -13219,18 +13219,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
- than its upper bound implies. When ALLOW_COMPREF is true considers
- REF when it's a COMPONENT_REF in addition ARRAY_REF and
- ARRAY_RANGE_REF. */
+/* 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, bool allow_compref)
+array_at_struct_end_p (tree ref)
{
- if (TREE_CODE (ref) != ARRAY_REF
- && TREE_CODE (ref) != ARRAY_RANGE_REF
- && (!allow_compref || TREE_CODE (ref) != COMPONENT_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))
@@ -13238,19 +13246,42 @@ array_at_struct_end_p (tree ref, bool allow_compref)
/* 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;
+
tree size = NULL;
if (TREE_CODE (ref) == MEM_REF
diff --git a/gcc/tree.h b/gcc/tree.h
index 0d805c0ca2a..375edcd4ba6 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4870,12 +4870,10 @@ extern tree array_ref_up_bound (tree);
EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
extern tree array_ref_low_bound (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
- than its upper bound implies. When second argument is true considers
- REF when it's a COMPONENT_REF in addition ARRAY_REF and
- ARRAY_RANGE_REF. */
-extern bool array_at_struct_end_p (tree, bool = false);
+/* 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. */
+extern bool array_at_struct_end_p (tree);
/* Return a tree representing the offset, in bytes, of the field referenced
by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */