The following fixes bogus truncation of a value-range for an int128 array index when computing the maximum extent for a variable array reference. Instead of possibly slowing things down by using widest_int the following makes sure the range bounds fit within the constraints offset_int were designed for.
Bootstrap and regtest running on x86_64-unknown-linux-gnu. OK? Thanks, Richard. PR middle-end/113396 * tree-dfa.cc (get_ref_base_and_extent): Use index range bounds only if they fit within the address-range constraints of offset_int. * gcc.dg/torture/pr113396.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr113396.c | 19 +++++++++++++++++++ gcc/tree-dfa.cc | 6 ++++-- 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr113396.c diff --git a/gcc/testsuite/gcc.dg/torture/pr113396.c b/gcc/testsuite/gcc.dg/torture/pr113396.c new file mode 100644 index 00000000000..585f717bdda --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr113396.c @@ -0,0 +1,19 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int128 } */ + +unsigned char m[] = {5, 79, 79, 79, 79}; +__int128 p; +int main() +{ + int g1 = 0; + p = 0; + for (int aj = 0; aj < 256; aj++) + { + m[0] = -4; + for (; p >= 0; p -= 1) { + g1 = m[p]; + } + } + if (g1 != 0xfc) + __builtin_abort(); +} diff --git a/gcc/tree-dfa.cc b/gcc/tree-dfa.cc index cbd3774b21f..93e53b29a6d 100644 --- a/gcc/tree-dfa.cc +++ b/gcc/tree-dfa.cc @@ -549,7 +549,8 @@ get_ref_base_and_extent (tree exp, poly_int64 *poffset, /* Try to constrain maxsize with range information. */ offset_int omax = offset_int::from (max, TYPE_SIGN (TREE_TYPE (index))); - if (known_lt (lbound, omax)) + if (wi::get_precision (max) <= ADDR_MAX_BITSIZE + && known_lt (lbound, omax)) { poly_offset_int rmaxsize; rmaxsize = (omax - lbound + 1) @@ -567,7 +568,8 @@ get_ref_base_and_extent (tree exp, poly_int64 *poffset, /* Try to adjust bit_offset with range information. */ offset_int omin = offset_int::from (min, TYPE_SIGN (TREE_TYPE (index))); - if (known_le (lbound, omin)) + if (wi::get_precision (min) <= ADDR_MAX_BITSIZE + && known_le (lbound, omin)) { poly_offset_int woffset = wi::sext (omin - lbound, -- 2.35.3