# HG changeset patch # User roland # Date 1570030328 -7200 # Node ID bada0782842ae3110fff30715ca127a4004cc6f0 # Parent 8991796c17d4b0776449581440b41c430eab78d9 8231550: C2: ShouldNotReachHere() in verify_strip_mined_scheduling Reviewed-by: vlivanov, thartmann diff -r 8991796c17d4 -r bada0782842a src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Tue Oct 01 10:28:12 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp Wed Oct 02 17:32:08 2019 +0200 @@ -1276,12 +1276,32 @@ // The rethrow call may have too many projections to be // properly handled here. Given there's no reason for a // barrier to depend on the call, move it above the call - if (phase->get_ctrl(val) == ctrl) { - assert(val->Opcode() == Op_DecodeN, "unexpected node"); - assert(phase->is_dominator(phase->get_ctrl(val->in(1)), call->in(0)), "Load is too low"); - phase->set_ctrl(val, call->in(0)); - } - phase->set_ctrl(lrb, call->in(0)); + stack.push(lrb, 0); + do { + Node* n = stack.node(); + uint idx = stack.index(); + if (idx < n->req()) { + Node* in = n->in(idx); + stack.set_index(idx+1); + if (in != NULL) { + if (phase->has_ctrl(in)) { + if (phase->is_dominator(call, phase->get_ctrl(in))) { +#ifdef ASSERT + for (uint i = 0; i < stack.size(); i++) { + assert(stack.node_at(i) != in, "node shouldn't have been seen yet"); + } +#endif + stack.push(in, 0); + } + } else { + assert(phase->is_dominator(in, call->in(0)), "no dependency on the call"); + } + } + } else { + phase->set_ctrl(n, call->in(0)); + stack.pop(); + } + } while(stack.size() > 0); continue; } CallProjections projs; diff -r 8991796c17d4 -r bada0782842a src/hotspot/share/opto/loopnode.cpp --- a/src/hotspot/share/opto/loopnode.cpp Tue Oct 01 10:28:12 2019 +0200 +++ b/src/hotspot/share/opto/loopnode.cpp Wed Oct 02 17:32:08 2019 +0200 @@ -4049,28 +4049,32 @@ // dominated by early is considered a potentially interfering store. // This can produce false positives. if (n->is_Load() && LCA != early) { - Node_List worklist; - - Node *mem = n->in(MemNode::Memory); - for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { - Node* s = mem->fast_out(i); - worklist.push(s); - } - while(worklist.size() != 0 && LCA != early) { - Node* s = worklist.pop(); - if (s->is_Load() || s->Opcode() == Op_SafePoint || - (s->is_CallStaticJava() && s->as_CallStaticJava()->uncommon_trap_request() != 0)) { - continue; - } else if (s->is_MergeMem()) { - for (DUIterator_Fast imax, i = s->fast_outs(imax); i < imax; i++) { - Node* s1 = s->fast_out(i); - worklist.push(s1); - } - } else { - Node *sctrl = has_ctrl(s) ? get_ctrl(s) : s->in(0); - assert(sctrl != NULL || s->outcnt() == 0, "must have control"); - if (sctrl != NULL && !sctrl->is_top() && is_dominator(early, sctrl)) { - LCA = dom_lca_for_get_late_ctrl(LCA, sctrl, n); + int load_alias_idx = C->get_alias_index(n->adr_type()); + if (C->alias_type(load_alias_idx)->is_rewritable()) { + + Node_List worklist; + + Node *mem = n->in(MemNode::Memory); + for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { + Node* s = mem->fast_out(i); + worklist.push(s); + } + while(worklist.size() != 0 && LCA != early) { + Node* s = worklist.pop(); + if (s->is_Load() || s->Opcode() == Op_SafePoint || + (s->is_CallStaticJava() && s->as_CallStaticJava()->uncommon_trap_request() != 0)) { + continue; + } else if (s->is_MergeMem()) { + for (DUIterator_Fast imax, i = s->fast_outs(imax); i < imax; i++) { + Node* s1 = s->fast_out(i); + worklist.push(s1); + } + } else { + Node *sctrl = has_ctrl(s) ? get_ctrl(s) : s->in(0); + assert(sctrl != NULL || s->outcnt() == 0, "must have control"); + if (sctrl != NULL && !sctrl->is_top() && C->can_alias(s->adr_type(), load_alias_idx) && is_dominator(early, sctrl)) { + LCA = dom_lca_for_get_late_ctrl(LCA, sctrl, n); + } } } } diff -r 8991796c17d4 -r bada0782842a test/hotspot/jtreg/compiler/loopstripmining/TestConservativeAntiDep.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/loopstripmining/TestConservativeAntiDep.java Wed Oct 02 17:32:08 2019 +0200 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019, 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 8231550 + * @summary C2: ShouldNotReachHere() in verify_strip_mined_scheduling + * + * @run main/othervm -XX:-BackgroundCompilation -XX:LoopMaxUnroll=0 TestConservativeAntiDep + * + */ + +import java.lang.reflect.Array; +import java.util.Arrays; + +public class TestConservativeAntiDep { + private static long longField; + + public static void main(String[] args) throws InstantiationException, IllegalAccessException { + for (int i = 0; i < 20_000; i++) { + test1(A.class); + test2(B.class); + } + } + + private static int test1(Class klass) { + Object[] in = (Object[])Array.newInstance(klass, 100); + + Object[] o = in; + int v = 1; + // CountedLoop has control dependent CastPP + for (int i = 0; i < 100 ; i++) { + longField = i; // sunk in outer strip mined loop + o = (A[]) o; + v *= 2; + } + + // LoadRange cannot float higher than CountedLoop (because of + // CastPP) and is found anti-dependent with long store so + // scheduled in outer strip mined loop + return v + o.length; + } + + private static int test2(Class klass) throws IllegalAccessException, InstantiationException { + A in = (A)klass.newInstance(); + + A o = in; + int v = 1; + // CountedLoop has control dependent CastPP + for (int i = 0; i < 100 ; i++) { + longField = i; // sunk in outer strip mined loop + o = (B) o; + v *= 2; + } + + // Load cannot float higher than CountedLoop (because of + // CastPP) and is found anti-dependent with long store so + // scheduled in outer strip mined loop + return v + o.intField; + } + + private static class A { + int intField; + public A() {} + } + + private static class B extends A { + public B() {} + } +}