diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-01-22 11:42:03 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-01-22 11:42:03 +0100 |
commit | e287a2a11d7958e5d9f7c6172e59cc83495e393a (patch) | |
tree | ffc177370b8b199ee6f381b0ac3f1b0009ea58d4 /gcc/tree-dfa.c | |
parent | fd61ca67f97acc5462d02676380af92329c37bb2 (diff) | |
download | gcc-e287a2a11d7958e5d9f7c6172e59cc83495e393a.zip gcc-e287a2a11d7958e5d9f7c6172e59cc83495e393a.tar.gz gcc-e287a2a11d7958e5d9f7c6172e59cc83495e393a.tar.bz2 |
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.
Diffstat (limited to 'gcc/tree-dfa.c')
-rw-r--r-- | gcc/tree-dfa.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 648fdd0..0482b05 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -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 (); } |