diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index f0e55d6ed48..9a7d93dc469 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -1424,6 +1424,14 @@ Node* MinLNode::Ideal(PhaseGVN* phase, bool can_reshape) { return nullptr; } +Node* MaxNode::Identity(PhaseGVN* phase) { + if (in(1) == in(2)) { + return in(1); + } + + return AddNode::Identity(phase); +} + //------------------------------add_ring--------------------------------------- const Type* MinFNode::add_ring(const Type* t0, const Type* t1 ) const { const TypeF* r0 = t0->isa_float_constant(); diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 19043b5e40f..fd044d6eead 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -269,6 +269,7 @@ public: virtual int max_opcode() const = 0; virtual int min_opcode() const = 0; Node* IdealI(PhaseGVN* phase, bool can_reshape); + virtual Node* Identity(PhaseGVN* phase); static Node* unsigned_max(Node* a, Node* b, const Type* t, PhaseGVN& gvn) { return build_min_max(a, b, true, true, t, gvn); diff --git a/test/hotspot/jtreg/compiler/intrinsics/math/TestMinMaxOpt.java b/test/hotspot/jtreg/compiler/intrinsics/math/TestMinMaxOpt.java new file mode 100644 index 00000000000..22b5e3e12ab --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/math/TestMinMaxOpt.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024, 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 8323429 + * @summary Test min and max optimizations + * @library /test/lib / + * @run driver compiler.intrinsics.math.TestMinMaxOpt + */ + +package compiler.intrinsics.math; + +import compiler.lib.ir_framework.Argument; +import compiler.lib.ir_framework.Arguments; +import compiler.lib.ir_framework.Check; +import compiler.lib.ir_framework.IR; +import compiler.lib.ir_framework.IRNode; +import compiler.lib.ir_framework.Test; +import compiler.lib.ir_framework.TestFramework; + +public class TestMinMaxOpt { + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MIN_I}) + private static int testIntMin(int v) { + return Math.min(v, v); + } + + @Check(test = "testIntMin") + public static void checkTestIntMin(int result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MAX_I}) + private static int testIntMax(int v) { + return Math.max(v, v); + } + + @Check(test = "testIntMax") + public static void checkTestIntMax(int result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MIN_L}) + private static long testLongMin(long v) { + return Math.min(v, v); + } + + @Check(test = "testLongMin") + public static void checkTestLongMin(long result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MAX_L}) + private static long testLongMax(long v) { + return Math.max(v, v); + } + + @Check(test = "testLongMax") + public static void checkTestLongMax(long result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MIN_F}) + private static float testFloatMin(float v) { + return Math.min(v, v); + } + + @Check(test = "testFloatMin") + public static void checkTestFloatMin(float result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MAX_F}) + private static float testFloatMax(float v) { + return Math.max(v, v); + } + + @Check(test = "testFloatMax") + public static void checkTestFloatMax(float result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MIN_D}) + private static double testDoubleMin(double v) { + return Math.min(v, v); + } + + @Check(test = "testDoubleMin") + public static void checkTestDoubleMin(double result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } + + @Test + @Arguments(values = {Argument.NUMBER_42}) + @IR(failOn = {IRNode.MAX_D}) + private static double testDoubleMax(double v) { + return Math.max(v, v); + } + + @Check(test = "testDoubleMax") + public static void checkTestDoubleMax(double result) { + if (result != 42) { + throw new RuntimeException("Incorrect result: " + result); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 366b17786ad..96698540019 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -819,7 +819,12 @@ public class IRNode { public static final String MAX = PREFIX + "MAX" + POSTFIX; static { - beforeMatchingNameRegex(MAX, "Max(I|L)"); + beforeMatchingNameRegex(MAX, "Max(I|L|F|D)"); + } + + public static final String MAX_D = PREFIX + "MAX_D" + POSTFIX; + static { + beforeMatchingNameRegex(MAX_D, "MaxD"); } public static final String MAX_D_REDUCTION_REG = PREFIX + "MAX_D_REDUCTION_REG" + POSTFIX; @@ -832,6 +837,11 @@ public class IRNode { machOnlyNameRegex(MAX_D_REG, "maxD_reg"); } + public static final String MAX_F = PREFIX + "MAX_F" + POSTFIX; + static { + beforeMatchingNameRegex(MAX_F, "MaxF"); + } + public static final String MAX_F_REDUCTION_REG = PREFIX + "MAX_F_REDUCTION_REG" + POSTFIX; static { machOnlyNameRegex(MAX_F_REDUCTION_REG, "maxF_reduction_reg"); @@ -887,6 +897,11 @@ public class IRNode { beforeMatchingNameRegex(MIN, "Min(I|L)"); } + public static final String MIN_D = PREFIX + "MIN_D" + POSTFIX; + static { + beforeMatchingNameRegex(MIN_D, "MinD"); + } + public static final String MIN_D_REDUCTION_REG = PREFIX + "MIN_D_REDUCTION_REG" + POSTFIX; static { machOnlyNameRegex(MIN_D_REDUCTION_REG, "minD_reduction_reg"); @@ -897,6 +912,11 @@ public class IRNode { machOnlyNameRegex(MIN_D_REG, "minD_reg"); } + public static final String MIN_F = PREFIX + "MIN_F" + POSTFIX; + static { + beforeMatchingNameRegex(MIN_F, "MinF"); + } + public static final String MIN_F_REDUCTION_REG = PREFIX + "MIN_F_REDUCTION_REG" + POSTFIX; static { machOnlyNameRegex(MIN_F_REDUCTION_REG, "minF_reduction_reg"); diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java index a3fcdbaa9b0..c1bef52a8b1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java @@ -240,7 +240,7 @@ public class BasicDoubleOpTest extends VectorizationTestRunner { @Test @IR(applyIfCPUFeatureOr = {"asimd", "true", "avx", "true"}, - counts = {IRNode.MAX_VD, ">0"}) + counts = {IRNode.MAX_VD, "0"}) public double[] vectorMax_8322090() { double[] res = new double[SIZE]; for (int i = 0; i < SIZE; i++) {