The following makes use of range-info to improve the basic building block of the alias-oracle so we can tell that in
a[0] = 1; for (int i = 5; i < 17; ++i) a[i] = i; a[0] = 2; the ao_ref for a[i] does not alias the a[0] acceses. Given range-info is not always going to improve things over knowledge gained from the type size of the access I'm only improving it over information gathered from the size. For the above this allows us to DSE the first store with another DSE improvement I'm testing separately. Bootstrap & regtest in progress on x86_64-unknown-linux-gnu. Richard. 2018-05-17 Richard Biener <rguent...@suse.de> * tree-dfa.c (get_ref_base_and_extent): Use range-info to refine results when processing array refs with variable index. * gcc.dg/tree-ssa/ssa-dse-35.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-35.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-35.c new file mode 100644 index 00000000000..1f21670406f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-35.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1-details" } */ + +int a[256]; +void foo (void) +{ + a[0] = 1; + for (int i = 5; i < 17; ++i) + a[i] = i; + a[0] = 2; +} + +/* { dg-final { scan-tree-dump-times "Deleted dead store" 1 "dse1" } } */ diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index a121b880bb0..993ac49554d 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -529,6 +529,48 @@ get_ref_base_and_extent (tree exp, poly_int64_pod *poffset, /* Remember that we have seen an array ref with a variable index. */ seen_variable_array_ref = true; + + wide_int min, max; + if (TREE_CODE (index) == SSA_NAME + && (low_bound = array_ref_low_bound (exp), + poly_int_tree_p (low_bound)) + && (unit_size = array_ref_element_size (exp), + TREE_CODE (unit_size) == INTEGER_CST) + && get_range_info (index, &min, &max) == VR_RANGE) + { + poly_offset_int lbound = wi::to_poly_offset (low_bound); + /* Try to constrain maxsize with range information. */ + offset_int omax + = offset_int::from (max, TYPE_SIGN (TREE_TYPE (index))); + if (known_lt (lbound, omax)) + { + poly_offset_int rmaxsize; + rmaxsize = (omax - lbound + 1) + * wi::to_offset (unit_size) << LOG2_BITS_PER_UNIT; + if (!known_size_p (maxsize) + || known_lt (rmaxsize, maxsize)) + { + maxsize = rmaxsize; + /* Given we know an upper bound this is no + longer variable. */ + seen_variable_array_ref = false; + } + } + /* 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)) + { + poly_offset_int woffset + = wi::sext (omin - lbound, + TYPE_PRECISION (TREE_TYPE (index))); + woffset *= wi::to_offset (unit_size); + woffset <<= LOG2_BITS_PER_UNIT; + bit_offset += woffset; + if (known_size_p (maxsize)) + maxsize -= woffset; + } + } } } break;