@@ -1864,6 +1864,46 @@ Node* RangeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) {
18641864 // then we are guaranteed to fail, so just start interpreting there.
18651865 // We 'expand' the top 3 range checks to include all post-dominating
18661866 // checks.
1867+ //
1868+ // Example:
1869+ // a[i+x] // (1) 1 < x < 6
1870+ // a[i+3] // (2)
1871+ // a[i+4] // (3)
1872+ // a[i+6] // max = max of all constants
1873+ // a[i+2]
1874+ // a[i+1] // min = min of all constants
1875+ //
1876+ // If x < 3:
1877+ // (1) a[i+x]: Leave unchanged
1878+ // (2) a[i+3]: Replace with a[i+max] = a[i+6]: i+x < i+3 <= i+6 -> (2) is covered
1879+ // (3) a[i+4]: Replace with a[i+min] = a[i+1]: i+1 < i+4 <= i+6 -> (3) and all following checks are covered
1880+ // Remove all other a[i+c] checks
1881+ //
1882+ // If x >= 3:
1883+ // (1) a[i+x]: Leave unchanged
1884+ // (2) a[i+3]: Replace with a[i+min] = a[i+1]: i+1 < i+3 <= i+x -> (2) is covered
1885+ // (3) a[i+4]: Replace with a[i+max] = a[i+6]: i+1 < i+4 <= i+6 -> (3) and all following checks are covered
1886+ // Remove all other a[i+c] checks
1887+ //
1888+ // We only need the top 2 range checks if x is the min or max of all constants.
1889+ //
1890+ // This, however, only works if the interval [i+min,i+max] is not larger than max_int (i.e. abs(max - min) < max_int):
1891+ // The theoretical max size of an array is max_int with:
1892+ // - Valid index space: [0,max_int-1]
1893+ // - Invalid index space: [max_int,-1] // max_int, min_int, min_int - 1 ..., -1
1894+ //
1895+ // The size of the consecutive valid index space is smaller than the size of the consecutive invalid index space.
1896+ // If we choose min and max in such a way that:
1897+ // - abs(max - min) < max_int
1898+ // - i+max and i+min are inside the valid index space
1899+ // then all indices [i+min,i+max] must be in the valid index space. Otherwise, the invalid index space must be
1900+ // smaller than the valid index space which is never the case for any array size.
1901+ //
1902+ // Choosing a smaller array size only makes the valid index space smaller and the invalid index space larger and
1903+ // the argument above still holds.
1904+ //
1905+ // Note that the same optimization with the same maximal accepted interval size can also be found in C1.
1906+ const jlong maximum_number_of_min_max_interval_indices = (jlong)max_jint;
18671907
18681908 // The top 3 range checks seen
18691909 const int NRC = 3 ;
@@ -1898,13 +1938,18 @@ Node* RangeCheckNode::Ideal(PhaseGVN *phase, bool can_reshape) {
18981938 found_immediate_dominator = true ;
18991939 break ;
19001940 }
1901- // Gather expanded bounds
1902- off_lo = MIN2 (off_lo,offset2);
1903- off_hi = MAX2 (off_hi,offset2);
1904- // Record top NRC range checks
1905- prev_checks[nb_checks%NRC].ctl = prev_dom;
1906- prev_checks[nb_checks%NRC].off = offset2;
1907- nb_checks++;
1941+
1942+ // "x - y" -> must add one to the difference for number of elements in [x,y]
1943+ const jlong diff = (jlong)MIN2 (offset2, off_lo) - (jlong)MAX2 (offset2, off_hi);
1944+ if (ABS (diff) < maximum_number_of_min_max_interval_indices) {
1945+ // Gather expanded bounds
1946+ off_lo = MIN2 (off_lo, offset2);
1947+ off_hi = MAX2 (off_hi, offset2);
1948+ // Record top NRC range checks
1949+ prev_checks[nb_checks % NRC].ctl = prev_dom;
1950+ prev_checks[nb_checks % NRC].off = offset2;
1951+ nb_checks++;
1952+ }
19081953 }
19091954 }
19101955 prev_dom = dom;
0 commit comments