From cb1d1d68f85c0710a1a2400819b663ae1b94fe82 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Fri, 11 Apr 2025 17:36:36 +0200 Subject: [PATCH 1/6] remove_dead_region in Blackhole::Ideal --- src/hotspot/share/opto/cfgnode.cpp | 3 +++ src/hotspot/share/opto/cfgnode.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 5bf0d6facc13b..72730ee30a1f3 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -3109,6 +3109,9 @@ void NeverBranchNode::format( PhaseRegAlloc *ra_, outputStream *st) const { } #endif +Node* BlackholeNode::Ideal(PhaseGVN *phase, bool can_reshape) { + return remove_dead_region(phase, can_reshape) ? this : nullptr; +} #ifndef PRODUCT void BlackholeNode::format(PhaseRegAlloc* ra, outputStream* st) const { st->print("blackhole "); diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 6786089a20327..30f814dbb7738 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -735,6 +735,7 @@ class BlackholeNode : public MultiNode { virtual int Opcode() const; virtual uint ideal_reg() const { return 0; } // not matched in the AD file virtual const Type* bottom_type() const { return TypeTuple::MEMBAR; } + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); const RegMask &in_RegMask(uint idx) const { // Fake the incoming arguments mask for blackholes: accept all registers From f636a4c90afa81a5b1b4391846d2d064a4e5809a Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Mon, 14 Apr 2025 10:30:25 +0200 Subject: [PATCH 2/6] Add test --- .../compiler/blackhole/DeadBhElimination.java | 67 +++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 12 ++++ 2 files changed, 79 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java diff --git a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java new file mode 100644 index 0000000000000..1845e68c24db7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025, Red Hat 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 8344251 + * @summary Test that blackhole without control input are removed + * @library /test/lib / + * @run driver compiler.blackhole.DeadBhElimination + */ + +package compiler.blackhole; + +import compiler.lib.ir_framework.*; + +public class DeadBhElimination { + public static void main(String[] args) { + TestFramework.runWithFlags( + "-Xcomp", + "-XX:-TieredCompilation", + "-XX:+UnlockExperimentalVMOptions", + "-XX:CompileCommand=blackhole,compiler.blackhole.DeadBhElimination::iAmABlackhole" + ); + } + + static public void iAmABlackhole(int x) {} + + @Test + @IR(counts = {IRNode.BLACKHOLE, "1"}, phase = CompilePhase.AFTER_PARSING) + @IR(failOn = {IRNode.BLACKHOLE}, phase = CompilePhase.FINAL_CODE) + static void removalAfterLoopOpt() { + int a = 77; + int b = 0; + do { + a--; + b++; + } while (a > 0); + // b == 77, known after first loop opts round + // loop is detected as empty loop + + if(b == 78) { // dead + iAmABlackhole(a); + } + } + + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 57e4d413fea07..ffcae5b280fc7 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -2707,6 +2707,11 @@ public class IRNode { macroNodes(MOD_D, regex); } + public static final String BLACKHOLE = PREFIX + "BLACKHOLE" + POSTFIX; + static { + fromBeforeRemoveUselessToFinalCode(BLACKHOLE, "Blackhole"); + } + /* * Utility methods to set up IR_NODE_MAPPINGS. */ @@ -2833,6 +2838,13 @@ private static void storeOfNodes(String irNodePlaceholder, String irNodeRegex) { beforeMatching(irNodePlaceholder, regex); } + private static void fromBeforeRemoveUselessToFinalCode(String irNodePlaceholder, String irNodeRegex) { + String regex = START + irNodeRegex + MID + END; + IR_NODE_MAPPINGS.put(irNodePlaceholder, new SinglePhaseRangeEntry(CompilePhase.PRINT_IDEAL, regex, + CompilePhase.BEFORE_REMOVEUSELESS, + CompilePhase.FINAL_CODE)); + } + /** * Apply {@code regex} on all ideal graph phases starting from {@link CompilePhase#PHASEIDEALLOOP1} which is the * first phase that could contain vector nodes from super word. From a71abe7df4fbde41f1fa9ca6b154ef51642c2483 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Tue, 15 Apr 2025 11:15:02 +0200 Subject: [PATCH 3/6] Format --- src/hotspot/share/opto/cfgnode.cpp | 2 +- src/hotspot/share/opto/cfgnode.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 72730ee30a1f3..2bbd5c33e3132 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -3109,7 +3109,7 @@ void NeverBranchNode::format( PhaseRegAlloc *ra_, outputStream *st) const { } #endif -Node* BlackholeNode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* BlackholeNode::Ideal(PhaseGVN* phase, bool can_reshape) { return remove_dead_region(phase, can_reshape) ? this : nullptr; } #ifndef PRODUCT diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 30f814dbb7738..a0e780c0e5742 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -735,7 +735,7 @@ class BlackholeNode : public MultiNode { virtual int Opcode() const; virtual uint ideal_reg() const { return 0; } // not matched in the AD file virtual const Type* bottom_type() const { return TypeTuple::MEMBAR; } - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); const RegMask &in_RegMask(uint idx) const { // Fake the incoming arguments mask for blackholes: accept all registers From 97aac30de3ac9a67b7cd6aa14de5e120bbaf3d3b Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Tue, 15 Apr 2025 17:26:38 +0200 Subject: [PATCH 4/6] Address review comments --- src/hotspot/share/opto/cfgnode.cpp | 1 + test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 2bbd5c33e3132..4885d44a13df7 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -3112,6 +3112,7 @@ void NeverBranchNode::format( PhaseRegAlloc *ra_, outputStream *st) const { Node* BlackholeNode::Ideal(PhaseGVN* phase, bool can_reshape) { return remove_dead_region(phase, can_reshape) ? this : nullptr; } + #ifndef PRODUCT void BlackholeNode::format(PhaseRegAlloc* ra, outputStream* st) const { st->print("blackhole "); diff --git a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java index 1845e68c24db7..7e8cf68f5162b 100644 --- a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java +++ b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java @@ -36,7 +36,7 @@ public class DeadBhElimination { public static void main(String[] args) { TestFramework.runWithFlags( - "-Xcomp", + "-XX:CompileThreshold=100", "-XX:-TieredCompilation", "-XX:+UnlockExperimentalVMOptions", "-XX:CompileCommand=blackhole,compiler.blackhole.DeadBhElimination::iAmABlackhole" From 487b1a64cc4dc3fd1495a1e6ced53f974a8d0a1e Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Tue, 15 Apr 2025 19:29:26 +0200 Subject: [PATCH 5/6] Using PerMethod(Spec)?TrapLimit --- test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java index 7e8cf68f5162b..ebef7c5dc4479 100644 --- a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java +++ b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java @@ -36,9 +36,12 @@ public class DeadBhElimination { public static void main(String[] args) { TestFramework.runWithFlags( - "-XX:CompileThreshold=100", "-XX:-TieredCompilation", "-XX:+UnlockExperimentalVMOptions", + // Prevent the dead branches to be compiled into an uncommon trap + // instead of generating a BlackholeNode. + "-XX:PerMethodTrapLimit=0", + "-XX:PerMethodSpecTrapLimit=0", "-XX:CompileCommand=blackhole,compiler.blackhole.DeadBhElimination::iAmABlackhole" ); } From 9f0009901f7b021f72d9f45676ef1df4a7d09ab3 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Wed, 16 Apr 2025 14:56:47 +0200 Subject: [PATCH 6/6] cosmetic --- test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java index ebef7c5dc4479..0fb503d2c44d3 100644 --- a/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java +++ b/test/hotspot/jtreg/compiler/blackhole/DeadBhElimination.java @@ -61,7 +61,7 @@ static void removalAfterLoopOpt() { // b == 77, known after first loop opts round // loop is detected as empty loop - if(b == 78) { // dead + if (b == 78) { // dead iAmABlackhole(a); } }