8356647: C2: Excessively strict assert in PhaseIdealLoop::do_unroll
Reviewed-by: chagedorn, epeter, dlong
This commit is contained in:
parent
c9e6c4d017
commit
4b9290af0a
@ -1907,6 +1907,8 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj
|
|||||||
"odd trip count for maximally unroll");
|
"odd trip count for maximally unroll");
|
||||||
// Don't need to adjust limit for maximally unroll since trip count is even.
|
// Don't need to adjust limit for maximally unroll since trip count is even.
|
||||||
} else if (loop_head->has_exact_trip_count() && init->is_Con()) {
|
} else if (loop_head->has_exact_trip_count() && init->is_Con()) {
|
||||||
|
// The trip count being exact means it has been set (using CountedLoopNode::set_exact_trip_count in compute_trip_count)
|
||||||
|
assert(old_trip_count < max_juint, "sanity");
|
||||||
// Loop's limit is constant. Loop's init could be constant when pre-loop
|
// Loop's limit is constant. Loop's init could be constant when pre-loop
|
||||||
// become peeled iteration.
|
// become peeled iteration.
|
||||||
jlong init_con = init->get_int();
|
jlong init_con = init->get_int();
|
||||||
@ -1920,8 +1922,10 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj
|
|||||||
int stride_m = new_stride_con - (stride_con > 0 ? 1 : -1);
|
int stride_m = new_stride_con - (stride_con > 0 ? 1 : -1);
|
||||||
jlong trip_count = (limit_con - init_con + stride_m)/new_stride_con;
|
jlong trip_count = (limit_con - init_con + stride_m)/new_stride_con;
|
||||||
// New trip count should satisfy next conditions.
|
// New trip count should satisfy next conditions.
|
||||||
assert(trip_count > 0 && (julong)trip_count < (julong)max_juint/2, "sanity");
|
assert(trip_count > 0 && (julong)trip_count <= (julong)max_juint/2, "sanity");
|
||||||
uint new_trip_count = (uint)trip_count;
|
uint new_trip_count = (uint)trip_count;
|
||||||
|
// Since old_trip_count has been set to < max_juint (that is at most 2^32-2),
|
||||||
|
// new_trip_count is lower than or equal to 2^31-1 and the multiplication cannot overflow.
|
||||||
adjust_min_trip = (old_trip_count != new_trip_count*2);
|
adjust_min_trip = (old_trip_count != new_trip_count*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,11 +304,14 @@ public:
|
|||||||
void set_post_loop (CountedLoopNode *main) { assert(is_normal_loop(),""); _loop_flags |= Post; _main_idx = main->_idx; }
|
void set_post_loop (CountedLoopNode *main) { assert(is_normal_loop(),""); _loop_flags |= Post; _main_idx = main->_idx; }
|
||||||
void set_normal_loop( ) { _loop_flags &= ~PreMainPostFlagsMask; }
|
void set_normal_loop( ) { _loop_flags &= ~PreMainPostFlagsMask; }
|
||||||
|
|
||||||
void set_trip_count(uint tc) { _trip_count = tc; }
|
// We use max_juint for the default value of _trip_count to signal it wasn't set.
|
||||||
|
// We shouldn't set _trip_count to max_juint explicitly.
|
||||||
|
void set_trip_count(uint tc) { assert(tc < max_juint, "Cannot set trip count to max_juint"); _trip_count = tc; }
|
||||||
uint trip_count() { return _trip_count; }
|
uint trip_count() { return _trip_count; }
|
||||||
|
|
||||||
bool has_exact_trip_count() const { return (_loop_flags & HasExactTripCount) != 0; }
|
bool has_exact_trip_count() const { return (_loop_flags & HasExactTripCount) != 0; }
|
||||||
void set_exact_trip_count(uint tc) {
|
void set_exact_trip_count(uint tc) {
|
||||||
|
assert(tc < max_juint, "Cannot set trip count to max_juint");
|
||||||
_trip_count = tc;
|
_trip_count = tc;
|
||||||
_loop_flags |= HasExactTripCount;
|
_loop_flags |= HasExactTripCount;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Oracle and/or its affiliates. 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 8356647
|
||||||
|
* @summary C2's unrolling code has a too strict assert when a counted loop's range is as wide as int's.
|
||||||
|
* @run main/othervm -XX:CompileCommand=compileonly,compiler.loopopts.UnrollWideLoopHitsTooStrictAssert::test -Xcomp
|
||||||
|
* compiler.loopopts.UnrollWideLoopHitsTooStrictAssert
|
||||||
|
* @run main compiler.loopopts.UnrollWideLoopHitsTooStrictAssert
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.loopopts;
|
||||||
|
|
||||||
|
public class UnrollWideLoopHitsTooStrictAssert {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
test(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long test(boolean flag) {
|
||||||
|
long x = 0;
|
||||||
|
for (int i = Integer.MIN_VALUE; i < Integer.MAX_VALUE; ++i) {
|
||||||
|
x += i;
|
||||||
|
if (flag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user