[PATCH] Fix overflows in get_ref_base_and_extent (PR tree-optimization/59779)
Richard Biener
rguenther@suse.de
Thu Mar 13 18:58:00 GMT 2014
On March 13, 2014 6:50:53 PM CET, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>The outer-1.c testcase apparently fails on 32-bit HWI targets, the
>problem
>is that the int x[10000][10000]; array has bitsize that fits into uhwi,
>but
>not shwi, so we get negative maxsize that isn't -1.
>
>After discussions with Richard on IRC, I've implemented computation of
>bitsize and maxsize in double_int.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, with
>bootstrap/regtest time changes in the noise. Ok for trunk?
OK.
Thanks,
Richard.
>John, could you please test this on some 32-bit HWI target with
>bootstrap/regtest?
>
>2014-03-13 Jakub Jelinek <jakub@redhat.com>
>
> PR tree-optimization/59779
> * tree-dfa.c (get_ref_base_and_extent): Use double_int
> type for bitsize and maxsize instead of HOST_WIDE_INT.
>
>--- gcc/tree-dfa.c.jj 2014-01-03 11:40:57.000000000 +0100
>+++ gcc/tree-dfa.c 2014-03-13 12:10:46.367886640 +0100
>@@ -389,11 +389,10 @@ get_ref_base_and_extent (tree exp, HOST_
> HOST_WIDE_INT *psize,
> HOST_WIDE_INT *pmax_size)
> {
>- HOST_WIDE_INT bitsize = -1;
>- HOST_WIDE_INT maxsize = -1;
>+ double_int bitsize = double_int_minus_one;
>+ double_int maxsize;
> tree size_tree = NULL_TREE;
> double_int bit_offset = double_int_zero;
>- HOST_WIDE_INT hbit_offset;
> bool seen_variable_array_ref = false;
>
>/* First get the final access size from just the outermost expression.
>*/
>@@ -407,15 +406,11 @@ get_ref_base_and_extent (tree exp, HOST_
> if (mode == BLKmode)
> size_tree = TYPE_SIZE (TREE_TYPE (exp));
> else
>- bitsize = GET_MODE_BITSIZE (mode);
>- }
>- if (size_tree != NULL_TREE)
>- {
>- if (! tree_fits_uhwi_p (size_tree))
>- bitsize = -1;
>- else
>- bitsize = tree_to_uhwi (size_tree);
>+ bitsize = double_int::from_uhwi (GET_MODE_BITSIZE (mode));
> }
>+ if (size_tree != NULL_TREE
>+ && TREE_CODE (size_tree) == INTEGER_CST)
>+ bitsize = tree_to_double_int (size_tree);
>
> /* Initially, maxsize is the same as the accessed element size.
> In the following it will only grow (or become -1). */
>@@ -448,7 +443,7 @@ get_ref_base_and_extent (tree exp, HOST_
> 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.is_minus_one ())
> {
> tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
> tree next = DECL_CHAIN (field);
>@@ -459,15 +454,22 @@ get_ref_base_and_extent (tree exp, HOST_
> {
> tree fsize = DECL_SIZE_UNIT (field);
> tree ssize = TYPE_SIZE_UNIT (stype);
>- if (tree_fits_shwi_p (fsize)
>- && tree_fits_shwi_p (ssize)
>- && doffset.fits_shwi ())
>- maxsize += ((tree_to_shwi (ssize)
>- - tree_to_shwi (fsize))
>- * BITS_PER_UNIT
>- - doffset.to_shwi ());
>+ if (fsize == NULL
>+ || TREE_CODE (fsize) != INTEGER_CST
>+ || ssize == NULL
>+ || TREE_CODE (ssize) != INTEGER_CST)
>+ maxsize = double_int_minus_one;
> else
>- maxsize = -1;
>+ {
>+ double_int tem = tree_to_double_int (ssize)
>+ - tree_to_double_int (fsize);
>+ if (BITS_PER_UNIT == 8)
>+ tem = tem.lshift (3);
>+ else
>+ tem *= double_int::from_uhwi (BITS_PER_UNIT);
>+ tem -= doffset;
>+ maxsize += tem;
>+ }
> }
> }
> }
>@@ -477,13 +479,12 @@ get_ref_base_and_extent (tree exp, HOST_
> /* 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
>+ if (!maxsize.is_minus_one ()
> && csize
>- && tree_fits_uhwi_p (csize)
>- && bit_offset.fits_shwi ())
>- maxsize = tree_to_uhwi (csize) - bit_offset.to_shwi ();
>+ && TREE_CODE (csize) == INTEGER_CST)
>+ maxsize = tree_to_double_int (csize) - bit_offset;
> else
>- maxsize = -1;
>+ maxsize = double_int_minus_one;
> }
> }
> break;
>@@ -520,13 +521,12 @@ get_ref_base_and_extent (tree exp, HOST_
> /* 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
>+ if (!maxsize.is_minus_one ()
> && asize
>- && tree_fits_uhwi_p (asize)
>- && bit_offset.fits_shwi ())
>- maxsize = tree_to_uhwi (asize) - bit_offset.to_shwi ();
>+ && TREE_CODE (asize) == INTEGER_CST)
>+ maxsize = tree_to_double_int (asize) - bit_offset;
> else
>- maxsize = -1;
>+ maxsize = double_int_minus_one;
>
> /* Remember that we have seen an array ref with a variable
> index. */
>@@ -539,7 +539,7 @@ get_ref_base_and_extent (tree exp, HOST_
> break;
>
> case IMAGPART_EXPR:
>- bit_offset += double_int::from_uhwi (bitsize);
>+ bit_offset += bitsize;
> break;
>
> case VIEW_CONVERT_EXPR:
>@@ -553,7 +553,7 @@ get_ref_base_and_extent (tree exp, HOST_
> {
> exp = TREE_OPERAND (TMR_BASE (exp), 0);
> bit_offset = double_int_zero;
>- maxsize = -1;
>+ maxsize = double_int_minus_one;
> goto done;
> }
> /* Fallthru. */
>@@ -569,13 +569,12 @@ get_ref_base_and_extent (tree exp, HOST_
> base type boundary. This needs to include possible trailing
> padding that is there for alignment purposes. */
> if (seen_variable_array_ref
>- && maxsize != -1
>- && (!bit_offset.fits_shwi ()
>- || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
>- || (bit_offset.to_shwi () + maxsize
>- == (HOST_WIDE_INT) tree_to_uhwi
>- (TYPE_SIZE (TREE_TYPE (exp))))))
>- maxsize = -1;
>+ && !maxsize.is_minus_one ()
>+ && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
>+ || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
>+ || (bit_offset + maxsize
>+ == tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
>+ maxsize = double_int_minus_one;
>
> /* Hand back the decl for MEM[&decl, off]. */
> if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
>@@ -606,25 +605,32 @@ get_ref_base_and_extent (tree exp, HOST_
>
> /* We need to deal with variable arrays ending structures. */
> if (seen_variable_array_ref
>- && maxsize != -1
>- && (!bit_offset.fits_shwi ()
>- || !tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp)))
>- || (bit_offset.to_shwi () + maxsize
>- == (HOST_WIDE_INT) tree_to_uhwi
>- (TYPE_SIZE (TREE_TYPE (exp))))))
>- maxsize = -1;
>+ && !maxsize.is_minus_one ()
>+ && (TYPE_SIZE (TREE_TYPE (exp)) == NULL_TREE
>+ || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST
>+ || (bit_offset + maxsize
>+ == tree_to_double_int (TYPE_SIZE (TREE_TYPE (exp))))))
>+ maxsize = double_int_minus_one;
>
> done:
>- if (!bit_offset.fits_shwi ())
>+ if (!bitsize.fits_shwi () || bitsize.is_negative ())
> {
> *poffset = 0;
>- *psize = bitsize;
>+ *psize = -1;
> *pmax_size = -1;
>
> return exp;
> }
>
>- hbit_offset = bit_offset.to_shwi ();
>+ *psize = bitsize.to_shwi ();
>+
>+ if (!bit_offset.fits_shwi ())
>+ {
>+ *poffset = 0;
>+ *pmax_size = -1;
>+
>+ return exp;
>+ }
>
> /* In case of a decl or constant base object we can do better. */
>
>@@ -632,25 +638,30 @@ get_ref_base_and_extent (tree exp, HOST_
> {
> /* If maxsize is unknown adjust it according to the size of the
> base decl. */
>- if (maxsize == -1
>- && tree_fits_uhwi_p (DECL_SIZE (exp)))
>- maxsize = tree_to_uhwi (DECL_SIZE (exp)) - hbit_offset;
>+ if (maxsize.is_minus_one ()
>+ && DECL_SIZE (exp)
>+ && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST)
>+ maxsize = tree_to_double_int (DECL_SIZE (exp)) - bit_offset;
> }
> else if (CONSTANT_CLASS_P (exp))
> {
> /* If maxsize is unknown adjust it according to the size of the
> base type constant. */
>- if (maxsize == -1
>- && tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (exp))))
>- maxsize = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (exp))) - hbit_offset;
>+ if (maxsize.is_minus_one ()
>+ && TYPE_SIZE (TREE_TYPE (exp))
>+ && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
>+ maxsize = tree_to_double_int (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
> in this case. */
>- *poffset = hbit_offset;
>- *psize = bitsize;
>- *pmax_size = maxsize;
>+ *poffset = bit_offset.to_shwi ();
>+ if (!maxsize.fits_shwi () || maxsize.is_negative ())
>+ *pmax_size = -1;
>+ else
>+ *pmax_size = maxsize.to_shwi ();
>
> return exp;
> }
>
> Jakub
More information about the Gcc-patches
mailing list