From 2cf9f3911fe23b2a061314d9783daef7e511f9b9 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 11 Dec 2023 14:36:16 +0100 Subject: [PATCH 1/3] Backport 7c9868c0b3c9bd3d305e71f91596190813cdccce --- src/hotspot/share/opto/mulnode.cpp | 15 +++ .../integerArithmetic/TestNegMultiply.java | 104 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/integerArithmetic/TestNegMultiply.java diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index cc42318d0cb..775e0f8aa5a 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -63,6 +63,21 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* in2 = in(2); Node* progress = nullptr; // Progress flag + // convert "(-a)*(-b)" into "a*b" + if (in1->is_Sub() && in2->is_Sub()) { + if (phase->type(in1->in(1))->is_zero_type() && + phase->type(in2->in(1))->is_zero_type()) { + set_req(1, in1->in(2)); + set_req(2, in2->in(2)); + PhaseIterGVN* igvn = phase->is_IterGVN(); + if (igvn) { + igvn->_worklist.push(in1); + igvn->_worklist.push(in2); + } + progress = this; + } + } + // convert "max(a,b) * min(a,b)" into "a*b". if ((in(1)->Opcode() == max_opcode() && in(2)->Opcode() == min_opcode()) || (in(1)->Opcode() == min_opcode() && in(2)->Opcode() == max_opcode())) { diff --git a/test/hotspot/jtreg/compiler/integerArithmetic/TestNegMultiply.java b/test/hotspot/jtreg/compiler/integerArithmetic/TestNegMultiply.java new file mode 100644 index 00000000000..a702dd7afa6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/integerArithmetic/TestNegMultiply.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2021, 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 + * @key randomness + * @bug 8273454 + * @summary Test transformation (-a)*(-b) = a*b + * + * @library /test/lib + * + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand="dontinline,TestNegMultiply::test*" TestNegMultiply + * + */ + +import java.util.Random; +import jdk.test.lib.Utils; +import jdk.test.lib.Asserts; + +public class TestNegMultiply { + private static final Random random = Utils.getRandomInstance(); + // Enough cycles to ensure test methods are JIT-ed + private static final int TEST_COUNT = 20_000; + + private static int testInt(int a, int b) { + return (-a) * (-b); + } + private static long testLong(long a, long b) { + return (-a) * (-b); + } + private static float testFloat(float a, float b) { + return (-a) * (-b); + } + private static double testDouble(double a, double b) { + return (-a) * (-b); + } + + private static void runIntTests() { + for (int index = 0; index < TEST_COUNT; index ++) { + int a = random.nextInt(); + int b = random.nextInt(); + int expected = (-a) * (-b); + int res = testInt(a, b); + Asserts.assertEQ(res, expected); + } + } + + private static void runLongTests() { + for (int index = 0; index < TEST_COUNT; index ++) { + long a = random.nextLong(); + long b = random.nextLong(); + long expected = (-a) * (-b); + long res = testLong(a, b); + Asserts.assertEQ(res, expected); + } + } + + private static void runFloatTests() { + for (int index = 0; index < TEST_COUNT; index ++) { + float a = random.nextFloat(); + float b = random.nextFloat(); + float expected = (-a) * (-b); + float res = testFloat(a, b); + Asserts.assertEQ(res, expected); + } + } + + private static void runDoubleTests() { + for (int index = 0; index < TEST_COUNT; index ++) { + double a = random.nextDouble(); + double b = random.nextDouble(); + double expected = (-a) * (-b); + double res = testDouble(a, b); + Asserts.assertEQ(res, expected); + } + } + + public static void main(String[] args) { + runIntTests(); + runLongTests(); + runFloatTests(); + runDoubleTests(); + } +} From 1a7414e93b6de9ac8e9d11f3391a4aee5431fbac Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Mon, 11 Dec 2023 14:41:05 +0100 Subject: [PATCH 2/3] Backport c77ebe88748b0a55f1fc7a5497314a752eab1e2a --- src/hotspot/share/opto/mulnode.cpp | 11 ++- .../integerArithmetic/TestNegAnd.java | 76 +++++++++++++++++++ 2 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/integerArithmetic/TestNegAnd.java diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 775e0f8aa5a..00e7e8f7ada 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -63,8 +63,14 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* in2 = in(2); Node* progress = nullptr; // Progress flag - // convert "(-a)*(-b)" into "a*b" - if (in1->is_Sub() && in2->is_Sub()) { + // This code is used by And nodes too, but some conversions are + // only valid for the actual Mul nodes. + uint op = Opcode(); + bool real_mul = (op == Op_MulI) || (op == Op_MulL) || + (op == Op_MulF) || (op == Op_MulD); + + // Convert "(-a)*(-b)" into "a*b". + if (real_mul && in1->is_Sub() && in2->is_Sub()) { if (phase->type(in1->in(1))->is_zero_type() && phase->type(in2->in(1))->is_zero_type()) { set_req(1, in1->in(2)); @@ -122,7 +128,6 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) { // If the right input is a constant, and the left input is a product of a // constant, flatten the expression tree. - uint op = Opcode(); if( t2->singleton() && // Right input is a constant? op != Op_MulF && // Float & double cannot reassociate op != Op_MulD ) { diff --git a/test/hotspot/jtreg/compiler/integerArithmetic/TestNegAnd.java b/test/hotspot/jtreg/compiler/integerArithmetic/TestNegAnd.java new file mode 100644 index 00000000000..284199169f7 --- /dev/null +++ b/test/hotspot/jtreg/compiler/integerArithmetic/TestNegAnd.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021, 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 + * @key randomness + * @bug 8274060 + * @summary Test broken transformation (-a) & (-b) = a & b does not happen + * + * @library /test/lib + * + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:CompileCommand="dontinline,TestNegAnd::test*" TestNegAnd + * + */ + +import java.util.Random; +import jdk.test.lib.Utils; +import jdk.test.lib.Asserts; + +public class TestNegAnd { + private static final Random random = Utils.getRandomInstance(); + // Enough cycles to ensure test methods are JIT-ed + private static final int TEST_COUNT = 20_000; + + private static int testInt(int a, int b) { + return (-a) & (-b); + } + private static long testLong(long a, long b) { + return (-a) & (-b); + } + + private static void runIntTests() { + for (int index = 0; index < TEST_COUNT; index ++) { + int a = random.nextInt(); + int b = random.nextInt(); + int expected = (-a) & (-b); + int res = testInt(a, b); + Asserts.assertEQ(res, expected); + } + } + + private static void runLongTests() { + for (int index = 0; index < TEST_COUNT; index ++) { + long a = random.nextLong(); + long b = random.nextLong(); + long expected = (-a) & (-b); + long res = testLong(a, b); + Asserts.assertEQ(res, expected); + } + } + + public static void main(String[] args) { + runIntTests(); + runLongTests(); + } +} From 2dab157f1f17d43fd4de1eb93c7999e8ccc9406a Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Wed, 13 Dec 2023 13:48:23 +0100 Subject: [PATCH 3/3] Part of 8274130 --- src/hotspot/share/opto/mulnode.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 00e7e8f7ada..6d35fd8bf7b 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -80,6 +80,8 @@ Node *MulNode::Ideal(PhaseGVN *phase, bool can_reshape) { igvn->_worklist.push(in1); igvn->_worklist.push(in2); } + in1 = in(1); + in2 = in(2); progress = this; } }