8202949: C2: assert(false) failed: Bad graph detected in build_loop_late

Fixed trip count computation for counted loop with negative stride to prevent over-unrolling.

Reviewed-by: roland
This commit is contained in:
Tobias Hartmann 2018-05-25 09:05:42 +02:00
parent 313a255558
commit 2d00538d92
2 changed files with 42 additions and 11 deletions
src/hotspot/share/opto
test/hotspot/jtreg/compiler/loopopts

@ -116,9 +116,11 @@ void IdealLoopTree::compute_trip_count(PhaseIdealLoop* phase) {
if (init_n != NULL && limit_n != NULL) {
// Use longs to avoid integer overflow.
int stride_con = cl->stride_con();
jlong init_con = phase->_igvn.type(init_n)->is_int()->_lo;
jlong limit_con = phase->_igvn.type(limit_n)->is_int()->_hi;
int stride_m = stride_con - (stride_con > 0 ? 1 : -1);
const TypeInt* init_type = phase->_igvn.type(init_n)->is_int();
const TypeInt* limit_type = phase->_igvn.type(limit_n)->is_int();
jlong init_con = (stride_con > 0) ? init_type->_lo : init_type->_hi;
jlong limit_con = (stride_con > 0) ? limit_type->_hi : limit_type->_lo;
int stride_m = stride_con - (stride_con > 0 ? 1 : -1);
jlong trip_count = (limit_con - init_con + stride_m)/stride_con;
if (trip_count > 0 && (julong)trip_count < (julong)max_juint) {
if (init_n->is_Con() && limit_n->is_Con()) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2018, 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
@ -23,20 +23,19 @@
/*
* @test
* @bug 8159016
* @bug 8159016 8202949
* @summary Tests correct dominator information after over-unrolling a loop.
* @requires vm.gc == "Parallel" | vm.gc == "null"
*
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation
* -XX:-UseG1GC -XX:+UseParallelGC
* compiler.loopopts.TestOverunrolling
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions
* -Xcomp -XX:-TieredCompilation -XX:-UseSwitchProfiling
* -XX:-UseG1GC -XX:+UseParallelGC compiler.loopopts.TestOverunrolling
*/
package compiler.loopopts;
public class TestOverunrolling {
public static Object test(int arg) {
public static Object test1(int arg) {
Object arr[] = new Object[3];
int lim = (arg & 3);
// The pre loop is executed for one iteration, initializing p[0].
@ -53,10 +52,40 @@ public class TestOverunrolling {
return arr;
}
public static long lFld = 0;
public static volatile double dFld = 0;
public static void test2() {
int iArr[] = new int[10];
// The inner for-loop is overunrolled because we fail to determine
// the constant lower and upper bound (6,8]. After unrolling multiple times,
// the range check dependent CastII/ConvI2L emitted for the iArr access become
// TOP because index 'j' is out of bounds. As a result, the memory graph is
// corrupted with memory consuming nodes still being reachable because the dead
// loop is not (yet) removed (Opaque1 nodes are still guarding the bounds).
for (int i = 6; i < 10; i++) {
for (int j = 8; j > i; j--) {
int k = 1;
do {
iArr[j] = 0;
switch (k) {
case 1:
lFld = 0;
break;
case 10:
dFld = 0;
break;
}
} while (++k < 1);
}
}
}
public static void main(String args[]) {
for (int i = 0; i < 42; ++i) {
test(i);
test1(i);
}
test2();
}
}