on ARRAY_REFs sign-extend offsets only from sizetype's precision [PR98255]

As discussed in the PR, the problem here is that the routines changed in
this patch sign extend the difference of index and low_bound from the
precision of the index, so e.g. when index is unsigned int and contains
value -2U, we treat it as index -2 rather than 0x00000000fffffffeU on 64-bit
arches.
On the other hand, get_inner_reference which is used during expansion, does:
            if (! integer_zerop (low_bound))
              index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
                                   index, low_bound);

            offset = size_binop (PLUS_EXPR, offset,
                                 size_binop (MULT_EXPR,
                                             fold_convert (sizetype, index),
                                             unit_size));
which effectively requires that either low_bound is constant 0 and then
index in ARRAY_REFs can be arbitrary type which is then sign or zero
extended to sizetype, or low_bound is something else and then index and
low_bound must have compatible types and it is still converted afterwards to
sizetype and from there then a few lines later:
expr.c-  if (poly_int_tree_p (offset))
expr.c-    {
expr.c:      poly_offset_int tem = wi::sext (wi::to_poly_offset (offset),
expr.c-                               TYPE_PRECISION (sizetype));
The following patch makes those routines match what get_inner_reference is
doing.

2021-01-22  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/98255
	* tree-dfa.c (get_ref_base_and_extent): For ARRAY_REFs, sign
	extend index - low_bound from sizetype's precision rather than index
	precision.
	(get_addr_base_and_unit_offset_1): Likewise.
	* tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): Likewise.
	* gimple-fold.c (fold_const_aggregate_ref_1): Likewise.

	* gcc.dg/pr98255.c: New test.
This commit is contained in:
Jakub Jelinek 2021-01-22 11:42:03 +01:00
parent fd61ca67f9
commit e287a2a11d
4 changed files with 54 additions and 5 deletions

View File

@ -8007,7 +8007,7 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
poly_offset_int woffset
= wi::sext (wi::to_poly_offset (idx)
- wi::to_poly_offset (low_bound),
TYPE_PRECISION (TREE_TYPE (idx)));
TYPE_PRECISION (sizetype));
woffset *= tree_to_uhwi (unit_size);
woffset *= BITS_PER_UNIT;
if (woffset.to_shwi (&offset))

View File

@ -0,0 +1,49 @@
/* PR tree-optimization/98255 */
/* { dg-do run } */
/* { dg-options "-Os" } */
/* { dg-additional-options "-fPIC" { target fpic } } */
struct A { volatile unsigned b; unsigned c; };
int d, *e, h, k, l;
static struct A f;
long g;
static unsigned i = -2U;
volatile int j;
long
foo (void)
{
char n[4][4][3]
= { { {9, 2, 8}, {9, 2, 8}, {9, 2, 8}, {9} }, { {8} }, { {8} }, { {2} } };
while (d)
{
for (; f.c < 4; f.c++)
{
*e = 0;
h = n[f.c + 4][0][d];
}
while (g)
return n[0][3][i];
while (1)
{
if (k)
{
j = 0;
if (j)
continue;
}
if (l)
break;
}
}
return 0;
}
int
main ()
{
asm volatile ("" : "+g" (d), "+g" (g), "+g" (f.c));
asm volatile ("" : "+g" (e), "+g" (k), "+g" (l));
foo ();
return 0;
}

View File

@ -503,7 +503,7 @@ get_ref_base_and_extent (tree exp, poly_int64_pod *poffset,
poly_offset_int woffset
= wi::sext (wi::to_poly_offset (index)
- wi::to_poly_offset (low_bound),
TYPE_PRECISION (TREE_TYPE (index)));
TYPE_PRECISION (sizetype));
woffset *= wi::to_offset (unit_size);
woffset <<= LOG2_BITS_PER_UNIT;
bit_offset += woffset;
@ -564,7 +564,7 @@ get_ref_base_and_extent (tree exp, poly_int64_pod *poffset,
{
poly_offset_int woffset
= wi::sext (omin - lbound,
TYPE_PRECISION (TREE_TYPE (index)));
TYPE_PRECISION (sizetype));
woffset *= wi::to_offset (unit_size);
woffset <<= LOG2_BITS_PER_UNIT;
bit_offset += woffset;
@ -822,7 +822,7 @@ get_addr_base_and_unit_offset_1 (tree exp, poly_int64_pod *poffset,
poly_offset_int woffset
= wi::sext (wi::to_poly_offset (index)
- wi::to_poly_offset (low_bound),
TYPE_PRECISION (TREE_TYPE (index)));
TYPE_PRECISION (sizetype));
woffset *= wi::to_offset (unit_size);
byte_offset += woffset.force_shwi ();
}

View File

@ -1108,7 +1108,7 @@ ao_ref_init_from_vn_reference (ao_ref *ref,
poly_offset_int woffset
= wi::sext (wi::to_poly_offset (op->op0)
- wi::to_poly_offset (op->op1),
TYPE_PRECISION (TREE_TYPE (op->op0)));
TYPE_PRECISION (sizetype));
woffset *= wi::to_offset (op->op2) * vn_ref_op_align_unit (op);
woffset <<= LOG2_BITS_PER_UNIT;
offset += woffset;