diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index a2e5899a1e9..a273bb6053e 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3479,37 +3479,22 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f ResourceMark rm; Unique_Node_List wq; wq.push(n); - - - // When we remove a CastPP, we need to pin all of its transitive users under the control of - // the removed node. The simplest approach is to pin all of the uses of the removed CastPP, - // but it is overly conservative, as an AddP does not really need pinning. As a result, we - // look through those nodes that do not need pinning and only pin memory access nodes under - // n->in(0). for (uint next = 0; next < wq.size(); ++next) { Node *m = wq.at(next); for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { Node* use = m->fast_out(i); - int use_op = use->Opcode(); - if (use->is_CFG() || use->pinned() || // already pinned at the exact control - use->is_Cmp() || use->Opcode() == Op_CastP2X) { // pure computations - continue; - } else if (use->is_EncodeNarrowPtr() || // EncodeP remembers whether its input is nullable, so it must be pinned - use_op == Op_PartialSubtypeCheck || // This accesses its pointer inputs, so it must depend on them being not-null - use->is_Mem() || use->is_memory_access_intrinsic()) { + if (use->is_Mem() || use->is_EncodeNarrowPtr()) { use->ensure_control_or_add_prec(n->in(0)); - } else if (use_op == Op_AddP || - use_op == Op_CastPP || use_op == Op_CheckCastPP || - use_op == Op_CMoveP || use_op == Op_CMoveN || - use_op == Op_DecodeN || use_op == Op_DecodeNKlass) { - // Look through use to find memory accesses if use does not need pinning - wq.push(use); } else { - // Should have handled all kinds of nodes, verify that we do not unexpectedly arrive - // here - assert(false, "unexpected node %s", use->Name()); - // Be conservative in product and pin the unexpected use - use->ensure_control_or_add_prec(n->in(0)); + switch(use->Opcode()) { + case Op_AddP: + case Op_DecodeN: + case Op_DecodeNKlass: + case Op_CheckCastPP: + case Op_CastPP: + wq.push(use); + break; + } } } } diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 1210693f957..997ce92fe1c 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -3001,27 +3001,6 @@ bool Node::is_data_proj_of_pure_function(const Node* maybe_pure_function) const return Opcode() == Op_Proj && as_Proj()->_con == TypeFunc::Parms && maybe_pure_function->is_CallLeafPure(); } -// Whether this is an intrinsic node that accesses memory and has a memory input, such as array -// equal intrinsic. Some nodes do access memory but do not have a memory input, such as -// PartialSubTypeCheck, they are not included here. -bool Node::is_memory_access_intrinsic() const { - switch (Opcode()) { - case Op_StrComp: - case Op_StrEquals: - case Op_StrIndexOf: - case Op_StrIndexOfChar: - case Op_StrCompressedCopy: - case Op_StrInflatedCopy: - case Op_AryEq: - case Op_CountPositives: - case Op_VectorizedHashCode: - case Op_EncodeISOArray: - return true; - default: - return false; - } -} - //--------------------------has_non_debug_uses------------------------------ // Checks whether the node has any non-debug uses or not. bool Node::has_non_debug_uses() const { diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 92bd03c0d63..1ef4b5a51b6 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1069,7 +1069,6 @@ public: uint is_Copy() const { return (_flags & Flag_is_Copy); } virtual bool is_CFG() const { return false; } - bool is_memory_access_intrinsic() const; // If this node is control-dependent on a test, can it be rerouted to a dominating equivalent // test? This means that the node can be executed safely as long as it happens after the test diff --git a/test/hotspot/jtreg/compiler/controldependency/TestRemoveCastPPWithCMoveUse.java b/test/hotspot/jtreg/compiler/controldependency/TestRemoveCastPPWithCMoveUse.java deleted file mode 100644 index 3d752cc74f5..00000000000 --- a/test/hotspot/jtreg/compiler/controldependency/TestRemoveCastPPWithCMoveUse.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ -package compiler.controldependency; - -/* - * @test - * @bug 8385420 - * @summary C2 correctly handles the case when the removed CastPPNode has a CMove use. - * @run main ${test.main.class} - * @run main/othervm -Xbatch -XX:CompileOnly=${test.main.class}::test - * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM ${test.main.class} - * - */ -public class TestRemoveCastPPWithCMoveUse { - public static void main(String[] args) { - for (int i = 0; i < 10_000; i++) { - test(null, false); - test(null, true); - test("", false); - test("", true); - } - } - - static int test(String a, boolean flag) { - StringBuilder sb = new StringBuilder(); - if (a == null) { - sb.append(""); - } else { - sb.append(flag ? a : ""); - } - return sb.length(); - } -}