Commit ca8d9092 by Eric Botcazou Committed by Eric Botcazou

tree-dfa.c (get_ref_base_and_extent): Compute the offset using double ints throughout.

	* tree-dfa.c (get_ref_base_and_extent): Compute the offset using
	double ints throughout.
	* tree-sra.c (build_user_friendly_ref_for_offset) <RECORD_TYPE>:
	Check that the position of the field is representable as an integer.

From-SVN: r188060
parent 1db1c6f5
2012-05-31 Eric Botcazou <ebotcazou@adacore.com>
* tree-dfa.c (get_ref_base_and_extent): Compute the offset using
double ints throughout.
* tree-sra.c (build_user_friendly_ref_for_offset) <RECORD_TYPE>:
Check that the position of the field is representable as an integer.
2012-05-31 Richard Guenther <rguenther@suse.de> 2012-05-31 Richard Guenther <rguenther@suse.de>
* tree-data-ref.c (dr_analyze_innermost): Properly convert * tree-data-ref.c (dr_analyze_innermost): Properly convert
......
...@@ -621,7 +621,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -621,7 +621,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
HOST_WIDE_INT bitsize = -1; HOST_WIDE_INT bitsize = -1;
HOST_WIDE_INT maxsize = -1; HOST_WIDE_INT maxsize = -1;
tree size_tree = NULL_TREE; 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; bool seen_variable_array_ref = false;
tree base_type; tree base_type;
...@@ -659,7 +660,9 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -659,7 +660,9 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
switch (TREE_CODE (exp)) switch (TREE_CODE (exp))
{ {
case BIT_FIELD_REF: 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; break;
case COMPONENT_REF: case COMPONENT_REF:
...@@ -667,22 +670,23 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -667,22 +670,23 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
tree field = TREE_OPERAND (exp, 1); tree field = TREE_OPERAND (exp, 1);
tree this_offset = component_ref_field_offset (exp); tree this_offset = component_ref_field_offset (exp);
if (this_offset if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
&& TREE_CODE (this_offset) == INTEGER_CST
&& host_integerp (this_offset, 0))
{ {
HOST_WIDE_INT hthis_offset = TREE_INT_CST_LOW (this_offset); double_int doffset = tree_to_double_int (this_offset);
hthis_offset *= BITS_PER_UNIT; doffset = double_int_lshift (doffset,
hthis_offset BITS_PER_UNIT == 8
+= TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); ? 3 : exact_log2 (BITS_PER_UNIT),
bit_offset += hthis_offset; 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 /* If we had seen a variable array ref already and we just
referenced the last field of a struct or a union member referenced the last field of a struct or a union member
then we have to adjust maxsize by the padding at the end then we have to adjust maxsize by the padding at the end
of our field. */ of our field. */
if (seen_variable_array_ref if (seen_variable_array_ref && maxsize != -1)
&& maxsize != -1)
{ {
tree stype = TREE_TYPE (TREE_OPERAND (exp, 0)); tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
tree next = DECL_CHAIN (field); tree next = DECL_CHAIN (field);
...@@ -694,10 +698,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -694,10 +698,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
tree fsize = DECL_SIZE_UNIT (field); tree fsize = DECL_SIZE_UNIT (field);
tree ssize = TYPE_SIZE_UNIT (stype); tree ssize = TYPE_SIZE_UNIT (stype);
if (host_integerp (fsize, 0) 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) maxsize += ((TREE_INT_CST_LOW (ssize)
- TREE_INT_CST_LOW (fsize)) - TREE_INT_CST_LOW (fsize))
* BITS_PER_UNIT - hthis_offset); * BITS_PER_UNIT
- double_int_to_shwi (doffset));
else else
maxsize = -1; maxsize = -1;
} }
...@@ -709,8 +715,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -709,8 +715,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
/* We need to adjust maxsize to the whole structure bitsize. /* We need to adjust maxsize to the whole structure bitsize.
But we can subtract any constant offset seen so far, But we can subtract any constant offset seen so far,
because that would get us out of the structure otherwise. */ because that would get us out of the structure otherwise. */
if (maxsize != -1 && csize && host_integerp (csize, 1)) if (maxsize != -1
maxsize = TREE_INT_CST_LOW (csize) - bit_offset; && 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 else
maxsize = -1; maxsize = -1;
} }
...@@ -722,24 +732,26 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -722,24 +732,26 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
{ {
tree index = TREE_OPERAND (exp, 1); tree index = TREE_OPERAND (exp, 1);
tree low_bound, unit_size; tree low_bound, unit_size;
double_int doffset;
/* If the resulting bit-offset is constant, track it. */ /* If the resulting bit-offset is constant, track it. */
if (TREE_CODE (index) == INTEGER_CST if (TREE_CODE (index) == INTEGER_CST
&& (low_bound = array_ref_low_bound (exp), && (low_bound = array_ref_low_bound (exp),
TREE_CODE (low_bound) == INTEGER_CST) TREE_CODE (low_bound) == INTEGER_CST)
&& (unit_size = array_ref_element_size (exp), && (unit_size = array_ref_element_size (exp),
host_integerp (unit_size, 1)) TREE_CODE (unit_size) == INTEGER_CST))
&& (doffset = double_int_sext
(double_int_sub (TREE_INT_CST (index),
TREE_INT_CST (low_bound)),
TYPE_PRECISION (TREE_TYPE (index))),
double_int_fits_in_shwi_p (doffset)))
{ {
HOST_WIDE_INT hoffset = double_int_to_shwi (doffset); double_int doffset
hoffset *= TREE_INT_CST_LOW (unit_size); = double_int_sext
hoffset *= BITS_PER_UNIT; (double_int_sub (TREE_INT_CST (index),
bit_offset += hoffset; 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 /* An array ref with a constant index up in the structure
hierarchy will constrain the size of any variable array ref hierarchy will constrain the size of any variable array ref
...@@ -752,8 +764,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -752,8 +764,12 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
/* We need to adjust maxsize to the whole array bitsize. /* We need to adjust maxsize to the whole array bitsize.
But we can subtract any constant offset seen so far, But we can subtract any constant offset seen so far,
because that would get us outside of the array otherwise. */ because that would get us outside of the array otherwise. */
if (maxsize != -1 && asize && host_integerp (asize, 1)) if (maxsize != -1
maxsize = TREE_INT_CST_LOW (asize) - bit_offset; && 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 else
maxsize = -1; maxsize = -1;
...@@ -768,7 +784,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -768,7 +784,8 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
break; break;
case IMAGPART_EXPR: case IMAGPART_EXPR:
bit_offset += bitsize; bit_offset
= double_int_add (bit_offset, uhwi_to_double_int (bitsize));
break; break;
case VIEW_CONVERT_EXPR: case VIEW_CONVERT_EXPR:
...@@ -787,10 +804,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -787,10 +804,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
BITS_PER_UNIT == 8 BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT), ? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT, true); 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)) 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); exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
} }
} }
...@@ -806,7 +823,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -806,7 +823,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
if (TMR_INDEX (exp) || TMR_INDEX2 (exp)) if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
{ {
exp = TREE_OPERAND (TMR_BASE (exp), 0); exp = TREE_OPERAND (TMR_BASE (exp), 0);
bit_offset = 0; bit_offset = double_int_zero;
maxsize = -1; maxsize = -1;
goto done; goto done;
} }
...@@ -819,10 +836,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -819,10 +836,10 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
BITS_PER_UNIT == 8 BITS_PER_UNIT == 8
? 3 : exact_log2 (BITS_PER_UNIT), ? 3 : exact_log2 (BITS_PER_UNIT),
HOST_BITS_PER_DOUBLE_INT, true); 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)) if (double_int_fits_in_shwi_p (off))
{ {
bit_offset = double_int_to_shwi (off); bit_offset = off;
exp = TREE_OPERAND (TMR_BASE (exp), 0); exp = TREE_OPERAND (TMR_BASE (exp), 0);
} }
} }
...@@ -837,6 +854,17 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -837,6 +854,17 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
} }
done: 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);
/* We need to deal with variable arrays ending structures such as /* We need to deal with variable arrays ending structures such as
struct { int length; int a[1]; } x; x.a[d] 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; int b; } a[1]; } x; x.a[d].a
...@@ -851,7 +879,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -851,7 +879,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
if (seen_variable_array_ref if (seen_variable_array_ref
&& maxsize != -1 && maxsize != -1
&& (!host_integerp (TYPE_SIZE (base_type), 1) && (!host_integerp (TYPE_SIZE (base_type), 1)
|| (bit_offset + maxsize || (hbit_offset + maxsize
== (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type))))) == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
maxsize = -1; maxsize = -1;
...@@ -863,7 +891,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -863,7 +891,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
base decl. */ base decl. */
if (maxsize == -1 if (maxsize == -1
&& host_integerp (DECL_SIZE (exp), 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)) else if (CONSTANT_CLASS_P (exp))
{ {
...@@ -871,13 +899,13 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, ...@@ -871,13 +899,13 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
base type constant. */ base type constant. */
if (maxsize == -1 if (maxsize == -1
&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 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 /* ??? Due to negative offsets in ARRAY_REF we can end up with
negative bit_offset here. We might want to store a zero offset negative bit_offset here. We might want to store a zero offset
in this case. */ in this case. */
*poffset = bit_offset; *poffset = hbit_offset;
*psize = bitsize; *psize = bitsize;
*pmax_size = maxsize; *pmax_size = maxsize;
......
...@@ -1549,17 +1549,20 @@ build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset, ...@@ -1549,17 +1549,20 @@ build_user_friendly_ref_for_offset (tree *res, tree type, HOST_WIDE_INT offset,
for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld)) for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
{ {
HOST_WIDE_INT pos, size; HOST_WIDE_INT pos, size;
tree expr, *expr_ptr; tree tr_pos, expr, *expr_ptr;
if (TREE_CODE (fld) != FIELD_DECL) if (TREE_CODE (fld) != FIELD_DECL)
continue; continue;
pos = int_bit_position (fld); tr_pos = bit_position (fld);
if (!tr_pos || !host_integerp (tr_pos, 1))
continue;
pos = TREE_INT_CST_LOW (tr_pos);
gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0); gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
tr_size = DECL_SIZE (fld); tr_size = DECL_SIZE (fld);
if (!tr_size || !host_integerp (tr_size, 1)) if (!tr_size || !host_integerp (tr_size, 1))
continue; continue;
size = tree_low_cst (tr_size, 1); size = TREE_INT_CST_LOW (tr_size);
if (size == 0) if (size == 0)
{ {
if (pos != offset) if (pos != offset)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment