8382536: C2: sharpen_type_after_if: assert(val->find_edge(con) > 0) failed: mismatch

Reviewed-by: chagedorn, mchevalier
This commit is contained in:
Vladimir Ivanov 2026-07-09 16:59:16 +00:00
parent 7544c91a81
commit 4d3723b802
2 changed files with 71 additions and 12 deletions

View File

@ -1749,6 +1749,10 @@ static bool match_type_check(PhaseGVN& gvn,
Node* con, const Type* tcon,
Node* val, const Type* tval,
Node** obj, const TypeOopPtr** cast_type) { // out-parameters
assert(tcon->singleton(), "not a constant: %s", Type::str(tcon));
assert(tcon == gvn.type(con), "mismatch: %s != %s", Type::str(tcon), Type::str(gvn.type(con)));
assert(tval == gvn.type(val), "mismatch: %s != %s", Type::str(tval), Type::str(gvn.type(val)));
// Look for opportunities to sharpen the type of a node whose klass is compared with a constant klass.
// The constant klass being tested against can come from many bytecode instructions (implicitly or explicitly),
// and also from profile data used by speculative casts.
@ -1783,14 +1787,14 @@ static bool match_type_check(PhaseGVN& gvn,
// Region
// \ ConI ConI
// \ | /
// val -> Phi ConI <- con
// \ /
// CmpI
// |
// Bool [btest]
// |
// val -> Phi ConI|CastII <- con
// \ /
// CmpI
// |
// Bool [btest]
// |
//
if (tval->isa_int() && val->is_Phi() && val->in(0)->as_Region()->is_diamond()) {
if (tcon->isa_int() && val->is_Phi() && val->in(0)->as_Region()->is_diamond()) {
RegionNode* diamond = val->in(0)->as_Region();
IfNode* if1 = diamond->in(1)->in(0)->as_If();
BoolNode* b1 = if1->in(1)->isa_Bool();
@ -1799,12 +1803,16 @@ static bool match_type_check(PhaseGVN& gvn,
b1->_test._test == BoolTest::ne, "%d", b1->_test._test);
ProjNode* success_proj = if1->proj_out(b1->_test._test == BoolTest::eq ? 1 : 0);
int idx = diamond->find_edge(success_proj);
assert(idx == 1 || idx == 2, "");
Node* vcon = val->in(idx);
int success_idx = diamond->find_edge(success_proj);
assert(success_idx == 1 || success_idx == 2, "");
assert(val->req() == 3, "not a diamond");
if ((btest == BoolTest::eq && vcon == con) || (btest == BoolTest::ne && vcon != con)) {
assert(val->find_edge(con) > 0, "mismatch");
// gen_instanceof() emits 1 on success and 0 on failure.
// Check whether current comparison selects the success value.
const Type* success_tval = gvn.type(val->in(success_idx));
assert(success_tval->isa_int(), "not an int: %s", Type::str(success_tval));
if ((btest == BoolTest::eq && tcon == success_tval) ||
(btest == BoolTest::ne && tcon->join(success_tval)->empty())) {
SubTypeCheckNode* sub = b1->in(1)->as_SubTypeCheck();
Node* obj_or_subklass = sub->in(SubTypeCheckNode::ObjOrSubKlass);
Node* superklass = sub->in(SubTypeCheckNode::SuperKlass);

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2026, 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 8382536
* @summary C2: sharpen_type_after_if: assert(val->find_edge(con) > 0) failed: mismatch
*
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,${test.main.class}::test ${test.main.class}
*/
package compiler.types;
public class TestSubTypeCheckConstantCastII {
static class A {}
static boolean isInstanceOfA(Object obj) {
return (obj instanceof A);
}
static void test(boolean b, Object obj) {
if (b) {
return;
}
// b == false
if (b != isInstanceOfA(obj)) {}
}
public static void main(String[] args) {
test(true, new A());
}
}