summaryrefslogtreecommitdiff
path: root/gcc/tree-dfa.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-20 15:02:49 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2011-05-20 15:02:49 +0000
commit06ec5ac445869acdd61d1e7cd686d1dbed81f4d5 (patch)
tree0f88181acea8ab0fc265d45d99e9be13fd4739e8 /gcc/tree-dfa.c
parent6ae2c05184201f8301277f98f0ab314c63ede0c5 (diff)
downloadgcc-06ec5ac445869acdd61d1e7cd686d1dbed81f4d5.tar.gz
2011-05-20 Richard Guenther <rguenther@suse.de>
PR tree-optimization/49079 * tree-dfa.c (get_ref_base_and_extent): Handle view-converting MEM_REFs correctly for the trailing array access detection. Special case constants the same way as decls for overall size constraining. * gcc.dg/torture/pr49079.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173954 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-dfa.c')
-rw-r--r--gcc/tree-dfa.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index 70e3c1d35cd..9791bccecae 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -714,6 +714,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
tree size_tree = NULL_TREE;
HOST_WIDE_INT bit_offset = 0;
bool seen_variable_array_ref = false;
+ tree base_type;
/* First get the final access size from just the outermost expression. */
if (TREE_CODE (exp) == COMPONENT_REF)
@@ -744,6 +745,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
and find the ultimate containing object. */
while (1)
{
+ base_type = TREE_TYPE (exp);
+
switch (TREE_CODE (exp))
{
case BIT_FIELD_REF:
@@ -931,9 +934,16 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
the array. The simplest way to conservatively deal with this
is to punt in the case that offset + maxsize reaches the
base type boundary. This needs to include possible trailing padding
- that is there for alignment purposes.
+ that is there for alignment purposes. */
+
+ if (seen_variable_array_ref
+ && maxsize != -1
+ && (!host_integerp (TYPE_SIZE (base_type), 1)
+ || (bit_offset + maxsize
+ == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
+ maxsize = -1;
- That is of course only true if the base object is not a decl. */
+ /* In case of a decl or constant base object we can do better. */
if (DECL_P (exp))
{
@@ -943,12 +953,14 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
&& host_integerp (DECL_SIZE (exp), 1))
maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - bit_offset;
}
- else if (seen_variable_array_ref
- && maxsize != -1
- && (!host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
- || (bit_offset + maxsize
- == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
- maxsize = -1;
+ else if (CONSTANT_CLASS_P (exp))
+ {
+ /* If maxsize is unknown adjust it according to the size of the
+ base type constant. */
+ if (maxsize == -1
+ && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1))
+ maxsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) - bit_offset;
+ }
/* ??? Due to negative offsets in ARRAY_REF we can end up with
negative bit_offset here. We might want to store a zero offset