--- old/src/hotspot/share/opto/cfgnode.cpp 2017-11-08 15:54:14.065683854 +0100 +++ new/src/hotspot/share/opto/cfgnode.cpp 2017-11-08 15:54:13.183684701 +0100 @@ -918,11 +918,18 @@ const TypeInt* stride_t = phase->type(stride)->isa_int(); if (lo != NULL && hi != NULL && stride_t != NULL) { // Dying loops might have TOP here assert(stride_t->_hi >= stride_t->_lo, "bad stride type"); - if (stride_t->_hi < 0) { // Down-counter loop - swap(lo, hi); - return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3); - } else if (stride_t->_lo >= 0) { - return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3); + BoolTest::mask bt = l->loopexit()->test_trip(); + // If the loop exit condition is "not equal", the condition + // would not trigger if init > limit (if stride > 0) or if + // init < limit if (stride > 0) so we can't deduce bounds + // for the iv from the exit condition. + if (bt != BoolTest::ne) { + if (stride_t->_hi < 0) { // Down-counter loop + swap(lo, hi); + return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3); + } else if (stride_t->_lo >= 0) { + return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3); + } } } } @@ -933,7 +940,7 @@ // before the special code for counted loop above has a chance // to run (that is as long as the type of the backedge's control // is top), we might end up with non monotonic types - return phase->type(in(LoopNode::EntryControl)); + return phase->type(in(LoopNode::EntryControl))->filter_speculative(_type); } } --- /dev/null 2017-09-29 08:45:25.790492889 +0200 +++ new/test/hotspot/jtreg/compiler/loopopts/TestCountedLoopBadIVRange.java 2017-11-08 15:54:14.170683753 +0100 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8190375 + * @summary Bad range for IV phi when exit condition is a not equal test + * @run main/othervm -XX:-TieredCompilation TestCountedLoopBadIVRange + * + */ + + +public class TestCountedLoopBadIVRange { + + static int test1(int[] arr) { + int j = 0; + int res = 0; + for (int i = 0; i < 2; i++) { + // When entered with j == 10, exit condition never + // succeeds so range of values for j can't be computed + // from exit condition + for (; j != 5; j++) { + if (j >= 20) { + break; + } + res += arr[j]; + } + j = 10; + } + return res; + } + + static int test2(int[] arr) { + int j = 10; + int res = 0; + for (int i = 0; i < 2; i++) { + // Same as above but loop variable is decreasing + for (; j != 5; j--) { + if (j < 0) { + break; + } + res += arr[j]; + } + j = 1; + } + return res; + } + + public static void main(String[] args) { + int[] arr = new int[20]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + for (int i = 0; i < 20_000; i++) { + int res = test1(arr); + if (res != 155) { + throw new RuntimeException("Incorrect result " + res); + } + res = test2(arr); + if (res != 41) { + throw new RuntimeException("Incorrect result " + res); + } + } + } +}