diff options
author | Richard Biener <rguenther@suse.de> | 2014-03-18 10:58:22 +0000 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2014-03-18 10:58:22 +0000 |
commit | 59a6ced4814cefd5a350355878c717076f61e0a4 (patch) | |
tree | 09d503bb033fd1bcbe0e96188cc76f3a31b7b41d | |
parent | 563f17debfe1bf5e72a491de90f03ea0a5fb9dcf (diff) |
2014-03-18 Richard Biener <rguenther@suse.de>
Backport from mainline
2013-11-05 Richard Biener <rguenther@suse.de>
PR middle-end/58941
* tree-dfa.c (get_ref_base_and_extent): Merge common code
in MEM_REF and TARGET_MEM_REF handling. Make sure to
process trailing array detection before diving into the
view-converted object (and possibly apply some extra offset).
* gcc.dg/torture/pr58941.c: New testcase.
2012-05-07 Eric Botcazou <ebotcazou@adacore.com>
* tree-dfa.c (get_ref_base_and_extent) <ARRAY_REF>: Do the offset
computation using the precision of the index type.
2012-05-31 Eric Botcazou <ebotcazou@adacore.com>
* tree-dfa.c (get_ref_base_and_extent): Compute the offset using
double ints throughout.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@208640 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr58941.c | 33 | ||||
-rw-r--r-- | gcc/tree-dfa.c | 185 |
4 files changed, 164 insertions, 83 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9eadc622bc8..f6867dcc11b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,25 @@ 2014-03-18 Richard Biener <rguenther@suse.de> + + Backport from mainline + 2013-11-05 Richard Biener <rguenther@suse.de> + + PR middle-end/58941 + * tree-dfa.c (get_ref_base_and_extent): Merge common code + in MEM_REF and TARGET_MEM_REF handling. Make sure to + process trailing array detection before diving into the + view-converted object (and possibly apply some extra offset). + + 2012-05-07 Eric Botcazou <ebotcazou@adacore.com> + + * tree-dfa.c (get_ref_base_and_extent) <ARRAY_REF>: Do the offset + computation using the precision of the index type. + + 2012-05-31 Eric Botcazou <ebotcazou@adacore.com> + + * tree-dfa.c (get_ref_base_and_extent): Compute the offset using + double ints throughout. + +2014-03-18 Richard Biener <rguenther@suse.de> Backport from mainline 2013-08-27 Richard Biener <rguenther@suse.de> diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 835bd98665d..451a078c104 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,4 +1,12 @@ 2014-03-18 Richard Biener <rguenther@suse.de> + + Backport from mainline + 2013-11-05 Richard Biener <rguenther@suse.de> + + PR middle-end/58941 + * gcc.dg/torture/pr58941.c: New testcase. + +2014-03-18 Richard Biener <rguenther@suse.de> Backport from mainline 2013-08-27 Richard Biener <rguenther@suse.de> diff --git a/gcc/testsuite/gcc.dg/torture/pr58941.c b/gcc/testsuite/gcc.dg/torture/pr58941.c new file mode 100644 index 00000000000..c0eea073165 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58941.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ + +extern void abort (void); + +typedef struct { + int msgLength; + unsigned char data[1000]; +} SMsg; + +typedef struct { + int dummy; + int d[0]; +} SData; + +int condition = 3; + +int main() +{ + SMsg msg; + SData *pData = (SData*)(msg.data); + unsigned int i = 0; + for (i = 0; i < 1; i++) + { + pData->d[i] = 0; + if(condition & 1) + pData->d[i] |= 0x55; + if(condition & 2) + pData->d[i] |= 0xaa; + } + if (pData->d[0] != 0xff) + abort (); + return 0; +} diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 0ecec816b6a..e380e9d47d6 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -713,9 +713,9 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, HOST_WIDE_INT bitsize = -1; HOST_WIDE_INT maxsize = -1; tree size_tree = NULL_TREE; - HOST_WIDE_INT bit_offset = 0; + double_int bit_offset = double_int_zero; + HOST_WIDE_INT hbit_offset; 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) @@ -746,12 +746,12 @@ 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: - bit_offset += TREE_INT_CST_LOW (TREE_OPERAND (exp, 2)); + bit_offset + = double_int_add (bit_offset, + tree_to_double_int (TREE_OPERAND (exp, 2))); break; case COMPONENT_REF: @@ -759,22 +759,23 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, tree field = TREE_OPERAND (exp, 1); tree this_offset = component_ref_field_offset (exp); - if (this_offset - && TREE_CODE (this_offset) == INTEGER_CST - && host_integerp (this_offset, 0)) + if (this_offset && TREE_CODE (this_offset) == INTEGER_CST) { - HOST_WIDE_INT hthis_offset = TREE_INT_CST_LOW (this_offset); - hthis_offset *= BITS_PER_UNIT; - hthis_offset - += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); - bit_offset += hthis_offset; + double_int doffset = tree_to_double_int (this_offset); + doffset = double_int_lshift (doffset, + BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT), + HOST_BITS_PER_DOUBLE_INT, true); + doffset = double_int_add (doffset, + tree_to_double_int + (DECL_FIELD_BIT_OFFSET (field))); + bit_offset = double_int_add (bit_offset, doffset); /* If we had seen a variable array ref already and we just 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 && maxsize != -1) { tree stype = TREE_TYPE (TREE_OPERAND (exp, 0)); tree next = DECL_CHAIN (field); @@ -786,10 +787,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, tree fsize = DECL_SIZE_UNIT (field); tree ssize = TYPE_SIZE_UNIT (stype); if (host_integerp (fsize, 0) - && host_integerp (ssize, 0)) + && host_integerp (ssize, 0) + && double_int_fits_in_shwi_p (doffset)) maxsize += ((TREE_INT_CST_LOW (ssize) - TREE_INT_CST_LOW (fsize)) - * BITS_PER_UNIT - hthis_offset); + * BITS_PER_UNIT + - double_int_to_shwi (doffset)); else maxsize = -1; } @@ -801,8 +804,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, /* We need to adjust maxsize to the whole structure bitsize. But we can subtract any constant offset seen so far, because that would get us out of the structure otherwise. */ - if (maxsize != -1 && csize && host_integerp (csize, 1)) - maxsize = TREE_INT_CST_LOW (csize) - bit_offset; + if (maxsize != -1 + && csize + && host_integerp (csize, 1) + && double_int_fits_in_shwi_p (bit_offset)) + maxsize = TREE_INT_CST_LOW (csize) + - double_int_to_shwi (bit_offset); else maxsize = -1; } @@ -817,18 +824,23 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, /* If the resulting bit-offset is constant, track it. */ if (TREE_CODE (index) == INTEGER_CST - && host_integerp (index, 0) && (low_bound = array_ref_low_bound (exp), - host_integerp (low_bound, 0)) + TREE_CODE (low_bound) == INTEGER_CST) && (unit_size = array_ref_element_size (exp), - host_integerp (unit_size, 1))) + TREE_CODE (unit_size) == INTEGER_CST)) { - HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index); - - hindex -= TREE_INT_CST_LOW (low_bound); - hindex *= TREE_INT_CST_LOW (unit_size); - hindex *= BITS_PER_UNIT; - bit_offset += hindex; + double_int doffset + = double_int_sext + (double_int_sub (TREE_INT_CST (index), + TREE_INT_CST (low_bound)), + TYPE_PRECISION (TREE_TYPE (index))); + doffset = double_int_mul (doffset, + tree_to_double_int (unit_size)); + doffset = double_int_lshift (doffset, + BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT), + HOST_BITS_PER_DOUBLE_INT, true); + bit_offset = double_int_add (bit_offset, doffset); /* An array ref with a constant index up in the structure hierarchy will constrain the size of any variable array ref @@ -841,8 +853,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, /* We need to adjust maxsize to the whole array bitsize. But we can subtract any constant offset seen so far, because that would get us outside of the array otherwise. */ - if (maxsize != -1 && asize && host_integerp (asize, 1)) - maxsize = TREE_INT_CST_LOW (asize) - bit_offset; + if (maxsize != -1 + && asize + && host_integerp (asize, 1) + && double_int_fits_in_shwi_p (bit_offset)) + maxsize = TREE_INT_CST_LOW (asize) + - double_int_to_shwi (bit_offset); else maxsize = -1; @@ -857,13 +873,45 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, break; case IMAGPART_EXPR: - bit_offset += bitsize; + bit_offset + = double_int_add (bit_offset, uhwi_to_double_int (bitsize)); break; case VIEW_CONVERT_EXPR: break; + case TARGET_MEM_REF: + /* Via the variable index or index2 we can reach the + whole object. Still hand back the decl here. */ + if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR + && (TMR_INDEX (exp) || TMR_INDEX2 (exp))) + { + exp = TREE_OPERAND (TMR_BASE (exp), 0); + bit_offset = double_int_zero; + maxsize = -1; + goto done; + } + /* Fallthru. */ case MEM_REF: + /* We need to deal with variable arrays ending structures such as + struct { int length; int a[1]; } x; x.a[d] + struct { struct { int a; int b; } a[1]; } x; x.a[d].a + struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0] + struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d] + where we do not know maxsize for variable index accesses to + 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. */ + if (seen_variable_array_ref + && maxsize != -1 + && (!double_int_fits_in_shwi_p (bit_offset) + || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) + || (double_int_to_shwi (bit_offset) + maxsize + == (HOST_WIDE_INT) TREE_INT_CST_LOW + (TYPE_SIZE (TREE_TYPE (exp)))))) + maxsize = -1; + /* Hand back the decl for MEM[&decl, off]. */ if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR) { @@ -876,74 +924,45 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, BITS_PER_UNIT == 8 ? 3 : exact_log2 (BITS_PER_UNIT), HOST_BITS_PER_DOUBLE_INT, true); - off = double_int_add (off, shwi_to_double_int (bit_offset)); + off = double_int_add (off, bit_offset); if (double_int_fits_in_shwi_p (off)) { - bit_offset = double_int_to_shwi (off); + bit_offset = off; exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); } } } goto done; - case TARGET_MEM_REF: - /* Hand back the decl for MEM[&decl, off]. */ - if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR) - { - /* Via the variable index or index2 we can reach the - whole object. */ - if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) - { - exp = TREE_OPERAND (TMR_BASE (exp), 0); - bit_offset = 0; - maxsize = -1; - goto done; - } - if (integer_zerop (TMR_OFFSET (exp))) - exp = TREE_OPERAND (TMR_BASE (exp), 0); - else - { - double_int off = mem_ref_offset (exp); - off = double_int_lshift (off, - BITS_PER_UNIT == 8 - ? 3 : exact_log2 (BITS_PER_UNIT), - HOST_BITS_PER_DOUBLE_INT, true); - off = double_int_add (off, shwi_to_double_int (bit_offset)); - if (double_int_fits_in_shwi_p (off)) - { - bit_offset = double_int_to_shwi (off); - exp = TREE_OPERAND (TMR_BASE (exp), 0); - } - } - } - goto done; - default: goto done; } exp = TREE_OPERAND (exp, 0); } - done: - - /* We need to deal with variable arrays ending structures such as - struct { int length; int a[1]; } x; x.a[d] - struct { struct { int a; int b; } a[1]; } x; x.a[d].a - struct { struct { int a[1]; } a[1]; } x; x.a[0][d], x.a[d][0] - struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d] - where we do not know maxsize for variable index accesses to - 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. */ + /* We need to deal with variable arrays ending structures. */ 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))))) + && (!double_int_fits_in_shwi_p (bit_offset) + || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) + || (double_int_to_shwi (bit_offset) + maxsize + == (HOST_WIDE_INT) + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp)))))) maxsize = -1; + done: + if (!double_int_fits_in_shwi_p (bit_offset)) + { + *poffset = 0; + *psize = bitsize; + *pmax_size = -1; + + return exp; + } + + hbit_offset = double_int_to_shwi (bit_offset); + /* In case of a decl or constant base object we can do better. */ if (DECL_P (exp)) @@ -952,7 +971,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, base decl. */ if (maxsize == -1 && host_integerp (DECL_SIZE (exp), 1)) - maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - bit_offset; + maxsize = TREE_INT_CST_LOW (DECL_SIZE (exp)) - hbit_offset; } else if (CONSTANT_CLASS_P (exp)) { @@ -960,13 +979,13 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, 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; + maxsize = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))) - hbit_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 in this case. */ - *poffset = bit_offset; + *poffset = hbit_offset; *psize = bitsize; *pmax_size = maxsize; |