From 1f0dfdbccac4d23c00cab5663324c965141e1b23 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Mon, 25 Aug 2025 06:51:28 +0000 Subject: [PATCH] 8360561: PhaseIdealLoop::create_new_if_for_predicate hits "must be a uct if pattern" assert Reviewed-by: mhaessig, thartmann, qamai --- src/hotspot/share/opto/subnode.cpp | 26 +++++++ .../igvn/CmpDisjointButNonOrderedRanges.java | 73 +++++++++++++++++++ .../igvn/CmpDisjointButNonOrderedRanges2.java | 68 +++++++++++++++++ .../CmpDisjointButNonOrderedRangesLong.java | 61 ++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java create mode 100644 test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java create mode 100644 test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 5f1af09463f..9c6c7498dd0 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -694,6 +694,11 @@ const Type *CmpINode::sub( const Type *t1, const Type *t2 ) const { return TypeInt::CC_LE; else if( r0->_lo == r1->_hi ) // Range is never low? return TypeInt::CC_GE; + + const Type* joined = r0->join(r1); + if (joined == Type::TOP) { + return TypeInt::CC_NE; + } return TypeInt::CC; // else use worst case results } @@ -798,6 +803,12 @@ const Type *CmpUNode::sub( const Type *t1, const Type *t2 ) const { // looks at the structure of the node in any other case.) if ((jint)lo0 >= 0 && (jint)lo1 >= 0 && is_index_range_check()) return TypeInt::CC_LT; + + const Type* joined = r0->join(r1); + if (joined == Type::TOP) { + return TypeInt::CC_NE; + } + return TypeInt::CC; // else use worst case results } @@ -939,6 +950,12 @@ const Type *CmpLNode::sub( const Type *t1, const Type *t2 ) const { return TypeInt::CC_LE; else if( r0->_lo == r1->_hi ) // Range is never low? return TypeInt::CC_GE; + + const Type* joined = r0->join(r1); + if (joined == Type::TOP) { + return TypeInt::CC_NE; + } + return TypeInt::CC; // else use worst case results } @@ -993,6 +1010,11 @@ const Type* CmpULNode::sub(const Type* t1, const Type* t2) const { } } + const Type* joined = r0->join(r1); + if (joined == Type::TOP) { + return TypeInt::CC_NE; + } + return TypeInt::CC; // else use worst case results } @@ -1368,6 +1390,10 @@ const Type *BoolTest::cc2logical( const Type *CC ) const { if( _test == le ) return TypeInt::ONE; if( _test == gt ) return TypeInt::ZERO; } + if( CC == TypeInt::CC_NE ) { + if( _test == ne ) return TypeInt::ONE; + if( _test == eq ) return TypeInt::ZERO; + } return TypeInt::BOOL; } diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java new file mode 100644 index 00000000000..a8f75b9c8f4 --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java @@ -0,0 +1,73 @@ +/* + * 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 8360561 + * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range) + * Comparing such values in such range with != should always be true. + * @run main/othervm -Xcomp + * -XX:CompileCommand=compileonly,compiler.igvn.CmpDisjointButNonOrderedRanges::* + * compiler.igvn.CmpDisjointButNonOrderedRanges + * @run main compiler.igvn.CmpDisjointButNonOrderedRanges + */ +package compiler.igvn; + +public class CmpDisjointButNonOrderedRanges { + static boolean bFld; + + public static void main(String[] strArr) { + test(); + } + + static void test() { + int x = 7; + int y = 4; + for (int i = 3; i < 12; i++) { + // x = 7 \/ x = -195 => x \in [-195, 7] as a signed value + // but [7, bitwise_cast_uint(-195)] as unsigned + // So 0 is not possible. + if (x != 0) { + A.foo(); + // Because A is not loaded, A.foo() traps and this point is not reachable. + } + // x is tighten to be in the meet (so Hotspot's join) of [0, 0] and [7, bitwise_cast_uint(-195)] + // that is bottom (Hotspot's top). Data is dead, control needs to be dead as well. + for (int j = 1; j < 8; j++) { + x = -195; + if (bFld) { + y += 2; + } + } + } + } + + static void foo() { + } +} + + +class A { + static void foo() { + } +} diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java new file mode 100644 index 00000000000..205a7f7d380 --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java @@ -0,0 +1,68 @@ +/* + * 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 8360561 + * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range) + * Comparing such values in such range with != should always be true. + * @run main/othervm -Xbatch + * -XX:CompileCommand=compileonly,compiler.igvn.CmpDisjointButNonOrderedRanges2::* + * -XX:-TieredCompilation + * -XX:+UnlockExperimentalVMOptions + * -XX:PerMethodTrapLimit=0 + * compiler.igvn.CmpDisjointButNonOrderedRanges2 + * @run main compiler.igvn.CmpDisjointButNonOrderedRanges2 + */ +package compiler.igvn; + +public class CmpDisjointButNonOrderedRanges2 { + int array[]; + + void test() { + int val = 2; + for (int i = 0; i < 10; i++) { + // val = 2 \/ val = -12 => val \in [-12, 2] as a signed value + // but [2, bitwise_cast_uint(-12)] as unsigned + // So 0 is not possible. + if (val != 0) { + return; + } + // val is tighten to be in the meet (so Hotspot's join) of [0, 0] and [2, bitwise_cast_uint(-12)] + // that is bottom (Hotspot's top). Data is dead, control needs to be dead as well. + for (int j = 0; j < 10; j++) { + array[1] = val; + val = -12; + } + } + } + + static public void main(String[] args) { + var c = new CmpDisjointButNonOrderedRanges2(); + for (int i = 0; i < 1000; ++i) { + c.test(); + for (int j = 0; j < 100; ++j) { + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java new file mode 100644 index 00000000000..c5ef1640721 --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java @@ -0,0 +1,61 @@ +/* + * 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 8360561 + * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range) + * Comparing such values in such range with != should always be true. + * @library /test/lib / + * @run main compiler.igvn.CmpDisjointButNonOrderedRangesLong + */ +package compiler.igvn; + +import compiler.lib.ir_framework.*; + +public class CmpDisjointButNonOrderedRangesLong { + static boolean bFld; + static double dFld1; + static double dFld2; + + public static void main(String[] strArr) { + TestFramework.run(); + } + + @Test + @IR(failOn = {IRNode.PHI}) + @Warmup(0) + static int test() { + long x = 7; + if (bFld) { + x = -195; + } + + dFld1 = dFld2 % 2.5; + + if (x == 0) { + return 0; + } + return 1; + } +}