diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index ca1d5f4102400..1b47a80453a35 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -3712,8 +3712,12 @@ void SuperWord::compute_vector_element_type() { assert(nn->is_Cmp(), "always have Cmp above Bool"); } if (nn->is_Cmp() && nn->in(0) == nullptr) { - nn = nn->in(1); - set_velt_type(n, velt_type(nn)); + assert(in_bb(nn->in(1)) || in_bb(nn->in(2)), "one of the inputs must be in the loop too"); + if (in_bb(nn->in(1))) { + set_velt_type(n, velt_type(nn->in(1))); + } else { + set_velt_type(n, velt_type(nn->in(2))); + } } } #ifndef PRODUCT diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java index 7f94e5a2d1fca..29f6675bb6e43 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 2023, 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 @@ -590,6 +591,32 @@ private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[ } } + // Use some constants in the comparison + @Test + @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float[] d, float[] r, float[] r2) { + for (int i = 0; i < b.length; i++) { + float cc = c[i]; + float dd = d[i]; + r2[i] = cc + dd; + r[i] = (a > b[i]) ? cc : dd; + } + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR, ">0", IRNode.VECTOR_MASK_CMP, ">0", IRNode.VECTOR_BLEND, ">0", IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float[] d, float[] r, float[] r2) { + for (int i = 0; i < a.length; i++) { + float cc = c[i]; + float dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] > b) ? cc : dd; + } + } + + // A case that is currently not supported and is not expected to vectorize @Test @IR(failOn = {IRNode.VECTOR_MASK_CMP, IRNode.VECTOR_BLEND}) private static void testCMoveVDUnsupported() { @@ -723,7 +750,9 @@ private void testCMove_runner() { "testCMoveDGTforI", "testCMoveDGTforL", "testCMoveDGTforF", - "testCMoveDGTforD"}) + "testCMoveDGTforD", + "testCMoveFGTforFCmpCon1", + "testCMoveFGTforFCmpCon2"}) private void testCMove_runner_two() { int[] aI = new int[SIZE]; int[] bI = new int[SIZE]; @@ -842,6 +871,17 @@ private void testCMove_runner_two() { for (int i = 0; i < SIZE; i++) { Asserts.assertEquals(rD[i], cmoveDGTforD(aD[i], bD[i], cD[i], dD[i])); } + + // Use some constants/invariants in the comparison + testCMoveFGTforFCmpCon1(aF[0], bF, cF, dF, rF, rF); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rF[i], cmoveFGTforF(aF[0], bF[i], cF[i], dF[i])); + } + + testCMoveFGTforFCmpCon2(aF, bF[0], cF, dF, rF, rF); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rF[i], cmoveFGTforF(aF[i], bF[0], cF[i], dF[i])); + } } private static void init(int[] a) { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestCmpInvar.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestCmpInvar.java new file mode 100644 index 0000000000000..f3eb1a9e92e37 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestCmpInvar.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2023, 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 8309268 + * @summary Test loop invariant input to Cmp. + * + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.loopopts.superword.TestCmpInvar::test* + * compiler.loopopts.superword.TestCmpInvar + */ +package compiler.loopopts.superword; + +public class TestCmpInvar { + static int N = 400; + static long myInvar; + + static void test1(int limit, float fcon) { + boolean a[] = new boolean[1000]; + for (int i = 0; i < limit; i++) { + a[i] = fcon > i; + } + } + + static void test2(int limit, float fcon) { + boolean a[] = new boolean[1000]; + for (int i = 0; i < limit; i++) { + a[i] = i > fcon; + } + } + + static int test3() { + int[] a = new int[N]; + int acc = 0; + for (int i = 1; i < 63; i++) { + acc += Math.min(myInvar, a[i]--); + } + return acc; + } + + static int test4() { + int[] a = new int[N]; + int acc = 0; + for (int i = 1; i < 63; i++) { + acc += Math.min(a[i]--, myInvar); + } + return acc; + } + + public static void main(String[] strArr) { + for (int i = 0; i < 10_100; i++) { + test1(500, 80.1f); + } + + for (int i = 0; i < 10_100; i++) { + test2(500, 80.1f); + } + + for (int i = 0; i < 10_000; i++) { + test3(); + } + + for (int i = 0; i < 10_000; i++) { + test4(); + } + } +}