From 1cf9335b24639938aa64250d6862d9636f8605f8 Mon Sep 17 00:00:00 2001 From: Denghui Dong Date: Thu, 4 Jan 2024 03:20:06 +0000 Subject: [PATCH 001/112] 8321404: Limit the number of heap dumps triggered by HeapDumpBeforeFullGC/AfterFullGC Reviewed-by: dholmes, cjplummer --- src/hotspot/share/gc/shared/collectedHeap.cpp | 8 +++- src/hotspot/share/runtime/globals.hpp | 11 ++++- .../HeapDump/FullGCHeapDumpLimitTest.java | 42 +++++++++++++++++++ 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 422fef2431889..1b65ee90b5d7a 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -558,9 +558,13 @@ void CollectedHeap::record_whole_heap_examined_timestamp() { void CollectedHeap::full_gc_dump(GCTimer* timer, bool before) { assert(timer != nullptr, "timer is null"); + static uint count = 0; if ((HeapDumpBeforeFullGC && before) || (HeapDumpAfterFullGC && !before)) { - GCTraceTime(Info, gc) tm(before ? "Heap Dump (before full gc)" : "Heap Dump (after full gc)", timer); - HeapDumper::dump_heap(); + if (FullGCHeapDumpLimit == 0 || count < FullGCHeapDumpLimit) { + GCTraceTime(Info, gc) tm(before ? "Heap Dump (before full gc)" : "Heap Dump (after full gc)", timer); + HeapDumper::dump_heap(); + count++; + } } LogTarget(Trace, gc, classhisto) lt; diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index b5ede76434a0b..af1c82b77146b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -546,10 +546,17 @@ const int ObjectAlignmentInBytes = 8; "thrown from JVM") \ \ product(bool, HeapDumpBeforeFullGC, false, MANAGEABLE, \ - "Dump heap to file before any major stop-the-world GC") \ + "Dump heap to file before any major stop-the-world GC " \ + "(also see FullGCHeapDumpLimit)") \ \ product(bool, HeapDumpAfterFullGC, false, MANAGEABLE, \ - "Dump heap to file after any major stop-the-world GC") \ + "Dump heap to file after any major stop-the-world GC " \ + "(also see FullGCHeapDumpLimit)") \ + \ + product(uint, FullGCHeapDumpLimit, 0, MANAGEABLE, \ + "Limit the number of heap dumps triggered by " \ + "HeapDumpBeforeFullGC or HeapDumpAfterFullGC " \ + "(0 means no limit)") \ \ product(bool, HeapDumpOnOutOfMemoryError, false, MANAGEABLE, \ "Dump heap to file when java.lang.OutOfMemoryError is thrown " \ diff --git a/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java b/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java new file mode 100644 index 0000000000000..cf5481ddf2b93 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023, Alibaba Group Holding Limited. 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 + * @summary Test of option -XX:FullGCHeapDumpLimit + * @library /test/lib + * @run main/othervm -XX:+UseSerialGC -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC -XX:HeapDumpPath=test.hprof -XX:FullGCHeapDumpLimit=1 FullGCHeapDumpLimitTest + */ + +import java.io.File; + +import jdk.test.lib.Asserts; + +public class FullGCHeapDumpLimitTest { + + public static void main(String[] args) throws Exception { + System.gc(); + Asserts.assertTrue(new File("test.hprof").exists()); + Asserts.assertFalse(new File("test.hprof.1").exists()); + } +} From 755722ced60a686799c7f419feae61c04ce41f09 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Thu, 4 Jan 2024 05:04:45 +0000 Subject: [PATCH 002/112] 8322214: Return value of XMLInputFactory.getProperty() changed from boolean to String in JDK 22 early access builds Reviewed-by: lancea --- .../xerces/internal/impl/PropertyManager.java | 7 +- .../internal/parsers/AbstractSAXParser.java | 9 +- .../common/dtd/DTDPropertiesTest.java | 132 ++++++++++++++++++ 3 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java index da21fb4a511b6..c8d032109a02e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/PropertyManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -46,7 +46,7 @@ * @author K Venugopal * @author Sunitha Reddy * - * @LastModified: Nov 2023 + * @LastModified: Jan 2024 */ public class PropertyManager { @@ -184,6 +184,9 @@ public boolean containsProperty(String property) { * @return the value of a property */ public Object getProperty(String property) { + if (XMLInputFactory.SUPPORT_DTD.equals(property)) { + return fSecurityManager.is(XMLSecurityManager.Limit.STAX_SUPPORT_DTD); + } /** * Check to see if the property is managed by the security manager * */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java index ff4e047d4ca99..614bd2fdc999a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/AbstractSAXParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -79,7 +79,7 @@ * @author Arnaud Le Hors, IBM * @author Andy Clark, IBM * - * @LastModified: July 2023 + * @LastModified: Jan 2024 */ @SuppressWarnings("deprecation") public abstract class AbstractSAXParser @@ -1831,6 +1831,11 @@ else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) { } */ + // Handle properties managed by XMLSecurityManager + if (featureId.equals(XMLSecurityManager.DISALLOW_DTD)) { + return securityManager.is(XMLSecurityManager.Limit.XERCES_DISALLOW_DTD); + } + return fConfiguration.getFeature(featureId); } catch (XMLConfigurationException e) { diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java new file mode 100644 index 0000000000000..14215004937c3 --- /dev/null +++ b/test/jaxp/javax/xml/jaxp/unittest/common/dtd/DTDPropertiesTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2024, 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 common.dtd; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLInputFactory; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.xml.sax.XMLReader; + +/* + * @test + * @bug 8322214 + * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest + * @run testng common.dtd.DTDPropertiesTest + * @summary Verifies the getProperty function on DTD properties works the same + * as before the property 'jdk.xml.dtd.support' was introduced. + */ +public class DTDPropertiesTest { + // Xerces Property + public static final String DISALLOW_DTD = "http://apache.org/xml/features/disallow-doctype-decl"; + + /* + * DataProvider for verifying Xerces' disallow-DTD feature + * Fields: property name, setting (null indicates not specified), expected + */ + @DataProvider(name = "XercesProperty") + public Object[][] getXercesProperty() throws Exception { + return new Object[][] { + { DISALLOW_DTD, null, false}, + { DISALLOW_DTD, true, true}, + { DISALLOW_DTD, false, false}, + }; + } + + /* + * DataProvider for verifying StAX's supportDTD feature + * Fields: property name, setting (null indicates not specified), expected + */ + @DataProvider(name = "StAXProperty") + public Object[][] getStAXProperty() throws Exception { + return new Object[][] { + { XMLInputFactory.SUPPORT_DTD, null, true}, + { XMLInputFactory.SUPPORT_DTD, true, true}, + { XMLInputFactory.SUPPORT_DTD, false, false}, + }; + } + + /** + * Verifies the disallow DTD feature with SAX. + * + * @param name the name of the property + * @param setting the setting of the property, null means not specified + * @param expected the expected value + * @throws Exception if the test fails + */ + @Test(dataProvider = "XercesProperty") + public void testSAX(String name, Boolean setting, Boolean expected) throws Exception { + SAXParserFactory spf = SAXParserFactory.newDefaultInstance(); + if (setting != null) { + spf.setFeature(name, setting); + } + Assert.assertEquals((Boolean)spf.getFeature(name), expected); + System.out.println(spf.getFeature(name)); + + + SAXParser saxParser = spf.newSAXParser(); + XMLReader reader = saxParser.getXMLReader(); + Assert.assertEquals((Boolean)reader.getFeature(name), expected); + System.out.println(reader.getFeature(name)); + } + + /** + * Verifies the disallow DTD feature with DOM. + * + * @param name the name of the property + * @param setting the setting of the property, null means not specified + * @param expected the expected value + * @throws Exception if the test fails + */ + @Test(dataProvider = "XercesProperty") + public void testDOM(String name, Boolean setting, Boolean expected) throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); + if (setting != null) { + dbf.setFeature(name, setting); + } + Assert.assertEquals((Boolean)dbf.getFeature(name), expected); + System.out.println(dbf.getFeature(name)); + } + + /** + * Verifies the StAX's supportDTD feature. + * + * @param name the name of the property + * @param setting the setting of the property, null means not specified + * @param expected the expected value + * @throws Exception if the test fails + */ + @Test(dataProvider = "StAXProperty") + public void testStAX(String name, Boolean setting, Boolean expected) throws Exception { + XMLInputFactory xif = XMLInputFactory.newInstance(); + if (setting != null) { + xif.setProperty(name, setting); + } + Assert.assertEquals((Boolean)xif.getProperty(name), expected); + System.out.println((Boolean)xif.getProperty(name)); + } +} From 4db7a1c3bb6b56cc7416aa27350406da27fe04a8 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 4 Jan 2024 05:59:52 +0000 Subject: [PATCH 003/112] 8322818: Thread::getStackTrace can fail with InternalError if virtual thread is timed-parked when pinned Reviewed-by: pchilanomate --- .../classes/java/lang/VirtualThread.java | 6 +- .../stress/GetStackTraceALotWhenPinned.java | 75 +++++++++++++++++++ 2 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 13ba543348ed7..36a673fde60cf 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -975,12 +975,12 @@ StackTraceElement[] asyncGetStackTrace() { * Returns null if the thread is mounted or in transition. */ private StackTraceElement[] tryGetStackTrace() { - int initialState = state(); + int initialState = state() & ~SUSPENDED; switch (initialState) { case NEW, STARTED, TERMINATED -> { return new StackTraceElement[0]; // unmounted, empty stack } - case RUNNING, PINNED -> { + case RUNNING, PINNED, TIMED_PINNED -> { return null; // mounted } case PARKED, TIMED_PARKED -> { @@ -992,7 +992,7 @@ private StackTraceElement[] tryGetStackTrace() { case PARKING, TIMED_PARKING, YIELDING -> { return null; // in transition } - default -> throw new InternalError(); + default -> throw new InternalError("" + initialState); } // thread is unmounted, prevent it from continuing diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java new file mode 100644 index 0000000000000..acf6b1c6bd257 --- /dev/null +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java @@ -0,0 +1,75 @@ +/* + * 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 8322818 + * @summary Stress test Thread.getStackTrace on a virtual thread that is pinned + * @requires vm.debug != true + * @run main GetStackTraceALotWhenPinned 100000 + */ + +/* + * @test + * @requires vm.debug == true + * @run main/timeout=300 GetStackTraceALotWhenPinned 10000 + */ + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.LockSupport; + +public class GetStackTraceALotWhenPinned { + + public static void main(String[] args) throws Exception { + var counter = new AtomicInteger(Integer.parseInt(args[0])); + + // Start a virtual thread that loops doing Thread.yield and parking while pinned. + // This loop creates the conditions for the main thread to sample the stack trace + // as it transitions from being unmounted to parking while pinned. + var thread = Thread.startVirtualThread(() -> { + boolean timed = false; + while (counter.decrementAndGet() > 0) { + Thread.yield(); + synchronized (GetStackTraceALotWhenPinned.class) { + if (timed) { + LockSupport.parkNanos(Long.MAX_VALUE); + } else { + LockSupport.park(); + } + } + timed = !timed; + } + }); + + long lastTimestamp = System.currentTimeMillis(); + while (thread.isAlive()) { + thread.getStackTrace(); + LockSupport.unpark(thread); + long currentTime = System.currentTimeMillis(); + if ((currentTime - lastTimestamp) > 500) { + System.out.println(counter.get() + " remaining ..."); + lastTimestamp = currentTime; + } + } + } +} From 1369c545ac51d7b5ff623d486e28c939869fecb8 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 4 Jan 2024 08:06:14 +0000 Subject: [PATCH 004/112] 8322782: Clean up usages of unnecessary fully qualified class name "java.util.Arrays" Reviewed-by: alanb, aivanov --- src/demo/share/jfc/J2Ddemo/java2d/Intro.java | 4 ++-- .../share/classes/com/sun/crypto/provider/DESKey.java | 8 ++++---- .../classes/com/sun/crypto/provider/DESedeKey.java | 10 +++++----- .../share/classes/com/sun/crypto/provider/PBEKey.java | 4 ++-- .../share/classes/java/lang/invoke/Invokers.java | 6 +++--- src/java.base/share/classes/java/math/BigInteger.java | 10 +++++----- .../share/classes/sun/net/ftp/impl/FtpClient.java | 4 ++-- .../share/classes/java/awt/image/IndexColorModel.java | 4 ++-- .../share/classes/sun/management/ThreadImpl.java | 8 ++++---- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/demo/share/jfc/J2Ddemo/java2d/Intro.java b/src/demo/share/jfc/J2Ddemo/java2d/Intro.java index 046768e3a6a4b..a4fd2e5b75374 100644 --- a/src/demo/share/jfc/J2Ddemo/java2d/Intro.java +++ b/src/demo/share/jfc/J2Ddemo/java2d/Intro.java @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -1716,7 +1716,7 @@ public Contributors(int beg, int end, Surface surf) { this.beginning = beg; this.ending = end; fm = surf.getMetrics(font); - java.util.Arrays.sort(members); + Arrays.sort(members); cast.add("CONTRIBUTORS"); cast.add(" "); cast.addAll(Arrays.asList(members)); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java index 17f82b2eacc34..ff7e1f4ddd57d 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DESKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -85,7 +85,7 @@ final class DESKey implements SecretKey { // Use the cleaner to zero the key when no longer referenced final byte[] k = this.key; CleanerFactory.cleaner().register(this, - () -> java.util.Arrays.fill(k, (byte)0x00)); + () -> Arrays.fill(k, (byte)0x00)); } public byte[] getEncoded() { @@ -136,7 +136,7 @@ public boolean equals(Object obj) { byte[] thatKey = that.getEncoded(); boolean ret = MessageDigest.isEqual(this.key, thatKey); - java.util.Arrays.fill(thatKey, (byte)0x00); + Arrays.fill(thatKey, (byte)0x00); return ret; } finally { // prevent this from being cleaned for the above block @@ -168,7 +168,7 @@ private void readObject(java.io.ObjectInputStream s) // Use the cleaner to zero the key when no longer referenced final byte[] k = this.key; CleanerFactory.cleaner().register(this, - () -> java.util.Arrays.fill(k, (byte)0x00)); + () -> Arrays.fill(k, (byte)0x00)); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java index f5c3d8384df73..53f72499a33d3 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -87,7 +87,7 @@ final class DESedeKey implements SecretKey { // Use the cleaner to zero the key when no longer referenced final byte[] k = this.key; CleanerFactory.cleaner().register(this, - () -> java.util.Arrays.fill(k, (byte)0x00)); + () -> Arrays.fill(k, (byte)0x00)); } public byte[] getEncoded() { @@ -137,7 +137,7 @@ public boolean equals(Object obj) { byte[] thatKey = that.getEncoded(); boolean ret = MessageDigest.isEqual(this.key, thatKey); - java.util.Arrays.fill(thatKey, (byte)0x00); + Arrays.fill(thatKey, (byte)0x00); return ret; } finally { // prevent this from being cleaned for the above block @@ -162,7 +162,7 @@ private void readObject(java.io.ObjectInputStream s) } byte[] temp = key; this.key = temp.clone(); - java.util.Arrays.fill(temp, (byte)0x00); + Arrays.fill(temp, (byte)0x00); DESKeyGenerator.setParityBit(key, 0); DESKeyGenerator.setParityBit(key, 8); @@ -171,7 +171,7 @@ private void readObject(java.io.ObjectInputStream s) // Use the cleaner to zero the key when no longer referenced final byte[] k = this.key; CleanerFactory.cleaner().register(this, - () -> java.util.Arrays.fill(k, (byte)0x00)); + () -> Arrays.fill(k, (byte)0x00)); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java index 480a0810425fc..21dc463572ee2 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java @@ -84,7 +84,7 @@ final class PBEKey implements SecretKey { // Use the cleaner to zero the key when no longer referenced final byte[] k = this.key; cleanable = CleanerFactory.cleaner().register(this, - () -> java.util.Arrays.fill(k, (byte)0x00)); + () -> Arrays.fill(k, (byte)0x00)); } public byte[] getEncoded() { @@ -196,7 +196,7 @@ private void readObject(java.io.ObjectInputStream s) // Use cleaner to zero the key when no longer referenced final byte[] k = this.key; cleanable = CleanerFactory.cleaner().register(this, - () -> java.util.Arrays.fill(k, (byte)0x00)); + () -> Arrays.fill(k, (byte)0x00)); } diff --git a/src/java.base/share/classes/java/lang/invoke/Invokers.java b/src/java.base/share/classes/java/lang/invoke/Invokers.java index f14ddc70b4062..6c383dd3f2ca3 100644 --- a/src/java.base/share/classes/java/lang/invoke/Invokers.java +++ b/src/java.base/share/classes/java/lang/invoke/Invokers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -190,7 +190,7 @@ static MemberName invokeBasicMethod(MethodType basicType) { private boolean checkInvoker(MethodHandle invoker) { assert(targetType.invokerType().equals(invoker.type())) - : java.util.Arrays.asList(targetType, targetType.invokerType(), invoker); + : Arrays.asList(targetType, targetType.invokerType(), invoker); assert(invoker.internalMemberName() == null || invoker.internalMemberName().getMethodType().equals(targetType)); assert(!invoker.isVarargsCollector()); @@ -200,7 +200,7 @@ private boolean checkInvoker(MethodHandle invoker) { private boolean checkVarHandleInvoker(MethodHandle invoker) { MethodType invokerType = targetType.insertParameterTypes(0, VarHandle.class); assert(invokerType.equals(invoker.type())) - : java.util.Arrays.asList(targetType, invokerType, invoker); + : Arrays.asList(targetType, invokerType, invoker); assert(invoker.internalMemberName() == null || invoker.internalMemberName().getMethodType().equals(targetType)); assert(!invoker.isVarargsCollector()); diff --git a/src/java.base/share/classes/java/math/BigInteger.java b/src/java.base/share/classes/java/math/BigInteger.java index 43c401dd13677..98f55ef3c8c0f 100644 --- a/src/java.base/share/classes/java/math/BigInteger.java +++ b/src/java.base/share/classes/java/math/BigInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, 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 @@ -1774,7 +1774,7 @@ private static BigInteger multiplyByInt(int[] x, int y, int sign) { carry = product >>> 32; } if (carry == 0L) { - rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length); + rmag = Arrays.copyOfRange(rmag, 1, rmag.length); } else { rmag[rstart] = (int)carry; } @@ -1819,7 +1819,7 @@ BigInteger multiply(long v) { rmag[0] = (int)carry; } if (carry == 0L) - rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length); + rmag = Arrays.copyOfRange(rmag, 1, rmag.length); return new BigInteger(rmag, rsign); } @@ -4593,7 +4593,7 @@ private static int[] stripLeadingZeroInts(int[] val) { // Find first nonzero byte for (keep = 0; keep < vlen && val[keep] == 0; keep++) ; - return java.util.Arrays.copyOfRange(val, keep, vlen); + return Arrays.copyOfRange(val, keep, vlen); } /** @@ -4607,7 +4607,7 @@ private static int[] trustedStripLeadingZeroInts(int[] val) { // Find first nonzero byte for (keep = 0; keep < vlen && val[keep] == 0; keep++) ; - return keep == 0 ? val : java.util.Arrays.copyOfRange(val, keep, vlen); + return keep == 0 ? val : Arrays.copyOfRange(val, keep, vlen); } private static int[] stripLeadingZeroBytes(byte[] a, int from, int len) { diff --git a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java index f8518fff4c4d5..8b6dd9c5ec7b1 100644 --- a/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/src/java.base/share/classes/sun/net/ftp/impl/FtpClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -204,7 +204,7 @@ private static boolean isASCIISuperset(String encoding) throws Exception { 47, 63, 58, 64, 38, 61, 43, 36, 44}; byte[] b = chkS.getBytes(encoding); - return java.util.Arrays.equals(b, chkB); + return Arrays.equals(b, chkB); } private class DefaultParser implements FtpDirParser { diff --git a/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java b/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java index 246eb1abbdd65..3547862615aea 100644 --- a/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java +++ b/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2024, 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 @@ -592,7 +592,7 @@ private int calcRealMapSize(int bits, int size) { private BigInteger getAllValid() { int numbytes = (map_size+7)/8; byte[] valid = new byte[numbytes]; - java.util.Arrays.fill(valid, (byte)0xff); + Arrays.fill(valid, (byte)0xff); valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); return new BigInteger(1, valid); diff --git a/src/java.management/share/classes/sun/management/ThreadImpl.java b/src/java.management/share/classes/sun/management/ThreadImpl.java index 7eb67e99bc8be..1f37b2da567fd 100644 --- a/src/java.management/share/classes/sun/management/ThreadImpl.java +++ b/src/java.management/share/classes/sun/management/ThreadImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -267,7 +267,7 @@ protected long[] getThreadCpuTime(long[] ids) { int length = ids.length; long[] times = new long[length]; - java.util.Arrays.fill(times, -1); + Arrays.fill(times, -1); if (verified) { if (length == 1) { @@ -306,7 +306,7 @@ protected long[] getThreadUserTime(long[] ids) { int length = ids.length; long[] times = new long[length]; - java.util.Arrays.fill(times, -1); + Arrays.fill(times, -1); if (verified) { if (length == 1) { @@ -390,7 +390,7 @@ protected long[] getThreadAllocatedBytes(long[] ids) { boolean verified = verifyThreadAllocatedMemory(ids); long[] sizes = new long[ids.length]; - java.util.Arrays.fill(sizes, -1); + Arrays.fill(sizes, -1); if (verified) { getThreadAllocatedMemory1(ids, sizes); From 730663649fdaf3a0e268ee27f41bd8673df2bbfd Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 4 Jan 2024 08:21:57 +0000 Subject: [PATCH 005/112] 8322945: Problemlist runtime/CompressedOops/CompressedClassPointers.java on AIX Reviewed-by: mdoerr --- test/hotspot/jtreg/ProblemList.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 8d8d760caa29d..754cf68ba591f 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2024, 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 @@ -107,6 +107,7 @@ runtime/os/TestTracePageSizes.java#G1 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Parallel 8267460 linux-aarch64 runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 +runtime/CompressedOops/CompressedClassPointers.java 8322943 aix-ppc64 runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le From bbe0079d984901d2bb483d48666c7818bda7a21f Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 4 Jan 2024 08:31:50 +0000 Subject: [PATCH 006/112] 8322298: Obsolete unused AdaptiveSizePolicyCollectionCostMargin Reviewed-by: tschatzl, sjohanss, kbarrett, gli --- src/hotspot/share/gc/shared/gc_globals.hpp | 5 ----- src/hotspot/share/runtime/arguments.cpp | 1 + 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index e2b30bc615e13..ae8674c84a9d0 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -408,11 +408,6 @@ "Allowed collection cost difference between generations") \ range(0, 100) \ \ - product(uint, AdaptiveSizePolicyCollectionCostMargin, 50, \ - "If collection costs are within margin, reduce both by full " \ - "delta") \ - range(0, 100) \ - \ product(uint, YoungGenerationSizeIncrement, 20, \ "Adaptive size percentage change in young generation") \ range(0, 100) \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index df466acdcfa31..95aa54f775fd0 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -525,6 +525,7 @@ static SpecialFlag const special_jvm_flags[] = { { "RefDiscoveryPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() }, { "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() }, + { "AdaptiveSizePolicyCollectionCostMargin", JDK_Version::undefined(), JDK_Version::jdk(23), JDK_Version::jdk(24) }, #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif From 83564ea5f382049722b8c9ca8dd1aa3313681d80 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 4 Jan 2024 08:32:00 +0000 Subject: [PATCH 007/112] 8322888: Parallel: Remove unused variables in PSPromotionManager Reviewed-by: kbarrett --- src/hotspot/share/gc/parallel/psPromotionManager.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 7610a6e13d77b..149acc1a4297f 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -173,13 +173,9 @@ void PSPromotionManager::reset_stats() { #endif // TASKQUEUE_STATS PSPromotionManager::PSPromotionManager() { - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); - // We set the old lab's start array. _old_lab.set_start_array(old_gen()->start_array()); - uint queue_size = claimed_stack_depth()->max_elems(); - if (ParallelGCThreads == 1) { _target_stack_size = 0; } else { From dd517c64047705d706b095d15d9fd4e0703ab39b Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 4 Jan 2024 08:39:50 +0000 Subject: [PATCH 008/112] 8237842: Separate definitions for default cache line and padding sizes Reviewed-by: stefank, kvn, stuefe, tschatzl --- .../cpu/aarch64/globalDefinitions_aarch64.hpp | 4 +++ src/hotspot/cpu/arm/globalDefinitions_arm.hpp | 4 +++ src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp | 5 ++- .../cpu/riscv/globalDefinitions_riscv.hpp | 4 +++ .../cpu/s390/globalDefinitions_s390.hpp | 3 ++ src/hotspot/cpu/x86/globalDefinitions_x86.hpp | 35 +++++++------------ .../cpu/zero/globalDefinitions_zero.hpp | 4 +++ src/hotspot/share/gc/g1/g1ConcurrentMark.hpp | 10 +++--- src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp | 10 +++--- src/hotspot/share/gc/g1/g1MonotonicArena.hpp | 2 +- .../share/gc/g1/g1ParScanThreadState.cpp | 2 +- .../share/gc/g1/g1RedirtyCardsQueue.hpp | 6 ++-- .../share/gc/shared/freeListAllocator.hpp | 4 +-- src/hotspot/share/gc/shared/satbMarkQueue.hpp | 4 +-- .../share/gc/shared/taskTerminator.hpp | 4 +-- src/hotspot/share/gc/shared/taskqueue.hpp | 10 +++--- .../share/jfr/utilities/jfrVersionSystem.hpp | 4 +-- src/hotspot/share/memory/padded.hpp | 12 +++---- src/hotspot/share/runtime/mutex.hpp | 4 +-- src/hotspot/share/runtime/objectMonitor.hpp | 4 --- src/hotspot/share/utilities/globalCounter.hpp | 4 +-- .../share/utilities/globalDefinitions.hpp | 7 +++- .../share/utilities/nonblockingQueue.hpp | 2 +- .../share/utilities/waitBarrier_generic.hpp | 6 ++-- .../gc/shared/test_bufferNodeAllocator.cpp | 2 +- 25 files changed, 84 insertions(+), 72 deletions(-) diff --git a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp index 2293d70c8dacd..63f6c9491c8de 100644 --- a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp @@ -42,8 +42,12 @@ const bool CCallingConventionRequiresIntsAsLongs = false; // and Operational Models for ARMv8" #define CPU_MULTI_COPY_ATOMIC +// The expected size in bytes of a cache line. #define DEFAULT_CACHE_LINE_SIZE 64 +// The default padding size for data structures to avoid false sharing. +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE + // According to the ARMv8 ARM, "Concurrent modification and execution // of instructions can lead to the resulting instruction performing // any behavior that can be achieved by executing any sequence of diff --git a/src/hotspot/cpu/arm/globalDefinitions_arm.hpp b/src/hotspot/cpu/arm/globalDefinitions_arm.hpp index 2041cf9e17ead..5b68dbc9dbd8b 100644 --- a/src/hotspot/cpu/arm/globalDefinitions_arm.hpp +++ b/src/hotspot/cpu/arm/globalDefinitions_arm.hpp @@ -49,8 +49,12 @@ const bool HaveVFP = true; // arm32 is not specified as multi-copy-atomic // So we must not #define CPU_MULTI_COPY_ATOMIC +// The expected size in bytes of a cache line. #define DEFAULT_CACHE_LINE_SIZE 64 +// The default padding size for data structures to avoid false sharing. +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE + #define STUBROUTINES_MD_HPP "stubRoutines_arm.hpp" #define INTERP_MASM_MD_HPP "interp_masm_arm.hpp" #define TEMPLATETABLE_MD_HPP "templateTable_arm.hpp" diff --git a/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp b/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp index bced453d784cf..30670d053fa6e 100644 --- a/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp +++ b/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp @@ -48,9 +48,12 @@ const bool CCallingConventionRequiresIntsAsLongs = true; // PPC64 is not specified as multi-copy-atomic // So we must not #define CPU_MULTI_COPY_ATOMIC -// The expected size in bytes of a cache line, used to pad data structures. +// The expected size in bytes of a cache line. #define DEFAULT_CACHE_LINE_SIZE 128 +// The default padding size for data structures to avoid false sharing. +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE + #define SUPPORT_RESERVED_STACK_AREA // If UseSIGTRAP is active, we only use the poll bit and no polling page. diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp index f40ffbeefa748..e368bbdc9141f 100644 --- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp +++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp @@ -50,6 +50,10 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define USE_POINTERS_TO_REGISTER_IMPL_ARRAY +// The expected size in bytes of a cache line. #define DEFAULT_CACHE_LINE_SIZE 64 +// The default padding size for data structures to avoid false sharing. +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE + #endif // CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP diff --git a/src/hotspot/cpu/s390/globalDefinitions_s390.hpp b/src/hotspot/cpu/s390/globalDefinitions_s390.hpp index 39baf5bf0478e..236d4c5bf69f1 100644 --- a/src/hotspot/cpu/s390/globalDefinitions_s390.hpp +++ b/src/hotspot/cpu/s390/globalDefinitions_s390.hpp @@ -48,6 +48,9 @@ const bool CCallingConventionRequiresIntsAsLongs = true; // The expected size in bytes of a cache line, used to pad data structures. #define DEFAULT_CACHE_LINE_SIZE 256 +// The default padding size for data structures to avoid false sharing. +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE + #define SUPPORT_RESERVED_STACK_AREA #endif // CPU_S390_GLOBALDEFINITIONS_S390_HPP diff --git a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp index 7eff43471b5dd..2e82453b38002 100644 --- a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp +++ b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp @@ -38,29 +38,18 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define CPU_MULTI_COPY_ATOMIC -// The expected size in bytes of a cache line, used to pad data structures. -#if COMPILER1_AND_COMPILER2 - #ifdef _LP64 - // tiered, 64-bit, large machine - #define DEFAULT_CACHE_LINE_SIZE 128 - #define OM_CACHE_LINE_SIZE 64 - #else - // tiered, 32-bit, medium machine - #define DEFAULT_CACHE_LINE_SIZE 64 - #endif -#elif defined(COMPILER1) - // pure C1, 32-bit, small machine - // i486 was the last Intel chip with 16-byte cache line size - #define DEFAULT_CACHE_LINE_SIZE 32 -#elif defined(COMPILER2) - #ifdef _LP64 - // pure C2, 64-bit, large machine - #define DEFAULT_CACHE_LINE_SIZE 128 - #define OM_CACHE_LINE_SIZE 64 - #else - // pure C2, 32-bit, medium machine - #define DEFAULT_CACHE_LINE_SIZE 64 - #endif +// The expected size in bytes of a cache line. +#define DEFAULT_CACHE_LINE_SIZE 64 + +// The default padding size for data structures to avoid false sharing. +#ifdef _LP64 +// The common wisdom is that adjacent cache line prefetchers on some hardware +// may pull two cache lines on access, so we have to pessimistically assume twice +// the cache line size for padding. TODO: Check if this is still true for modern +// hardware. If not, DEFAULT_CACHE_LINE_SIZE might as well suffice. +#define DEFAULT_PADDING_SIZE (DEFAULT_CACHE_LINE_SIZE*2) +#else +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE #endif #if defined(COMPILER2) diff --git a/src/hotspot/cpu/zero/globalDefinitions_zero.hpp b/src/hotspot/cpu/zero/globalDefinitions_zero.hpp index 810f7de3cb3f6..0f78b3eeefba2 100644 --- a/src/hotspot/cpu/zero/globalDefinitions_zero.hpp +++ b/src/hotspot/cpu/zero/globalDefinitions_zero.hpp @@ -30,8 +30,12 @@ #define SUPPORTS_NATIVE_CX8 #endif +// The expected size in bytes of a cache line. #define DEFAULT_CACHE_LINE_SIZE 64 +// The default padding size for data structures to avoid false sharing. +#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE + #define SUPPORT_MONITOR_COUNT #include diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp index efc6584bda048..a4315ec5f6c48 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp @@ -167,9 +167,9 @@ class G1CMMarkStack { size_t _num_buckets; bool _should_grow; TaskQueueEntryChunk* volatile* _buckets; - char _pad0[DEFAULT_CACHE_LINE_SIZE]; + char _pad0[DEFAULT_PADDING_SIZE]; volatile size_t _size; - char _pad4[DEFAULT_CACHE_LINE_SIZE - sizeof(size_t)]; + char _pad4[DEFAULT_PADDING_SIZE - sizeof(size_t)]; size_t bucket_size(size_t bucket) { return (bucket == 0) ? @@ -232,12 +232,12 @@ class G1CMMarkStack { ChunkAllocator _chunk_allocator; - char _pad0[DEFAULT_CACHE_LINE_SIZE]; + char _pad0[DEFAULT_PADDING_SIZE]; TaskQueueEntryChunk* volatile _free_list; // Linked list of free chunks that can be allocated by users. - char _pad1[DEFAULT_CACHE_LINE_SIZE - sizeof(TaskQueueEntryChunk*)]; + char _pad1[DEFAULT_PADDING_SIZE - sizeof(TaskQueueEntryChunk*)]; TaskQueueEntryChunk* volatile _chunk_list; // List of chunks currently containing data. volatile size_t _chunks_in_chunk_list; - char _pad2[DEFAULT_CACHE_LINE_SIZE - sizeof(TaskQueueEntryChunk*) - sizeof(size_t)]; + char _pad2[DEFAULT_PADDING_SIZE - sizeof(TaskQueueEntryChunk*) - sizeof(size_t)]; // Atomically add the given chunk to the list. void add_chunk_to_list(TaskQueueEntryChunk* volatile* list, TaskQueueEntryChunk* elem); diff --git a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp index bf25e3828d11f..1dd3a9afacee8 100644 --- a/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp +++ b/src/hotspot/share/gc/g1/g1DirtyCardQueue.hpp @@ -135,7 +135,7 @@ class G1DirtyCardQueueSet: public PtrQueueSet { // and install the next list, and meanwhile there can be a thread dealing // with the previous list. PausedList* volatile _plist; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(PausedList*)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(PausedList*)); NONCOPYABLE(PausedBuffers); @@ -157,19 +157,19 @@ class G1DirtyCardQueueSet: public PtrQueueSet { HeadTail take_all(); }; - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); // Upper bound on the number of cards in the completed and paused buffers. volatile size_t _num_cards; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(size_t)); // If the queue contains more cards than configured here, the // mutator must start doing some of the concurrent refinement work. volatile size_t _mutator_refinement_threshold; - DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t)); + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_PADDING_SIZE, sizeof(size_t)); // Buffers ready for refinement. // NonblockingQueue has inner padding of one cache line. NonblockingQueue _completed; // Add a trailer padding after NonblockingQueue. - DEFINE_PAD_MINUS_SIZE(3, DEFAULT_CACHE_LINE_SIZE, sizeof(BufferNode*)); + DEFINE_PAD_MINUS_SIZE(3, DEFAULT_PADDING_SIZE, sizeof(BufferNode*)); // Buffers for which refinement is temporarily paused. // PausedBuffers has inner padding, including trailer. PausedBuffers _paused; diff --git a/src/hotspot/share/gc/g1/g1MonotonicArena.hpp b/src/hotspot/share/gc/g1/g1MonotonicArena.hpp index 8a6bb88e008ca..586766a8c8f97 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArena.hpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArena.hpp @@ -125,7 +125,7 @@ class G1MonotonicArena::Segment { char* _bottom; // Actual data. // Do not add class member variables beyond this point - static size_t header_size() { return align_up(sizeof(Segment), DEFAULT_CACHE_LINE_SIZE); } + static size_t header_size() { return align_up(sizeof(Segment), DEFAULT_PADDING_SIZE); } static size_t payload_size(uint slot_size, uint num_slots) { // The cast (size_t) is required to guard against overflow wrap around. diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp index 8d7ee0b1dfdd0..92aec50def6f2 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp @@ -95,7 +95,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, // entries, since entry 0 keeps track of surviving bytes for non-young regions. // We also add a few elements at the beginning and at the end in // an attempt to eliminate cache contention - const size_t padding_elem_num = (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t)); + const size_t padding_elem_num = (DEFAULT_PADDING_SIZE / sizeof(size_t)); size_t array_length = padding_elem_num + _surviving_words_length + padding_elem_num; _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC); diff --git a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp index f270e31f77266..970cce1623ec6 100644 --- a/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp +++ b/src/hotspot/share/gc/g1/g1RedirtyCardsQueue.hpp @@ -66,11 +66,11 @@ class G1RedirtyCardsLocalQueueSet : private PtrQueueSet { // collected (and processed) buffers reverts back to collecting, allowing // the set to be reused for another round of redirtying. class G1RedirtyCardsQueueSet : public PtrQueueSet { - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, 0); BufferNode::Stack _list; - DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(size_t)); + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_PADDING_SIZE, sizeof(size_t)); volatile size_t _entry_count; - DEFINE_PAD_MINUS_SIZE(3, DEFAULT_CACHE_LINE_SIZE, sizeof(BufferNode*)); + DEFINE_PAD_MINUS_SIZE(3, DEFAULT_PADDING_SIZE, sizeof(BufferNode*)); BufferNode* _tail; DEBUG_ONLY(mutable bool _collecting;) diff --git a/src/hotspot/share/gc/shared/freeListAllocator.hpp b/src/hotspot/share/gc/shared/freeListAllocator.hpp index d8ab4c4e8bc1b..74b896963a736 100644 --- a/src/hotspot/share/gc/shared/freeListAllocator.hpp +++ b/src/hotspot/share/gc/shared/freeListAllocator.hpp @@ -109,10 +109,10 @@ class FreeListAllocator { typedef LockFreeStack Stack; FreeListConfig* _config; - char _name[DEFAULT_CACHE_LINE_SIZE - sizeof(FreeListConfig*)]; // Use name as padding. + char _name[DEFAULT_PADDING_SIZE - sizeof(FreeListConfig*)]; // Use name as padding. #define DECLARE_PADDED_MEMBER(Id, Type, Name) \ - Type Name; DEFINE_PAD_MINUS_SIZE(Id, DEFAULT_CACHE_LINE_SIZE, sizeof(Type)) + Type Name; DEFINE_PAD_MINUS_SIZE(Id, DEFAULT_PADDING_SIZE, sizeof(Type)) DECLARE_PADDED_MEMBER(1, volatile size_t, _free_count); DECLARE_PADDED_MEMBER(2, Stack, _free_list); DECLARE_PADDED_MEMBER(3, volatile bool, _transfer_lock); diff --git a/src/hotspot/share/gc/shared/satbMarkQueue.hpp b/src/hotspot/share/gc/shared/satbMarkQueue.hpp index d92523d7e4f78..78fe203329623 100644 --- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp +++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp @@ -85,7 +85,7 @@ class SATBMarkQueue: public PtrQueue { class SATBMarkQueueSet: public PtrQueueSet { - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, 0); PaddedEnd _list; volatile size_t _count_and_process_flag; // These are rarely (if ever) changed, so same cache line as count. @@ -93,7 +93,7 @@ class SATBMarkQueueSet: public PtrQueueSet { size_t _buffer_enqueue_threshold; // SATB is only active during marking. Enqueuing is only done when active. bool _all_active; - DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 4 * sizeof(size_t)); + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_PADDING_SIZE, 4 * sizeof(size_t)); BufferNode* get_completed_buffer(); void abandon_completed_buffers(); diff --git a/src/hotspot/share/gc/shared/taskTerminator.hpp b/src/hotspot/share/gc/shared/taskTerminator.hpp index aac4e065a5ceb..540d91c88bb48 100644 --- a/src/hotspot/share/gc/shared/taskTerminator.hpp +++ b/src/hotspot/share/gc/shared/taskTerminator.hpp @@ -72,9 +72,9 @@ class TaskTerminator : public CHeapObj { uint _n_threads; TaskQueueSetSuper* _queue_set; - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); volatile uint _offered_termination; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile uint)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(volatile uint)); Monitor _blocker; Thread* _spin_master; diff --git a/src/hotspot/share/gc/shared/taskqueue.hpp b/src/hotspot/share/gc/shared/taskqueue.hpp index a5e3dfdf8079d..2e21ba33b0bf7 100644 --- a/src/hotspot/share/gc/shared/taskqueue.hpp +++ b/src/hotspot/share/gc/shared/taskqueue.hpp @@ -233,11 +233,11 @@ class TaskQueueSuper: public CHeapObj { } private: - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); // Index of the first free element after the last one pushed (mod N). volatile uint _bottom; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(uint)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(uint)); // top() is the index of the oldest pushed element (mod N), and tag() // is the associated epoch, to distinguish different modifications of @@ -245,7 +245,7 @@ class TaskQueueSuper: public CHeapObj { // (_bottom - top()) mod N == N-1; the latter indicates underflow // during concurrent pop_local/pop_global. volatile Age _age; - DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(Age)); + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_PADDING_SIZE, sizeof(Age)); NONCOPYABLE(TaskQueueSuper); @@ -396,7 +396,7 @@ class GenericTaskQueue: public TaskQueueSuper { // Element array. E* _elems; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(E*)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(E*)); // Queue owner local variables. Not to be accessed by other threads. static const uint InvalidQueueId = uint(-1); @@ -404,7 +404,7 @@ class GenericTaskQueue: public TaskQueueSuper { int _seed; // Current random seed used for selecting a random queue during stealing. - DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, sizeof(uint) + sizeof(int)); + DEFINE_PAD_MINUS_SIZE(2, DEFAULT_PADDING_SIZE, sizeof(uint) + sizeof(int)); public: int next_random_queue_id(); diff --git a/src/hotspot/share/jfr/utilities/jfrVersionSystem.hpp b/src/hotspot/share/jfr/utilities/jfrVersionSystem.hpp index 5005b5b8f3f8d..39c40fd714779 100644 --- a/src/hotspot/share/jfr/utilities/jfrVersionSystem.hpp +++ b/src/hotspot/share/jfr/utilities/jfrVersionSystem.hpp @@ -105,9 +105,9 @@ class JfrVersionSystem : public JfrCHeapObj { NodePtr synchronize_with(Type version, NodePtr last) const; DEBUG_ONLY(void assert_state(const Node* node) const;) struct PaddedTip { - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); volatile Type _value; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile Type)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(volatile Type)); }; PaddedTip _tip; NodePtr _head; diff --git a/src/hotspot/share/memory/padded.hpp b/src/hotspot/share/memory/padded.hpp index 1811810c19e42..0597dbd9f3c20 100644 --- a/src/hotspot/share/memory/padded.hpp +++ b/src/hotspot/share/memory/padded.hpp @@ -40,14 +40,14 @@ // effective only when applied to derived-most (leaf) classes. // When no args are passed to the base ctor. -template +template class Padded : public T { private: char _pad_buf_[PADDING_SIZE(T, alignment)]; }; // When either 0 or 1 args may be passed to the base ctor. -template +template class Padded01 : public T { public: Padded01(): T() { } @@ -75,7 +75,7 @@ class PaddedEndImpl : public T { // minimal amount of padding needed to make the size of the objects be aligned. // This will help reducing false sharing, // if the start address is a multiple of alignment. -template +template class PaddedEnd : public PaddedEndImpl { // C++ doesn't allow zero-length arrays. The padding is put in a // super class that is specialized for the pad_size == 0 case. @@ -89,7 +89,7 @@ class PaddedEnd : public PaddedEndImpl { // Helper class to create an array of PaddedEnd objects. All elements will // start at a multiple of alignment and the size will be aligned to alignment. -template +template class PaddedArray { public: // Creates an aligned padded array. @@ -100,7 +100,7 @@ class PaddedArray { // Helper class to create an array of references to arrays of primitive types // Both the array of references and the data arrays are aligned to the given // alignment. The allocated memory is zero-filled. -template +template class Padded2DArray { public: // Creates an aligned padded 2D array. @@ -112,7 +112,7 @@ class Padded2DArray { // Helper class to create an array of T objects. The array as a whole will // start at a multiple of alignment and its size will be aligned to alignment. -template +template class PaddedPrimitiveArray { public: static T* create_unfreeable(size_t length); diff --git a/src/hotspot/share/runtime/mutex.hpp b/src/hotspot/share/runtime/mutex.hpp index 3f38bcd5ed551..10671d651b100 100644 --- a/src/hotspot/share/runtime/mutex.hpp +++ b/src/hotspot/share/runtime/mutex.hpp @@ -221,7 +221,7 @@ class Monitor : public Mutex { class PaddedMutex : public Mutex { enum { - CACHE_LINE_PADDING = (int)DEFAULT_CACHE_LINE_SIZE - (int)sizeof(Mutex), + CACHE_LINE_PADDING = (int)DEFAULT_PADDING_SIZE - (int)sizeof(Mutex), PADDING_LEN = CACHE_LINE_PADDING > 0 ? CACHE_LINE_PADDING : 1 }; char _padding[PADDING_LEN]; @@ -232,7 +232,7 @@ class PaddedMutex : public Mutex { class PaddedMonitor : public Monitor { enum { - CACHE_LINE_PADDING = (int)DEFAULT_CACHE_LINE_SIZE - (int)sizeof(Monitor), + CACHE_LINE_PADDING = (int)DEFAULT_PADDING_SIZE - (int)sizeof(Monitor), PADDING_LEN = CACHE_LINE_PADDING > 0 ? CACHE_LINE_PADDING : 1 }; char _padding[PADDING_LEN]; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index fc15e20309f77..ab48bd19b5e43 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -121,11 +121,7 @@ class ObjectWaiter : public StackObj { // intptr_t. There's no reason to use a 64-bit type for this field // in a 64-bit JVM. -#ifndef OM_CACHE_LINE_SIZE -// Use DEFAULT_CACHE_LINE_SIZE if not already specified for -// the current build platform. #define OM_CACHE_LINE_SIZE DEFAULT_CACHE_LINE_SIZE -#endif class ObjectMonitor : public CHeapObj { friend class ObjectSynchronizer; diff --git a/src/hotspot/share/utilities/globalCounter.hpp b/src/hotspot/share/utilities/globalCounter.hpp index 7e971f33ae3e5..b336ed4a1dac5 100644 --- a/src/hotspot/share/utilities/globalCounter.hpp +++ b/src/hotspot/share/utilities/globalCounter.hpp @@ -46,9 +46,9 @@ class GlobalCounter : public AllStatic { // Since do not know what we will end up next to in BSS, we make sure the // counter is on a separate cacheline. struct PaddedCounter { - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); volatile uintx _counter; - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(volatile uintx)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(volatile uintx)); }; // The global counter diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index a6bf8a3e7d3ca..08eb25828703f 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -602,11 +602,16 @@ const bool support_IRIW_for_not_multiple_copy_atomic_cpu = false; const bool support_IRIW_for_not_multiple_copy_atomic_cpu = PPC64_ONLY(true) NOT_PPC64(false); #endif -// The expected size in bytes of a cache line, used to pad data structures. +// The expected size in bytes of a cache line. #ifndef DEFAULT_CACHE_LINE_SIZE #error "Platform should define DEFAULT_CACHE_LINE_SIZE" #endif +// The default padding size for data structures to avoid false sharing. +#ifndef DEFAULT_PADDING_SIZE +#error "Platform should define DEFAULT_PADDING_SIZE" +#endif + //---------------------------------------------------------------------------------------------------- // Utility macros for compilers diff --git a/src/hotspot/share/utilities/nonblockingQueue.hpp b/src/hotspot/share/utilities/nonblockingQueue.hpp index 0c62f07719012..814132809fa8f 100644 --- a/src/hotspot/share/utilities/nonblockingQueue.hpp +++ b/src/hotspot/share/utilities/nonblockingQueue.hpp @@ -62,7 +62,7 @@ template class NonblockingQueue { T* volatile _head; // Padding of one cache line to avoid false sharing. - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, sizeof(T*)); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, sizeof(T*)); T* volatile _tail; NONCOPYABLE(NonblockingQueue); diff --git a/src/hotspot/share/utilities/waitBarrier_generic.hpp b/src/hotspot/share/utilities/waitBarrier_generic.hpp index d3a45b33b82ef..e980b3022ef8e 100644 --- a/src/hotspot/share/utilities/waitBarrier_generic.hpp +++ b/src/hotspot/share/utilities/waitBarrier_generic.hpp @@ -38,7 +38,7 @@ class GenericWaitBarrier : public CHeapObj { // This would insulate from stalls when adjacent cells have returning // workers and contend over the cache line for current latency-critical // cell. - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); Semaphore _sem; @@ -81,14 +81,14 @@ class GenericWaitBarrier : public CHeapObj { Cell _cells[CELLS_COUNT]; // Trailing padding to protect the last cell. - DEFINE_PAD_MINUS_SIZE(0, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(0, DEFAULT_PADDING_SIZE, 0); volatile int _barrier_tag; // Trailing padding to insulate the rest of the barrier from adjacent // data structures. The leading padding is not needed, as cell padding // handles this for us. - DEFINE_PAD_MINUS_SIZE(1, DEFAULT_CACHE_LINE_SIZE, 0); + DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, 0); NONCOPYABLE(GenericWaitBarrier); diff --git a/test/hotspot/gtest/gc/shared/test_bufferNodeAllocator.cpp b/test/hotspot/gtest/gc/shared/test_bufferNodeAllocator.cpp index e07e073974fce..752aef02d5a52 100644 --- a/test/hotspot/gtest/gc/shared/test_bufferNodeAllocator.cpp +++ b/test/hotspot/gtest/gc/shared/test_bufferNodeAllocator.cpp @@ -239,7 +239,7 @@ static void run_test(BufferNode::Allocator* allocator, CompletedList* cbl) { } TEST_VM(BufferNodeAllocatorTest, stress_free_list_allocator) { - const size_t buffer_capacity = DEFAULT_CACHE_LINE_SIZE / sizeof(void*); + const size_t buffer_capacity = DEFAULT_PADDING_SIZE / sizeof(void*); BufferNode::Allocator allocator("Test Allocator", buffer_capacity); CompletedList completed; run_test(&allocator, &completed); From c3cd1f1814c1561c99caec58a2a61d069f6cd181 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 4 Jan 2024 11:35:56 +0000 Subject: [PATCH 009/112] 8323000: Parallel: Remove unused class declarations in psScavenge Reviewed-by: stefank --- src/hotspot/share/gc/parallel/psScavenge.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index 69fa18aa0bec7..0c61bc9c30e1e 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -33,12 +33,10 @@ #include "oops/oop.hpp" #include "utilities/stack.hpp" -class OopStack; class ReferenceProcessor; class ParallelScavengeHeap; class ParallelScavengeTracer; class PSIsAliveClosure; -class PSRefProcTaskExecutor; class STWGCTimer; class PSScavenge: AllStatic { From df22fb322e6c4c9931a770bd0abf4c43b83c4e4a Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Thu, 4 Jan 2024 12:46:31 +0000 Subject: [PATCH 010/112] 8322512: StringBuffer.repeat does not work correctly after toString() was called Reviewed-by: rriggs, jpai --- .../share/classes/java/lang/StringBuffer.java | 2 ++ .../lang/StringBuilder/StringBufferRepeat.java | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java index ec7ecb5d2451f..d77462f0c706f 100644 --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -715,6 +715,7 @@ public synchronized StringBuffer reverse() { */ @Override public synchronized StringBuffer repeat(int codePoint, int count) { + toStringCache = null; super.repeat(codePoint, count); return this; } @@ -726,6 +727,7 @@ public synchronized StringBuffer repeat(int codePoint, int count) { */ @Override public synchronized StringBuffer repeat(CharSequence cs, int count) { + toStringCache = null; super.repeat(cs, count); return this; } diff --git a/test/jdk/java/lang/StringBuilder/StringBufferRepeat.java b/test/jdk/java/lang/StringBuilder/StringBufferRepeat.java index 2d1f3c64f60cc..d78066fb4170e 100644 --- a/test/jdk/java/lang/StringBuilder/StringBufferRepeat.java +++ b/test/jdk/java/lang/StringBuilder/StringBufferRepeat.java @@ -29,7 +29,7 @@ /** * @test - * @bug 8302323 + * @bug 8302323 8322512 * @summary Test StringBuffer.repeat sanity tests * @run testng/othervm -XX:-CompactStrings StringBufferRepeat * @run testng/othervm -XX:+CompactStrings StringBufferRepeat @@ -129,6 +129,19 @@ public void sanity() { expected = "\u0000\u0000\u0000\u0000\u0000\u0000\u0020\u0020\u0020\u0020\u0020\u0020\u2461\u2462\u2462\u2462\u2462\u2462\udbff\udfff\udbff\udfff\udbff\udfff\udbff\udfff\udbff\udfff\udbff\udfff"; assertEquals(expected, sb.toString()); + // toStringCache + + sb.setLength(0); + sb.toString(); + sb.repeat('*', 5); + expected = "*****"; + assertEquals(sb.toString(), expected); + sb.setLength(0); + sb.toString(); + sb.repeat("*", 5); + assertEquals(sb.toString(), expected); + + } public void exceptions() { From 27d5f5c237910bc3d2df62367d2e0a83c1132885 Mon Sep 17 00:00:00 2001 From: Denghui Dong Date: Thu, 4 Jan 2024 13:11:47 +0000 Subject: [PATCH 011/112] 8322781: C1: Debug build crash in GraphBuilder::vmap() when print stats Reviewed-by: kvn, thartmann, shade --- src/hotspot/share/c1/c1_GraphBuilder.cpp | 4 +++- .../jtreg/compiler/arguments/TestC1Globals.java | 11 +++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index edf6f29478c4d..fb2aa28ec86a3 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -4468,7 +4468,9 @@ void GraphBuilder::append_unsafe_get_and_set(ciMethod* callee, bool is_add) { #ifndef PRODUCT void GraphBuilder::print_stats() { - vmap()->print(); + if (UseLocalValueNumbering) { + vmap()->print(); + } } #endif // PRODUCT diff --git a/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java b/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java index ff639a69bd937..3944b78bc2764 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java +++ b/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java @@ -57,6 +57,17 @@ * */ +/** + * @test + * @bug 8322781 + * @requires vm.debug + * @summary Test flag with c1 value numbering + * + * @run main/othervm -XX:+PrintValueNumbering -XX:+Verbose -XX:-UseLocalValueNumbering + * -Xcomp -XX:TieredStopAtLevel=1 + * compiler.arguments.TestC1Globals + */ + package compiler.arguments; public class TestC1Globals { From d33dfe5cb2bec682f94fbae850e167d6f437fecb Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 4 Jan 2024 15:20:23 +0000 Subject: [PATCH 012/112] 8323002: test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java times out on macosx-x64 Reviewed-by: pchilanomate --- .../Thread/virtual/stress/GetStackTraceALotWhenPinned.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java index acf6b1c6bd257..1790ef5eeac5b 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALotWhenPinned.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -26,7 +26,7 @@ * @bug 8322818 * @summary Stress test Thread.getStackTrace on a virtual thread that is pinned * @requires vm.debug != true - * @run main GetStackTraceALotWhenPinned 100000 + * @run main GetStackTraceALotWhenPinned 25000 */ /* @@ -35,6 +35,7 @@ * @run main/timeout=300 GetStackTraceALotWhenPinned 10000 */ +import java.time.Instant; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; @@ -67,7 +68,7 @@ public static void main(String[] args) throws Exception { LockSupport.unpark(thread); long currentTime = System.currentTimeMillis(); if ((currentTime - lastTimestamp) > 500) { - System.out.println(counter.get() + " remaining ..."); + System.out.format("%s %d remaining ...%n", Instant.now(), counter.get()); lastTimestamp = currentTime; } } From ea19e9c6aa86034055a39c8780156ae4c569de5b Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Thu, 4 Jan 2024 16:28:52 +0000 Subject: [PATCH 013/112] 8323011: ProblemList serviceability/HeapDump/FullGCHeapDumpLimitTest.java Reviewed-by: azvegint, ctornqvi --- test/hotspot/jtreg/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 754cf68ba591f..484aad97b8c12 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -141,6 +141,8 @@ serviceability/attach/ConcAttachTest.java 8290043 linux-all serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 +serviceability/HeapDump/FullGCHeapDumpLimitTest.java 8322989 generic-all + ############################################################################# # :hotspot_misc From ade40741cab0b5e4d8519a55ebcd51e386999f5d Mon Sep 17 00:00:00 2001 From: Joshua Cao Date: Thu, 4 Jan 2024 16:55:04 +0000 Subject: [PATCH 014/112] 8322976: Remove reference to transform_no_reclaim Reviewed-by: shade, thartmann --- src/hotspot/share/opto/phaseX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 46d76258eb4f3..c791146f75769 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -685,7 +685,7 @@ Node* PhaseGVN::transform(Node* n) { k = i; #ifdef ASSERT if (loop_count >= K + C->live_nodes()) { - dump_infinite_loop_info(i, "PhaseGVN::transform_no_reclaim"); + dump_infinite_loop_info(i, "PhaseGVN::transform"); } #endif i = apply_ideal(k, /*can_reshape=*/false); From 15cf8f853105050ec356756d5affa153f79894fa Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Thu, 4 Jan 2024 17:16:22 +0000 Subject: [PATCH 015/112] 8319626: Override toString() for ZipFile Reviewed-by: jpai, alanb, coffeys --- .../share/classes/java/util/zip/ZipFile.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index 7281db3297b6b..d48910fe5efa0 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -95,7 +95,8 @@ */ public class ZipFile implements ZipConstants, Closeable { - private final String name; // zip file name + private final String filePath; // zip file path + private final String fileName; // name of the file private volatile boolean closeRequested; // The "resource" used by this zip file that needs to be @@ -245,7 +246,8 @@ public ZipFile(File file, int mode, Charset charset) throws IOException } Objects.requireNonNull(charset, "charset"); - this.name = name; + this.filePath = name; + this.fileName = file.getName(); long t0 = System.nanoTime(); this.res = new CleanableResource(this, ZipCoder.get(charset), file, mode); @@ -483,7 +485,16 @@ public int available() throws IOException { * @return the path name of the ZIP file */ public String getName() { - return name; + return filePath; + } + + /** + * {@return a string identifying this {@code ZipFile}, for debugging} + */ + @Override + public String toString() { + return this.fileName + + "@" + Integer.toHexString(System.identityHashCode(this)); } private class ZipEntryIterator From ad31ec5c5f120082cedd7b9ece45b6b44147c0c5 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 4 Jan 2024 17:16:33 +0000 Subject: [PATCH 016/112] 8322647: Short name for the `Europe/Lisbon` time zone is incorrect Reviewed-by: joehw, iris --- .../tools/cldrconverter/CLDRConverter.java | 41 +++++++++++-- .../test/java/time/format/TestUTCParse.java | 12 ++-- .../resources/cldr/TimeZoneNamesTest.java | 61 +++++++++++++++---- 3 files changed, 92 insertions(+), 22 deletions(-) diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index b6298c00c9a19..442a245f92fea 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -1289,25 +1289,58 @@ private static Map coverageLevelsMap() throws Exception { */ private static void generateTZDBShortNamesMap() throws IOException { Files.walk(Path.of(tzDataDir), 1, FileVisitOption.FOLLOW_LINKS) - .filter(p -> p.toFile().isFile()) + .filter(p -> p.toFile().isFile() && !p.endsWith("jdk11_backward")) .forEach(p -> { try { String zone = null; String rule = null; String format = null; + boolean inVanguard = false; + boolean inRearguard = false; for (var line : Files.readAllLines(p)) { - if (line.contains("#STDOFF")) continue; + // Interpret the line in rearguard mode so that STD/DST + // correctly handles negative DST cases, such as "GMT/IST" + // vs. "IST/GMT" case for Europe/Dublin + if (inVanguard) { + if (line.startsWith("# Rearguard")) { + inVanguard = false; + inRearguard = true; + } + continue; + } else if (line.startsWith("# Vanguard")) { + inVanguard = true; + continue; + } + if (inRearguard) { + if (line.startsWith("# End of rearguard")) { + inRearguard = false; + continue; + } else { + if (line.startsWith("#\t")) { + line = line.substring(1); // omit # + } + } + } + if (line.isBlank() || line.matches("^[ \t]*#.*")) { + // ignore blank/comment lines + continue; + } + // remove comments in-line line = line.replaceAll("[ \t]*#.*", ""); // Zone line if (line.startsWith("Zone")) { + if (zone != null) { + tzdbShortNamesMap.put(zone, format + NBSP + rule); + } var zl = line.split("[ \t]+", -1); zone = zl[1]; rule = zl[3]; format = zl[4]; } else { if (zone != null) { - if (line.isBlank()) { + if (line.startsWith("Rule") || + line.startsWith("Link")) { tzdbShortNamesMap.put(zone, format + NBSP + rule); zone = null; rule = null; diff --git a/test/jdk/java/time/test/java/time/format/TestUTCParse.java b/test/jdk/java/time/test/java/time/format/TestUTCParse.java index 6da94f04f0413..c1766b4703070 100644 --- a/test/jdk/java/time/test/java/time/format/TestUTCParse.java +++ b/test/jdk/java/time/test/java/time/format/TestUTCParse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -23,7 +23,7 @@ /* * @test * @modules jdk.localedata - * @bug 8303440 8317979 + * @bug 8303440 8317979 8322647 * @summary Test parsing "UTC-XX:XX" text works correctly */ package test.java.time.format; @@ -43,8 +43,8 @@ public class TestUTCParse { static { - // Assuming CLDR's SHORT name for "America/Juneau" - // produces "UTC\u212209:00" + // Assuming CLDR's SHORT name for "America/Manaus" + // produces "UTC\u221204:00" System.setProperty("java.locale.providers", "CLDR"); } @@ -60,9 +60,9 @@ public Object[][] utcZoneIdStrings() { @Test public void testUTCShortNameRoundTrip() { var fmt = DateTimeFormatter.ofPattern("z", Locale.FRANCE); - var zdt = ZonedDateTime.of(2023, 3, 3, 0, 0, 0, 0, ZoneId.of("America/Juneau")); + var zdt = ZonedDateTime.of(2023, 3, 3, 0, 0, 0, 0, ZoneId.of("America/Manaus")); var formatted = fmt.format(zdt); - assertEquals(formatted, "UTC\u221209:00"); + assertEquals(formatted, "UTC\u221204:00"); assertEquals(fmt.parse(formatted).query(TemporalQueries.zoneId()), zdt.getZone()); } diff --git a/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java b/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java index eb56c087ad654..a468f6b1f1b03 100644 --- a/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java +++ b/test/jdk/sun/util/resources/cldr/TimeZoneNamesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -23,9 +23,10 @@ /* * @test - * @bug 8181157 8202537 8234347 8236548 8261279 + * @bug 8181157 8202537 8234347 8236548 8261279 8322647 * @modules jdk.localedata - * @summary Checks CLDR time zone names are generated correctly at runtime + * @summary Checks CLDR time zone names are generated correctly at + * either build or runtime * @run testng/othervm -Djava.locale.providers=CLDR TimeZoneNamesTest */ @@ -45,8 +46,8 @@ @Test public class TimeZoneNamesTest { - @DataProvider(name="noResourceTZs") - Object[][] data() { + @DataProvider + Object[][] sampleTZs() { return new Object[][] { // tzid, locale, style, expected @@ -174,11 +175,49 @@ Object[][] data() { "UTC+03:00", "heure : Istanbul", "UTC+03:00"}, + + // Short names derived from TZDB at build time + {"Europe/Lisbon", Locale.US, "Western European Standard Time", + "WET", + "Western European Summer Time", + "WEST", + "Western European Time", + "WET"}, + {"Atlantic/Azores", Locale.US, "Azores Standard Time", + "GMT-01:00", + "Azores Summer Time", + "GMT", + "Azores Time", + "GMT-01:00"}, + {"Australia/Perth", Locale.US, "Australian Western Standard Time", + "AWST", + "Australian Western Daylight Time", + "AWDT", + "Western Australia Time", + "AWT"}, + {"Africa/Harare", Locale.US, "Central Africa Time", + "CAT", + "Harare Daylight Time", + "CAT", + "Harare Time", + "CAT"}, + {"Europe/Dublin", Locale.US, "Greenwich Mean Time", + "GMT", + "Irish Standard Time", + "IST", + "Dublin Time", + "GMT"}, + {"Pacific/Gambier", Locale.US, "Gambier Time", + "GMT-09:00", + "Gambier Daylight Time", + "GMT-09:00", + "Gambier Time", + "GMT-09:00"}, }; } - @Test(dataProvider="noResourceTZs") + @Test(dataProvider="sampleTZs") public void test_tzNames(String tzid, Locale locale, String lstd, String sstd, String ldst, String sdst, String lgen, String sgen) { // Standard time assertEquals(TimeZone.getTimeZone(tzid).getDisplayName(false, TimeZone.LONG, locale), lstd); @@ -197,16 +236,14 @@ public void test_tzNames(String tzid, Locale locale, String lstd, String sstd, S @Test public void test_getZoneStrings() { assertFalse( - Arrays.stream(Locale.getAvailableLocales()) + Locale.availableLocales() .limit(30) .peek(l -> System.out.println("Locale: " + l)) .map(l -> DateFormatSymbols.getInstance(l).getZoneStrings()) - .flatMap(zs -> Arrays.stream(zs)) + .flatMap(Arrays::stream) .peek(names -> System.out.println(" tz: " + names[0])) - .flatMap(names -> Arrays.stream(names)) - .filter(name -> Objects.isNull(name) || name.isEmpty()) - .findAny() - .isPresent(), + .flatMap(Arrays::stream) + .anyMatch(name -> Objects.isNull(name) || name.isEmpty()), "getZoneStrings() returned array containing non-empty string element(s)"); } } From 3fbccb01dcffe9eb48a08d99aab0e9aa311a18cf Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Thu, 4 Jan 2024 17:22:49 +0000 Subject: [PATCH 017/112] 8322978: Remove debug agent debugMonitorTimedWait() function. It is no longer used. Reviewed-by: dholmes, sspitsyn --- .../share/native/libjdwp/util.c | 19 +------------------ .../share/native/libjdwp/util.h | 3 +-- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/src/jdk.jdwp.agent/share/native/libjdwp/util.c index 6ac15d3de6e78..0bb7c8837d851 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -1073,23 +1073,6 @@ debugMonitorWait(jrawMonitorID monitor) } } -void -debugMonitorTimedWait(jrawMonitorID monitor, jlong millis) -{ - jvmtiError error; - error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorWait) - (gdata->jvmti, monitor, millis); - if (error == JVMTI_ERROR_INTERRUPT) { - /* See comment above */ - handleInterrupt(); - error = JVMTI_ERROR_NONE; - } - error = ignore_vm_death(error); - if (error != JVMTI_ERROR_NONE) { - EXIT_ERROR(error, "on raw monitor timed wait"); - } -} - void debugMonitorNotify(jrawMonitorID monitor) { diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/src/jdk.jdwp.agent/share/native/libjdwp/util.h index 7e3ff7047e93c..c5b8a2b5f519a 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -354,7 +354,6 @@ jrawMonitorID debugMonitorCreate(char *name); void debugMonitorEnter(jrawMonitorID theLock); void debugMonitorExit(jrawMonitorID theLock); void debugMonitorWait(jrawMonitorID theLock); -void debugMonitorTimedWait(jrawMonitorID theLock, jlong millis); void debugMonitorNotify(jrawMonitorID theLock); void debugMonitorNotifyAll(jrawMonitorID theLock); void debugMonitorDestroy(jrawMonitorID theLock); From 3b1e56a4275addeadcefe180b5ce60d9d74cca7b Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Fri, 5 Jan 2024 00:00:24 +0000 Subject: [PATCH 018/112] 8322322: Support archived full module graph when -Xbootclasspath/a is used Reviewed-by: alanb, mchung --- src/hotspot/share/runtime/arguments.cpp | 4 -- .../jdk/internal/loader/ClassLoaders.java | 14 +++--- .../OptimizeModuleHandlingTest.java | 46 ++++++++++++++++++- .../ReplaceCriticalClassesForSubgraphs.java | 3 +- 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 95aa54f775fd0..7dae2cce16ea2 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2215,10 +2215,6 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, bool* patch_m // -bootclasspath/a: } else if (match_option(option, "-Xbootclasspath/a:", &tail)) { Arguments::append_sysclasspath(tail); -#if INCLUDE_CDS - MetaspaceShared::disable_optimized_module_handling(); - log_info(cds)("optimized module handling: disabled because bootclasspath was appended"); -#endif // -bootclasspath/p: } else if (match_option(option, "-Xbootclasspath/p:", &tail)) { jio_fprintf(defaultStream::output_stream(), diff --git a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java index 75922c34e652c..7b0f4d13e4096 100644 --- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java +++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java @@ -64,19 +64,19 @@ private static void setArchivedServicesCatalog(ClassLoader loader) { // Creates the built-in class loaders. static { ArchivedClassLoaders archivedClassLoaders = ArchivedClassLoaders.get(); + // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute + String append = VM.getSavedProperty("jdk.boot.class.path.append"); + URLClassPath bootUcp = (append != null && !append.isEmpty()) + ? new URLClassPath(append, true) + : null; if (archivedClassLoaders != null) { - // assert VM.getSavedProperty("jdk.boot.class.path.append") == null BOOT_LOADER = (BootClassLoader) archivedClassLoaders.bootLoader(); + BOOT_LOADER.setClassPath(bootUcp); setArchivedServicesCatalog(BOOT_LOADER); PLATFORM_LOADER = (PlatformClassLoader) archivedClassLoaders.platformLoader(); setArchivedServicesCatalog(PLATFORM_LOADER); } else { - // -Xbootclasspath/a or -javaagent with Boot-Class-Path attribute - String append = VM.getSavedProperty("jdk.boot.class.path.append"); - URLClassPath ucp = (append != null && !append.isEmpty()) - ? new URLClassPath(append, true) - : null; - BOOT_LOADER = new BootClassLoader(ucp); + BOOT_LOADER = new BootClassLoader(bootUcp); PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER); } // A class path is required when no initial module is specified. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java index eecc218a71aa3..53de474d9cd41 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java @@ -306,7 +306,7 @@ public static void runWithJarPath(String... extraRuntimeArgs) throws Exception { .shouldNotContain(OPTIMIZE_ENABLED) .shouldNotContain(OPTIMIZE_DISABLED); }); - tty("10. run with CDS on, with main/test jars on classpath also with -Xbootclasspath/a: should not pass"); + tty("10. run with CDS on, with main/test jars on classpath also with -Xbootclasspath/a: should pass"); TestCommon.run("-Xlog:cds", "-cp", mainJar.toString() + PATH_SEPARATOR + testJar.toString(), "-Xbootclasspath/a:", ".", @@ -314,9 +314,51 @@ public static void runWithJarPath(String... extraRuntimeArgs) throws Exception { .assertAbnormalExit(out -> { out.shouldNotContain(CLASS_FOUND_MESSAGE) .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) - .shouldContain(OPTIMIZE_DISABLED) .shouldNotContain(OPTIMIZE_ENABLED) .shouldContain(MAP_FAILED); }); + + // Dump an archive with -Xbootclasspath/a + output = TestCommon.createArchive( + testJar.toString(), + appClasses, + "-Xbootclasspath/a:" + mainJar.toString()); + TestCommon.checkDump(output); + tty("11. run with CDS on, with test jar on classpath and with main jar on -Xbootclasspath/a: should pass"); + TestCommon.run("-Xlog:cds", + "-cp", testJar.toString(), + "-Xbootclasspath/a:" + mainJar.toString(), + MAIN_CLASS) + .assertNormalExit(out -> { + out.shouldNotContain(CLASS_FOUND_MESSAGE) + .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) + .shouldContain(OPTIMIZE_ENABLED); + }); + tty("12. run with CDS on, with main jar on classpath and with test jar on -Xbootclasspath/a: should not pass due to class paths mismatch"); + TestCommon.run("-Xlog:cds", + "-cp", mainJar.toString(), + "-Xbootclasspath/a:" + testJar.toString(), + MAIN_CLASS) + .assertAbnormalExit(out -> { + out.shouldNotContain(CLASS_FOUND_MESSAGE) + .shouldNotContain(CLASS_NOT_FOUND_MESSAGE) + .shouldNotContain(OPTIMIZE_ENABLED) + .shouldContain(MAP_FAILED); + }); + // Dump an archive with only -Xbootclasspath/a + output = TestCommon.createArchive( + null, + appClasses, + "-Xbootclasspath/a:" + mainJar.toString()); + TestCommon.checkDump(output); + tty("13. run with CDS on, with the same -Xbootclasspath/a as dump time and adding a -cp with test.jar: should pass"); + TestCommon.run("-Xlog:cds,class+load", + "-cp", testJar.toString(), + "-Xbootclasspath/a:" + mainJar.toString(), + MAIN_CLASS) + .assertNormalExit(out -> { + out.shouldMatch(MAIN_FROM_CDS) + .shouldContain(OPTIMIZE_ENABLED); + }); } } diff --git a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java index f7d50fd7fe6bf..71d984d3a638c 100644 --- a/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java +++ b/test/hotspot/jtreg/runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java @@ -47,7 +47,8 @@ public String[] getTests() { // CDS should not be disabled -- these critical classes cannot be replaced because // JvmtiExport::early_class_hook_env() is false. - "-subgraph java/lang/module/ResolvedModule jdk.internal.module.ArchivedModuleGraph", + "-subgraph java/lang/module/Configuration java.lang.module.Configuration", + "-subgraph java/lang/ModuleLayer java.lang.ModuleLayer", "-subgraph java/lang/Integer java.lang.Integer$IntegerCache", // Tests for archived full module graph. We cannot use whitebox, which requires appending to bootclasspath. From 5235cc987d8c4455622acda947bed7321086a385 Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Fri, 5 Jan 2024 04:39:55 +0000 Subject: [PATCH 019/112] 8322583: RISC-V: Enable fast class initialization checks Reviewed-by: rehn, fyang, fjiang --- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 0981ec3382a55..290b44eb0efe9 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -209,6 +209,9 @@ class VM_Version : public Abstract_VM_Version { constexpr static bool supports_stack_watermark_barrier() { return true; } static bool supports_on_spin_wait() { return UseZihintpause; } + + // RISCV64 supports fast class initialization checks + static bool supports_fast_class_init_checks() { return true; } }; #endif // CPU_RISCV_VM_VERSION_RISCV_HPP From 2a9c3589d941d9a57e536ea0b3d7919c6ddb82dc Mon Sep 17 00:00:00 2001 From: Johny Jose Date: Fri, 5 Jan 2024 08:12:59 +0000 Subject: [PATCH 020/112] 8322725: (tz) Update Timezone Data to 2023d Reviewed-by: coffeys, naoto --- src/java.base/share/data/tzdata/VERSION | 2 +- src/java.base/share/data/tzdata/africa | 7 --- src/java.base/share/data/tzdata/antarctica | 57 ++++++++++++++++++- src/java.base/share/data/tzdata/asia | 6 +- src/java.base/share/data/tzdata/australasia | 8 ++- src/java.base/share/data/tzdata/backward | 1 - src/java.base/share/data/tzdata/europe | 29 +++++++--- src/java.base/share/data/tzdata/iso3166.tab | 17 ++++-- src/java.base/share/data/tzdata/leapseconds | 8 +-- src/java.base/share/data/tzdata/northamerica | 3 +- src/java.base/share/data/tzdata/southamerica | 6 ++ src/java.base/share/data/tzdata/zone.tab | 24 ++++---- .../java/util/TimeZone/TimeZoneData/VERSION | 2 +- .../util/TimeZone/TimeZoneData/aliases.txt | 1 - 14 files changed, 125 insertions(+), 46 deletions(-) diff --git a/src/java.base/share/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION index 66bd061e8bcf9..560884d1a8253 100644 --- a/src/java.base/share/data/tzdata/VERSION +++ b/src/java.base/share/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2023c +tzdata2023d diff --git a/src/java.base/share/data/tzdata/africa b/src/java.base/share/data/tzdata/africa index a73405fdb01f2..b4789b16c71e5 100644 --- a/src/java.base/share/data/tzdata/africa +++ b/src/java.base/share/data/tzdata/africa @@ -308,13 +308,6 @@ Rule Egypt 2007 only - Sep Thu>=1 24:00 0 - # reproduced by other (more accessible) sites[, e.g.,]... # http://elgornal.net/news/news.aspx?id=4699258 -# From Paul Eggert (2014-06-04): -# Sarah El Deeb and Lee Keath of AP report that the Egyptian government says -# the change is because of blackouts in Cairo, even though Ahram Online (cited -# above) says DST had no affect on electricity consumption. There is -# no information about when DST will end this fall. See: -# http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833 - # From Steffen Thorsen (2015-04-08): # Egypt will start DST on midnight after Thursday, April 30, 2015. # This is based on a law (no 35) from May 15, 2014 saying it starts the last diff --git a/src/java.base/share/data/tzdata/antarctica b/src/java.base/share/data/tzdata/antarctica index 3de5e726eb4d7..fc7176cd0d57a 100644 --- a/src/java.base/share/data/tzdata/antarctica +++ b/src/java.base/share/data/tzdata/antarctica @@ -103,6 +103,11 @@ # - 2018 Oct 7 4:00 - 2019 Mar 17 3:00 - 2019 Oct 4 3:00 - 2020 Mar 8 3:00 # and now - 2020 Oct 4 0:01 +# From Paul Eggert (2023-12-20): +# Transitions from 2021 on are taken from: +# https://www.timeanddate.com/time/zone/antarctica/casey +# retrieved at various dates. + # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Antarctica/Casey 0 - -00 1969 8:00 - +08 2009 Oct 18 2:00 @@ -116,7 +121,12 @@ Zone Antarctica/Casey 0 - -00 1969 8:00 - +08 2019 Oct 4 3:00 11:00 - +11 2020 Mar 8 3:00 8:00 - +08 2020 Oct 4 0:01 - 11:00 - +11 + 11:00 - +11 2021 Mar 14 0:00 + 8:00 - +08 2021 Oct 3 0:01 + 11:00 - +11 2022 Mar 13 0:00 + 8:00 - +08 2022 Oct 2 0:01 + 11:00 - +11 2023 Mar 9 3:00 + 8:00 - +08 Zone Antarctica/Davis 0 - -00 1957 Jan 13 7:00 - +07 1964 Nov 0 - -00 1969 Feb @@ -263,7 +273,50 @@ Zone Antarctica/Troll 0 - -00 2005 Feb 12 # year-round from 1960/61 to 1992 # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11 -# See Asia/Urumqi. +# From Craig Mundell (1994-12-15): +# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP +# Vostok, which is one of the Russian stations, is set on the same +# time as Moscow, Russia. +# +# From Lee Hotz (2001-03-08): +# I queried the folks at Columbia who spent the summer at Vostok and this is +# what they had to say about time there: +# "in the US Camp (East Camp) we have been on New Zealand (McMurdo) +# time, which is 12 hours ahead of GMT. The Russian Station Vostok was +# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead +# of GMT). This is a time zone I think two hours east of Moscow. The +# natural time zone is in between the two: 8 hours ahead of GMT." +# +# From Paul Eggert (2001-05-04): +# This seems to be hopelessly confusing, so I asked Lee Hotz about it +# in person. He said that some Antarctic locations set their local +# time so that noon is the warmest part of the day, and that this +# changes during the year and does not necessarily correspond to mean +# solar noon. So the Vostok time might have been whatever the clocks +# happened to be during their visit. So we still don't really know what time +# it is at Vostok. +# +# From Zakhary V. Akulov (2023-12-17 22:00:48 +0700): +# ... from December, 18, 2023 00:00 by my decision the local time of +# the Antarctic research base Vostok will correspond to UTC+5. +# (2023-12-19): We constantly interact with Progress base, with company who +# builds new wintering station, with sledge convoys, with aviation - they all +# use UTC+5. Besides, difference between Moscow time is just 2 hours now, not 4. +# (2023-12-19, in response to the question "Has local time at Vostok +# been UTC+6 ever since 1957, or has it changed before?"): No. At least +# since my antarctic career start, 10 years ago, Vostok base has UTC+7. +# (In response to a 2023-12-18 question "from 02:00 to 00:00 today"): This. +# +# From Paul Eggert (2023-12-18): +# For lack of better info, guess Vostok was at +07 from founding through today, +# except when closed. + +# Zone NAME STDOFF RULES FORMAT [UNTIL] +Zone Antarctica/Vostok 0 - -00 1957 Dec 16 + 7:00 - +07 1994 Feb + 0 - -00 1994 Nov + 7:00 - +07 2023 Dec 18 2:00 + 5:00 - +05 # S Africa - year-round bases # Marion Island, -4653+03752 diff --git a/src/java.base/share/data/tzdata/asia b/src/java.base/share/data/tzdata/asia index 6a048c3ad283e..f86f84b2d2707 100644 --- a/src/java.base/share/data/tzdata/asia +++ b/src/java.base/share/data/tzdata/asia @@ -678,7 +678,6 @@ Zone Asia/Shanghai 8:05:43 - LMT 1901 8:00 PRC C%sT # Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi # / Wulumuqi. (Please use Asia/Shanghai if you prefer Beijing time.) -# Vostok base in Antarctica matches this since 1970. Zone Asia/Urumqi 5:50:20 - LMT 1928 6:00 - +06 @@ -3450,6 +3449,9 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # From Heba Hamad (2023-03-22): # ... summer time will begin in Palestine from Saturday 04-29-2023, # 02:00 AM by 60 minutes forward. +# From Heba Hemad (2023-10-09): +# ... winter time will begin in Palestine from Saturday 10-28-2023, +# 02:00 AM by 60 minutes back. # # From Paul Eggert (2023-03-22): # For now, guess that spring and fall transitions will normally @@ -3571,13 +3573,13 @@ Rule Palestine 2070 only - Oct 4 2:00 0 - Rule Palestine 2071 only - Sep 19 2:00 0 - Rule Palestine 2072 only - Sep 10 2:00 0 - Rule Palestine 2072 only - Oct 15 2:00 1:00 S +Rule Palestine 2072 max - Oct Sat<=30 2:00 0 - Rule Palestine 2073 only - Sep 2 2:00 0 - Rule Palestine 2073 only - Oct 7 2:00 1:00 S Rule Palestine 2074 only - Aug 18 2:00 0 - Rule Palestine 2074 only - Sep 29 2:00 1:00 S Rule Palestine 2075 only - Aug 10 2:00 0 - Rule Palestine 2075 only - Sep 14 2:00 1:00 S -Rule Palestine 2075 max - Oct Sat<=30 2:00 0 - Rule Palestine 2076 only - Jul 25 2:00 0 - Rule Palestine 2076 only - Sep 5 2:00 1:00 S Rule Palestine 2077 only - Jul 17 2:00 0 - diff --git a/src/java.base/share/data/tzdata/australasia b/src/java.base/share/data/tzdata/australasia index 893d7055eaba4..366cfd10cc154 100644 --- a/src/java.base/share/data/tzdata/australasia +++ b/src/java.base/share/data/tzdata/australasia @@ -414,8 +414,14 @@ Zone Antarctica/Macquarie 0 - -00 1899 Nov # Please note that there will not be any daylight savings time change # in Fiji for 2022-2023.... # https://www.facebook.com/FijianGovernment/posts/pfbid0mmWVTYmTibn66ybpFda75pDcf34SSpoSaskJW5gXwaKo5Sgc7273Q4fXWc6kQV6Hl + +# From Almaz Mingaleev (2023-10-06): +# Cabinet approved the suspension of Daylight Saving and appropriate +# legislative changes will be considered including the repeal of the +# Daylight Saving Act 1998 +# https://www.fiji.gov.fj/Media-Centre/Speeches/English/CABINET-DECISIONS-3-OCTOBER-2023 # -# From Paul Eggert (2022-10-27): +# From Paul Eggert (2023-10-06): # For now, assume DST is suspended indefinitely. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S diff --git a/src/java.base/share/data/tzdata/backward b/src/java.base/share/data/tzdata/backward index c0746d6dd1bc8..7ddc6cc3d93b0 100644 --- a/src/java.base/share/data/tzdata/backward +++ b/src/java.base/share/data/tzdata/backward @@ -228,7 +228,6 @@ Link America/Puerto_Rico America/Tortola Link Pacific/Port_Moresby Antarctica/DumontDUrville Link Pacific/Auckland Antarctica/McMurdo Link Asia/Riyadh Antarctica/Syowa -Link Asia/Urumqi Antarctica/Vostok Link Europe/Berlin Arctic/Longyearbyen Link Asia/Riyadh Asia/Aden Link Asia/Qatar Asia/Bahrain diff --git a/src/java.base/share/data/tzdata/europe b/src/java.base/share/data/tzdata/europe index 446d2e1e658fa..f1b084f64d034 100644 --- a/src/java.base/share/data/tzdata/europe +++ b/src/java.base/share/data/tzdata/europe @@ -1146,6 +1146,23 @@ Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn # 2. The shift *from* DST in 2023 happens as normal, but coincides with the # shift to UTC-02 normaltime (people will not change their clocks here). # 3. After this, DST is still observed, but as -02/-01 instead of -03/-02. +# +# From Múte Bourup Egede via Jógvan Svabo Samuelsen (2023-03-15): +# Greenland will not switch to Daylight Saving Time this year, 2023, +# because the standard time for Greenland will change from UTC -3 to UTC -2. +# However, Greenland will change to Daylight Saving Time again in 2024 +# and onwards. + +# From a contributor who wishes to remain anonymous for now (2023-10-29): +# https://www.dr.dk/nyheder/seneste/i-nat-skal-uret-stilles-en-time-tilbage-men-foerste-gang-sker-det-ikke-i-groenland +# with a link to that page: +# https://naalakkersuisut.gl/Nyheder/2023/10/2710_sommertid +# ... Ittoqqortoormiit joins the time of Nuuk at March 2024. +# What would mean that America/Scoresbysund would either be in -01 year round +# or in -02/-01 like America/Nuuk, but no longer in -01/+00. +# +# From Paul Eggert (2023-10-29): +# For now, assume it will be like America/Nuuk. # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Thule 1991 1992 - Mar lastSun 2:00 1:00 D @@ -1166,10 +1183,12 @@ Zone America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28 Zone America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 # Ittoqqortoormiit -2:00 - -02 1980 Apr 6 2:00 -2:00 C-Eur -02/-01 1981 Mar 29 - -1:00 EU -01/+00 + -1:00 EU -01/+00 2024 Mar 31 + -2:00 EU -02/-01 Zone America/Nuuk -3:26:56 - LMT 1916 Jul 28 # Godthåb -3:00 - -03 1980 Apr 6 2:00 - -3:00 EU -03/-02 2023 Oct 29 1:00u + -3:00 EU -03/-02 2023 Mar 26 1:00u + -2:00 - -02 2023 Oct 29 1:00u -2:00 EU -02/-01 Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik -4:00 Thule A%sT @@ -3734,11 +3753,7 @@ Zone Europe/Istanbul 1:55:52 - LMT 1880 # and not at 3:00 as would have been under EU rules. # This is why I have set the change to EU rules into May 1996, # so that the change in March is stil covered by the Ukraine rule. -# The next change in October 1996 happened under EU rules.... -# TZ database holds three other zones for Ukraine.... I have not yet -# worked out the consequences for these three zones, as we (me and my -# US colleague David Cochrane) are still trying to get more -# information upon these local deviations from Kiev rules. +# The next change in October 1996 happened under EU rules. # # From Paul Eggert (2022-08-27): # For now, assume that Ukraine's zones all followed the same rules, diff --git a/src/java.base/share/data/tzdata/iso3166.tab b/src/java.base/share/data/tzdata/iso3166.tab index cea17732dd138..7fa350ecbe3db 100644 --- a/src/java.base/share/data/tzdata/iso3166.tab +++ b/src/java.base/share/data/tzdata/iso3166.tab @@ -26,17 +26,22 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # -# From Paul Eggert (2022-11-18): +# From Paul Eggert (2023-09-06): # This file contains a table of two-letter country codes. Columns are # separated by a single tab. Lines beginning with '#' are comments. # All text uses UTF-8 encoding. The columns of the table are as follows: # # 1. ISO 3166-1 alpha-2 country code, current as of -# ISO 3166-1 N1087 (2022-09-02). See: Updates on ISO 3166-1 -# https://isotc.iso.org/livelink/livelink/Open/16944257 -# 2. The usual English name for the coded region, -# chosen so that alphabetic sorting of subsets produces helpful lists. -# This is not the same as the English name in the ISO 3166 tables. +# ISO/TC 46 N1108 (2023-04-05). See: ISO/TC 46 Documents +# https://www.iso.org/committee/48750.html?view=documents +# 2. The usual English name for the coded region. This sometimes +# departs from ISO-listed names, sometimes so that sorted subsets +# of names are useful (e.g., "Samoa (American)" and "Samoa +# (western)" rather than "American Samoa" and "Samoa"), +# sometimes to avoid confusion among non-experts (e.g., +# "Czech Republic" and "Turkey" rather than "Czechia" and "Türkiye"), +# and sometimes to omit needless detail or churn (e.g., "Netherlands" +# rather than "Netherlands (the)" or "Netherlands (Kingdom of the)"). # # The table is sorted by country code. # diff --git a/src/java.base/share/data/tzdata/leapseconds b/src/java.base/share/data/tzdata/leapseconds index 89ce8b89cd28f..ab2c1af4bed59 100644 --- a/src/java.base/share/data/tzdata/leapseconds +++ b/src/java.base/share/data/tzdata/leapseconds @@ -95,11 +95,11 @@ Leap 2016 Dec 31 23:59:60 + S # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2023 Dec 28 00:00:00 +#Expires 2024 Jun 28 00:00:00 # POSIX timestamps for the data in this file: #updated 1467936000 (2016-07-08 00:00:00 UTC) -#expires 1703721600 (2023-12-28 00:00:00 UTC) +#expires 1719532800 (2024-06-28 00:00:00 UTC) -# Updated through IERS Bulletin C65 -# File expires on: 28 December 2023 +# Updated through IERS Bulletin C66 +# File expires on: 28 June 2024 diff --git a/src/java.base/share/data/tzdata/northamerica b/src/java.base/share/data/tzdata/northamerica index e240cf35103c4..b96269a0e26f5 100644 --- a/src/java.base/share/data/tzdata/northamerica +++ b/src/java.base/share/data/tzdata/northamerica @@ -1,3 +1,4 @@ +# # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -1475,7 +1476,7 @@ Rule StJohns 1989 2006 - Apr Sun>=1 0:01 1:00 D Rule StJohns 2007 2011 - Mar Sun>=8 0:01 1:00 D Rule StJohns 2007 2010 - Nov Sun>=1 0:01 0 S # -# St John's has an apostrophe, but Posix file names can't have apostrophes. +# St John's has an apostrophe, but POSIX file names can't have apostrophes. # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone America/St_Johns -3:30:52 - LMT 1884 -3:30:52 StJohns N%sT 1918 diff --git a/src/java.base/share/data/tzdata/southamerica b/src/java.base/share/data/tzdata/southamerica index 4024e7180cdb9..da2c623926247 100644 --- a/src/java.base/share/data/tzdata/southamerica +++ b/src/java.base/share/data/tzdata/southamerica @@ -1720,6 +1720,12 @@ Rule Para 2010 2012 - Apr Sun>=8 0:00 0 - # From Carlos Raúl Perasso (2014-02-28): # Decree 1264 can be found at: # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf +# +# From Paul Eggert (2023-07-26): +# Transition dates are now set by Law No. 7115, not by presidential decree. +# https://www.abc.com.py/politica/2023/07/12/promulgacion-el-cambio-de-hora-sera-por-ley/ +# From Carlos Raúl Perasso (2023-07-27): +# http://silpy.congreso.gov.py/descarga/ley-144138 Rule Para 2013 max - Mar Sun>=22 0:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] diff --git a/src/java.base/share/data/tzdata/zone.tab b/src/java.base/share/data/tzdata/zone.tab index 3edb0d61c8099..0a01e8777dd25 100644 --- a/src/java.base/share/data/tzdata/zone.tab +++ b/src/java.base/share/data/tzdata/zone.tab @@ -71,7 +71,7 @@ AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER, AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN) AR -2411-06518 America/Argentina/Jujuy Jujuy (JY) AR -2649-06513 America/Argentina/Tucuman Tucuman (TM) -AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH) +AR -2828-06547 America/Argentina/Catamarca Catamarca (CT), Chubut (CH) AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR) AR -3132-06831 America/Argentina/San_Juan San Juan (SJ) AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ) @@ -110,7 +110,7 @@ BN +0456+11455 Asia/Brunei BO -1630-06809 America/La_Paz BQ +120903-0681636 America/Kralendijk BR -0351-03225 America/Noronha Atlantic islands -BR -0127-04829 America/Belem Para (east); Amapa +BR -0127-04829 America/Belem Para (east), Amapa BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB) BR -0803-03454 America/Recife Pernambuco BR -0712-04812 America/Araguaina Tocantins @@ -130,21 +130,21 @@ BT +2728+08939 Asia/Thimphu BW -2439+02555 Africa/Gaborone BY +5354+02734 Europe/Minsk BZ +1730-08812 America/Belize -CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast) -CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE +CA +4734-05243 America/St_Johns Newfoundland, Labrador (SE) +CA +4439-06336 America/Halifax Atlantic - NS (most areas), PE CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton) CA +4606-06447 America/Moncton Atlantic - New Brunswick CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas) CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore) -CA +4339-07923 America/Toronto Eastern - ON, QC (most areas) +CA +4339-07923 America/Toronto Eastern - ON & QC (most areas) CA +6344-06828 America/Iqaluit Eastern - NU (most areas) -CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H) -CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba +CA +484531-0913718 America/Atikokan EST - ON (Atikokan), NU (Coral H) +CA +4953-09709 America/Winnipeg Central - ON (west), Manitoba CA +744144-0944945 America/Resolute Central - NU (Resolute) CA +624900-0920459 America/Rankin_Inlet Central - NU (central) CA +5024-10439 America/Regina CST - SK (most areas) CA +5017-10750 America/Swift_Current CST - SK (midwest) -CA +5333-11328 America/Edmonton Mountain - AB; BC (E); NT (E); SK (W) +CA +5333-11328 America/Edmonton Mountain - AB, BC(E), NT(E), SK(W) CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west) CA +682059-1334300 America/Inuvik Mountain - NT (west) CA +4906-11631 America/Creston MST - BC (Creston) @@ -230,8 +230,8 @@ HT +1832-07220 America/Port-au-Prince HU +4730+01905 Europe/Budapest ID -0610+10648 Asia/Jakarta Java, Sumatra ID -0002+10920 Asia/Pontianak Borneo (west, central) -ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west) -ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas +ID -0507+11924 Asia/Makassar Borneo (east, south), Sulawesi/Celebes, Bali, Nusa Tengarra, Timor (west) +ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya), Malukus/Moluccas IE +5320-00615 Europe/Dublin IL +314650+0351326 Asia/Jerusalem IM +5409-00428 Europe/Isle_of_Man @@ -378,7 +378,7 @@ RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky RU +5934+15048 Asia/Magadan MSK+08 - Magadan RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island -RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); N Kuril Is +RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E), N Kuril Is RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea RW -0157+03004 Africa/Kigali @@ -441,7 +441,7 @@ US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver) US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural) US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer) US +394421-1045903 America/Denver Mountain (most areas) -US +433649-1161209 America/Boise Mountain - ID (south); OR (east) +US +433649-1161209 America/Boise Mountain - ID (south), OR (east) US +332654-1120424 America/Phoenix MST - AZ (except Navajo) US +340308-1181434 America/Los_Angeles Pacific US +611305-1495401 America/Anchorage Alaska (most areas) diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION index c5483b485120a..f92096d49aafd 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION @@ -1 +1 @@ -tzdata2023c +tzdata2023d diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt index 07c5edbafee70..82bad17c55320 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt +++ b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt @@ -148,7 +148,6 @@ Link America/Puerto_Rico America/Tortola Link Pacific/Port_Moresby Antarctica/DumontDUrville Link Pacific/Auckland Antarctica/McMurdo Link Asia/Riyadh Antarctica/Syowa -Link Asia/Urumqi Antarctica/Vostok Link Europe/Berlin Arctic/Longyearbyen Link Asia/Riyadh Asia/Aden Link Asia/Qatar Asia/Bahrain From 868f8745faf70c915d8294ae8f85b2d6aa096900 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 5 Jan 2024 09:07:03 +0000 Subject: [PATCH 021/112] 8322920: Some ProcessTools.execute* functions are declared to throw Throwable Reviewed-by: dholmes, lmesnik --- test/lib/jdk/test/lib/process/ProcessTools.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/test/lib/jdk/test/lib/process/ProcessTools.java b/test/lib/jdk/test/lib/process/ProcessTools.java index 774af8e150dd6..aafb6fe3f4c74 100644 --- a/test/lib/jdk/test/lib/process/ProcessTools.java +++ b/test/lib/jdk/test/lib/process/ProcessTools.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -764,7 +764,7 @@ public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input, * @param cmds The command line to execute. * @return The output from the process. */ - public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + public static OutputAnalyzer executeProcess(String... cmds) throws Exception { return executeProcess(new ProcessBuilder(cmds)); } @@ -809,8 +809,7 @@ public static String getCommandLine(ProcessBuilder pb) { * @param cmds The command line to execute. * @return The {@linkplain OutputAnalyzer} instance wrapping the process. */ - public static OutputAnalyzer executeCommand(String... cmds) - throws Throwable { + public static OutputAnalyzer executeCommand(String... cmds) throws Exception { String cmdLine = String.join(" ", cmds); System.out.println("Command line: [" + cmdLine + "]"); OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds); @@ -827,8 +826,7 @@ public static OutputAnalyzer executeCommand(String... cmds) * @param pb The ProcessBuilder to execute. * @return The {@linkplain OutputAnalyzer} instance wrapping the process. */ - public static OutputAnalyzer executeCommand(ProcessBuilder pb) - throws Throwable { + public static OutputAnalyzer executeCommand(ProcessBuilder pb) throws Exception { String cmdLine = pb.command().stream() .map(x -> (x.contains(" ") || x.contains("$")) ? ("'" + x + "'") : x) From 1d1cd32bc355a33448d8f15555e142570bb49c21 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 5 Jan 2024 09:12:24 +0000 Subject: [PATCH 022/112] 8321812: Update GC tests to use execute[Limited]TestJava Reviewed-by: tschatzl, aboldtch --- test/hotspot/jtreg/gc/TestAgeOutput.java | 3 +- test/hotspot/jtreg/gc/TestAllocateHeapAt.java | 3 +- .../jtreg/gc/TestAllocateHeapAtError.java | 3 +- .../jtreg/gc/TestAllocateHeapAtMultiple.java | 3 +- .../jtreg/gc/TestCardTablePageCommits.java | 3 +- .../hotspot/jtreg/gc/TestNumWorkerOutput.java | 3 +- .../jtreg/gc/TestPLABAdaptToMinTLABSize.java | 4 +- test/hotspot/jtreg/gc/TestSmallHeap.java | 3 +- .../jtreg/gc/TestVerifyDuringStartup.java | 3 +- test/hotspot/jtreg/gc/TestVerifySilently.java | 3 +- test/hotspot/jtreg/gc/TestVerifySubSet.java | 3 +- .../jtreg/gc/arguments/GCArguments.java | 17 +++ .../gc/arguments/TestAggressiveHeap.java | 4 +- .../arguments/TestCompressedClassFlags.java | 12 +- .../gc/arguments/TestDisableDefaultGC.java | 15 ++- .../TestG1ConcMarkStepDurationMillis.java | 3 +- .../TestG1ConcRefinementThreads.java | 3 +- .../gc/arguments/TestG1HeapRegionSize.java | 3 +- .../gc/arguments/TestG1PercentageOptions.java | 3 +- .../jtreg/gc/arguments/TestG1RemSetFlags.java | 3 +- .../jtreg/gc/arguments/TestHeapFreeRatio.java | 3 +- .../TestInitialTenuringThreshold.java | 6 +- .../gc/arguments/TestMaxHeapSizeTools.java | 9 +- .../TestMaxMinHeapFreeRatioFlags.java | 6 +- .../jtreg/gc/arguments/TestMaxNewSize.java | 3 +- .../jtreg/gc/arguments/TestMaxRAMFlags.java | 6 +- .../TestMinAndInitialSurvivorRatioFlags.java | 3 +- .../jtreg/gc/arguments/TestNewRatioFlag.java | 3 +- .../jtreg/gc/arguments/TestNewSizeFlags.java | 8 +- .../arguments/TestNewSizeThreadIncrease.java | 15 ++- .../gc/arguments/TestObjectTenuringFlags.java | 3 +- .../gc/arguments/TestParallelGCThreads.java | 9 +- .../gc/arguments/TestParallelRefProc.java | 4 +- .../gc/arguments/TestSelectDefaultGC.java | 3 +- ...tSmallInitialHeapWithLargePageAndNUMA.java | 3 +- .../gc/arguments/TestSurvivorRatioFlag.java | 3 +- .../TestTargetSurvivorRatioFlag.java | 6 +- .../TestUnrecognizedVMOptionsHandling.java | 9 +- .../TestUseCompressedOopsErgoTools.java | 6 +- .../TestUseCompressedOopsFlagsWithUlimit.java | 5 +- .../gc/arguments/TestUseNUMAInterleaving.java | 3 +- .../TestVerifyBeforeAndAfterGCFlags.java | 3 +- .../TestG1ClassUnloadingHWM.java | 3 +- .../jtreg/gc/epsilon/TestDieDefault.java | 6 +- .../jtreg/gc/epsilon/TestDieWithHeapDump.java | 3 +- .../jtreg/gc/epsilon/TestDieWithOnError.java | 6 +- .../TestDynamicNumberOfGCThreads.java | 8 +- .../TestInitialGCThreadLogging.java | 4 +- test/hotspot/jtreg/gc/g1/Test2GbHeap.java | 3 +- .../jtreg/gc/g1/TestAllocationFailure.java | 19 ++-- .../g1/TestEagerReclaimHumongousRegions.java | 4 +- ...rReclaimHumongousRegionsClearMarkBits.java | 3 +- .../TestEagerReclaimHumongousRegionsLog.java | 3 +- ...tEagerReclaimHumongousRegionsWithRefs.java | 4 +- .../jtreg/gc/g1/TestG1SkipCompaction.java | 3 +- ...stG1TraceEagerReclaimHumongousObjects.java | 18 ++- .../jtreg/gc/g1/TestGCLogMessages.java | 104 ++++++++---------- .../g1/TestHumongousAllocConcurrentStart.java | 3 +- .../TestHumongousAllocNearlyFullRegion.java | 3 +- .../gc/g1/TestHumongousCodeCacheRoots.java | 3 +- .../g1/TestHumongousConcurrentStartUndo.java | 3 +- .../gc/g1/TestLargePageUseForAuxMemory.java | 8 +- .../jtreg/gc/g1/TestLargePageUseForHeap.java | 31 +++--- .../jtreg/gc/g1/TestMarkStackSizes.java | 4 +- .../jtreg/gc/g1/TestMixedGCLiveThreshold.java | 4 +- .../jtreg/gc/g1/TestOneEdenRegionAfterGC.java | 3 +- test/hotspot/jtreg/gc/g1/TestPLABOutput.java | 3 +- .../jtreg/gc/g1/TestPLABSizeBounds.java | 3 +- .../jtreg/gc/g1/TestPeriodicLogMessages.java | 22 ++-- .../g1/TestPrintRegionRememberedSetInfo.java | 3 +- .../jtreg/gc/g1/TestRemsetLoggingThreads.java | 14 +-- .../jtreg/gc/g1/TestRemsetLoggingTools.java | 3 +- .../gc/g1/TestSharedArchiveWithPreTouch.java | 9 +- .../jtreg/gc/g1/TestShrinkAuxiliaryData.java | 3 +- .../gc/g1/TestShrinkDefragmentedHeap.java | 3 +- .../gc/g1/TestSkipRebuildRemsetPhase.java | 21 ++-- .../hotspot/jtreg/gc/g1/TestVerifyGCType.java | 5 +- .../ClassLoaderGenerator.java | 4 +- .../gc/g1/humongousObjects/G1SampleClass.java | 5 +- .../TestHumongousClassLoader.java | 4 +- .../TestHumongousNonArrayAllocation.java | 3 +- .../jtreg/gc/g1/mixedgc/TestLogging.java | 3 +- .../gc/g1/numa/TestG1NUMATouchRegions.java | 3 +- .../g1/pinnedobjs/TestPinnedObjectTypes.java | 22 ++-- .../TestPinnedObjectsEvacuation.java | 26 ++--- .../TestPinnedOldObjectsEvacuation.java | 36 +++--- .../gc/logging/TestDeprecatedPrintFlags.java | 12 +- test/hotspot/jtreg/gc/logging/TestGCId.java | 6 +- .../jtreg/gc/logging/TestMetaSpaceLog.java | 24 ++-- .../jtreg/gc/logging/TestPrintReferences.java | 24 ++-- .../CompressedClassSpaceSizeInJmapHeap.java | 5 +- .../gc/metaspace/TestMetaspaceSizeFlags.java | 3 +- .../gc/metaspace/TestSizeTransitions.java | 3 +- .../jtreg/gc/serial/HeapChangeLogging.java | 3 +- .../jtreg/gc/shenandoah/TestEvilSyncBug.java | 3 +- .../jtreg/gc/shenandoah/TestJcmdHeapDump.java | 7 +- .../gc/shenandoah/TestObjItrWithHeapDump.java | 3 +- .../jtreg/gc/shenandoah/TestPeriodicGC.java | 3 +- .../gc/shenandoah/oom/TestAllocLargeObj.java | 6 +- .../oom/TestAllocLargerThanHeap.java | 6 +- .../gc/shenandoah/oom/TestAllocSmallObj.java | 6 +- .../shenandoah/oom/TestClassLoaderLeak.java | 4 +- .../gc/shenandoah/oom/TestThreadFailure.java | 3 +- .../options/TestArgumentRanges.java | 21 ++-- .../options/TestClassUnloadingArguments.java | 3 +- .../gc/shenandoah/options/TestExplicitGC.java | 15 +-- .../options/TestExplicitGCNoConcurrent.java | 3 +- .../options/TestHeuristicsUnlock.java | 9 +- .../options/TestHumongousThresholdArgs.java | 9 +- .../options/TestLoopMiningArguments.java | 3 +- .../gc/shenandoah/options/TestModeUnlock.java | 9 +- .../options/TestRegionSizeArgs.java | 48 +++----- .../options/TestSelectiveBarrierFlags.java | 3 +- .../options/TestSoftMaxHeapSize.java | 9 +- .../shenandoah/options/TestThreadCounts.java | 3 +- .../options/TestThreadCountsOverride.java | 6 +- .../options/TestWrongBarrierDisable.java | 6 +- .../options/TestWrongBarrierEnable.java | 6 +- .../stress/TestReclaimStringsLeaksMemory.java | 4 +- .../gc/stress/TestStressG1Humongous.java | 3 +- .../jtreg/gc/stress/TestStressG1Uncommit.java | 3 +- .../TestStringDeduplicationTools.java | 3 +- .../hotspot/jtreg/gc/testlibrary/Helpers.java | 15 ++- test/hotspot/jtreg/gc/whitebox/TestWBGC.java | 3 +- .../jtreg/gc/x/TestAllocateHeapAt.java | 22 ++-- .../jtreg/gc/x/TestPageCacheFlush.java | 22 ++-- test/hotspot/jtreg/gc/x/TestSmallHeap.java | 20 ++-- .../jtreg/gc/z/TestAllocateHeapAt.java | 22 ++-- .../jtreg/gc/z/TestPageCacheFlush.java | 22 ++-- test/hotspot/jtreg/gc/z/TestSmallHeap.java | 20 ++-- ...stZForceDiscontiguousHeapReservations.java | 22 ++-- test/hotspot/jtreg/gc/z/TestZNMT.java | 30 ++--- 132 files changed, 478 insertions(+), 671 deletions(-) diff --git a/test/hotspot/jtreg/gc/TestAgeOutput.java b/test/hotspot/jtreg/gc/TestAgeOutput.java index fa4445e34bbde..cbee132a0afec 100644 --- a/test/hotspot/jtreg/gc/TestAgeOutput.java +++ b/test/hotspot/jtreg/gc/TestAgeOutput.java @@ -66,7 +66,7 @@ public static void checkPattern(String pattern, String what) throws Exception { } public static void runTest(String gcArg) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", @@ -75,7 +75,6 @@ public static void runTest(String gcArg) throws Exception { "-Xmx10M", "-Xlog:gc+age=trace", GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAt.java b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java index 8daf0bbcdc731..d1e96751ab844 100644 --- a/test/hotspot/jtreg/gc/TestAllocateHeapAt.java +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAt.java @@ -36,13 +36,12 @@ public class TestAllocateHeapAt { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeTestJava( "-XX:AllocateHeapAt=" + System.getProperty("test.dir", "."), "-Xlog:gc+heap=info", "-Xmx32m", "-Xms32m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println("Output:\n" + output.getOutput()); diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java index 372437b8898a9..28e2f71d09d73 100644 --- a/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtError.java @@ -45,13 +45,12 @@ public static void main(String args[]) throws Exception { f = new File(test_dir, UUID.randomUUID().toString()); } while(f.exists()); - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeTestJava( "-XX:AllocateHeapAt=" + f.getName(), "-Xlog:gc+heap=info", "-Xmx32m", "-Xms32m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println("Output:\n" + output.getOutput()); diff --git a/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java index b2d2f1e429d53..d8d1b4bd88d31 100644 --- a/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java +++ b/test/hotspot/jtreg/gc/TestAllocateHeapAtMultiple.java @@ -60,8 +60,7 @@ public static void main(String args[]) throws Exception { "-Xlog:gc+heap=info", "-version"}); - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(flags); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeTestJava(flags); System.out.println("Output:\n" + output.getOutput()); diff --git a/test/hotspot/jtreg/gc/TestCardTablePageCommits.java b/test/hotspot/jtreg/gc/TestCardTablePageCommits.java index c468a771076b2..6c10dd0100e86 100644 --- a/test/hotspot/jtreg/gc/TestCardTablePageCommits.java +++ b/test/hotspot/jtreg/gc/TestCardTablePageCommits.java @@ -42,12 +42,11 @@ public static void main(String args[]) throws Exception { // because of 8kB pages, assume 4 KB pages for all other CPUs. String Xmx = "-Xmx4m"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( Xmx, "-XX:NativeMemoryTracking=detail", "-XX:+UseParallelGC", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/TestNumWorkerOutput.java b/test/hotspot/jtreg/gc/TestNumWorkerOutput.java index fd48c5a85d0af..c4c0dce0c9909 100644 --- a/test/hotspot/jtreg/gc/TestNumWorkerOutput.java +++ b/test/hotspot/jtreg/gc/TestNumWorkerOutput.java @@ -58,7 +58,7 @@ public static void checkPatternOnce(String pattern, String what) throws Exceptio } public static void runTest(String gcArg) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", @@ -67,7 +67,6 @@ public static void runTest(String gcArg) throws Exception { "-Xmx10M", "-XX:+PrintGCDetails", GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/TestPLABAdaptToMinTLABSize.java b/test/hotspot/jtreg/gc/TestPLABAdaptToMinTLABSize.java index c5c4854946d4b..8dfefcb7d9538 100644 --- a/test/hotspot/jtreg/gc/TestPLABAdaptToMinTLABSize.java +++ b/test/hotspot/jtreg/gc/TestPLABAdaptToMinTLABSize.java @@ -48,9 +48,7 @@ private static void runTest(boolean shouldSucceed, String... extraArgs) throws E Collections.addAll(testArguments, extraArgs); testArguments.add("-version"); - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(testArguments); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeTestJava(testArguments); System.out.println(output.getStderr()); diff --git a/test/hotspot/jtreg/gc/TestSmallHeap.java b/test/hotspot/jtreg/gc/TestSmallHeap.java index a9b32eb81c8f9..fd6c5860f0177 100644 --- a/test/hotspot/jtreg/gc/TestSmallHeap.java +++ b/test/hotspot/jtreg/gc/TestSmallHeap.java @@ -96,12 +96,11 @@ public static void main(String[] args) throws Exception { private static void verifySmallHeapSize(String gc, long expectedMaxHeap) throws Exception { long minMaxHeap = 4 * 1024 * 1024; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( gc, "-Xmx" + minMaxHeap, "-XX:+PrintFlagsFinal", VerifyHeapSize.class.getName()); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(0); expectedMaxHeap = Math.max(expectedMaxHeap, minMaxHeap); diff --git a/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java b/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java index 4ad9f9675d91a..e651295d5b5bb 100644 --- a/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java +++ b/test/hotspot/jtreg/gc/TestVerifyDuringStartup.java @@ -37,13 +37,12 @@ public class TestVerifyDuringStartup { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeTestJava( "-XX:-UseTLAB", "-XX:+UnlockDiagnosticVMOptions", "-XX:+VerifyDuringStartup", "-Xlog:gc+verify=debug", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println("Output:\n" + output.getOutput()); diff --git a/test/hotspot/jtreg/gc/TestVerifySilently.java b/test/hotspot/jtreg/gc/TestVerifySilently.java index b7b07a1eb8ec2..2f245f5eed2c2 100644 --- a/test/hotspot/jtreg/gc/TestVerifySilently.java +++ b/test/hotspot/jtreg/gc/TestVerifySilently.java @@ -57,8 +57,7 @@ private static OutputAnalyzer runTest(boolean verifySilently) throws Exception { "-XX:+VerifyAfterGC", (verifySilently ? "-Xlog:gc":"-Xlog:gc+verify=debug"), TestVerifySilentlyRunSystemGC.class.getName()}); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(vmOpts); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(vmOpts); System.out.println("Output:\n" + output.getOutput()); return output; diff --git a/test/hotspot/jtreg/gc/TestVerifySubSet.java b/test/hotspot/jtreg/gc/TestVerifySubSet.java index 5aa8cc3eb1334..08cddc74a00be 100644 --- a/test/hotspot/jtreg/gc/TestVerifySubSet.java +++ b/test/hotspot/jtreg/gc/TestVerifySubSet.java @@ -59,8 +59,7 @@ private static OutputAnalyzer runTest(String subset) throws Exception { "-Xlog:gc+verify=debug", "-XX:VerifySubSet="+subset, TestVerifySubSetRunSystemGC.class.getName()}); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(vmOpts); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(vmOpts); System.out.println("Output:\n" + output.getOutput()); return output; diff --git a/test/hotspot/jtreg/gc/arguments/GCArguments.java b/test/hotspot/jtreg/gc/arguments/GCArguments.java index c59a14954bfa3..3908ce17966a5 100644 --- a/test/hotspot/jtreg/gc/arguments/GCArguments.java +++ b/test/hotspot/jtreg/gc/arguments/GCArguments.java @@ -27,6 +27,7 @@ import java.util.Collections; import java.util.List; import jdk.test.lib.Platform; +import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; /** @@ -81,4 +82,20 @@ static public ProcessBuilder createTestJavaProcessBuilder(List arguments static public ProcessBuilder createTestJavaProcessBuilder(String... arguments) { return ProcessTools.createTestJavaProcessBuilder(withDefaults(arguments)); } + + static public OutputAnalyzer executeLimitedTestJava(List arguments) throws Exception { + return executeLimitedTestJava(arguments.toArray(String[]::new)); + } + + static public OutputAnalyzer executeLimitedTestJava(String... arguments) throws Exception { + return ProcessTools.executeLimitedTestJava(withDefaults(arguments)); + } + + static public OutputAnalyzer executeTestJava(List arguments) throws Exception { + return executeTestJava(arguments.toArray(String[]::new)); + } + + static public OutputAnalyzer executeTestJava(String... arguments) throws Exception { + return ProcessTools.executeTestJava(withDefaults(arguments)); + } } diff --git a/test/hotspot/jtreg/gc/arguments/TestAggressiveHeap.java b/test/hotspot/jtreg/gc/arguments/TestAggressiveHeap.java index d01773fd71105..4ed673a40feab 100644 --- a/test/hotspot/jtreg/gc/arguments/TestAggressiveHeap.java +++ b/test/hotspot/jtreg/gc/arguments/TestAggressiveHeap.java @@ -65,11 +65,9 @@ public static void main(String args[]) throws Exception { " *bool +UseParallelGC *= *true +\\{product\\} *\\{command line\\}"; private static void testFlag() throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeTestJava( option, heapSizeOption, "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); String value = output.firstMatch(parallelGCPattern); diff --git a/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java b/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java index 0b6dce0fc0efd..c1975d6b69257 100644 --- a/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestCompressedClassFlags.java @@ -41,17 +41,13 @@ public class TestCompressedClassFlags { public static void main(String[] args) throws Exception { if (Platform.is64bit()) { - OutputAnalyzer output = runJava("-XX:CompressedClassSpaceSize=1g", - "-XX:-UseCompressedClassPointers", - "-version"); + OutputAnalyzer output = GCArguments.executeTestJava( + "-XX:CompressedClassSpaceSize=1g", + "-XX:-UseCompressedClassPointers", + "-version"); output.shouldContain("warning"); output.shouldNotContain("error"); output.shouldHaveExitValue(0); } } - - private static OutputAnalyzer runJava(String ... args) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(args); - return new OutputAnalyzer(pb.start()); - } } diff --git a/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java b/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java index e8e4552da0127..0828622fa7a5a 100644 --- a/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java +++ b/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java @@ -40,14 +40,13 @@ public class TestDisableDefaultGC { public static void main(String[] args) throws Exception { // Start VM, disabling all possible default GCs - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder("-XX:-UseSerialGC", - "-XX:-UseParallelGC", - "-XX:-UseG1GC", - "-XX:-UseZGC", - "-XX:+UnlockExperimentalVMOptions", - "-XX:-UseShenandoahGC", - "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava("-XX:-UseSerialGC", + "-XX:-UseParallelGC", + "-XX:-UseG1GC", + "-XX:-UseZGC", + "-XX:+UnlockExperimentalVMOptions", + "-XX:-UseShenandoahGC", + "-version"); output.shouldMatch("Garbage collector not selected"); output.shouldHaveExitValue(1); } diff --git a/test/hotspot/jtreg/gc/arguments/TestG1ConcMarkStepDurationMillis.java b/test/hotspot/jtreg/gc/arguments/TestG1ConcMarkStepDurationMillis.java index 21a4eddb410ec..c5f595e7a1a81 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1ConcMarkStepDurationMillis.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1ConcMarkStepDurationMillis.java @@ -78,8 +78,7 @@ private static void runG1ConcMarkStepDurationMillisTest(String expectedValue, in Collections.addAll(vmOpts, "-XX:+UseG1GC", "-XX:G1ConcMarkStepDurationMillis="+expectedValue, "-XX:+PrintFlagsFinal", "-version"); - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(vmOpts); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(vmOpts); output.shouldHaveExitValue(expectedResult == PASS ? 0 : 1); String stdout = output.getStdout(); diff --git a/test/hotspot/jtreg/gc/arguments/TestG1ConcRefinementThreads.java b/test/hotspot/jtreg/gc/arguments/TestG1ConcRefinementThreads.java index 91be97782f53f..f82d2b31711f7 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1ConcRefinementThreads.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1ConcRefinementThreads.java @@ -69,8 +69,7 @@ private static void runG1ConcRefinementThreadsTest(String[] passedOpts, } Collections.addAll(vmOpts, "-XX:+UseG1GC", "-XX:+PrintFlagsFinal", "-version"); - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(vmOpts); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(vmOpts); output.shouldHaveExitValue(0); String stdout = output.getStdout(); diff --git a/test/hotspot/jtreg/gc/arguments/TestG1HeapRegionSize.java b/test/hotspot/jtreg/gc/arguments/TestG1HeapRegionSize.java index 0d63dec0c26ee..5ecd27e24e856 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1HeapRegionSize.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1HeapRegionSize.java @@ -53,8 +53,7 @@ private static void checkG1HeapRegionSize(String[] flags, int expectedValue, int flagList.add("-XX:+PrintFlagsFinal"); flagList.add("-version"); - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(flagList); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(flagList); output.shouldHaveExitValue(exitValue); if (exitValue == 0) { diff --git a/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java b/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java index 875e995374aee..e8ee2598c9ad2 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java @@ -63,8 +63,7 @@ private static final class OptionDescription { }; private static void check(String flag, boolean is_valid) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder("-XX:+UseG1GC", flag, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava("-XX:+UseG1GC", flag, "-version"); if (is_valid) { output.shouldHaveExitValue(0); } else { diff --git a/test/hotspot/jtreg/gc/arguments/TestG1RemSetFlags.java b/test/hotspot/jtreg/gc/arguments/TestG1RemSetFlags.java index 84483f3927251..63b9d782c0638 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1RemSetFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1RemSetFlags.java @@ -48,8 +48,7 @@ private static void checkG1RemSetFlags(String[] flags, int exitValue) throws Exc flagList.add("-XX:+PrintFlagsFinal"); flagList.add("-version"); - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(flagList); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(flagList); output.shouldHaveExitValue(exitValue); } diff --git a/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java b/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java index 19ecb1814184c..c8eaa0f46e379 100644 --- a/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java +++ b/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java @@ -48,11 +48,10 @@ enum Validation { } private static void testMinMaxFreeRatio(String min, String max, Validation type) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeTestJava( "-Xminf" + min, "-Xmaxf" + max, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (type) { case VALID: diff --git a/test/hotspot/jtreg/gc/arguments/TestInitialTenuringThreshold.java b/test/hotspot/jtreg/gc/arguments/TestInitialTenuringThreshold.java index 7bf78a001bf95..07a9065cee131 100644 --- a/test/hotspot/jtreg/gc/arguments/TestInitialTenuringThreshold.java +++ b/test/hotspot/jtreg/gc/arguments/TestInitialTenuringThreshold.java @@ -41,14 +41,13 @@ public class TestInitialTenuringThreshold { public static void runWithThresholds(int initial, int max, boolean shouldfail) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeTestJava( "-XX:+UseParallelGC", "-XX:InitialTenuringThreshold=" + String.valueOf(initial), "-XX:MaxTenuringThreshold=" + String.valueOf(max), "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); if (shouldfail) { output.shouldHaveExitValue(1); } else { @@ -58,14 +57,13 @@ public static void runWithThresholds(int initial, int max, boolean shouldfail) t public static void main(String args[]) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeTestJava( // some value below the default value of InitialTenuringThreshold of 7 "-XX:+UseParallelGC", "-XX:MaxTenuringThreshold=1", "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); // successful tests runWithThresholds(0, 10, false); diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java b/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java index 3a5d472f9f8ce..5af005063c171 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java @@ -115,9 +115,8 @@ private static long align_up(long value, long alignment) { } private static void getNewOldSize(String gcflag, long[] values) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(gcflag, + OutputAnalyzer output = GCArguments.executeTestJava(gcflag, "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); String stdout = output.getStdout(); @@ -208,8 +207,7 @@ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, finalargs.add(classname); finalargs.addAll(Arrays.asList(arguments)); - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(finalargs.toArray(String[]::new)); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(finalargs.toArray(String[]::new)); output.shouldHaveExitValue(0); return output; @@ -308,8 +306,7 @@ private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, } private static void expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(flags); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(flags); shouldContainOrNot(output, hasWarning, "Warning"); shouldContainOrNot(output, hasError, "Error"); output.shouldHaveExitValue(errorcode); diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java b/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java index 7e91fe60cfb79..11729aa582730 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxMinHeapFreeRatioFlags.java @@ -98,8 +98,7 @@ public static void positiveTest(int minRatio, boolean useXminf, Boolean.toString(shrinkHeapInSteps) ); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(0); } @@ -123,8 +122,7 @@ public static void negativeTest(int minRatio, boolean useXminf, "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED", "-version" ); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(1); analyzer.shouldContain("Error: Could not create the Java Virtual Machine."); } diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java index f2214b8b0cfb9..ff6c31276405d 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java @@ -95,8 +95,7 @@ private static String getMaxNewSize(String[] flags) throws Exception { finalargs.add("-XX:+PrintFlagsFinal"); finalargs.add("-version"); - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder(finalargs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeTestJava(finalargs); output.shouldHaveExitValue(0); String stdout = output.getStdout(); return getFlagValue("MaxNewSize", stdout); diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxRAMFlags.java b/test/hotspot/jtreg/gc/arguments/TestMaxRAMFlags.java index 4c66afd5cf54d..13bb36ecc43d4 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxRAMFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxRAMFlags.java @@ -61,8 +61,7 @@ private static void checkMaxRAMSize(long maxram, int maxrampercent, boolean forc args.add("-XX:+PrintFlagsFinal"); args.add("-version"); - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(args); output.shouldHaveExitValue(0); String stdout = output.getStdout(); @@ -84,8 +83,7 @@ private static long getHeapBaseMinAddress() throws Exception { args.add("-XX:+PrintFlagsFinal"); args.add("-version"); - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(args); output.shouldHaveExitValue(0); String stdout = output.getStdout(); return (new Long(getFlagValue("HeapBaseMinAddress", stdout)).longValue()); diff --git a/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java b/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java index 83f564b98a5ef..d3a51c40b613d 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestMinAndInitialSurvivorRatioFlags.java @@ -102,8 +102,7 @@ public static void testSurvivorRatio(int survivorRatio, Boolean.toString(useAdaptiveSizePolicy) ); vmOptions.removeIf((String p) -> p.isEmpty()); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/arguments/TestNewRatioFlag.java b/test/hotspot/jtreg/gc/arguments/TestNewRatioFlag.java index 9076005fa8662..6eff65f3fa85a 100644 --- a/test/hotspot/jtreg/gc/arguments/TestNewRatioFlag.java +++ b/test/hotspot/jtreg/gc/arguments/TestNewRatioFlag.java @@ -82,8 +82,7 @@ public static void testNewRatio(int ratio, LinkedList options) throws Ex Integer.toString(ratio) ); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(0); System.out.println(analyzer.getOutput()); } diff --git a/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java b/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java index 3c3aff980dde4..8fc522f8be8b7 100644 --- a/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestNewSizeFlags.java @@ -133,7 +133,7 @@ public static void testVMOptions(long newSize, long maxNewSize, long heapSize, long maxHeapSize, long expectedNewSize, long expectedMaxNewSize, LinkedList options, boolean failureExpected) throws Exception { - OutputAnalyzer analyzer = startVM(options, newSize, maxNewSize, heapSize, maxHeapSize, expectedNewSize, expectedMaxNewSize); + OutputAnalyzer analyzer = executeLimitedTestJava(options, newSize, maxNewSize, heapSize, maxHeapSize, expectedNewSize, expectedMaxNewSize); if (failureExpected) { analyzer.shouldHaveExitValue(1); @@ -144,7 +144,7 @@ public static void testVMOptions(long newSize, long maxNewSize, } } - private static OutputAnalyzer startVM(LinkedList options, + private static OutputAnalyzer executeLimitedTestJava(LinkedList options, long newSize, long maxNewSize, long heapSize, long maxHeapSize, long expectedNewSize, long expectedMaxNewSize) throws Exception, IOException { @@ -166,9 +166,7 @@ private static OutputAnalyzer startVM(LinkedList options, Long.toString(maxHeapSize) ); vmOptions.removeIf(String::isEmpty); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); - return analyzer; + return GCArguments.executeLimitedTestJava(vmOptions); } /** diff --git a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java index 82e98429100c0..583176dfc696f 100644 --- a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java +++ b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java @@ -65,14 +65,13 @@ public static void main(String[] args) throws Exception { } static void runNewSizeThreadIncreaseTest(String expectedValue, boolean isNewsizeChanged) throws Exception { - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder("-XX:+UseSerialGC", - "-Xms96M", - "-Xmx128M", - "-XX:NewRatio=2", - "-Xlog:gc+heap+ergo=debug", - "-XX:NewSizeThreadIncrease="+expectedValue, - GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava("-XX:+UseSerialGC", + "-Xms96M", + "-Xmx128M", + "-XX:NewRatio=2", + "-Xlog:gc+heap+ergo=debug", + "-XX:NewSizeThreadIncrease="+expectedValue, + GCTest.class.getName()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/arguments/TestObjectTenuringFlags.java b/test/hotspot/jtreg/gc/arguments/TestObjectTenuringFlags.java index ca45def0b2b72..ee1e73f955007 100644 --- a/test/hotspot/jtreg/gc/arguments/TestObjectTenuringFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestObjectTenuringFlags.java @@ -161,8 +161,7 @@ private static void runTenuringFlagsConsistencyTest(String[] tenuringFlags, } Collections.addAll(vmOpts, "-XX:+UseParallelGC", "-XX:+PrintFlagsFinal", "-version"); - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(vmOpts); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(vmOpts); if (shouldFail) { output.shouldHaveExitValue(1); diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java index 1055f4fee1304..8cc3292b25fa5 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java @@ -56,10 +56,9 @@ public static void main(String args[]) throws Exception { private static final String printFlagsFinalPattern = " *uint *" + flagName + " *:?= *(\\d+) *\\{product\\} *"; public static void testDefaultValue() throws Exception { - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeLimitedTestJava( "-XX:+UnlockExperimentalVMOptions", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); String value = output.firstMatch(printFlagsFinalPattern, 1); try { @@ -94,12 +93,11 @@ public static void testFlags() throws Exception { for (String gc : supportedGC) { // Make sure the VM does not allow ParallelGCThreads set to 0 - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeLimitedTestJava( "-XX:+Use" + gc + "GC", "-XX:ParallelGCThreads=0", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(1); // Do some basic testing to ensure the flag updates the count @@ -124,8 +122,7 @@ public static void testFlags() throws Exception { } public static long getParallelGCThreadCount(String... flags) throws Exception { - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(flags); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(flags); output.shouldHaveExitValue(0); String stdout = output.getStdout(); return FlagsValue.getFlagLongValue("ParallelGCThreads", stdout); diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java b/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java index d47d277e30b82..40dfc4dc7fbee 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java @@ -77,9 +77,7 @@ private static void testFlag(String[] args, boolean expectedTrue) throws Excepti result.addAll(Arrays.asList(args)); result.add("-XX:+PrintFlagsFinal"); result.add("-version"); - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(result); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(result); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java b/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java index a48f21c957bed..fb4787f452fea 100644 --- a/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java +++ b/test/hotspot/jtreg/gc/arguments/TestSelectDefaultGC.java @@ -44,12 +44,11 @@ public static void assertVMOption(OutputAnalyzer output, String option, boolean public static void testDefaultGC(boolean actAsServer) throws Exception { // Start VM without specifying GC - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeLimitedTestJava( "-XX:" + (actAsServer ? "+" : "-") + "AlwaysActAsServerClassMachine", "-XX:" + (actAsServer ? "-" : "+") + "NeverActAsServerClassMachine", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); final boolean isServer = actAsServer; diff --git a/test/hotspot/jtreg/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java b/test/hotspot/jtreg/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java index 779a5d8b53714..f517e094edd44 100644 --- a/test/hotspot/jtreg/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java +++ b/test/hotspot/jtreg/gc/arguments/TestSmallInitialHeapWithLargePageAndNUMA.java @@ -60,14 +60,13 @@ public static void main(String[] args) throws Exception { long initHeap = heapAlignment; long maxHeap = heapAlignment * 2; - ProcessBuilder pb_enabled = GCArguments.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava( "-XX:+UseParallelGC", "-Xms" + String.valueOf(initHeap), "-Xmx" + String.valueOf(maxHeap), "-XX:+UseNUMA", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb_enabled.start()); if (largePageOrNumaEnabled(analyzer)) { // We reach here, if both NUMA and HugeTLB are supported. diff --git a/test/hotspot/jtreg/gc/arguments/TestSurvivorRatioFlag.java b/test/hotspot/jtreg/gc/arguments/TestSurvivorRatioFlag.java index 8567615220ad9..a593970e6f7b3 100644 --- a/test/hotspot/jtreg/gc/arguments/TestSurvivorRatioFlag.java +++ b/test/hotspot/jtreg/gc/arguments/TestSurvivorRatioFlag.java @@ -87,8 +87,7 @@ public static void testSurvivorRatio(int ratio, LinkedList options) thro Integer.toString(ratio) ); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/arguments/TestTargetSurvivorRatioFlag.java b/test/hotspot/jtreg/gc/arguments/TestTargetSurvivorRatioFlag.java index 8f8b4aa10877a..afe424896b567 100644 --- a/test/hotspot/jtreg/gc/arguments/TestTargetSurvivorRatioFlag.java +++ b/test/hotspot/jtreg/gc/arguments/TestTargetSurvivorRatioFlag.java @@ -116,8 +116,7 @@ public static void negativeTest(int ratio, LinkedList options) throws Ex vmOptions.add("-XX:TargetSurvivorRatio=" + ratio); vmOptions.add("-version"); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(1); analyzer.shouldContain("Error: Could not create the Java Virtual Machine."); @@ -151,8 +150,7 @@ public static void positiveTest(int ratio, LinkedList options) throws Ex Integer.toString(ratio) ); - ProcessBuilder procBuilder = GCArguments.createLimitedTestJavaProcessBuilder(vmOptions); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOptions); analyzer.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/arguments/TestUnrecognizedVMOptionsHandling.java b/test/hotspot/jtreg/gc/arguments/TestUnrecognizedVMOptionsHandling.java index 24da380298b78..f944c0c4e7423 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUnrecognizedVMOptionsHandling.java +++ b/test/hotspot/jtreg/gc/arguments/TestUnrecognizedVMOptionsHandling.java @@ -40,32 +40,29 @@ public class TestUnrecognizedVMOptionsHandling { public static void main(String args[]) throws Exception { // The first two JAVA processes are expected to fail, but with a correct VM option suggestion - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder( + OutputAnalyzer outputWithError = GCArguments.executeLimitedTestJava( "-XX:+UseDynamicNumberOfGcThreads", "-version" ); - OutputAnalyzer outputWithError = new OutputAnalyzer(pb.start()); outputWithError.shouldContain("Did you mean '(+/-)UseDynamicNumberOfGCThreads'?"); if (outputWithError.getExitValue() == 0) { throw new RuntimeException("Not expected to get exit value 0"); } - pb = GCArguments.createLimitedTestJavaProcessBuilder( + outputWithError = GCArguments.executeLimitedTestJava( "-XX:MaxiumHeapSize=500m", "-version" ); - outputWithError = new OutputAnalyzer(pb.start()); outputWithError.shouldContain("Did you mean 'MaxHeapSize='?"); if (outputWithError.getExitValue() == 0) { throw new RuntimeException("Not expected to get exit value 0"); } // The last JAVA process should run successfully for the purpose of sanity check - pb = GCArguments.createLimitedTestJavaProcessBuilder( + OutputAnalyzer outputWithNoError = GCArguments.executeLimitedTestJava( "-XX:+UseDynamicNumberOfGCThreads", "-version" ); - OutputAnalyzer outputWithNoError = new OutputAnalyzer(pb.start()); outputWithNoError.shouldNotContain("Did you mean '(+/-)UseDynamicNumberOfGCThreads'?"); outputWithNoError.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgoTools.java b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgoTools.java index 19ebdea3c0eba..2a1d2fef879de 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgoTools.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsErgoTools.java @@ -93,8 +93,7 @@ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, finalargs.add(classname); finalargs.addAll(Arrays.asList(arguments)); - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(finalargs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(finalargs); output.shouldHaveExitValue(0); return output; } @@ -157,8 +156,7 @@ private static boolean getFlagBoolValue(String flag, String where) { } private static String expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception { - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(flags); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = GCArguments.executeLimitedTestJava(flags); output.shouldHaveExitValue(errorcode); return output.getStdout(); } diff --git a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java index 07cf4126970a8..495b36407b120 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java @@ -59,9 +59,8 @@ private static void checkFlag(long ulimit, long maxram, int maxrampercent, boole // Convert bytes to kbytes for ulimit -v var ulimit_prefix = "ulimit -v " + (ulimit / 1024); - String cmd = ProcessTools.getCommandLine(ProcessTools.createTestJavaProcessBuilder(args.toArray(String[]::new))); - ProcessBuilder pb = new ProcessBuilder("sh", "-c", ulimit_prefix + ";" + cmd); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + String cmd = ProcessTools.getCommandLine(ProcessTools.createTestJavaProcessBuilder(args)); + OutputAnalyzer output = ProcessTools.executeProcess("sh", "-c", ulimit_prefix + ";" + cmd); output.shouldHaveExitValue(0); String stdout = output.getStdout(); diff --git a/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java b/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java index 4a7fb7108c3c7..29c13f1fd9010 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseNUMAInterleaving.java @@ -39,11 +39,10 @@ public class TestUseNUMAInterleaving { public static void main(String[] args) throws Exception { - ProcessBuilder pb = GCArguments.createTestJavaProcessBuilder( + OutputAnalyzer output = GCArguments.executeTestJava( "-XX:+UseNUMA", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); boolean isNUMAEnabled = Boolean.parseBoolean(output.firstMatch(NUMA_FLAG_PATTERN, 1)); diff --git a/test/hotspot/jtreg/gc/arguments/TestVerifyBeforeAndAfterGCFlags.java b/test/hotspot/jtreg/gc/arguments/TestVerifyBeforeAndAfterGCFlags.java index a3d6d5a7440c5..cc1f9be6fb704 100644 --- a/test/hotspot/jtreg/gc/arguments/TestVerifyBeforeAndAfterGCFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestVerifyBeforeAndAfterGCFlags.java @@ -99,8 +99,7 @@ public static void testVerifyFlags(boolean verifyBeforeGC, : "-XX:-VerifyAfterGC"), GarbageProducer.class.getName(), doFullGC ? "t" : "f" }); - ProcessBuilder pb = GCArguments.createLimitedTestJavaProcessBuilder(vmOpts); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + OutputAnalyzer analyzer = GCArguments.executeLimitedTestJava(vmOpts); analyzer.shouldHaveExitValue(0); analyzer.shouldNotMatch(VERIFY_BEFORE_GC_CORRUPTED_PATTERN); diff --git a/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java b/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java index 238e747fb1ef7..9af3baf87b32c 100644 --- a/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java +++ b/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java @@ -45,7 +45,7 @@ public class TestG1ClassUnloadingHWM { private static long YoungGenSize = 32 * 1024 * 1024; private static OutputAnalyzer run(boolean enableUnloading) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + return ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", @@ -57,7 +57,6 @@ private static OutputAnalyzer run(boolean enableUnloading) throws Exception { TestG1ClassUnloadingHWM.AllocateBeyondMetaspaceSize.class.getName(), "" + MetaspaceSize, "" + YoungGenSize); - return new OutputAnalyzer(pb.start()); } public static OutputAnalyzer runWithG1ClassUnloading() throws Exception { diff --git a/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java b/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java index c978f149fcac5..016bb517c3c56 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java +++ b/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java @@ -37,15 +37,13 @@ public class TestDieDefault { public static void passWith(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); + OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); out.shouldNotContain("OutOfMemoryError"); out.shouldHaveExitValue(0); } public static void failWith(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); + OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); out.shouldContain("OutOfMemoryError"); if (out.getExitValue() == 0) { throw new IllegalStateException("Should have failed with non-zero exit code"); diff --git a/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java b/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java index 2e19141d286cb..8f6e9a36d7723 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java +++ b/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java @@ -38,8 +38,7 @@ public class TestDieWithHeapDump { public static void passWith(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); + OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); out.shouldNotContain("OutOfMemoryError"); out.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java b/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java index a6593fecdff8b..7be60c59595db 100644 --- a/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java +++ b/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java @@ -39,16 +39,14 @@ public class TestDieWithOnError { static String ON_ERR_MSG = "Epsilon error handler message"; public static void passWith(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); + OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); out.shouldNotContain("OutOfMemoryError"); out.stdoutShouldNotMatch("^" + ON_ERR_MSG); out.shouldHaveExitValue(0); } public static void failWith(String... args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); + OutputAnalyzer out = ProcessTools.executeLimitedTestJava(args); out.shouldContain("OutOfMemoryError"); if (out.getExitValue() == 0) { throw new IllegalStateException("Should have failed with non-zero exit code"); diff --git a/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java b/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java index 288d27393a3e5..511f482980b46 100644 --- a/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java +++ b/test/hotspot/jtreg/gc/ergonomics/TestDynamicNumberOfGCThreads.java @@ -68,16 +68,16 @@ private static void testDynamicNumberOfGCThreads(String gcFlag) throws Exception String[] baseArgs = {"-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", GCTest.class.getName()}; // Base test with gc and +UseDynamicNumberOfGCThreads: - ProcessBuilder pb_enabled = ProcessTools.createLimitedTestJavaProcessBuilder(baseArgs); - verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start())); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(baseArgs); + verifyDynamicNumberOfGCThreads(output); // Turn on parallel reference processing String[] parRefProcArg = {"-XX:+ParallelRefProcEnabled", "-XX:-ShowMessageBoxOnError"}; String[] parRefArgs = new String[baseArgs.length + parRefProcArg.length]; System.arraycopy(parRefProcArg, 0, parRefArgs, 0, parRefProcArg.length); System.arraycopy(baseArgs, 0, parRefArgs, parRefProcArg.length, baseArgs.length); - pb_enabled = ProcessTools.createLimitedTestJavaProcessBuilder(parRefArgs); - verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start())); + output = ProcessTools.executeLimitedTestJava(parRefArgs); + verifyDynamicNumberOfGCThreads(output); } static class GCTest { diff --git a/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java b/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java index dc1b83cd2c1ee..e58b930b51940 100644 --- a/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java +++ b/test/hotspot/jtreg/gc/ergonomics/TestInitialGCThreadLogging.java @@ -70,13 +70,13 @@ private static void verifyDynamicNumberOfGCThreads(OutputAnalyzer output, String private static void testInitialGCThreadLogging(String gcFlag, String threadName) throws Exception { // Base test with gc and +UseDynamicNumberOfGCThreads: - ProcessBuilder pb_enabled = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xmx10M", "-XX:+UseDynamicNumberOfGCThreads", "-Xlog:gc+task=trace", "-version"); - verifyDynamicNumberOfGCThreads(new OutputAnalyzer(pb_enabled.start()), threadName); + verifyDynamicNumberOfGCThreads(output, threadName); } } diff --git a/test/hotspot/jtreg/gc/g1/Test2GbHeap.java b/test/hotspot/jtreg/gc/g1/Test2GbHeap.java index 8e06ac3ee2c69..9b9818837145f 100644 --- a/test/hotspot/jtreg/gc/g1/Test2GbHeap.java +++ b/test/hotspot/jtreg/gc/g1/Test2GbHeap.java @@ -49,9 +49,8 @@ public static void main(String[] args) throws Exception { testArguments.add("-Xmx2g"); testArguments.add("-version"); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(testArguments); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(testArguments); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java b/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java index 0723eb89f51c9..ab5e9d1b06036 100644 --- a/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java +++ b/test/hotspot/jtreg/gc/g1/TestAllocationFailure.java @@ -43,17 +43,16 @@ public class TestAllocationFailure { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx32M", - "-Xmn16M", - "-XX:+G1GCAllocationFailureALot", - "-XX:G1GCAllocationFailureALotCount=100", - "-XX:G1GCAllocationFailureALotInterval=1", - "-XX:+UnlockDiagnosticVMOptions", - "-Xlog:gc", - GCTestWithAllocationFailure.class.getName()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx32M", + "-Xmn16M", + "-XX:+G1GCAllocationFailureALot", + "-XX:G1GCAllocationFailureALotCount=100", + "-XX:G1GCAllocationFailureALotInterval=1", + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:gc", + GCTestWithAllocationFailure.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println(output.getStdout()); output.shouldContain("(Evacuation Failure:"); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java index a334783eca6c1..d1ae8ab734c94 100644 --- a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java +++ b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegions.java @@ -80,7 +80,7 @@ public static void main(String[] args) { public class TestEagerReclaimHumongousRegions { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-XX:+UseG1GC", "-Xms128M", "-Xmx128M", @@ -90,8 +90,6 @@ public static void main(String[] args) throws Exception { Pattern p = Pattern.compile("Full GC"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - int found = 0; Matcher m = p.matcher(output.getStdout()); while (m.find()) { found++; } diff --git a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java index 56de136fe5970..4e4f864d33911 100644 --- a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java +++ b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsClearMarkBits.java @@ -119,7 +119,7 @@ public static void main(String[] args) { public class TestEagerReclaimHumongousRegionsClearMarkBits { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-XX:+UseG1GC", "-Xms128M", "-Xmx128M", @@ -132,7 +132,6 @@ public static void main(String[] args) throws Exception { "-XX:ConcGCThreads=1", // Want to make marking as slow as possible. "-XX:+G1VerifyBitmaps", TestEagerReclaimHumongousRegionsClearMarkBitsReclaimRegionFast.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsLog.java b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsLog.java index 03af9c2b4bba7..33825bff0b773 100644 --- a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsLog.java +++ b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsLog.java @@ -54,7 +54,7 @@ private static String getSumValue(String s) { } public static void runTest() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", @@ -65,7 +65,6 @@ public static void runTest() throws Exception { "-Xmx128M", "-Xlog:gc+phases=trace,gc+heap=info", GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java index 335567a9c3659..a555977eb3e01 100644 --- a/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java +++ b/test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsWithRefs.java @@ -92,7 +92,7 @@ public static void main(String[] args) { public class TestEagerReclaimHumongousRegionsWithRefs { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-XX:+UseG1GC", "-Xms128M", "-Xmx128M", @@ -102,8 +102,6 @@ public static void main(String[] args) throws Exception { Pattern p = Pattern.compile("Full GC"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - int found = 0; Matcher m = p.matcher(output.getStdout()); while (m.find()) { diff --git a/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java b/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java index 8455e03b18fa6..3e986a5dede09 100644 --- a/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java +++ b/test/hotspot/jtreg/gc/g1/TestG1SkipCompaction.java @@ -54,8 +54,7 @@ public static void runTest() throws Exception { "-XX:G1HeapRegionSize=1m", GCTest.class.getName() }; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(arguments); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(arguments); System.out.println(output.getStdout()); String pattern = ".*skip compaction region.*"; diff --git a/test/hotspot/jtreg/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java b/test/hotspot/jtreg/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java index 4dedac0a61bbb..d1cb29b314e35 100644 --- a/test/hotspot/jtreg/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java +++ b/test/hotspot/jtreg/gc/g1/TestG1TraceEagerReclaimHumongousObjects.java @@ -41,16 +41,14 @@ public class TestG1TraceEagerReclaimHumongousObjects { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xms128M", - "-Xmx128M", - "-Xmn16M", - "-XX:G1HeapRegionSize=1M", - "-Xlog:gc+phases=trace,gc+humongous=trace", - "-XX:+UnlockExperimentalVMOptions", - GCWithHumongousObjectTest.class.getName()); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn16M", + "-XX:G1HeapRegionSize=1M", + "-Xlog:gc+phases=trace,gc+humongous=trace", + "-XX:+UnlockExperimentalVMOptions", + GCWithHumongousObjectTest.class.getName()); System.out.println(output.getStdout()); // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed. diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index c29919e8afff8..e5db6cb0daeda 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -218,28 +218,25 @@ public static void main(String[] args) throws Exception { private void testNormalLogs() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx10M", - GCTest.class.getName()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx10M", + GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); checkMessagesAtLevel(output, allLogMessages, Level.OFF); output.shouldHaveExitValue(0); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx10M", - "-Xlog:gc+phases=debug", - GCTest.class.getName()); + output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx10M", + "-Xlog:gc+phases=debug", + GCTest.class.getName()); - output = new OutputAnalyzer(pb.start()); checkMessagesAtLevel(output, allLogMessages, Level.DEBUG); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx10M", - "-Xlog:gc+phases=trace", - GCTest.class.getName()); + output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx10M", + "-Xlog:gc+phases=trace", + GCTest.class.getName()); - output = new OutputAnalyzer(pb.start()); checkMessagesAtLevel(output, allLogMessages, Level.TRACE); output.shouldHaveExitValue(0); } @@ -253,11 +250,10 @@ private void testNormalLogs() throws Exception { }; private void testConcurrentRefinementLogs() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx10M", - "-Xlog:gc+refine+stats=debug", - GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx10M", + "-Xlog:gc+refine+stats=debug", + GCTest.class.getName()); checkMessagesAtLevel(output, concRefineMessages, Level.DEBUG); } @@ -272,29 +268,27 @@ private void testConcurrentRefinementLogs() throws Exception { }; private void testWithEvacuationFailureLogs() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx32M", - "-Xmn16M", - "-XX:+G1GCAllocationFailureALot", - "-XX:G1GCAllocationFailureALotCount=100", - "-XX:G1GCAllocationFailureALotInterval=1", - "-XX:+UnlockDiagnosticVMOptions", - "-Xlog:gc+phases=debug", - GCTestWithAllocationFailure.class.getName()); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx32M", + "-Xmn16M", + "-XX:+G1GCAllocationFailureALot", + "-XX:G1GCAllocationFailureALotCount=100", + "-XX:G1GCAllocationFailureALotInterval=1", + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:gc+phases=debug", + GCTestWithAllocationFailure.class.getName()); + checkMessagesAtLevel(output, exhFailureMessages, Level.DEBUG); output.shouldHaveExitValue(0); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx32M", - "-Xmn16M", - "-Xms32M", - "-XX:+UnlockDiagnosticVMOptions", - "-Xlog:gc+phases=trace", - GCTestWithAllocationFailure.class.getName()); + output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx32M", + "-Xmn16M", + "-Xms32M", + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:gc+phases=trace", + GCTestWithAllocationFailure.class.getName()); - output = new OutputAnalyzer(pb.start()); checkMessagesAtLevel(output, exhFailureMessages, Level.TRACE); output.shouldHaveExitValue(0); } @@ -305,29 +299,27 @@ private void testWithEvacuationFailureLogs() throws Exception { }; private void testWithConcurrentStart() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx10M", - "-Xbootclasspath/a:.", - "-Xlog:gc*=debug", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - GCTestWithConcurrentStart.class.getName()); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx10M", + "-Xbootclasspath/a:.", + "-Xlog:gc*=debug", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + GCTestWithConcurrentStart.class.getName()); + checkMessagesAtLevel(output, concurrentStartMessages, Level.TRACE); output.shouldHaveExitValue(0); } private void testExpandHeap() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-Xmx10M", - "-Xbootclasspath/a:.", - "-Xlog:gc+ergo+heap=debug", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - GCTest.class.getName()); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-Xmx10M", + "-Xbootclasspath/a:.", + "-Xlog:gc+ergo+heap=debug", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + GCTest.class.getName()); + output.shouldContain("Expand the heap. requested expansion amount: "); output.shouldContain("B expansion amount: "); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestHumongousAllocConcurrentStart.java b/test/hotspot/jtreg/gc/g1/TestHumongousAllocConcurrentStart.java index b3a754f74c5a9..9631fd1855ce1 100644 --- a/test/hotspot/jtreg/gc/g1/TestHumongousAllocConcurrentStart.java +++ b/test/hotspot/jtreg/gc/g1/TestHumongousAllocConcurrentStart.java @@ -45,7 +45,7 @@ public class TestHumongousAllocConcurrentStart { private static final int initiatingHeapOccupancyPercent = 50; // % public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeTestJava( "-XX:+UseG1GC", "-Xms" + heapSize + "m", "-Xmx" + heapSize + "m", @@ -54,7 +54,6 @@ public static void main(String[] args) throws Exception { "-Xlog:gc", HumongousObjectAllocator.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Pause Young (Concurrent Start) (G1 Humongous Allocation)"); output.shouldNotContain("Full GC"); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestHumongousAllocNearlyFullRegion.java b/test/hotspot/jtreg/gc/g1/TestHumongousAllocNearlyFullRegion.java index fb33e9cc7c547..d6d8b5578cce9 100644 --- a/test/hotspot/jtreg/gc/g1/TestHumongousAllocNearlyFullRegion.java +++ b/test/hotspot/jtreg/gc/g1/TestHumongousAllocNearlyFullRegion.java @@ -47,7 +47,7 @@ public class TestHumongousAllocNearlyFullRegion { private static final int heapRegionSize = 1; // MB public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-XX:+UseG1GC", "-Xms" + heapSize + "m", "-Xmx" + heapSize + "m", @@ -55,7 +55,6 @@ public static void main(String[] args) throws Exception { "-Xlog:gc", HumongousObjectAllocator.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Pause Young (Concurrent Start) (G1 Humongous Allocation)"); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/g1/TestHumongousCodeCacheRoots.java b/test/hotspot/jtreg/gc/g1/TestHumongousCodeCacheRoots.java index 2e669f6dfe19d..97ffd6c8da7c2 100644 --- a/test/hotspot/jtreg/gc/g1/TestHumongousCodeCacheRoots.java +++ b/test/hotspot/jtreg/gc/g1/TestHumongousCodeCacheRoots.java @@ -106,8 +106,7 @@ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, finalargs.add(classname); finalargs.addAll(Arrays.asList(arguments)); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(finalargs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(finalargs); output.shouldHaveExitValue(0); return output; } diff --git a/test/hotspot/jtreg/gc/g1/TestHumongousConcurrentStartUndo.java b/test/hotspot/jtreg/gc/g1/TestHumongousConcurrentStartUndo.java index d30d9240103fc..ed5ff35021a3e 100644 --- a/test/hotspot/jtreg/gc/g1/TestHumongousConcurrentStartUndo.java +++ b/test/hotspot/jtreg/gc/g1/TestHumongousConcurrentStartUndo.java @@ -56,7 +56,7 @@ public class TestHumongousConcurrentStartUndo { private static final int YoungSize = HeapSize / 8; public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-XX:+UseG1GC", "-Xms" + HeapSize + "m", @@ -70,7 +70,6 @@ public static void main(String[] args) throws Exception { "-Xlog:gc*", EdenObjectAllocatorWithHumongousAllocation.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Pause Young (Concurrent Start) (G1 Humongous Allocation)"); output.shouldContain("Concurrent Undo Cycle"); output.shouldContain("Concurrent Mark Cycle"); diff --git a/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java b/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java index 777391845a422..3051cd7310b89 100644 --- a/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java +++ b/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java @@ -120,12 +120,9 @@ static List getOpts(long heapsize, boolean largePageEnabled) { static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception { System.out.println(what + " heapsize " + heapsize + " card table should use large pages " + cardsShouldUseLargePages + " " + "bitmaps should use large pages " + bitmapShouldUseLargePages); - ProcessBuilder pb; // Test with large page enabled. - pb = ProcessTools.createLimitedTestJavaProcessBuilder(getOpts(heapsize, true)); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(getOpts(heapsize, true)); // Only expect large page size if large pages are enabled. if (largePagesEnabled(output)) { @@ -138,9 +135,8 @@ static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, output.shouldHaveExitValue(0); // Test with large page disabled. - pb = ProcessTools.createLimitedTestJavaProcessBuilder(getOpts(heapsize, false)); + output = ProcessTools.executeLimitedTestJava(getOpts(heapsize, false)); - output = new OutputAnalyzer(pb.start()); checkSmallTables(output, smallPageSize); checkBitmap(output, smallPageSize); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestLargePageUseForHeap.java b/test/hotspot/jtreg/gc/g1/TestLargePageUseForHeap.java index 72afde512bc57..7009ae00d9268 100644 --- a/test/hotspot/jtreg/gc/g1/TestLargePageUseForHeap.java +++ b/test/hotspot/jtreg/gc/g1/TestLargePageUseForHeap.java @@ -85,29 +85,26 @@ static void checkHeap(OutputAnalyzer output, long expectedPageSize) throws Excep } static void testVM(long regionSize) throws Exception { - ProcessBuilder pb; // Test with large page enabled. - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:G1HeapRegionSize=" + regionSize, - "-Xmx128m", - "-Xlog:gc+init,pagesize,gc+heap+coops=debug", - "-XX:+UseLargePages", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:G1HeapRegionSize=" + regionSize, + "-Xmx128m", + "-Xlog:gc+init,pagesize,gc+heap+coops=debug", + "-XX:+UseLargePages", + "-version"); + boolean largePageEnabled = checkLargePageEnabled(output); checkHeap(output, largePageEnabled ? largePageSize : smallPageSize); output.shouldHaveExitValue(0); // Test with large page disabled. - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:G1HeapRegionSize=" + regionSize, - "-Xmx128m", - "-Xlog:gc+init,pagesize,gc+heap+coops=debug", - "-XX:-UseLargePages", - "-version"); - - output = new OutputAnalyzer(pb.start()); + output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:G1HeapRegionSize=" + regionSize, + "-Xmx128m", + "-Xlog:gc+init,pagesize,gc+heap+coops=debug", + "-XX:-UseLargePages", + "-version"); + checkHeap(output, smallPageSize); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/g1/TestMarkStackSizes.java b/test/hotspot/jtreg/gc/g1/TestMarkStackSizes.java index d056a5ef74720..0a1c373199cb5 100644 --- a/test/hotspot/jtreg/gc/g1/TestMarkStackSizes.java +++ b/test/hotspot/jtreg/gc/g1/TestMarkStackSizes.java @@ -50,9 +50,7 @@ private static void runTest(boolean shouldSucceed, String... extraArgs) throws E Collections.addAll(testArguments, extraArgs); testArguments.add("-version"); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(testArguments); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(testArguments); System.out.println(output.getStderr()); diff --git a/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java b/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java index 035a6b896796f..e0aa08277492e 100644 --- a/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java +++ b/test/hotspot/jtreg/gc/g1/TestMixedGCLiveThreshold.java @@ -109,9 +109,7 @@ private static OutputAnalyzer testWithMixedGCLiveThresholdPercent(int percent) t basicOpts.add(GCTest.class.getName()); - ProcessBuilder procBuilder = ProcessTools.createLimitedTestJavaProcessBuilder(basicOpts); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); - return analyzer; + return ProcessTools.executeLimitedTestJava(basicOpts); } private static boolean regionsSelectedForRebuild(String output) throws Exception { diff --git a/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java b/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java index 36c3c04c629d3..6bbf0213f36ca 100644 --- a/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java +++ b/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java @@ -40,7 +40,7 @@ public class TestOneEdenRegionAfterGC { private static long YoungGenSize = 32 * 1024 * 1024; private static OutputAnalyzer run() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + return ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-Xmn" + YoungGenSize, "-Xmx512M", @@ -50,7 +50,6 @@ private static OutputAnalyzer run() throws Exception { "-Xlog:gc,gc+ergo*=trace", TestOneEdenRegionAfterGC.Allocate.class.getName(), "" + YoungGenSize); - return new OutputAnalyzer(pb.start()); } public static void main(String args[]) throws Exception { diff --git a/test/hotspot/jtreg/gc/g1/TestPLABOutput.java b/test/hotspot/jtreg/gc/g1/TestPLABOutput.java index e6342a1911c6b..fecb8dcfc415a 100644 --- a/test/hotspot/jtreg/gc/g1/TestPLABOutput.java +++ b/test/hotspot/jtreg/gc/g1/TestPLABOutput.java @@ -59,8 +59,7 @@ public static void runTest() throws Exception { GCTest.class.getName() }; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(arguments); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(arguments); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestPLABSizeBounds.java b/test/hotspot/jtreg/gc/g1/TestPLABSizeBounds.java index ade281a4a929f..c0427e1ada3a1 100644 --- a/test/hotspot/jtreg/gc/g1/TestPLABSizeBounds.java +++ b/test/hotspot/jtreg/gc/g1/TestPLABSizeBounds.java @@ -62,8 +62,7 @@ public static void runTest(int regionSize, int plabSize, boolean shouldSucceed) testArguments.add("-XX:OldPLABSize=" + plabSize); testArguments.add(GCTest.class.getName()); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(testArguments); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(testArguments); if (shouldSucceed) { output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestPeriodicLogMessages.java b/test/hotspot/jtreg/gc/g1/TestPeriodicLogMessages.java index de79be020b491..7b4303e55a258 100644 --- a/test/hotspot/jtreg/gc/g1/TestPeriodicLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestPeriodicLogMessages.java @@ -40,24 +40,22 @@ public class TestPeriodicLogMessages { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:G1PeriodicGCInterval=0", - "-Xlog:gc+init,gc+periodic=debug", - "-Xmx10M", - GCTest.class.getName()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:G1PeriodicGCInterval=0", + "-Xlog:gc+init,gc+periodic=debug", + "-Xmx10M", + GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Periodic GC: Disabled"); output.shouldNotContain("Checking for periodic GC"); output.shouldHaveExitValue(0); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:G1PeriodicGCInterval=100", - "-Xlog:gc+init,gc+periodic=debug", - "-Xmx10M", - GCTest.class.getName()); + output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:G1PeriodicGCInterval=100", + "-Xlog:gc+init,gc+periodic=debug", + "-Xmx10M", + GCTest.class.getName()); - output = new OutputAnalyzer(pb.start()); output.shouldContain("Periodic GC: Enabled"); output.shouldContain("Periodic GC Interval: 100ms"); output.shouldContain("Checking for periodic GC"); diff --git a/test/hotspot/jtreg/gc/g1/TestPrintRegionRememberedSetInfo.java b/test/hotspot/jtreg/gc/g1/TestPrintRegionRememberedSetInfo.java index ea718c7f6ed08..11f02643d1d70 100644 --- a/test/hotspot/jtreg/gc/g1/TestPrintRegionRememberedSetInfo.java +++ b/test/hotspot/jtreg/gc/g1/TestPrintRegionRememberedSetInfo.java @@ -69,8 +69,7 @@ public static String runTest(String arg) throws Exception { finalargs.add(RunAndWaitForMarking.class.getName()); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(finalargs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(finalargs); output.shouldHaveExitValue(0); String result = output.getStdout(); diff --git a/test/hotspot/jtreg/gc/g1/TestRemsetLoggingThreads.java b/test/hotspot/jtreg/gc/g1/TestRemsetLoggingThreads.java index 5d4b4d958f8ed..c2b1be603227e 100644 --- a/test/hotspot/jtreg/gc/g1/TestRemsetLoggingThreads.java +++ b/test/hotspot/jtreg/gc/g1/TestRemsetLoggingThreads.java @@ -44,14 +44,12 @@ public class TestRemsetLoggingThreads { private static void runTest(int refinementThreads, int workerThreads) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:+UnlockDiagnosticVMOptions", - "-Xlog:gc+remset+exit=trace", - "-XX:G1ConcRefinementThreads=" + refinementThreads, - "-XX:ParallelGCThreads=" + workerThreads, - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:+UnlockDiagnosticVMOptions", + "-Xlog:gc+remset+exit=trace", + "-XX:G1ConcRefinementThreads=" + refinementThreads, + "-XX:ParallelGCThreads=" + workerThreads, + "-version"); String pattern = "Concurrent refinement threads times \\(s\\)$"; Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(output.getStdout()); diff --git a/test/hotspot/jtreg/gc/g1/TestRemsetLoggingTools.java b/test/hotspot/jtreg/gc/g1/TestRemsetLoggingTools.java index 69f34e071462f..7e44c41e1a4a5 100644 --- a/test/hotspot/jtreg/gc/g1/TestRemsetLoggingTools.java +++ b/test/hotspot/jtreg/gc/g1/TestRemsetLoggingTools.java @@ -77,8 +77,7 @@ public static String runTest(String[] additionalArgs, int numGCs) throws Excepti finalargs.add(VerifySummaryOutput.class.getName()); finalargs.add(String.valueOf(numGCs)); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(finalargs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(finalargs); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java b/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java index d894c58d73757..aef9a98530c59 100644 --- a/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java +++ b/test/hotspot/jtreg/gc/g1/TestSharedArchiveWithPreTouch.java @@ -50,8 +50,6 @@ public static void main(String[] args) throws Exception { final List BaseOptions = Arrays.asList(new String[] {"-XX:+UseG1GC", "-XX:+AlwaysPreTouch", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=" + ArchiveFileName }); - ProcessBuilder pb; - List dump_args = new ArrayList(BaseOptions); if (Platform.is64bit()) { @@ -59,8 +57,8 @@ public static void main(String[] args) throws Exception { } dump_args.addAll(Arrays.asList(new String[] { "-Xshare:dump", "-Xlog:cds" })); - pb = ProcessTools.createLimitedTestJavaProcessBuilder(dump_args); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(dump_args); + try { output.shouldContain("Loading classes to share"); output.shouldHaveExitValue(0); @@ -72,8 +70,7 @@ public static void main(String[] args) throws Exception { } load_args.addAll(Arrays.asList(new String[] { "-Xshare:on", "-version" })); - pb = ProcessTools.createLimitedTestJavaProcessBuilder(load_args.toArray(new String[0])); - output = new OutputAnalyzer(pb.start()); + output = ProcessTools.executeLimitedTestJava(load_args.toArray(new String[0])); output.shouldContain("sharing"); output.shouldHaveExitValue(0); } catch (RuntimeException e) { diff --git a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java index 645e545443d1d..8f68ccba9ada9 100644 --- a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java +++ b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryData.java @@ -88,9 +88,8 @@ protected void test() throws Exception { } private void performTest(List opts) throws Exception { - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(opts); + OutputAnalyzer output = ProcessTools.executeTestJava(opts); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println(output.getStdout()); System.err.println(output.getStderr()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java b/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java index acdce6b641752..7934660a32309 100644 --- a/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java +++ b/test/hotspot/jtreg/gc/g1/TestShrinkDefragmentedHeap.java @@ -61,7 +61,7 @@ public class TestShrinkDefragmentedHeap { private static final int REGION_SIZE = 1 * 1024 * 1024; public static void main(String[] args) throws Exception, Throwable { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-XX:InitialHeapSize=" + INITIAL_HEAP_SIZE, "-Xmn" + MINIMAL_YOUNG_SIZE, "-Xmx" + MAXIMUM_HEAP_SIZE, @@ -74,7 +74,6 @@ public static void main(String[] args) throws Exception, Throwable { GCTest.class.getName() ); - OutputAnalyzer output = ProcessTools.executeProcess(pb); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java index 4c7190ada02d6..f7f768c9d7dfd 100644 --- a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java +++ b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java @@ -40,17 +40,16 @@ public class TestSkipRebuildRemsetPhase { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xbootclasspath/a:.", - "-XX:+UseG1GC", - "-XX:+UnlockExperimentalVMOptions", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-XX:G1MixedGCLiveThresholdPercent=20", - "-Xlog:gc+marking=debug,gc+phases=debug,gc+remset+tracking=trace", - "-Xms10M", - "-Xmx10M", - GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-Xbootclasspath/a:.", + "-XX:+UseG1GC", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:G1MixedGCLiveThresholdPercent=20", + "-Xlog:gc+marking=debug,gc+phases=debug,gc+remset+tracking=trace", + "-Xms10M", + "-Xmx10M", + GCTest.class.getName()); output.shouldContain("Skipping Remembered Set Rebuild."); output.shouldContain("No Remembered Sets to update after rebuild"); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java index d14fcf95de198..2f3b3128038a5 100644 --- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java +++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java @@ -178,10 +178,7 @@ private static OutputAnalyzer testWithVerificationType(String[] types, String... basicOpts.add(TriggerGCs.class.getName()); - ProcessBuilder procBuilder = ProcessTools.createLimitedTestJavaProcessBuilder(basicOpts); - OutputAnalyzer analyzer = new OutputAnalyzer(procBuilder.start()); - - return analyzer; + return ProcessTools.executeLimitedTestJava(basicOpts); } private static void verifyCollection(String name, boolean expectBefore, boolean expectDuring, boolean expectAfter, String data) { diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/ClassLoaderGenerator.java b/test/hotspot/jtreg/gc/g1/humongousObjects/ClassLoaderGenerator.java index 25510063b55cd..01ad5e1c0b3a9 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/ClassLoaderGenerator.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/ClassLoaderGenerator.java @@ -34,7 +34,7 @@ * Since the generation depends on current host architecture it cannot be done as part of pre-compilation step */ public class ClassLoaderGenerator { - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws Exception { if (args.length != 1) { throw new Error("Test Bug: Expected region size wasn't provided as command line argument"); @@ -47,7 +47,7 @@ public static void main(String[] args) throws IOException { } - public static void generateClassLoader(long regionSize, Path wrkDir) throws IOException { + public static void generateClassLoader(long regionSize, Path wrkDir) throws Exception { // Generating simple classloader String finalSimpleClassLoaderPrototype = TestHumongousClassLoader.GENERIC_PROTOTYPE .replace("${Methods}", diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/G1SampleClass.java b/test/hotspot/jtreg/gc/g1/humongousObjects/G1SampleClass.java index 1a321c9b11505..8e11eff27499e 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/G1SampleClass.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/G1SampleClass.java @@ -75,12 +75,11 @@ public long expectedInstanceSize() { * @param wrkDir working dir where generated classes are put and compiled * @param classNamePrefix prefix for service classes (ones we use to create chain of inheritance) * @return a class with instances of the specified size loaded in specified class loader - * @throws IOException - * @throws ClassNotFoundException + * @throws Exception */ public Class getCls(ClassLoader classLoader, Path wrkDir, String classNamePrefix) - throws IOException, ClassNotFoundException { + throws Exception { return Helpers.generateCompileAndLoad(classLoader, Helpers.enumNameToClassName(name()) + "Class", expectedInstanceSize(), wrkDir, classNamePrefix); } diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java index c2be830f57c05..34333e90ef28e 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousClassLoader.java @@ -140,9 +140,7 @@ public void provoke() { public abstract void provoke(); } - public static void main(String[] args) throws ClassNotFoundException, InstantiationException, - IllegalAccessException, IOException, NoSuchMethodException, InvocationTargetException { - + public static void main(String[] args) throws Exception { if (args.length != 1) { throw new Error("Test Bug: Expected GC type wasn't provided as command line argument"); } diff --git a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousNonArrayAllocation.java b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousNonArrayAllocation.java index 32a4251a6a8d9..0e43217720899 100644 --- a/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousNonArrayAllocation.java +++ b/test/hotspot/jtreg/gc/g1/humongousObjects/TestHumongousNonArrayAllocation.java @@ -82,8 +82,7 @@ public class TestHumongousNonArrayAllocation { private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final String CLASS_NAME_PREFIX = TestHumongousNonArrayAllocation.class.getSimpleName() + "_"; - public static void main(String[] args) throws ClassNotFoundException, InstantiationException, - IllegalAccessException, IOException { + public static void main(String[] args) throws Exception { if (args.length != 1) { throw new Error("Test Bug: Expected class name wasn't provided as command line argument"); diff --git a/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java b/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java index 0c8d4896c4e01..0e8f2b4776267 100644 --- a/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java +++ b/test/hotspot/jtreg/gc/g1/mixedgc/TestLogging.java @@ -90,8 +90,7 @@ private static OutputAnalyzer spawnMixedGCProvoker(String... extraFlags) Collections.addAll(testOpts, extraFlags); testOpts.add(RunMixedGC.class.getName()); System.out.println(testOpts); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(testOpts); - return new OutputAnalyzer(pb.start()); + return ProcessTools.executeLimitedTestJava(testOpts); } } diff --git a/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java b/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java index 4f972e10f3110..832281c825773 100644 --- a/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java +++ b/test/hotspot/jtreg/gc/g1/numa/TestG1NUMATouchRegions.java @@ -181,7 +181,7 @@ static void testMemoryTouch(String largePagesSetting, int regionSizeInMB) throws return; } - ProcessBuilder pb_enabled = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xbootclasspath/a:.", "-Xlog:pagesize,gc+heap+region=trace", "-XX:+UseG1GC", @@ -195,7 +195,6 @@ static void testMemoryTouch(String largePagesSetting, int regionSizeInMB) throws largePagesSetting, "-XX:G1HeapRegionSize=" + regionSizeInMB + "m", GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start()); // Check NUMA availability. if (status == NUMASupportStatus.NOT_CHECKED) { diff --git a/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectTypes.java b/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectTypes.java index 1223bfdd02700..c96f1a1759af9 100644 --- a/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectTypes.java +++ b/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectTypes.java @@ -48,18 +48,17 @@ public static void main(String[] args) throws Exception { } private static void testPinning(String type, boolean shouldSucceed) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-Xbootclasspath/a:.", - "-XX:-CreateCoredumpOnCrash", - "-Xmx32M", - "-Xmn16M", - "-Xlog:gc", - TestObjectPin.class.getName(), - type); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:.", + "-XX:-CreateCoredumpOnCrash", + "-Xmx32M", + "-Xmn16M", + "-Xlog:gc", + TestObjectPin.class.getName(), + type); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println(output.getStdout()); if (shouldSucceed) { output.shouldHaveExitValue(0); @@ -84,4 +83,3 @@ public static void main(String[] args) { wb.pinObject(o); } } - diff --git a/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectsEvacuation.java b/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectsEvacuation.java index 7ffd9432eb582..975b1feb53669 100644 --- a/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectsEvacuation.java +++ b/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedObjectsEvacuation.java @@ -64,19 +64,18 @@ private static void assertMatches(int expected, int actual, String what) { } private static void testPinnedEvacuation(int younGCsBeforeUnpin, int expectedSkipEvents, int expectedDropEvents, int expectedReclaimEvents) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-Xbootclasspath/a:.", - "-Xmx32M", - "-Xmn16M", - "-XX:G1NumCollectionsKeepPinned=2", - "-XX:+VerifyAfterGC", - "-Xlog:gc,gc+ergo+cset=trace", - TestObjectPin.class.getName(), - String.valueOf(younGCsBeforeUnpin)); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:.", + "-Xmx32M", + "-Xmn16M", + "-XX:G1NumCollectionsKeepPinned=2", + "-XX:+VerifyAfterGC", + "-Xlog:gc,gc+ergo+cset=trace", + TestObjectPin.class.getName(), + String.valueOf(younGCsBeforeUnpin)); + System.out.println(output.getStdout()); output.shouldHaveExitValue(0); @@ -128,4 +127,3 @@ public static void main(String[] args) { wb.youngGC(); } } - diff --git a/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedOldObjectsEvacuation.java b/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedOldObjectsEvacuation.java index 86f7a62ef7042..f30b3e8a7a586 100644 --- a/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedOldObjectsEvacuation.java +++ b/test/hotspot/jtreg/gc/g1/pinnedobjs/TestPinnedOldObjectsEvacuation.java @@ -257,24 +257,23 @@ private static void testPinnedEvacuation(int youngGCsBeforeUnpin, int expectedDropEvents, int expectedMarkingReclaimEvents, int expectedRetainedReclaimEvents) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UseG1GC", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-Xbootclasspath/a:.", - "-Xmx32M", - "-Xmn16M", - "-XX:MarkSweepDeadRatio=0", - "-XX:G1NumCollectionsKeepPinned=3", - "-XX:+UnlockExperimentalVMOptions", - // Take all old regions to make sure that the pinned one is included in the collection set. - "-XX:G1MixedGCLiveThresholdPercent=100", - "-XX:G1HeapWastePercent=0", - "-XX:+VerifyAfterGC", - "-Xlog:gc,gc+ergo+cset=trace", - TestObjectPin.class.getName(), - String.valueOf(youngGCsBeforeUnpin)); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UseG1GC", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xbootclasspath/a:.", + "-Xmx32M", + "-Xmn16M", + "-XX:MarkSweepDeadRatio=0", + "-XX:G1NumCollectionsKeepPinned=3", + "-XX:+UnlockExperimentalVMOptions", + // Take all old regions to make sure that the pinned one is included in the collection set. + "-XX:G1MixedGCLiveThresholdPercent=100", + "-XX:G1HeapWastePercent=0", + "-XX:+VerifyAfterGC", + "-Xlog:gc,gc+ergo+cset=trace", + TestObjectPin.class.getName(), + String.valueOf(youngGCsBeforeUnpin)); + System.out.println(output.getStdout()); output.shouldHaveExitValue(0); @@ -334,4 +333,3 @@ public static void main(String[] args) { wb.youngGC(); } } - diff --git a/test/hotspot/jtreg/gc/logging/TestDeprecatedPrintFlags.java b/test/hotspot/jtreg/gc/logging/TestDeprecatedPrintFlags.java index 04607502a2226..78089ea6452dc 100644 --- a/test/hotspot/jtreg/gc/logging/TestDeprecatedPrintFlags.java +++ b/test/hotspot/jtreg/gc/logging/TestDeprecatedPrintFlags.java @@ -42,8 +42,7 @@ public class TestDeprecatedPrintFlags { public static void testPrintGC() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+PrintGC", DoGC.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+PrintGC", DoGC.class.getName()); output.shouldContain("-XX:+PrintGC is deprecated. Will use -Xlog:gc instead."); output.shouldNotContain("PrintGCDetails"); output.stdoutShouldMatch("\\[info.*\\]\\[gc *\\]"); @@ -52,8 +51,7 @@ public static void testPrintGC() throws Exception { } public static void testPrintGCDetails() throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+PrintGCDetails", DoGC.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+PrintGCDetails", DoGC.class.getName()); output.shouldContain("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); output.shouldNotContain("PrintGC is deprecated"); output.stdoutShouldMatch("\\[info.*\\]\\[gc *\\]"); @@ -63,8 +61,7 @@ public static void testPrintGCDetails() throws Exception { public static void testXloggc() throws Exception { String fileName = "gc-test.log"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xloggc:" + fileName, DoGC.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-Xloggc:" + fileName, DoGC.class.getName()); output.shouldContain("-Xloggc is deprecated. Will use -Xlog:gc:gc-test.log instead."); output.shouldNotContain("PrintGCDetails"); output.shouldNotContain("PrintGC"); @@ -80,8 +77,7 @@ public static void testXloggc() throws Exception { public static void testXloggcWithPrintGCDetails() throws Exception { String fileName = "gc-test.log"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+PrintGCDetails", "-Xloggc:" + fileName, DoGC.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+PrintGCDetails", "-Xloggc:" + fileName, DoGC.class.getName()); output.shouldContain("-XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead."); output.shouldContain("-Xloggc is deprecated. Will use -Xlog:gc:gc-test.log instead."); output.shouldNotContain("PrintGC is deprecated"); diff --git a/test/hotspot/jtreg/gc/logging/TestGCId.java b/test/hotspot/jtreg/gc/logging/TestGCId.java index dca1681e0e8a5..b1015f46435b1 100644 --- a/test/hotspot/jtreg/gc/logging/TestGCId.java +++ b/test/hotspot/jtreg/gc/logging/TestGCId.java @@ -73,9 +73,9 @@ private static void verifyContainsGCIDs(OutputAnalyzer output) { } private static void testGCId(String gcFlag) throws Exception { - ProcessBuilder pb_default = - ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xlog:gc", "-Xmx10M", GCTest.class.getName()); - verifyContainsGCIDs(new OutputAnalyzer(pb_default.start())); + OutputAnalyzer output = + ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+" + gcFlag, "-Xlog:gc", "-Xmx10M", GCTest.class.getName()); + verifyContainsGCIDs(output); } static class GCTest { diff --git a/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java b/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java index b67063091fb32..044ad1cf9f58e 100644 --- a/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java +++ b/test/hotspot/jtreg/gc/logging/TestMetaSpaceLog.java @@ -93,24 +93,24 @@ private static boolean check(String line) { } private static void testMetaSpaceUpdate() throws Exception { - ProcessBuilder pb = - ProcessTools.createTestJavaProcessBuilder( - "-Xlog:gc*", - "-Xbootclasspath/a:.", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-Xmx1000M", - "-Xms1000M", - StressMetaSpace.class.getName()); - OutputAnalyzer output = null; try { - output = new OutputAnalyzer(pb.start()); + output = ProcessTools.executeTestJava( + "-Xlog:gc*", + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-Xmx1000M", + "-Xms1000M", + StressMetaSpace.class.getName()); + verifyContainsMetaSpaceUpdate(output); } catch (Exception e) { // For error diagnosis: print and throw. e.printStackTrace(); - output.reportDiagnosticSummary(); + if (output != null) { + output.reportDiagnosticSummary(); + } throw e; } } diff --git a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java index 99932bc68a640..96e0e7f14d4f3 100644 --- a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java +++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java @@ -67,11 +67,10 @@ static String indent(int count) { } public static void testRefs() throws Exception { - ProcessBuilder pb_enabled = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:gc+ref+phases=debug", - "-XX:+UseG1GC", - "-Xmx32M", - GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-Xlog:gc+ref+phases=debug", + "-XX:+UseG1GC", + "-Xmx32M", + GCTest.class.getName()); checkRefsLogFormat(output); @@ -95,14 +94,13 @@ private static void checkRefsLogFormat(OutputAnalyzer output) { } public static void testPhases(boolean parallelRefProcEnabled) throws Exception { - ProcessBuilder pb_enabled = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:gc+phases+ref=debug", - "-XX:+UseG1GC", - "-Xmx32M", - "-XX:" + (parallelRefProcEnabled ? "+" : "-") + "ParallelRefProcEnabled", - "-XX:-UseDynamicNumberOfGCThreads", - "-XX:ParallelGCThreads=2", - GCTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb_enabled.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-Xlog:gc+phases+ref=debug", + "-XX:+UseG1GC", + "-Xmx32M", + "-XX:" + (parallelRefProcEnabled ? "+" : "-") + "ParallelRefProcEnabled", + "-XX:-UseDynamicNumberOfGCThreads", + "-XX:ParallelGCThreads=2", + GCTest.class.getName()); checkLogFormat(output, parallelRefProcEnabled); checkLogValue(output); diff --git a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java index 30553a7b8c6a9..5955006ec0f31 100644 --- a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java +++ b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -77,9 +77,8 @@ public static void main(String[] args) throws Exception { } private static void run(ProcessBuilder pb) throws Exception { - Process p = pb.start(); - p.waitFor(); - int exitValue = p.exitValue(); + OutputAnalyzer output = ProcessTools.executeProcess(pb); + int exitValue = output.getExitValue(); if (exitValue != 0) { throw new Exception("jmap -heap exited with error code: " + exitValue); } diff --git a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceSizeFlags.java b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceSizeFlags.java index eda71fa9c4bb4..7e6066557dd29 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestMetaspaceSizeFlags.java +++ b/test/hotspot/jtreg/gc/metaspace/TestMetaspaceSizeFlags.java @@ -84,13 +84,12 @@ private static MetaspaceFlags runAndGetValue(long maxMetaspaceSize, long metaspa } private static OutputAnalyzer run(long maxMetaspaceSize, long metaspaceSize) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + return ProcessTools.executeLimitedTestJava( "-XX:MaxMetaspaceSize=" + maxMetaspaceSize, "-XX:MetaspaceSize=" + metaspaceSize, "-XX:-UseLargePages", // Prevent us from using 2GB large pages on solaris + sparc. "-XX:+PrintFlagsFinal", "-version"); - return new OutputAnalyzer(pb.start()); } private static class MetaspaceFlags { diff --git a/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java b/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java index a87ed22e15b06..458a90b08a4cf 100644 --- a/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java +++ b/test/hotspot/jtreg/gc/metaspace/TestSizeTransitions.java @@ -119,8 +119,7 @@ public static void main(String... args) throws Exception { System.out.println(" " + a); } - final ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(jvmArgs); - final OutputAnalyzer output = new OutputAnalyzer(pb.start()); + final OutputAnalyzer output = ProcessTools.executeLimitedTestJava(jvmArgs); System.out.println(output.getStdout()); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/serial/HeapChangeLogging.java b/test/hotspot/jtreg/gc/serial/HeapChangeLogging.java index 8480d046dfbde..486fdbe0ed1fe 100644 --- a/test/hotspot/jtreg/gc/serial/HeapChangeLogging.java +++ b/test/hotspot/jtreg/gc/serial/HeapChangeLogging.java @@ -41,8 +41,7 @@ public class HeapChangeLogging { public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xmx128m", "-Xmn100m", "-XX:+UseSerialGC", "-Xlog:gc", HeapFiller.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-Xmx128m", "-Xmn100m", "-XX:+UseSerialGC", "-Xlog:gc", HeapFiller.class.getName()); String stdout = output.getStdout(); System.out.println(stdout); Matcher stdoutMatcher = Pattern.compile(".*\\(Allocation Failure\\) [0-9]+[KMG]->[0-9]+[KMG]\\([0-9]+[KMG]\\)", Pattern.MULTILINE).matcher(stdout); diff --git a/test/hotspot/jtreg/gc/shenandoah/TestEvilSyncBug.java b/test/hotspot/jtreg/gc/shenandoah/TestEvilSyncBug.java index 67690d8cad53d..8765105b5c085 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestEvilSyncBug.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestEvilSyncBug.java @@ -56,14 +56,13 @@ public static void main(String[] args) throws Exception { for (int c = 0; c < NUM_RUNS; c++) { Callable task = () -> { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xms128m", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-Xms128m", "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCHeuristics=aggressive", "TestEvilSyncBug", "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); return null; }; diff --git a/test/hotspot/jtreg/gc/shenandoah/TestJcmdHeapDump.java b/test/hotspot/jtreg/gc/shenandoah/TestJcmdHeapDump.java index cc5bc5d425e83..40a36d0a5ef23 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestJcmdHeapDump.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestJcmdHeapDump.java @@ -127,6 +127,7 @@ */ import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import java.io.File; @@ -141,11 +142,7 @@ public static void main(String[] args) { jcmd.addToolArg(dumpFileName); try { - ProcessBuilder pb = new ProcessBuilder(jcmd.getCommand()); - Process jcmdProc = pb.start(); - - OutputAnalyzer output = new OutputAnalyzer(jcmdProc); - jcmdProc.waitFor(); + OutputAnalyzer output = ProcessTools.executeProcess(jcmd.getCommand()); output.shouldHaveExitValue(0); } catch (Exception e) { throw new RuntimeException("Test failed: " + e); diff --git a/test/hotspot/jtreg/gc/shenandoah/TestObjItrWithHeapDump.java b/test/hotspot/jtreg/gc/shenandoah/TestObjItrWithHeapDump.java index c0161b7a2382d..a0612a60a9f11 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestObjItrWithHeapDump.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestObjItrWithHeapDump.java @@ -41,9 +41,8 @@ public static void testWith(String... args) throws Exception { String[] cmds = Arrays.copyOf(args, args.length + 2); cmds[args.length] = TestObjItrWithHeapDump.class.getName(); cmds[args.length + 1] = "test"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(cmds); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(cmds); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); output.shouldContain("Class Histogram (before full gc)"); output.shouldContain("Class Histogram (after full gc)"); diff --git a/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java b/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java index b65aa0cd0b46a..3a5780069eff7 100644 --- a/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java +++ b/test/hotspot/jtreg/gc/shenandoah/TestPeriodicGC.java @@ -42,9 +42,8 @@ public static void testWith(String msg, boolean periodic, String... args) throws String[] cmds = Arrays.copyOf(args, args.length + 2); cmds[args.length] = TestPeriodicGC.class.getName(); cmds[args.length + 1] = "test"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(cmds); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(cmds); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); if (periodic && !output.getOutput().contains("Trigger: Time since last GC")) { throw new AssertionError(msg + ": Should have periodic GC in logs"); diff --git a/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargeObj.java b/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargeObj.java index 1057eb4a97762..f9e660cb20022 100644 --- a/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargeObj.java +++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargeObj.java @@ -55,27 +55,25 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx16m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestAllocLargeObj.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(1); analyzer.shouldContain("java.lang.OutOfMemoryError: Java heap space"); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx1g", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestAllocLargeObj.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(0); analyzer.shouldNotContain("java.lang.OutOfMemoryError: Java heap space"); } diff --git a/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargerThanHeap.java b/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargerThanHeap.java index 1567e3d05da2c..a87fda5c98d81 100644 --- a/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargerThanHeap.java +++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocLargerThanHeap.java @@ -50,27 +50,25 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx16m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestAllocLargerThanHeap.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(1); analyzer.shouldContain("java.lang.OutOfMemoryError: Java heap space"); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx1g", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestAllocLargerThanHeap.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(0); analyzer.shouldNotContain("java.lang.OutOfMemoryError: Java heap space"); } diff --git a/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocSmallObj.java b/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocSmallObj.java index bc32c1f0aa0ea..572351b498f80 100644 --- a/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocSmallObj.java +++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestAllocSmallObj.java @@ -54,27 +54,25 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx16m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestAllocSmallObj.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(1); analyzer.shouldContain("java.lang.OutOfMemoryError: Java heap space"); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx1g", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestAllocSmallObj.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(0); analyzer.shouldNotContain("java.lang.OutOfMemoryError: Java heap space"); } diff --git a/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java b/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java index beb57b0b40122..9d17e91608952 100644 --- a/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java +++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestClassLoaderLeak.java @@ -99,9 +99,7 @@ public static void testWith(boolean shouldPass, String... args) throws Exception pbArgs.add(TestClassLoaderLeak.class.getName()); pbArgs.add("test"); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(pbArgs.toArray(new String[0])); - - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava(pbArgs.toArray(new String[0])); if (shouldPass) { analyzer.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/shenandoah/oom/TestThreadFailure.java b/test/hotspot/jtreg/gc/shenandoah/oom/TestThreadFailure.java index 75cb2d5c31a24..fea5761df2fad 100644 --- a/test/hotspot/jtreg/gc/shenandoah/oom/TestThreadFailure.java +++ b/test/hotspot/jtreg/gc/shenandoah/oom/TestThreadFailure.java @@ -62,14 +62,13 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer analyzer = ProcessTools.executeLimitedTestJava( "-Xmx32m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", TestThreadFailure.class.getName(), "test"); - OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); analyzer.shouldHaveExitValue(0); analyzer.shouldContain("java.lang.OutOfMemoryError"); analyzer.shouldContain("All good"); diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestArgumentRanges.java b/test/hotspot/jtreg/gc/shenandoah/options/TestArgumentRanges.java index 2cc2c2c2197ab..597d9a74c1d35 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestArgumentRanges.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestArgumentRanges.java @@ -46,36 +46,33 @@ public static void main(String[] args) throws Exception { private static void testHeuristics() throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCHeuristics=aggressive", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCHeuristics=static", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCHeuristics=fluff", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Unknown -XX:ShenandoahGCHeuristics option"); output.shouldHaveExitValue(1); } @@ -83,47 +80,43 @@ private static void testHeuristics() throws Exception { private static void testRange(String option, int min, int max) throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:" + option + "=" + (max + 1), "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:" + option + "=" + max, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:" + option + "=" + (min - 1), "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:" + option + "=" + min, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestClassUnloadingArguments.java b/test/hotspot/jtreg/gc/shenandoah/options/TestClassUnloadingArguments.java index c575b51084c79..bf49ad3ec9c5b 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestClassUnloadingArguments.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestClassUnloadingArguments.java @@ -43,8 +43,7 @@ public static void testWith(String msg, boolean cu, boolean cuConc, String... ar cmds[args.length] = "-Xmx128m"; cmds[args.length + 1] = "-XX:+PrintFlagsFinal"; cmds[args.length + 2] = "-version"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(cmds); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(cmds); output.shouldHaveExitValue(0); output.shouldContain("ClassUnloading"); output.shouldContain("ClassUnloadingWithConcurrentMark"); diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGC.java b/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGC.java index 49e7c41713057..7fe5d56f7de99 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGC.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGC.java @@ -60,14 +60,13 @@ public static void main(String[] args) throws Exception { }; { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xlog:gc", TestExplicitGC.class.getName(), "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); for (String p : full) { output.shouldNotContain(p); } @@ -77,7 +76,7 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", @@ -85,7 +84,6 @@ public static void main(String[] args) throws Exception { "-XX:+DisableExplicitGC", TestExplicitGC.class.getName(), "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); for (String p : full) { output.shouldNotContain(p); } @@ -95,7 +93,7 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", @@ -103,7 +101,6 @@ public static void main(String[] args) throws Exception { "-XX:+ExplicitGCInvokesConcurrent", TestExplicitGC.class.getName(), "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); for (String p : full) { output.shouldNotContain(p); } @@ -113,7 +110,7 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", @@ -121,7 +118,6 @@ public static void main(String[] args) throws Exception { "-XX:-ExplicitGCInvokesConcurrent", TestExplicitGC.class.getName(), "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); for (String p : full) { output.shouldContain(p); } @@ -131,7 +127,7 @@ public static void main(String[] args) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", @@ -140,7 +136,6 @@ public static void main(String[] args) throws Exception { "-XX:ShenandoahGCMode=iu", TestExplicitGC.class.getName(), "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); for (String p : full) { output.shouldNotContain(p); } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGCNoConcurrent.java b/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGCNoConcurrent.java index 6499457b667aa..176e4a2ca7ae5 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGCNoConcurrent.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestExplicitGCNoConcurrent.java @@ -60,7 +60,7 @@ public static void main(String[] args) throws Exception { }; for (String opt : opts) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", @@ -70,7 +70,6 @@ public static void main(String[] args) throws Exception { "-XX:ShenandoahGCHeuristics=passive", TestExplicitGCNoConcurrent.class.getName(), "test"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); for (String p : concurrent) { output.shouldNotContain(p); } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestHeuristicsUnlock.java b/test/hotspot/jtreg/gc/shenandoah/options/TestHeuristicsUnlock.java index c9f1c75b4e112..9d0065fe80315 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestHeuristicsUnlock.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestHeuristicsUnlock.java @@ -52,7 +52,7 @@ public static void main(String[] args) throws Exception { private static void testWith(String h, Mode mode) throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:-UnlockDiagnosticVMOptions", "-XX:-UnlockExperimentalVMOptions", @@ -60,7 +60,6 @@ private static void testWith(String h, Mode mode) throws Exception { h, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (mode) { case PRODUCT: output.shouldHaveExitValue(0); @@ -73,7 +72,7 @@ private static void testWith(String h, Mode mode) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:-UnlockExperimentalVMOptions", @@ -81,7 +80,6 @@ private static void testWith(String h, Mode mode) throws Exception { h, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (mode) { case PRODUCT: case DIAGNOSTIC: @@ -94,7 +92,7 @@ private static void testWith(String h, Mode mode) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:-UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -102,7 +100,6 @@ private static void testWith(String h, Mode mode) throws Exception { h, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (mode) { case PRODUCT: case EXPERIMENTAL: diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestHumongousThresholdArgs.java b/test/hotspot/jtreg/gc/shenandoah/options/TestHumongousThresholdArgs.java index 523f434dbbd39..47d4115ce749f 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestHumongousThresholdArgs.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestHumongousThresholdArgs.java @@ -38,12 +38,11 @@ public class TestHumongousThresholdArgs { public static void main(String[] args) throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } @@ -51,24 +50,22 @@ public static void main(String[] args) throws Exception { int[] invalid = new int[] {-100, -1, 0, 101, 1000}; for (int v : valid) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahHumongousThreshold=" + v, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } for (int v : invalid) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahHumongousThreshold=" + v, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(1); } } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java b/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java index 79452b6cbc5f9..6d37b2877da77 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestLoopMiningArguments.java @@ -44,8 +44,7 @@ public static void testWith(String msg, boolean cls, int iters, String... args) cmds[args.length] = "-Xmx128m"; cmds[args.length + 1] = "-XX:+PrintFlagsFinal"; cmds[args.length + 2] = "-version"; - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(cmds); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(cmds); output.shouldHaveExitValue(0); output.shouldContain("UseCountedLoopSafepoints"); output.shouldContain("LoopStripMiningIter"); diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestModeUnlock.java b/test/hotspot/jtreg/gc/shenandoah/options/TestModeUnlock.java index 0c8fea7f9933f..802038363b5fa 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestModeUnlock.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestModeUnlock.java @@ -51,7 +51,7 @@ public static void main(String[] args) throws Exception { private static void testWith(String h, Mode mode) throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:-UnlockDiagnosticVMOptions", "-XX:-UnlockExperimentalVMOptions", @@ -59,7 +59,6 @@ private static void testWith(String h, Mode mode) throws Exception { h, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (mode) { case PRODUCT: output.shouldHaveExitValue(0); @@ -72,7 +71,7 @@ private static void testWith(String h, Mode mode) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:-UnlockExperimentalVMOptions", @@ -80,7 +79,6 @@ private static void testWith(String h, Mode mode) throws Exception { h, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (mode) { case PRODUCT: case DIAGNOSTIC: @@ -93,7 +91,7 @@ private static void testWith(String h, Mode mode) throws Exception { } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:-UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -101,7 +99,6 @@ private static void testWith(String h, Mode mode) throws Exception { h, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); switch (mode) { case PRODUCT: case EXPERIMENTAL: diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestRegionSizeArgs.java b/test/hotspot/jtreg/gc/shenandoah/options/TestRegionSizeArgs.java index 79d0b517e8990..a8d5155584b23 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestRegionSizeArgs.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestRegionSizeArgs.java @@ -45,113 +45,103 @@ public static void main(String[] args) throws Exception { private static void testInvalidRegionSizes() throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms4m", "-Xmx1g", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms8m", "-Xmx1g", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahRegionSize=200m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahRegionSize option"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahRegionSize=9m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahRegionSize=255K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahRegionSize option"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahRegionSize=260K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms1g", "-Xmx1g", "-XX:ShenandoahRegionSize=32M", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms1g", "-Xmx1g", "-XX:ShenandoahRegionSize=64M", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahRegionSize option"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms1g", "-Xmx1g", "-XX:ShenandoahRegionSize=256K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms1g", "-Xmx1g", "-XX:ShenandoahRegionSize=128K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahRegionSize option"); output.shouldHaveExitValue(1); } @@ -160,49 +150,45 @@ private static void testInvalidRegionSizes() throws Exception { private static void testMinRegionSize() throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahMinRegionSize=255K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahMinRegionSize option"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahMinRegionSize=1M", "-XX:ShenandoahMaxRegionSize=260K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahMinRegionSize or -XX:ShenandoahMaxRegionSize"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahMinRegionSize=200m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahMinRegionSize option"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahMinRegionSize=9m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } @@ -211,26 +197,24 @@ private static void testMinRegionSize() throws Exception { private static void testMaxRegionSize() throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahMaxRegionSize=255K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahMaxRegionSize option"); output.shouldHaveExitValue(1); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms100m", "-Xmx1g", "-XX:ShenandoahMinRegionSize=1M", "-XX:ShenandoahMaxRegionSize=260K", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Invalid -XX:ShenandoahMinRegionSize or -XX:ShenandoahMaxRegionSize"); output.shouldHaveExitValue(1); } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java b/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java index 5b34bfab3a008..094e62f53f35a 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestSelectiveBarrierFlags.java @@ -89,8 +89,7 @@ public static void main(String[] args) throws Exception { pool.submit(() -> { try { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(conf.toArray(new String[0])); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(conf.toArray(new String[0])); output.shouldHaveExitValue(0); } catch (Exception e) { e.printStackTrace(); diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestSoftMaxHeapSize.java b/test/hotspot/jtreg/gc/shenandoah/options/TestSoftMaxHeapSize.java index 78bbf75189c0c..212ffb4103706 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestSoftMaxHeapSize.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestSoftMaxHeapSize.java @@ -38,35 +38,32 @@ public class TestSoftMaxHeapSize { public static void main(String[] args) throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms4m", "-Xmx128m", "-XX:SoftMaxHeapSize=4m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms4m", "-Xmx128m", "-XX:SoftMaxHeapSize=128m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+UnlockExperimentalVMOptions", + OutputAnalyzer output = ProcessTools.executeLimitedTestJava("-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-Xms4m", "-Xmx128m", "-XX:SoftMaxHeapSize=129m", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(1); output.shouldContain("SoftMaxHeapSize must be less than or equal to the maximum heap size"); } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCounts.java b/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCounts.java index f7f9ee56b59ab..90985eb4c4dfc 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCounts.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCounts.java @@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception { } private static void testWith(int conc, int par) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -53,7 +53,6 @@ private static void testWith(int conc, int par) throws Exception { "-XX:ConcGCThreads=" + conc, "-XX:ParallelGCThreads=" + par, "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); if (conc == 0) { output.shouldContain("Shenandoah expects ConcGCThreads > 0"); diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCountsOverride.java b/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCountsOverride.java index 5e63595e726fe..b3d8ba34567ec 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCountsOverride.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestThreadCountsOverride.java @@ -38,7 +38,7 @@ public class TestThreadCountsOverride { public static void main(String[] args) throws Exception { { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -46,14 +46,13 @@ public static void main(String[] args) throws Exception { "-XX:ParallelGCThreads=1", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("ParallelGCThreads(.*)= 1 "); output.shouldHaveExitValue(0); } { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -61,7 +60,6 @@ public static void main(String[] args) throws Exception { "-XX:ConcGCThreads=1", "-XX:+PrintFlagsFinal", "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("ConcGCThreads(.*)= 1 "); output.shouldHaveExitValue(0); diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java b/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java index 0e913375534da..aa6b79356498c 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierDisable.java @@ -63,7 +63,7 @@ public static void main(String[] args) throws Exception { private static void shouldFailAll(String h, String[] barriers) throws Exception { for (String b : barriers) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -72,7 +72,6 @@ private static void shouldFailAll(String h, String[] barriers) throws Exception "-XX:-" + b, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); output.shouldContain("GC mode needs "); output.shouldContain("to work correctly"); @@ -81,7 +80,7 @@ private static void shouldFailAll(String h, String[] barriers) throws Exception private static void shouldPassAll(String h, String[] barriers) throws Exception { for (String b : barriers) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -90,7 +89,6 @@ private static void shouldPassAll(String h, String[] barriers) throws Exception "-XX:-" + b, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierEnable.java b/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierEnable.java index 84645621eb401..486860728aba9 100644 --- a/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierEnable.java +++ b/test/hotspot/jtreg/gc/shenandoah/options/TestWrongBarrierEnable.java @@ -55,7 +55,7 @@ public static void main(String[] args) throws Exception { private static void shouldFailAll(String h, String[] barriers) throws Exception { for (String b : barriers) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -64,7 +64,6 @@ private static void shouldFailAll(String h, String[] barriers) throws Exception "-XX:+" + b, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotHaveExitValue(0); output.shouldContain("GC mode needs "); output.shouldContain("to work correctly"); @@ -73,7 +72,7 @@ private static void shouldFailAll(String h, String[] barriers) throws Exception private static void shouldPassAll(String h, String[] barriers) throws Exception { for (String b : barriers) { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeLimitedTestJava( "-Xmx128m", "-XX:+UnlockDiagnosticVMOptions", "-XX:+UnlockExperimentalVMOptions", @@ -82,7 +81,6 @@ private static void shouldPassAll(String h, String[] barriers) throws Exception "-XX:+" + b, "-version" ); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java index 83f211ad5fa10..bfe19e2c9c5af 100644 --- a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java +++ b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java @@ -61,8 +61,8 @@ public static void main(String[] args) throws Exception { "-XX:+PrintNMTStatistics" )); baseargs.addAll(Arrays.asList(args)); baseargs.add(GCTest.class.getName()); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(baseargs); - verifySymbolMemoryUsageNotTooHigh(new OutputAnalyzer(pb.start())); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(baseargs); + verifySymbolMemoryUsageNotTooHigh(output); } private static void verifySymbolMemoryUsageNotTooHigh(OutputAnalyzer output) throws Exception { diff --git a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java index 2a02039c60e42..70544e8af3160 100644 --- a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java +++ b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java @@ -101,8 +101,7 @@ public static void main(String[] args) throws Exception { "-Dregionsize=" + regionSize, TestStressG1HumongousImpl.class.getName() ); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(options); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(options); output.shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java b/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java index 2f61c166cb8f0..d3575e8cd4bd9 100644 --- a/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java +++ b/test/hotspot/jtreg/gc/stress/TestStressG1Uncommit.java @@ -59,8 +59,7 @@ public static void main(String[] args) throws Exception { "-XX:+UseG1GC", StressUncommit.class.getName() ); - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(options); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeLimitedTestJava(options); output.shouldHaveExitValue(0); output.shouldMatch("Uncommit regions"); output.outputTo(System.out); diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java index 31c11b66dfc7e..8b8fea1f2e33e 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java @@ -299,8 +299,7 @@ private static OutputAnalyzer runTest(String... extraArgs) throws Exception { args.addAll(Arrays.asList(defaultArgs)); args.addAll(Arrays.asList(extraArgs)); - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(args); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeTestJava(args); System.err.println(output.getStderr()); System.out.println(output.getStdout()); return output; diff --git a/test/hotspot/jtreg/gc/testlibrary/Helpers.java b/test/hotspot/jtreg/gc/testlibrary/Helpers.java index 225a5bda0e615..03d67e44455da 100644 --- a/test/hotspot/jtreg/gc/testlibrary/Helpers.java +++ b/test/hotspot/jtreg/gc/testlibrary/Helpers.java @@ -25,6 +25,7 @@ import jdk.test.lib.JDKToolLauncher; import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; import jdk.test.whitebox.WhiteBox; import java.io.File; @@ -89,7 +90,7 @@ public static int detectByteArrayAllocationOverhead() { * @param source class source * @throws IOException if cannot write file to specified directory */ - public static void compileClass(String className, Path root, String source) throws IOException { + public static void compileClass(String className, Path root, String source) throws Exception { Path sourceFile = root.resolve(className + ".java"); Files.write(sourceFile, source.getBytes()); @@ -100,8 +101,7 @@ public static void compileClass(String className, Path root, String source) thro .addToolArg(System.getProperty("java.class.path") + File.pathSeparator + root.toAbsolutePath()) .addToolArg(sourceFile.toAbsolutePath().toString()); - ProcessBuilder pb = new ProcessBuilder(jar.getCommand()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeProcess(jar.getCommand()); output.shouldHaveExitValue(0); } @@ -199,12 +199,11 @@ public static String enumNameToClassName(String enumName) { * @param prefix prefix for service classes (ones we use to create chain of inheritance). * The names will be prefix_1, prefix_2,.., prefix_n * @return Class object of generated and compiled class loaded in specified class loader - * @throws IOException - * @throws ClassNotFoundException + * @throws Exception */ public static Class generateCompileAndLoad(ClassLoader classLoader, String className, long instanceSize, Path workDir, String prefix) - throws IOException, ClassNotFoundException { + throws Exception { generateByTemplateAndCompile(className, null, "public class ${ClassName} extends ${BaseClass} {\n${Fields}}\n", "", instanceSize, workDir, prefix); @@ -243,11 +242,11 @@ public static Class generateCompileAndLoad(ClassLoader classLoader, String cl * @param prefix prefix for service classes (ones we use to create chain of inheritance). * The names will be prefix_1, prefix_2,.., prefix_n * @return Class object of generated and compiled class loaded in specified class loader - * @throws IOException if cannot write or read to workDir + * @throws Exception if cannot write or read to workDir */ public static void generateByTemplateAndCompile(String className, String baseClass, String classTemplate, String constructorTemplate, long instanceSize, Path workDir, - String prefix) throws IOException { + String prefix) throws Exception { if (instanceSize % SIZE_OF_LONG != 0L) { throw new Error(String.format("Test bug: only sizes aligned by %d bytes are supported and %d was specified", diff --git a/test/hotspot/jtreg/gc/whitebox/TestWBGC.java b/test/hotspot/jtreg/gc/whitebox/TestWBGC.java index c2fe2633e4e90..38f3593b63827 100644 --- a/test/hotspot/jtreg/gc/whitebox/TestWBGC.java +++ b/test/hotspot/jtreg/gc/whitebox/TestWBGC.java @@ -43,7 +43,7 @@ public class TestWBGC { public static void main(String args[]) throws Exception { - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + OutputAnalyzer output = ProcessTools.executeTestJava( "-Xbootclasspath/a:.", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", @@ -51,7 +51,6 @@ public static void main(String args[]) throws Exception { "-Xlog:gc", GCYoungTest.class.getName()); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); System.out.println(output.getStdout()); output.shouldHaveExitValue(0); output.shouldContain("WhiteBox Initiated Young GC"); diff --git a/test/hotspot/jtreg/gc/x/TestAllocateHeapAt.java b/test/hotspot/jtreg/gc/x/TestAllocateHeapAt.java index de3d1f585a7cb..3bf83d9076864 100644 --- a/test/hotspot/jtreg/gc/x/TestAllocateHeapAt.java +++ b/test/hotspot/jtreg/gc/x/TestAllocateHeapAt.java @@ -41,16 +41,16 @@ public static void main(String[] args) throws Exception { final String heapBackingFile = "Heap Backing File: " + directory; final String failedToCreateFile = "Failed to create file " + directory; - ProcessTools.executeProcess(ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:-ZGenerational", - "-Xlog:gc*", - "-Xms32M", - "-Xmx32M", - "-XX:AllocateHeapAt=" + directory, - "-version")) - .shouldContain(exists ? heapBackingFile : failedToCreateFile) - .shouldNotContain(exists ? failedToCreateFile : heapBackingFile) - .shouldHaveExitValue(exists ? 0 : 1); + ProcessTools.executeLimitedTestJava( + "-XX:+UseZGC", + "-XX:-ZGenerational", + "-Xlog:gc*", + "-Xms32M", + "-Xmx32M", + "-XX:AllocateHeapAt=" + directory, + "-version") + .shouldContain(exists ? heapBackingFile : failedToCreateFile) + .shouldNotContain(exists ? failedToCreateFile : heapBackingFile) + .shouldHaveExitValue(exists ? 0 : 1); } } diff --git a/test/hotspot/jtreg/gc/x/TestPageCacheFlush.java b/test/hotspot/jtreg/gc/x/TestPageCacheFlush.java index 5a20ee8322aef..cb8685d0d090c 100644 --- a/test/hotspot/jtreg/gc/x/TestPageCacheFlush.java +++ b/test/hotspot/jtreg/gc/x/TestPageCacheFlush.java @@ -68,16 +68,16 @@ public static void main(String[] args) throws Exception { } public static void main(String[] args) throws Exception { - ProcessTools.executeProcess(ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:-ZGenerational", - "-Xms128M", - "-Xmx128M", - "-Xlog:gc,gc+init,gc+heap=debug", - Test.class.getName())) - .outputTo(System.out) - .errorTo(System.out) - .shouldContain("Page Cache Flushed:") - .shouldHaveExitValue(0); + ProcessTools.executeLimitedTestJava( + "-XX:+UseZGC", + "-XX:-ZGenerational", + "-Xms128M", + "-Xmx128M", + "-Xlog:gc,gc+init,gc+heap=debug", + Test.class.getName()) + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("Page Cache Flushed:") + .shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/x/TestSmallHeap.java b/test/hotspot/jtreg/gc/x/TestSmallHeap.java index 0fc6477b59b74..8fc6f07be398f 100644 --- a/test/hotspot/jtreg/gc/x/TestSmallHeap.java +++ b/test/hotspot/jtreg/gc/x/TestSmallHeap.java @@ -53,16 +53,16 @@ public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception { for (var maxCapacity: args) { - ProcessTools.executeProcess(ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:-ZGenerational", - "-Xlog:gc,gc+init,gc+reloc,gc+heap", - "-Xmx" + maxCapacity, - Test.class.getName())) - .outputTo(System.out) - .errorTo(System.out) - .shouldContain("Success") - .shouldHaveExitValue(0); + ProcessTools.executeLimitedTestJava( + "-XX:+UseZGC", + "-XX:-ZGenerational", + "-Xlog:gc,gc+init,gc+reloc,gc+heap", + "-Xmx" + maxCapacity, + Test.class.getName()) + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("Success") + .shouldHaveExitValue(0); } } } diff --git a/test/hotspot/jtreg/gc/z/TestAllocateHeapAt.java b/test/hotspot/jtreg/gc/z/TestAllocateHeapAt.java index f5a6113f6ff88..9f47c4b60d3cb 100644 --- a/test/hotspot/jtreg/gc/z/TestAllocateHeapAt.java +++ b/test/hotspot/jtreg/gc/z/TestAllocateHeapAt.java @@ -41,16 +41,16 @@ public static void main(String[] args) throws Exception { final String heapBackingFile = "Heap Backing File: " + directory; final String failedToCreateFile = "Failed to create file " + directory; - ProcessTools.executeProcess(ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:+ZGenerational", - "-Xlog:gc*", - "-Xms32M", - "-Xmx32M", - "-XX:AllocateHeapAt=" + directory, - "-version")) - .shouldContain(exists ? heapBackingFile : failedToCreateFile) - .shouldNotContain(exists ? failedToCreateFile : heapBackingFile) - .shouldHaveExitValue(exists ? 0 : 1); + ProcessTools.executeLimitedTestJava( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xlog:gc*", + "-Xms32M", + "-Xmx32M", + "-XX:AllocateHeapAt=" + directory, + "-version") + .shouldContain(exists ? heapBackingFile : failedToCreateFile) + .shouldNotContain(exists ? failedToCreateFile : heapBackingFile) + .shouldHaveExitValue(exists ? 0 : 1); } } diff --git a/test/hotspot/jtreg/gc/z/TestPageCacheFlush.java b/test/hotspot/jtreg/gc/z/TestPageCacheFlush.java index 629edccd49629..387053b580ad8 100644 --- a/test/hotspot/jtreg/gc/z/TestPageCacheFlush.java +++ b/test/hotspot/jtreg/gc/z/TestPageCacheFlush.java @@ -68,16 +68,16 @@ public static void main(String[] args) throws Exception { } public static void main(String[] args) throws Exception { - ProcessTools.executeProcess(ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:+ZGenerational", - "-Xms128M", - "-Xmx128M", - "-Xlog:gc,gc+init,gc+heap=debug", - Test.class.getName())) - .outputTo(System.out) - .errorTo(System.out) - .shouldContain("Page Cache Flushed:") - .shouldHaveExitValue(0); + ProcessTools.executeLimitedTestJava( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xms128M", + "-Xmx128M", + "-Xlog:gc,gc+init,gc+heap=debug", + Test.class.getName()) + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("Page Cache Flushed:") + .shouldHaveExitValue(0); } } diff --git a/test/hotspot/jtreg/gc/z/TestSmallHeap.java b/test/hotspot/jtreg/gc/z/TestSmallHeap.java index bfe1c0310ca49..354cd4164f1fd 100644 --- a/test/hotspot/jtreg/gc/z/TestSmallHeap.java +++ b/test/hotspot/jtreg/gc/z/TestSmallHeap.java @@ -53,16 +53,16 @@ public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception { for (var maxCapacity: args) { - ProcessTools.executeProcess(ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:+ZGenerational", - "-Xlog:gc,gc+init,gc+reloc,gc+heap", - "-Xmx" + maxCapacity, - Test.class.getName())) - .outputTo(System.out) - .errorTo(System.out) - .shouldContain("Success") - .shouldHaveExitValue(0); + ProcessTools.executeLimitedTestJava( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xlog:gc,gc+init,gc+reloc,gc+heap", + "-Xmx" + maxCapacity, + Test.class.getName()) + .outputTo(System.out) + .errorTo(System.out) + .shouldContain("Success") + .shouldHaveExitValue(0); } } } diff --git a/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java b/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java index 2993038faa583..f1a14f0cf902b 100644 --- a/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java +++ b/test/hotspot/jtreg/gc/z/TestZForceDiscontiguousHeapReservations.java @@ -45,17 +45,17 @@ private static void testValue(int n) throws Exception { */ final int XmxInM = 2000; final int XmsInM = Math.min(16 * XmxInM / (n + 1), XmxInM); - OutputAnalyzer oa = ProcessTools.executeProcess(ProcessTools.createTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:+ZGenerational", - "-Xms" + XmsInM + "M", - "-Xmx" + XmxInM + "M", - "-Xlog:gc,gc+init", - "-XX:ZForceDiscontiguousHeapReservations=" + n, - "-version")) - .outputTo(System.out) - .errorTo(System.out) - .shouldHaveExitValue(0); + OutputAnalyzer oa = ProcessTools.executeTestJava( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xms" + XmsInM + "M", + "-Xmx" + XmxInM + "M", + "-Xlog:gc,gc+init", + "-XX:ZForceDiscontiguousHeapReservations=" + n, + "-version") + .outputTo(System.out) + .errorTo(System.out) + .shouldHaveExitValue(0); if (n > 1) { oa.shouldContain("Address Space Type: Discontiguous"); } diff --git a/test/hotspot/jtreg/gc/z/TestZNMT.java b/test/hotspot/jtreg/gc/z/TestZNMT.java index 066ebd063f60a..db37a0e1e1423 100644 --- a/test/hotspot/jtreg/gc/z/TestZNMT.java +++ b/test/hotspot/jtreg/gc/z/TestZNMT.java @@ -68,21 +68,21 @@ private static void testValue(int zForceDiscontiguousHeapReservations) throws Ex * reservations. */ final int XmsInM = Math.min(16 * XmxInM / (zForceDiscontiguousHeapReservations + 1), XmxInM); - OutputAnalyzer oa = ProcessTools.executeProcess(ProcessTools.createTestJavaProcessBuilder( - "-XX:+UseZGC", - "-XX:+ZGenerational", - "-Xms" + XmsInM + "M", - "-Xmx" + XmxInM + "M", - "-Xlog:gc,gc+init", - "-XX:ZForceDiscontiguousHeapReservations=" + zForceDiscontiguousHeapReservations, - "-XX:NativeMemoryTracking=detail", - "-XX:+PrintNMTStatistics", - Test.class.getName(), - Integer.toString(zForceDiscontiguousHeapReservations), - Integer.toString(XmxInM))) - .outputTo(System.out) - .errorTo(System.out) - .shouldHaveExitValue(0); + OutputAnalyzer oa = ProcessTools.executeTestJava( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xms" + XmsInM + "M", + "-Xmx" + XmxInM + "M", + "-Xlog:gc,gc+init", + "-XX:ZForceDiscontiguousHeapReservations=" + zForceDiscontiguousHeapReservations, + "-XX:NativeMemoryTracking=detail", + "-XX:+PrintNMTStatistics", + Test.class.getName(), + Integer.toString(zForceDiscontiguousHeapReservations), + Integer.toString(XmxInM)) + .outputTo(System.out) + .errorTo(System.out) + .shouldHaveExitValue(0); if (zForceDiscontiguousHeapReservations > 1) { oa.shouldContain("Address Space Type: Discontiguous"); } From 3dc4bd858139f133f5e5b17e7bd3082dd6766d02 Mon Sep 17 00:00:00 2001 From: Denghui Dong Date: Fri, 5 Jan 2024 09:23:42 +0000 Subject: [PATCH 023/112] 8322989: New test serviceability/HeapDump/FullGCHeapDumpLimitTest.java fails Reviewed-by: stefank, dholmes --- test/hotspot/jtreg/ProblemList.txt | 2 -- .../jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 484aad97b8c12..754cf68ba591f 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -141,8 +141,6 @@ serviceability/attach/ConcAttachTest.java 8290043 linux-all serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 -serviceability/HeapDump/FullGCHeapDumpLimitTest.java 8322989 generic-all - ############################################################################# # :hotspot_misc diff --git a/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java b/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java index cf5481ddf2b93..c44fea3e10bcc 100644 --- a/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java +++ b/test/hotspot/jtreg/serviceability/HeapDump/FullGCHeapDumpLimitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Alibaba Group Holding Limited. All Rights Reserved. + * Copyright (c) 2023, 2024 Alibaba Group Holding Limited. 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 @@ -23,6 +23,7 @@ /** * @test + * @requires vm.gc.Serial & (vm.opt.DisableExplicitGC != "true") * @summary Test of option -XX:FullGCHeapDumpLimit * @library /test/lib * @run main/othervm -XX:+UseSerialGC -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC -XX:HeapDumpPath=test.hprof -XX:FullGCHeapDumpLimit=1 FullGCHeapDumpLimitTest From f0e2e4311b8cab160dc9e35f43e9ae5a145c5e23 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 5 Jan 2024 10:39:08 +0000 Subject: [PATCH 024/112] 8323021: Shenandoah: Encountered reference count always attributed to first worker thread Reviewed-by: kdnilsen, ysr, shade --- .../share/gc/shenandoah/shenandoahReferenceProcessor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index f99de804bd5dc..f395119d46a35 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -362,7 +362,7 @@ bool ShenandoahReferenceProcessor::discover_reference(oop reference, ReferenceTy log_trace(gc, ref)("Encountered Reference: " PTR_FORMAT " (%s)", p2i(reference), reference_type_name(type)); uint worker_id = WorkerThread::worker_id(); - _ref_proc_thread_locals->inc_encountered(type); + _ref_proc_thread_locals[worker_id].inc_encountered(type); if (UseCompressedOops) { return discover(reference, type, worker_id); From 78623c95f2a3954384963c4c761d2e4e5f4aefed Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 5 Jan 2024 11:13:34 +0000 Subject: [PATCH 025/112] 8323012: C2 fails with fatal error: no reachable node should have no use Reviewed-by: chagedorn --- src/hotspot/share/opto/cfgnode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 772e4050987f2..5362a7b0751af 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2170,7 +2170,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { cast = phase->transform(cast); n = cast; } - cast = new CheckCastPPNode(r, uin, phi_type, ConstraintCastNode::StrongDependency, extra_types); + cast = new CheckCastPPNode(r, n, phi_type, ConstraintCastNode::StrongDependency, extra_types); } if (cast == nullptr) { cast = new CastPPNode(r, uin, phi_type, ConstraintCastNode::StrongDependency, extra_types); From f0cfd361bd6a98dc1192dab2116fdd3904f130f8 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 5 Jan 2024 11:34:03 +0000 Subject: [PATCH 026/112] 8322532: JShell : Unnamed variable issue Reviewed-by: asotona --- .../share/classes/jdk/jshell/CompletenessAnalyzer.java | 2 +- test/langtools/jdk/jshell/VariablesTest.java | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java index 1579a48786cbf..663ca164a3de6 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java @@ -190,7 +190,7 @@ static enum TK { EOF(TokenKind.EOF, 0), // ERROR(TokenKind.ERROR, XERRO), // IDENTIFIER(TokenKind.IDENTIFIER, XEXPR1|XDECL1|XTERM), // - UNDERSCORE(TokenKind.UNDERSCORE, XDECL1), // _ + UNDERSCORE(TokenKind.UNDERSCORE, XDECL1|XEXPR), // _ CLASS(TokenKind.CLASS, XEXPR|XDECL1|XBRACESNEEDED), // class decl (MAPPED: DOTCLASS) MONKEYS_AT(TokenKind.MONKEYS_AT, XEXPR|XDECL1), // @ IMPORT(TokenKind.IMPORT, XDECL1|XSTART), // import -- consider declaration diff --git a/test/langtools/jdk/jshell/VariablesTest.java b/test/langtools/jdk/jshell/VariablesTest.java index 51ccbd17d6040..56546955e0829 100644 --- a/test/langtools/jdk/jshell/VariablesTest.java +++ b/test/langtools/jdk/jshell/VariablesTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 + * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 8322532 * @summary Tests for EvaluationState.variables * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -621,4 +621,10 @@ public void varAnonymousClassAndStaticField() { //JDK-8294431 assertEval("var obj = new Object() { public static final String msg = \"hello\"; };"); } + public void underscoreAsLambdaParameter() { //JDK-8322532 + assertAnalyze("Func f = _ -> 0; int i;", + "Func f = _ -> 0;", + " int i;", true); + } + } From ade21a965f8a5fc889cd48bba76fad507bdeddf5 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 5 Jan 2024 13:48:31 +0000 Subject: [PATCH 027/112] 8310844: [AArch64] C1 compilation fails because monitor offset in OSR buffer is too large for immediate Reviewed-by: aph, chagedorn --- .../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 5 +- .../compiler/c1/TestLargeMonitorOffset.java | 146 ++++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 360ef7a747a83..b83d618506298 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -282,7 +282,8 @@ void LIR_Assembler::osr_entry() { __ bind(L); } #endif - __ ldp(r19, r20, Address(OSR_buf, slot_offset)); + __ ldr(r19, Address(OSR_buf, slot_offset)); + __ ldr(r20, Address(OSR_buf, slot_offset + BytesPerWord)); __ str(r19, frame_map()->address_for_monitor_lock(i)); __ str(r20, frame_map()->address_for_monitor_object(i)); } diff --git a/test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java b/test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java new file mode 100644 index 0000000000000..d5cdb6bee5208 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c1/TestLargeMonitorOffset.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2024, 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 8310844 + * @summary Verify that monitors with large offset in the OSR buffer are handled properly. + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,TestLargeMonitorOffset::* TestLargeMonitorOffset + */ + +public class TestLargeMonitorOffset { + + public static void test() { + long l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, + l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, + l21, l22, l23, l24, l25, l26, l27, l28, l29, l30, + l31, l32, l33, l34, l35, l36, l37, l38, l39, l40, + l41, l42, l43, l44, l45, l46, l47, l48, l49, l50, + l51, l52, l53, l54, l55, l56, l57, l58, l59, l60, + l61, l62, l63, l64, l65, l66, l67, l68, l69, l70, + l71, l72, l73, l74, l75, l76, l77, l78, l79, l80, + l81, l82, l83, l84, l85, l86, l87, l88, l89, l90, + l91, l92, l93, l94, l95, l96, l97, l98, l99, l100, + l101, l102, l103, l104, l105, l106, l107, l108, l109, l110, + l111, l112, l113, l114, l115, l116, l117, l118, l119, l120, + l121, l122, l123, l124, l125, l126, l127, l128, l129, l130, + l131, l132, l133, l134, l135, l136, l137, l138, l139, l140, + l141, l142, l143, l144, l145, l146, l147, l148, l149, l150, + l151, l152, l153, l154, l155, l156, l157, l158, l159, l160, + l161, l162, l163, l164, l165, l166, l167, l168, l169, l170, + l171, l172, l173, l174, l175, l176, l177, l178, l179, l180, + l181, l182, l183, l184, l185, l186, l187, l188, l189, l190, + l191, l192, l193, l194, l195, l196, l197, l198, l199, l200, + l201, l202, l203, l204, l205, l206, l207, l208, l209, l210, + l211, l212, l213, l214, l215, l216, l217, l218, l219, l220, + l221, l222, l223, l224, l225, l226, l227, l228, l229, l230, + l231, l232, l233, l234, l235, l236, l237, l238, l239, l240, + l241, l242, l243, l244, l245, l246, l247, l248, l249, l250, + l251, l252, l253, l254, l255, l256, l257, l258, l259, l260, + l261, l262, l263, l264, l265, l266, l267, l268, l269, l270, + l271, l272, l273, l274, l275, l276, l277, l278, l279, l280, + l281, l282, l283, l284, l285, l286, l287, l288, l289, l290, + l291, l292, l293, l294, l295, l296, l297, l298, l299, l300, + l301, l302, l303, l304, l305, l306, l307, l308, l309, l310, + l311, l312, l313, l314, l315, l316, l317, l318, l319, l320, + l321, l322, l323, l324, l325, l326, l327, l328, l329, l330, + l331, l332, l333, l334, l335, l336, l337, l338, l339, l340, + l341, l342, l343, l344, l345, l346, l347, l348, l349, l350, + l351, l352, l353, l354, l355, l356, l357, l358, l359, l360, + l361, l362, l363, l364, l365, l366, l367, l368, l369, l370, + l371, l372, l373, l374, l375, l376, l377, l378, l379, l380, + l381, l382, l383, l384, l385, l386, l387, l388, l389, l390, + l391, l392, l393, l394, l395, l396, l397, l398, l399, l400, + l401, l402, l403, l404, l405, l406, l407, l408, l409, l410, + l411, l412, l413, l414, l415, l416, l417, l418, l419, l420, + l421, l422, l423, l424, l425, l426, l427, l428, l429, l430, + l431, l432, l433, l434, l435, l436, l437, l438, l439, l440, + l441, l442, l443, l444, l445, l446, l447, l448, l449, l450, + l451, l452, l453, l454, l455, l456, l457, l458, l459, l460, + l461, l462, l463, l464, l465, l466, l467, l468, l469, l470, + l471, l472, l473, l474, l475, l476, l477, l478, l479, l480, + l481, l482, l483, l484, l485, l486, l487, l488, l489, l490, + l491, l492, l493, l494, l495, l496, l497, l498, l499, l500, + l501, l502, l503, l504, l505, l506, l507, l508, l509, l510, + l511, l512, l513, l514, l515, l516, l517, l518, l519, l520, + l521, l522, l523, l524, l525, l526, l527, l528, l529, l530, + l531, l532, l533, l534, l535, l536, l537, l538, l539, l540, + l541, l542, l543, l544, l545, l546, l547, l548, l549, l550, + l551, l552, l553, l554, l555, l556, l557, l558, l559, l560, + l561, l562, l563, l564, l565, l566, l567, l568, l569, l570, + l571, l572, l573, l574, l575, l576, l577, l578, l579, l580, + l581, l582, l583, l584, l585, l586, l587, l588, l589, l590, + l591, l592, l593, l594, l595, l596, l597, l598, l599, l600, + l601, l602, l603, l604, l605, l606, l607, l608, l609, l610, + l611, l612, l613, l614, l615, l616, l617, l618, l619, l620, + l621, l622, l623, l624, l625, l626, l627, l628, l629, l630, + l631, l632, l633, l634, l635, l636, l637, l638, l639, l640, + l641, l642, l643, l644, l645, l646, l647, l648, l649, l650, + l651, l652, l653, l654, l655, l656, l657, l658, l659, l660, + l661, l662, l663, l664, l665, l666, l667, l668, l669, l670, + l671, l672, l673, l674, l675, l676, l677, l678, l679, l680, + l681, l682, l683, l684, l685, l686, l687, l688, l689, l690, + l691, l692, l693, l694, l695, l696, l697, l698, l699, l700, + l701, l702, l703, l704, l705, l706, l707, l708, l709, l710, + l711, l712, l713, l714, l715, l716, l717, l718, l719, l720, + l721, l722, l723, l724, l725, l726, l727, l728, l729, l730, + l731, l732, l733, l734, l735, l736, l737, l738, l739, l740, + l741, l742, l743, l744, l745, l746, l747, l748, l749, l750, + l751, l752, l753, l754, l755, l756, l757, l758, l759, l760, + l761, l762, l763, l764, l765, l766, l767, l768, l769, l770, + l771, l772, l773, l774, l775, l776, l777, l778, l779, l780, + l781, l782, l783, l784, l785, l786, l787, l788, l789, l790, + l791, l792, l793, l794, l795, l796, l797, l798, l799, l800, + l801, l802, l803, l804, l805, l806, l807, l808, l809, l810, + l811, l812, l813, l814, l815, l816, l817, l818, l819, l820, + l821, l822, l823, l824, l825, l826, l827, l828, l829, l830, + l831, l832, l833, l834, l835, l836, l837, l838, l839, l840, + l841, l842, l843, l844, l845, l846, l847, l848, l849, l850, + l851, l852, l853, l854, l855, l856, l857, l858, l859, l860, + l861, l862, l863, l864, l865, l866, l867, l868, l869, l870, + l871, l872, l873, l874, l875, l876, l877, l878, l879, l880, + l881, l882, l883, l884, l885, l886, l887, l888, l889, l890, + l891, l892, l893, l894, l895, l896, l897, l898, l899, l900, + l901, l902, l903, l904, l905, l906, l907, l908, l909, l910, + l911, l912, l913, l914, l915, l916, l917, l918, l919, l920, + l921, l922, l923, l924, l925, l926, l927, l928, l929, l930, + l931, l932, l933, l934, l935, l936, l937, l938, l939, l940, + l941, l942, l943, l944, l945, l946, l947, l948, l949, l950, + l951, l952, l953, l954, l955, l956, l957, l958, l959, l960, + l961, l962, l963, l964, l965, l966, l967, l968, l969, l970, + l971, l972, l973, l974, l975, l976, l977, l978, l979, l980, + l981, l982, l983, l984, l985, l986, l987, l988, l989, l990, + l991, l992, l993, l994, l995, l996, l997, l998, l999, l1000; + + synchronized (TestLargeMonitorOffset.class) { + // Trigger OSR compilation with monitor in the OSR buffer + for (int i = 0; i < 1_000_000; ++i) { + + } + } + } + + public static void main(String[] args) { + test(); + } +} From ed9f3243f04718a50bbdc589437872f7215c0e08 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 5 Jan 2024 15:40:32 +0000 Subject: [PATCH 028/112] 8322985: [BACKOUT] 8318562: Computational test more than 2x slower when AVX instructions are used Reviewed-by: chagedorn, shade --- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 86 ----------- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 17 --- src/hotspot/cpu/x86/x86_64.ad | 4 +- .../bench/vm/compiler/x86/ComputePI.java | 142 ------------------ 4 files changed, 2 insertions(+), 247 deletions(-) delete mode 100644 test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index aec1f3c9105a9..882966564859e 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1871,92 +1871,6 @@ void MacroAssembler::cmpoop(Register src1, jobject src2, Register rscratch) { } #endif -void MacroAssembler::cvtss2sd(XMMRegister dst, XMMRegister src) { - if ((UseAVX > 0) && (dst != src)) { - xorpd(dst, dst); - } - Assembler::cvtss2sd(dst, src); -} - -void MacroAssembler::cvtss2sd(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtss2sd(dst, src); -} - -void MacroAssembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { - if ((UseAVX > 0) && (dst != src)) { - xorps(dst, dst); - } - Assembler::cvtsd2ss(dst, src); -} - -void MacroAssembler::cvtsd2ss(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsd2ss(dst, src); -} - -void MacroAssembler::cvtsi2sdl(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdl(dst, src); -} - -void MacroAssembler::cvtsi2sdl(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdl(dst, src); -} - -void MacroAssembler::cvtsi2ssl(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssl(dst, src); -} - -void MacroAssembler::cvtsi2ssl(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssl(dst, src); -} - -#ifdef _LP64 -void MacroAssembler::cvtsi2sdq(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdq(dst, src); -} - -void MacroAssembler::cvtsi2sdq(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdq(dst, src); -} - -void MacroAssembler::cvtsi2ssq(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssq(dst, src); -} - -void MacroAssembler::cvtsi2ssq(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssq(dst, src); -} -#endif // _LP64 - void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch) { assert(rscratch != noreg || always_reachable(adr), "missing"); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index b474944c4bead..4b30168452796 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -800,23 +800,6 @@ class MacroAssembler: public Assembler { void cmpxchgptr(Register reg, Address adr); - - // cvt instructions - void cvtss2sd(XMMRegister dst, XMMRegister src); - void cvtss2sd(XMMRegister dst, Address src); - void cvtsd2ss(XMMRegister dst, XMMRegister src); - void cvtsd2ss(XMMRegister dst, Address src); - void cvtsi2sdl(XMMRegister dst, Register src); - void cvtsi2sdl(XMMRegister dst, Address src); - void cvtsi2ssl(XMMRegister dst, Register src); - void cvtsi2ssl(XMMRegister dst, Address src); -#ifdef _LP64 - void cvtsi2sdq(XMMRegister dst, Register src); - void cvtsi2sdq(XMMRegister dst, Address src); - void cvtsi2ssq(XMMRegister dst, Register src); - void cvtsi2ssq(XMMRegister dst, Address src); -#endif - void locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch = noreg); void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 759dd8a1d485b..80f281a1bf92d 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -10095,7 +10095,7 @@ instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{ instruct convF2D_reg_reg(regD dst, regF src) %{ match(Set dst (ConvF2D src)); - effect(TEMP dst); + format %{ "cvtss2sd $dst, $src" %} ins_encode %{ __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister); @@ -10117,7 +10117,7 @@ instruct convF2D_reg_mem(regD dst, memory src) instruct convD2F_reg_reg(regF dst, regD src) %{ match(Set dst (ConvD2F src)); - effect(TEMP dst); + format %{ "cvtsd2ss $dst, $src" %} ins_encode %{ __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister); diff --git a/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java b/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java deleted file mode 100644 index 7d8e479172e90..0000000000000 --- a/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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. - */ - -package org.openjdk.bench.vm.compiler; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@State(Scope.Thread) -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -public class ComputePI { - - @Benchmark - public double compute_pi_int_dbl() { - double pi = 4.0; - boolean sign = false; - - for (int i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0 / i; - } else { - pi -= 4.0 / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_int_flt() { - float pi = 4.0f; - boolean sign = false; - - for (int i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0f / i; - } else { - pi -= 4.0f / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_long_dbl() { - double pi = 4.0; - boolean sign = false; - - for (long i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0 / i; - } else { - pi -= 4.0 / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_long_flt() { - float pi = 4.0f; - boolean sign = false; - - for (long i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0f / i; - } else { - pi -= 4.0f / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_flt_dbl() { - double pi = 4.0; - boolean sign = false; - - for (float i = 3.0f; i < 1000.0f; i += 2.0f) { - if (sign) { - pi += 4.0 / i; - } else { - pi -= 4.0 / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_dbl_flt() { - float pi = 4.0f; - boolean sign = false; - - for (float i = 3.0f; i < 1000.0f; i += 2.0f) { - if (sign) { - pi += 4.0f / i; - } else { - pi -= 4.0f / i; - } - sign = !sign; - } - return pi; - } -} From 631a9f60f30fe298791aa953fa573001127ff58a Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 5 Jan 2024 16:26:02 +0000 Subject: [PATCH 029/112] 8323073: ProblemList gc/g1/TestSkipRebuildRemsetPhase.java on linux-aarch64 8323075: ProblemList runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java Reviewed-by: thartmann --- test/hotspot/jtreg/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 754cf68ba591f..f6913a0734ddc 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -93,6 +93,7 @@ gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithSerial.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithShenandoah.java 8180622 generic-all gc/stress/TestStressG1Humongous.java 8286554 windows-x64 +gc/g1/TestSkipRebuildRemsetPhase.java 8323066 linux-aarch64 ############################################################################# @@ -112,6 +113,7 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 +runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java 8323032 generic-all applications/jcstress/copy.java 8229852 linux-all From 700c25f5b45e8a228d07c57dcf925e93d494af23 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 5 Jan 2024 17:04:32 +0000 Subject: [PATCH 030/112] 8322954: Shenandoah: Convert evac-update closures asserts to rich asserts Reviewed-by: wkemper, kdnilsen, ysr --- .../share/gc/shenandoah/shenandoahBarrierSet.inline.hpp | 2 +- .../share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp | 2 +- src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp index b8da50dd6e109..bfb69c38c332c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -357,7 +357,7 @@ void ShenandoahBarrierSet::arraycopy_work(T* src, size_t count) { if (EVAC && obj == fwd) { fwd = _heap->evacuate_object(obj, thread); } - assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded"); + shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc()); ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o); obj = fwd; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp index b548073be3306..13371f5e194d9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp @@ -53,7 +53,7 @@ class ShenandoahUpdateRefsForOopClosure: public BasicOopIterateClosure { if (EVAC && obj == fwd) { fwd = _heap->evacuate_object(obj, _thread); } - assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded"); + shenandoah_assert_forwarded_except(p, obj, _heap->cancelled_gc()); ShenandoahHeap::atomic_update_oop(fwd, p, o); obj = fwd; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 7564af5f6b7c1..c7284fbceadbd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -705,10 +705,8 @@ void ShenandoahEvacUpdateCleanupOopStorageRootsClosure::do_oop(oop* p) { if (resolved == obj) { resolved = _heap->evacuate_object(obj, _thread); } + shenandoah_assert_not_in_cset_except(p, resolved, _heap->cancelled_gc()); ShenandoahHeap::atomic_update_oop(resolved, p, obj); - assert(_heap->cancelled_gc() || - _mark_context->is_marked(resolved) && !_heap->in_collection_set(resolved), - "Sanity"); } } } From 46965a096ce74d9375df36a3a66107e9295cc180 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Fri, 5 Jan 2024 17:53:45 +0000 Subject: [PATCH 031/112] 8322981: Fix 2 locations in JDI that throw IOException without using the "Caused by" exception Reviewed-by: dholmes, lmesnik --- .../classes/com/sun/tools/jdi/ProcessAttachingConnector.java | 4 ++-- .../classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java index 230f3eb1cd3f8..cc5063a2fc4ec 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -103,7 +103,7 @@ public VirtualMachine attach(Map args) Properties props = vm.getAgentProperties(); address = props.getProperty("sun.jdwp.listenerAddress"); } catch (Exception x) { - throw new IOException(x.getMessage()); + throw new IOException(x); } finally { if (vm != null) vm.detach(); } diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java index 074677260d80b..c17c46237b6cb 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -226,7 +226,7 @@ public synchronized VirtualMachine createVirtualMachine( vm = new VirtualMachineImpl(this, connection, process, ++vmSequenceNumber); } catch (VMDisconnectedException e) { - throw new IOException(e.getMessage()); + throw new IOException(e); } targets.add(vm); return vm; From 35a1b77da541e4df3c4d1bab0825ea39e653808c Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Fri, 5 Jan 2024 19:00:18 +0000 Subject: [PATCH 032/112] 8322636: [JVMCI] HotSpotSpeculationLog can be inconsistent across a single compile Reviewed-by: dnsimon, never --- .../classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java index 481686b0f4eb3..57cec3ef1942a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java @@ -207,11 +207,14 @@ byte[] getFlattenedSpeculations(boolean validate) { return result; } + /** + * @return {@code true} if the given speculation can be performed, i.e., it never failed so far, otherwise + * return {@code false}. Note, that this method returns consistent results for any given speculation for the + * entire lifetime of the enclosing SpeculationLog object. This means that speculations failed during a + * compilation will not be updated. + */ @Override public boolean maySpeculate(SpeculationReason reason) { - if (failedSpeculations == null) { - collectFailedSpeculations(); - } if (failedSpeculations != null && failedSpeculations.length != 0) { byte[] encoding = encode(reason); return !contains(failedSpeculations, 0, encoding); From be4614eb5e4efcea3f3ef4d18f94cfb36fd557f4 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 5 Jan 2024 22:16:52 +0000 Subject: [PATCH 033/112] 8323016: Improve reporting for bad options Reviewed-by: prappo --- .../jdk/javadoc/internal/tool/Start.java | 39 +++++++++- .../tool/resources/javadoc.properties | 11 ++- .../jdk/javadoc/tool/BadOptionsTest.java | 73 ++++++++++++++++++- 3 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index 3f06cf1ae2042..6407196a2aba8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -40,6 +40,7 @@ import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; @@ -457,6 +458,7 @@ private Result begin(List options, Iterable fi if (haveErrors && result.isOK()) { result = ERROR; } + log.flush(); log.printErrorWarningCounts(); log.flush(); } @@ -657,11 +659,44 @@ int consumeDocletOption(int idx, List args, boolean isToolOption) throws // check if arg is accepted by the tool before emitting error if (!isToolOption) { text = log.getText("main.invalid_flag", arg); - throw new OptionException(ERROR, this::showUsage, text); + throw new OptionException(ERROR, () -> reportBadOption(arg), text); } return m * idx; } + private void reportBadOption(String name) { + var allOptionNames = Stream.concat( + getToolOptions().getSupportedOptions().stream() + .flatMap(o -> o.getNames().stream()), + docletOptions.stream() + .flatMap(o -> o.getNames().stream())); + record Pair(String word, double similarity) { } + final double MIN_SIMILARITY = 0.7; + var suggestions = allOptionNames + .map(t -> new Pair(t, similarity(t, name))) + .sorted(Comparator.comparingDouble(Pair::similarity).reversed() /* more similar first */) + // .peek(p -> System.out.printf("%.3f, (%s ~ %s)%n", p.similarity, p.word, name)) // debug + .takeWhile(p -> Double.compare(p.similarity, MIN_SIMILARITY) >= 0) + .map(Pair::word) + .toList(); + switch (suggestions.size()) { + case 0 -> { } + case 1 -> showLinesUsingKey("main.did-you-mean", suggestions.getFirst()); + default -> showLinesUsingKey("main.did-you-mean-one-of", String.join(" ", suggestions)); + } + showLinesUsingKey("main.for-more-details-see-usage"); + } + + // a value in [0, 1] range: the closer the value is to 1, the more similar + // the strings are + private static double similarity(String a, String b) { + // Normalize the distance so that similarity between "x" and "y" is + // less than that of "ax" and "ay". Use the greater of two lengths + // as normalizer, as it's an upper bound for the distance. + return 1.0 - ((double) StringUtils.DamerauLevenshteinDistance.of(a, b)) + / Math.max(a.length(), b.length()); + } + private static Set getSupportedOptionsOf(Doclet doclet) { Set options = doclet.getSupportedOptions(); return options == null ? Set.of() : options; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties index e4aacca212d18..ef9425a02be4b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2024, 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 @@ -34,6 +34,15 @@ main.usage=Usage:\n\ \ javadoc [options] [packagenames] [sourcefiles] [@files]\n\ where options include: +main.did-you-mean=\ + Did you mean: {0} + +main.did-you-mean-one-of=\ + Did you mean one of: {0} + +main.for-more-details-see-usage=\ + For more details on available options, use --help or --help-extra + main.opt.at.arg=\ main.opt.at.desc=\ diff --git a/test/langtools/jdk/javadoc/tool/BadOptionsTest.java b/test/langtools/jdk/javadoc/tool/BadOptionsTest.java index e0887ed564653..568b6de90556a 100644 --- a/test/langtools/jdk/javadoc/tool/BadOptionsTest.java +++ b/test/langtools/jdk/javadoc/tool/BadOptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8169676 8175055 + * @bug 8169676 8175055 8323016 * @summary boolean result of Option.process is often ignored * @modules jdk.compiler/com.sun.tools.javac.api * @modules jdk.compiler/com.sun.tools.javac.main @@ -151,6 +151,75 @@ public void testSourcePathAndModuleSourceConflict() throws IOException { "1 error"); } + @Test + public void testOptionNotFound_NoSuggestions() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--not-a-path") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --not-a-path + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_OneSuggestion() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--middle-path") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --middle-path + Did you mean: --module-path + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_TwoSuggestions() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--sourcepath") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --sourcepath + Did you mean one of: --source-path -sourcepath + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_ThreeSuggestions() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--classpath") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --classpath + Did you mean one of: --class-path -classpath -bootclasspath + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_DocletOption() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("-tiglet") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: -tiglet + Did you mean: -taglet + For more details on available options, use --help or --help-extra""" + ); + } + private void checkFound(String log, String... expect) { for (String e : expect) { if (!log.contains(e)) { From ace010b38a83e0c9b43aeeb6bc5c92d0886dc53f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 6 Jan 2024 08:52:27 +0000 Subject: [PATCH 034/112] 8319757: java/nio/channels/DatagramChannel/InterruptibleOrNot.java failed: wrong exception thrown Reviewed-by: jpai, bpb --- .../DatagramChannel/InterruptibleOrNot.java | 238 ++++++++++-------- 1 file changed, 132 insertions(+), 106 deletions(-) diff --git a/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java b/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java index 7d369d7ddd99f..794ede84a924a 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java +++ b/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -25,7 +25,7 @@ * @test * @bug 8236246 * @modules java.base/sun.nio.ch - * @run testng InterruptibleOrNot + * @run junit InterruptibleOrNot * @summary Test SelectorProviderImpl.openDatagramChannel(boolean) to create * DatagramChannel objects that optionally support interrupt */ @@ -40,152 +40,178 @@ import java.nio.channels.ClosedByInterruptException; import java.nio.channels.DatagramChannel; import java.time.Duration; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.Arrays; import sun.nio.ch.DefaultSelectorProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.function.Executable; +import static org.junit.jupiter.api.Assertions.*; -@Test public class InterruptibleOrNot { + // DatagramChannel implementation class + private static String dcImplClassName; - public void testInterruptBeforeInterruptibleReceive() throws Exception { - testInterruptBeforeReceive(true); - } - - public void testInterruptDuringInterruptibleReceive() throws Exception { - testInterruptDuringReceive(true); - } - - public void testInterruptBeforeUninterruptibleReceive() throws Exception { - testInterruptBeforeReceive(false); - } - - public void testInterruptDuringUninterruptibleReceive() throws Exception { - testInterruptDuringReceive(false); - } - - public void testInterruptBeforeInterruptibleSend() throws Exception { - testInterruptBeforeSend(true); + @BeforeAll + static void setup() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + dcImplClassName = dc.getClass().getName(); + } } - public void testInterruptBeforeUninterruptibleSend() throws Exception { - testInterruptBeforeSend(false); + /** + * Call DatagramChannel.receive with the interrupt status set, the DatagramChannel + * is interruptible. + */ + @Test + public void testInterruptBeforeInterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + Thread.currentThread().interrupt(); + assertThrows(ClosedByInterruptException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); + } finally { + Thread.interrupted(); // clear interrupt status + } } /** - * Test invoking DatagramChannel receive with interrupt status set + * Test interrupting a thread blocked in DatagramChannel.receive, the DatagramChannel + * is interruptible. */ - static void testInterruptBeforeReceive(boolean interruptible) - throws Exception - { - try (DatagramChannel dc = openDatagramChannel(interruptible)) { - dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); - Future timeout = scheduleClose(dc, Duration.ofSeconds(2)); - try { - ByteBuffer buf = ByteBuffer.allocate(100); - Thread.currentThread().interrupt(); - assertThrows(expectedException(interruptible), () -> dc.receive(buf)); - } finally { - timeout.cancel(false); - } + @Test + public void testInterruptDuringInterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + Thread thread = Thread.currentThread(); + onReceive(thread::interrupt); + assertThrows(ClosedByInterruptException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); } finally { - Thread.interrupted(); // clear interrupt + Thread.interrupted(); // clear interrupt status } } /** - * Test Thread.interrupt when target thread is blocked in DatagramChannel receive + * Call DatagramChannel.receive with the interrupt status set, the DatagramChannel + * is not interruptible. */ - static void testInterruptDuringReceive(boolean interruptible) - throws Exception - { - try (DatagramChannel dc = openDatagramChannel(interruptible)) { - dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); - Future timerTask = scheduleClose(dc, Duration.ofSeconds(5)); - Future interruptTask = scheduleInterrupt(Thread.currentThread(), Duration.ofSeconds(1)); - try { - ByteBuffer buf = ByteBuffer.allocate(100); - assertThrows(expectedException(interruptible), () -> dc.receive(buf)); - } finally { - timerTask.cancel(false); - interruptTask.cancel(false); - } + @Test + public void testInterruptBeforeUninterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(false)) { + ByteBuffer buf = ByteBuffer.allocate(100); + onReceive(() -> { + // close the channel after a delay to ensure receive wakes up + Thread.sleep(1000); + dc.close(); + }); + Thread.currentThread().interrupt(); + assertThrows(AsynchronousCloseException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); } finally { - Thread.interrupted(); // clear interrupt + Thread.interrupted(); // clear interrupt status } } /** - * Test invoking DatagramChannel send with interrupt status set + * Test interrupting a thread blocked in DatagramChannel.receive, the DatagramChannel + * is not interruptible. */ - static void testInterruptBeforeSend(boolean interruptible) - throws Exception - { - try (DatagramChannel dc = openDatagramChannel(interruptible)) { - dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); - Future timeout = scheduleClose(dc, Duration.ofSeconds(2)); - try { - ByteBuffer buf = ByteBuffer.allocate(100); - SocketAddress target = dc.getLocalAddress(); - Thread.currentThread().interrupt(); - if (interruptible) { - assertThrows(ClosedByInterruptException.class, () -> dc.send(buf, target)); - } else { - int n = dc.send(buf, target); - assertTrue(n == 100); - } - } finally { - timeout.cancel(false); - } + @Test + public void testInterruptDuringUninterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + + Thread thread = Thread.currentThread(); + onReceive(() -> { + // interrupt should not cause the receive to wakeup + thread.interrupt(); + + // close the channel after a delay to ensure receive wakes up + Thread.sleep(1000); + dc.close(); + }); + assertThrows(AsynchronousCloseException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); } finally { - Thread.interrupted(); // clear interrupt + Thread.interrupted(); // clear interrupt status } } /** - * Creates a DatagramChannel that is interruptible or not. + * Call DatagramChannel.send with the interrupt status set, the DatagramChannel + * is interruptible. */ - static DatagramChannel openDatagramChannel(boolean interruptible) throws IOException { - if (interruptible) { - return DatagramChannel.open(); - } else { - return DefaultSelectorProvider.get().openUninterruptibleDatagramChannel(); + @Test + public void testInterruptBeforeInterruptibleSend() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + SocketAddress target = dc.getLocalAddress(); + Thread.currentThread().interrupt(); + assertThrows(ClosedByInterruptException.class, () -> dc.send(buf, target)); + assertFalse(dc.isOpen()); + } finally { + Thread.interrupted(); // clear interrupt } } /** - * Expect ClosedByInterruptException if interruptible. + * Call DatagramChannel.send with the interrupt status set, the DatagramChannel + * is not interruptible. */ - static Class expectedException(boolean expectInterrupt) { - if (expectInterrupt) { - return ClosedByInterruptException.class; - } else { - return AsynchronousCloseException.class; + @Test + public void testInterruptBeforeUninterruptibleSend() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(false)) { + ByteBuffer buf = ByteBuffer.allocate(100); + SocketAddress target = dc.getLocalAddress(); + Thread.currentThread().interrupt(); + int n = dc.send(buf, target); + assertEquals(100, n); + assertTrue(dc.isOpen()); + } finally { + Thread.interrupted(); // clear interrupt status } } /** - * Schedule the given object to be closed. + * Creates a DatagramChannel that is interruptible or not, and bound to the loopback + * address. */ - static Future scheduleClose(Closeable c, Duration timeout) { - long nanos = TimeUnit.NANOSECONDS.convert(timeout); - return STPE.schedule(() -> { - c.close(); - return null; - }, nanos, TimeUnit.NANOSECONDS); + static DatagramChannel boundDatagramChannel(boolean interruptible) throws IOException { + DatagramChannel dc; + if (interruptible) { + dc = DatagramChannel.open(); + } else { + dc = DefaultSelectorProvider.get().openUninterruptibleDatagramChannel(); + } + try { + dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + } catch (IOException ioe) { + dc.close(); + throw ioe; + } + return dc; } /** - * Schedule the given thread to be interrupted. + * Runs the given action when the current thread is sampled in DatagramChannel.receive. */ - static Future scheduleInterrupt(Thread t, Duration timeout) { - long nanos = TimeUnit.NANOSECONDS.convert(timeout); - return STPE.schedule(t::interrupt, nanos, TimeUnit.NANOSECONDS); + static void onReceive(Executable action) { + Thread target = Thread.currentThread(); + Thread.ofPlatform().daemon().start(() -> { + try { + boolean found = false; + while (!found) { + Thread.sleep(20); + StackTraceElement[] stack = target.getStackTrace(); + found = Arrays.stream(stack) + .anyMatch(e -> dcImplClassName.equals(e.getClassName()) + && "receive".equals(e.getMethodName())); + } + action.execute(); + } catch (Throwable ex) { + ex.printStackTrace(); + } + }); } - - static final ScheduledExecutorService STPE = Executors.newScheduledThreadPool(0); } From faa9c6909dda635eb008b9dada6e06fca47c17d6 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 6 Jan 2024 18:24:28 +0000 Subject: [PATCH 035/112] 8322846: Running with -Djdk.tracePinnedThreads set can hang Reviewed-by: jpai --- .../java/lang/PinnedThreadPrinter.java | 65 ++++++++++------- .../classes/java/lang/VirtualThread.java | 10 ++- .../Thread/virtual/TracePinnedThreads.java | 69 +++++++++++++++++-- 3 files changed, 116 insertions(+), 28 deletions(-) diff --git a/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java b/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java index 02e0683a1b9af..a9b40d028f531 100644 --- a/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java +++ b/src/java.base/share/classes/java/lang/PinnedThreadPrinter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 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 @@ -34,6 +34,10 @@ import java.util.Set; import java.util.stream.Collectors; import static java.lang.StackWalker.Option.*; +import jdk.internal.access.JavaIOPrintStreamAccess; +import jdk.internal.access.SharedSecrets; +import jdk.internal.misc.InternalLock; +import jdk.internal.vm.Continuation; /** * Helper class to print the virtual thread stack trace when pinned. @@ -42,7 +46,8 @@ * code in that Class. This is used to avoid printing the same stack trace many times. */ class PinnedThreadPrinter { - static final StackWalker STACK_WALKER; + private static final JavaIOPrintStreamAccess JIOPSA = SharedSecrets.getJavaIOPrintStreamAccess(); + private static final StackWalker STACK_WALKER; static { var options = Set.of(SHOW_REFLECT_FRAMES, RETAIN_CLASS_REFERENCE); PrivilegedAction pa = () -> @@ -86,45 +91,59 @@ private static int hash(List stack) { } /** - * Prints the continuation stack trace. + * Returns true if the frame is native, a class initializer, or holds monitors. + */ + private static boolean isInterestingFrame(LiveStackFrame f) { + return f.isNativeMethod() + || "".equals(f.getMethodName()) + || (f.getMonitors().length > 0); + } + + /** + * Prints the current thread's stack trace. * * @param printAll true to print all stack frames, false to only print the * frames that are native or holding a monitor */ - static void printStackTrace(PrintStream out, boolean printAll) { + static void printStackTrace(PrintStream out, Continuation.Pinned reason, boolean printAll) { List stack = STACK_WALKER.walk(s -> s.map(f -> (LiveStackFrame) f) .filter(f -> f.getDeclaringClass() != PinnedThreadPrinter.class) .collect(Collectors.toList()) ); + Object lockObj = JIOPSA.lock(out); + if (lockObj instanceof InternalLock lock && lock.tryLock()) { + try { + // find the closest frame that is causing the thread to be pinned + stack.stream() + .filter(f -> isInterestingFrame(f)) + .map(LiveStackFrame::getDeclaringClass) + .findFirst() + .ifPresentOrElse(klass -> { + // print the stack trace if not already seen + int hash = hash(stack); + if (HASHES.get(klass).add(hash)) { + printStackTrace(out, reason, stack, printAll); + } + }, () -> printStackTrace(out, reason, stack, true)); // not found - // find the closest frame that is causing the thread to be pinned - stack.stream() - .filter(f -> (f.isNativeMethod() || f.getMonitors().length > 0)) - .map(LiveStackFrame::getDeclaringClass) - .findFirst() - .ifPresentOrElse(klass -> { - int hash = hash(stack); - Hashes hashes = HASHES.get(klass); - synchronized (hashes) { - // print the stack trace if not already seen - if (hashes.add(hash)) { - printStackTrace(stack, out, printAll); - } - } - }, () -> printStackTrace(stack, out, true)); // not found + } finally { + lock.unlock(); + } + } } - private static void printStackTrace(List stack, - PrintStream out, + private static void printStackTrace(PrintStream out, + Continuation.Pinned reason, + List stack, boolean printAll) { - out.println(Thread.currentThread()); + out.format("%s reason:%s%n", Thread.currentThread(), reason); for (LiveStackFrame frame : stack) { var ste = frame.toStackTraceElement(); int monitorCount = frame.getMonitors().length; if (monitorCount > 0) { out.format(" %s <== monitors:%d%n", ste, monitorCount); - } else if (frame.isNativeMethod() || printAll) { + } else if (printAll || isInterestingFrame(frame)) { out.format(" %s%n", ste); } } diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 36a673fde60cf..6f82516d86452 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -191,7 +191,15 @@ private static class VThreadContinuation extends Continuation { protected void onPinned(Continuation.Pinned reason) { if (TRACE_PINNING_MODE > 0) { boolean printAll = (TRACE_PINNING_MODE == 1); - PinnedThreadPrinter.printStackTrace(System.out, printAll); + VirtualThread vthread = (VirtualThread) Thread.currentThread(); + int oldState = vthread.state(); + try { + // avoid printing when in transition states + vthread.setState(RUNNING); + PinnedThreadPrinter.printStackTrace(System.out, reason, printAll); + } finally { + vthread.setState(oldState); + } } } private static Runnable wrap(VirtualThread vthread, Runnable task) { diff --git a/test/jdk/java/lang/Thread/virtual/TracePinnedThreads.java b/test/jdk/java/lang/Thread/virtual/TracePinnedThreads.java index 01fbdc76d494a..5db29c631a323 100644 --- a/test/jdk/java/lang/Thread/virtual/TracePinnedThreads.java +++ b/test/jdk/java/lang/Thread/virtual/TracePinnedThreads.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -23,7 +23,7 @@ /** * @test - * @bug 8284161 8289284 + * @bug 8284161 8289284 8322846 * @summary Basic test of debugging option to trace pinned threads * @requires vm.continuations * @library /test/lib @@ -34,6 +34,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.time.Duration; +import java.util.concurrent.Executors; import java.util.concurrent.locks.LockSupport; import jdk.test.lib.thread.VThreadRunner; @@ -67,8 +68,8 @@ void testPinnedCausedBySynchronizedBlock() throws Exception { park(); } }); + assertContains(output, "reason:MONITOR"); assertContains(output, "<== monitors:1"); - assertDoesNotContain(output, "(Native Method)"); } /** @@ -78,8 +79,68 @@ void testPinnedCausedBySynchronizedBlock() throws Exception { void testPinnedCausedByNativeMethod() throws Exception { System.loadLibrary("TracePinnedThreads"); String output = run(() -> invokePark()); + assertContains(output, "reason:NATIVE"); assertContains(output, "(Native Method)"); - assertDoesNotContain(output, "<== monitors"); + } + + /** + * Test parking in class initializer. + */ + @Test + void testPinnedCausedByClassInitializer() throws Exception { + class C { + static { + park(); + } + } + String output = run(C::new); + assertContains(output, "reason:NATIVE"); + assertContains(output, ""); + } + + /** + * Test contention writing to System.out when pinned. The test creates four threads + * that write to System.out when pinned, this is enough to potentially deadlock + * without the changes in JDK-8322846. + */ + @Test + void testContention() throws Exception { + // use several classes to avoid duplicate stack traces + class C1 { + synchronized void print() { + System.out.println("hello"); + } + } + class C2 { + synchronized void print() { + System.out.println("hello"); + } + } + class C3 { + synchronized void print() { + System.out.println("hello"); + } + } + class C4 { + synchronized void print() { + System.out.println("hello"); + } + } + + try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { + executor.submit(() -> { + new C1().print(); + }); + executor.submit(() -> { + new C2().print(); + }); + executor.submit(() -> { + new C3().print(); + }); + executor.submit(() -> { + new C4().print(); + }); + } } /** From 3560e680bcd5f9427b43f616f21f87adee8e8aca Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 8 Jan 2024 02:37:10 +0000 Subject: [PATCH 036/112] 8322815: Eliminate -Wparentheses warnings in shenandoah code Reviewed-by: shade, zgu --- src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index d0de328a7b82d..c9c566ad611b6 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -2158,7 +2158,7 @@ void MemoryGraphFixer::collect_memory_nodes() { assert(m != nullptr || (c->is_Loop() && j == LoopNode::LoopBackControl && iteration == 1) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "expect memory state"); if (m != nullptr) { if (m == prev_region && ((c->is_Loop() && j == LoopNode::LoopBackControl) || (prev_region->is_Phi() && prev_region->in(0) == c))) { - assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), ""); + assert((c->is_Loop() && j == LoopNode::LoopBackControl) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), ""); // continue } else if (unique == nullptr) { unique = m; From e44276989fc6358065412be7567d0141c84f1282 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 8 Jan 2024 02:46:10 +0000 Subject: [PATCH 037/112] 8322754: click JComboBox when dialog about to close causes IllegalComponentStateException Reviewed-by: abhiscxk, serb --- .../swing/plaf/basic/BasicComboPopup.java | 4 +- .../javax/swing/JComboBox/ComboPopupBug.java | 92 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/swing/JComboBox/ComboPopupBug.java diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java index 9e20ce3de6b76..38798d4c94fed 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -921,7 +921,7 @@ public void mousePressed(MouseEvent e) { if (e.getSource() == list) { return; } - if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled()) + if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled() || !comboBox.isShowing()) return; if ( comboBox.isEditable() ) { diff --git a/test/jdk/javax/swing/JComboBox/ComboPopupBug.java b/test/jdk/javax/swing/JComboBox/ComboPopupBug.java new file mode 100644 index 0000000000000..3a4fb4b8bc78f --- /dev/null +++ b/test/jdk/javax/swing/JComboBox/ComboPopupBug.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2024, 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. + */ + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 8322754 + * @summary Verifies clicking JComboBox during frame closure causes Exception + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ComboPopupBug + */ + +public class ComboPopupBug { + private static final String instructionsText = """ + This test is used to verify that clicking on JComboBox + when frame containing it is about to close should not + cause IllegalStateException. + + A JComboBox is shown with Close button at the bottom. + Click on Close and then click on JComboBox arrow button + to try to show combobox popup. + If IllegalStateException is thrown, test will automatically Fail + otherwise click Pass. """; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("ComboPopup Instructions") + .instructions(instructionsText) + .testTimeOut(5) + .rows(10) + .columns(35) + .build(); + + SwingUtilities.invokeAndWait(() -> { + JFrame frame = new JFrame("ComboPopup"); + + JComboBox cb = new JComboBox(); + cb.setEditable(true); + cb.addItem("test"); + cb.addItem("test2"); + cb.addItem("test3"); + frame.getContentPane().add(cb, "North"); + + JButton b = new JButton("Close"); + b.addActionListener( + (e)->{ + try { + Thread.sleep(3000); + } + catch (Exception ex) { + } + frame.setVisible(false); + + }); + frame.getContentPane().add(b, "South"); + frame.setSize(200, 200); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, + PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} From d75d876eddfd2e59d9d28c2860fdab4ef3ec3c6b Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 8 Jan 2024 07:30:21 +0000 Subject: [PATCH 038/112] 8322806: Eliminate -Wparentheses warnings in aarch64 code Reviewed-by: stefank, dholmes --- src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index f5b46a5351973..5c850c6bcbd65 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -195,7 +195,7 @@ inline bool frame::equal(frame other) const { && unextended_sp() == other.unextended_sp() && fp() == other.fp() && pc() == other.pc(); - assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction"); + assert(!ret || (cb() == other.cb() && _deopt_state == other._deopt_state), "inconsistent construction"); return ret; } From 7edd10e5fa71dafbbad23455553b7f5ff0a75ac9 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 8 Jan 2024 08:20:07 +0000 Subject: [PATCH 039/112] 8321786: SegmentAllocator:allocateFrom(ValueLayout, MemorySegment,ValueLayout,long,long) spec mismatch in exception scenario Reviewed-by: mcimadamore --- .../java/lang/foreign/MemoryLayout.java | 2 +- .../java/lang/foreign/MemorySegment.java | 42 +++++++++- .../java/lang/foreign/SegmentAllocator.java | 6 +- .../foreign/AbstractMemorySegmentImpl.java | 8 +- .../classes/jdk/internal/foreign/Utils.java | 21 +++-- .../foreign/layout/AbstractLayout.java | 9 +-- .../foreign/layout/MemoryLayoutUtil.java | 7 -- test/jdk/java/foreign/TestLayouts.java | 4 +- .../foreign/TestMemoryAccessInstance.java | 7 ++ .../java/foreign/TestScopedOperations.java | 3 + .../java/foreign/TestSegmentAllocators.java | 77 +++++++++++++++++++ test/jdk/java/foreign/TestSegmentCopy.java | 60 +++++++++++++++ test/jdk/java/foreign/TestSegments.java | 11 ++- 13 files changed, 218 insertions(+), 39 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java index 321d9b09bad34..8a2b3b4df303e 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java @@ -1016,7 +1016,7 @@ static PaddingLayout paddingLayout(long byteSize) { * @throws IllegalArgumentException if {@code elementLayout.byteSize() % elementLayout.byteAlignment() != 0} */ static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) { - MemoryLayoutUtil.requireNonNegative(elementCount); + Utils.checkNonNegativeArgument(elementCount, "elementCount"); Objects.requireNonNull(elementLayout); Utils.checkElementAlignment(elementLayout, "Element layout size is not multiple of alignment"); diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index da255b9912b25..faf28b01bf0ac 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -44,6 +44,7 @@ import jdk.internal.foreign.AbstractMemorySegmentImpl; import jdk.internal.foreign.MemorySessionImpl; import jdk.internal.foreign.SegmentFactories; +import jdk.internal.foreign.Utils; import jdk.internal.javac.Restricted; import jdk.internal.reflect.CallerSensitive; import jdk.internal.vm.annotation.ForceInline; @@ -1591,6 +1592,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ byte get(ValueLayout.OfByte layout, long offset); @@ -1609,6 +1611,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1629,6 +1632,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ boolean get(ValueLayout.OfBoolean layout, long offset); @@ -1647,6 +1651,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1667,6 +1672,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ char get(ValueLayout.OfChar layout, long offset); @@ -1685,6 +1691,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1705,6 +1712,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ short get(ValueLayout.OfShort layout, long offset); @@ -1723,6 +1731,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1743,6 +1752,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ int get(ValueLayout.OfInt layout, long offset); @@ -1761,6 +1771,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1781,6 +1792,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ float get(ValueLayout.OfFloat layout, long offset); @@ -1799,6 +1811,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1819,6 +1832,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ long get(ValueLayout.OfLong layout, long offset); @@ -1837,6 +1851,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1857,6 +1872,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ double get(ValueLayout.OfDouble layout, long offset); @@ -1875,6 +1891,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} */ @@ -1905,6 +1922,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in {@code T} * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} + * or {@code offset < 0} */ MemorySegment get(AddressLayout layout, long offset); @@ -1923,8 +1941,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * incompatible with the alignment constraint * in the provided layout * @throws IndexOutOfBoundsException if {@code offset > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is - * {@linkplain #isReadOnly() read-only} + * or {@code offset < 0} * @throws IllegalArgumentException if {@code value} is not a * {@linkplain #isNative() native} segment * @throws IllegalArgumentException if this segment is @@ -1951,6 +1968,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ byte getAtIndex(ValueLayout.OfByte layout, long index); @@ -1973,6 +1991,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ boolean getAtIndex(ValueLayout.OfBoolean layout, long index); @@ -1995,6 +2014,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ char getAtIndex(ValueLayout.OfChar layout, long index); @@ -2017,7 +2037,8 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * or {@code index < 0} + * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfChar layout, long index, char value); @@ -2040,6 +2061,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ short getAtIndex(ValueLayout.OfShort layout, long index); @@ -2061,6 +2083,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfByte layout, long index, byte value); @@ -2084,6 +2107,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfBoolean layout, long index, boolean value); @@ -2107,6 +2131,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfShort layout, long index, short value); @@ -2130,6 +2155,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ int getAtIndex(ValueLayout.OfInt layout, long index); @@ -2152,6 +2178,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfInt layout, long index, int value); @@ -2175,6 +2202,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ float getAtIndex(ValueLayout.OfFloat layout, long index); @@ -2197,6 +2225,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfFloat layout, long index, float value); @@ -2220,6 +2249,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ long getAtIndex(ValueLayout.OfLong layout, long index); @@ -2242,6 +2272,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfLong layout, long index, long value); @@ -2265,6 +2296,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ double getAtIndex(ValueLayout.OfDouble layout, long index); @@ -2287,6 +2319,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} * @throws IllegalArgumentException if this segment is {@linkplain #isReadOnly() read-only} */ void setAtIndex(ValueLayout.OfDouble layout, long index, double value); @@ -2319,6 +2352,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * in {@code T} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} + * or {@code index < 0} */ MemorySegment getAtIndex(AddressLayout layout, long index); @@ -2341,7 +2375,7 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr * @throws IllegalArgumentException if {@code layout.byteAlignment() > layout.byteSize()} * @throws IndexOutOfBoundsException if {@code index * layout.byteSize()} overflows * @throws IndexOutOfBoundsException if {@code index * layout.byteSize() > byteSize() - layout.byteSize()} - * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only} + * or {@code index < 0} * @throws IllegalArgumentException if {@code value} is not a {@linkplain #isNative() native} segment * @throws IllegalArgumentException if this segment is * {@linkplain #isReadOnly() read-only} diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java index 6be9d949ea652..6c9cf51bee8b7 100644 --- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java +++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java @@ -33,6 +33,7 @@ import jdk.internal.foreign.ArenaImpl; import jdk.internal.foreign.SlicingAllocator; import jdk.internal.foreign.StringSupport; +import jdk.internal.foreign.Utils; import jdk.internal.vm.annotation.ForceInline; /** @@ -390,9 +391,10 @@ default MemorySegment allocateFrom(AddressLayout layout, MemorySegment value) { * with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive} * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code source.isAccessibleBy(T) == false} - * @throws IndexOutOfBoundsException if {@code elementCount * sourceElementLayout.byteSize()} overflows + * @throws IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows + * @throws IllegalArgumentException if {@code elementCount < 0} * @throws IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())} - * @throws IndexOutOfBoundsException if either {@code sourceOffset} or {@code elementCount} are {@code < 0} + * @throws IndexOutOfBoundsException if {@code sourceOffset < 0} */ @ForceInline default MemorySegment allocateFrom(ValueLayout elementLayout, diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 305594952d44e..0efe62c1e4fbc 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -153,9 +153,7 @@ public final MemorySegment reinterpret(Arena arena, Consumer clea public MemorySegment reinterpretInternal(Class callerClass, long newSize, Scope scope, Consumer cleanup) { Reflection.ensureNativeAccess(callerClass, MemorySegment.class, "reinterpret"); - if (newSize < 0) { - throw new IllegalArgumentException("newSize < 0"); - } + Utils.checkNonNegativeArgument(newSize, "newSize"); if (!isNative()) throw new UnsupportedOperationException("Not a native segment"); Runnable action = cleanup != null ? () -> cleanup.accept(SegmentFactories.makeNativeSegmentUnchecked(address(), newSize)) : @@ -594,6 +592,7 @@ public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset, long elementCount) { + Utils.checkNonNegativeIndex(elementCount, "elementCount"); AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment; if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) { @@ -625,7 +624,7 @@ public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset, Object dstArray, int dstIndex, int elementCount) { - + Utils.checkNonNegativeIndex(elementCount, "elementCount"); var dstInfo = Utils.BaseAndScale.of(dstArray); if (dstArray.getClass().componentType() != srcLayout.carrier()) { throw new IllegalArgumentException("Incompatible value layout: " + srcLayout); @@ -652,7 +651,6 @@ public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long sr public static void copy(Object srcArray, int srcIndex, MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset, int elementCount) { - var srcInfo = Utils.BaseAndScale.of(srcArray); if (srcArray.getClass().componentType() != dstLayout.carrier()) { throw new IllegalArgumentException("Incompatible value layout: " + dstLayout); diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java index d0d5c866f6b4e..6a081e23eac0d 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java @@ -200,11 +200,8 @@ public static long pointeeByteAlign(AddressLayout addressLayout) { } public static void checkAllocationSizeAndAlign(long byteSize, long byteAlignment) { - // size should be >= 0 - if (byteSize < 0) { - throw new IllegalArgumentException("Invalid allocation size : " + byteSize); - } - + // byteSize should be >= 0 + Utils.checkNonNegativeArgument(byteSize, "allocation size"); checkAlign(byteAlignment); } @@ -216,6 +213,20 @@ public static void checkAlign(long byteAlignment) { } } + @ForceInline + public static void checkNonNegativeArgument(long value, String name) { + if (value < 0) { + throw new IllegalArgumentException("The provided " + name + " is negative: " + value); + } + } + + @ForceInline + public static void checkNonNegativeIndex(long value, String name) { + if (value < 0) { + throw new IndexOutOfBoundsException("The provided " + name + " is negative: " + value); + } + } + private static long computePadding(long offset, long align) { boolean isAligned = offset == 0 || offset % align == 0; if (isAligned) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java index e4d931127af99..3c0cf3902bbd0 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java @@ -151,13 +151,8 @@ private static long requirePowerOfTwoAndGreaterOrEqualToOne(long value) { } public long scale(long offset, long index) { - if (offset < 0) { - throw new IllegalArgumentException("Negative offset: " + offset); - } - if (index < 0) { - throw new IllegalArgumentException("Negative index: " + index); - } - + Utils.checkNonNegativeArgument(offset, "offset"); + Utils.checkNonNegativeArgument(index, "index"); return Math.addExact(offset, Math.multiplyExact(byteSize(), index)); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java b/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java index dce061410285f..6b8e7738198cc 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java @@ -30,13 +30,6 @@ public final class MemoryLayoutUtil { private MemoryLayoutUtil() { } - public static long requireNonNegative(long value) { - if (value < 0) { - throw new IllegalArgumentException("The provided value was negative: " + value); - } - return value; - } - public static long requireByteSizeValid(long byteSize, boolean allowZero) { if ((byteSize == 0 && !allowZero) || byteSize < 0) { throw new IllegalArgumentException("Invalid byte size: " + byteSize); diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java index f4048aaa68a08..2aa398468cc9f 100644 --- a/test/jdk/java/foreign/TestLayouts.java +++ b/test/jdk/java/foreign/TestLayouts.java @@ -371,13 +371,13 @@ public void testVarHandleCaching() { } @Test(expectedExceptions=IllegalArgumentException.class, - expectedExceptionsMessageRegExp=".*Negative offset.*") + expectedExceptionsMessageRegExp=".*offset is negative.*") public void testScaleNegativeOffset() { JAVA_INT.scale(-1, 0); } @Test(expectedExceptions=IllegalArgumentException.class, - expectedExceptionsMessageRegExp=".*Negative index.*") + expectedExceptionsMessageRegExp=".*index is negative.*") public void testScaleNegativeIndex() { JAVA_INT.scale(0, -1); } diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index d56f44388a4bb..b749c96ac5421 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -164,6 +164,13 @@ public void badAccessOverflowInIndexedAccess(String t } } + @Test(dataProvider = "segmentAccessors") + public void negativeOffset(String testName, Accessor accessor) { + MemorySegment segment = MemorySegment.ofArray(new byte[100]); + assertThrows(IndexOutOfBoundsException.class, () -> accessor.get(segment, -ValueLayout.JAVA_LONG.byteSize())); + assertThrows(IndexOutOfBoundsException.class, () -> accessor.set(segment, -ValueLayout.JAVA_LONG.byteSize(), accessor.value)); + } + static final ByteOrder NE = ByteOrder.nativeOrder(); @DataProvider(name = "segmentAccessors") diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java index 70223c00c008d..d680d23414570 100644 --- a/test/jdk/java/foreign/TestScopedOperations.java +++ b/test/jdk/java/foreign/TestScopedOperations.java @@ -27,6 +27,7 @@ */ import java.lang.foreign.Arena; +import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; @@ -135,6 +136,8 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_FLOAT, new float[]{0}), "Arena::allocateFrom/float"); ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_LONG, new long[]{0}), "Arena::allocateFrom/long"); ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_DOUBLE, new double[]{0}), "Arena::allocateFrom/double"); + var source = MemorySegment.ofArray(new byte[]{}); + ScopedOperation.ofScope(a -> a.allocateFrom(ValueLayout.JAVA_INT, source, JAVA_BYTE, 0, 1), "Arena::allocateFrom/5arg"); }; @DataProvider(name = "scopedOperations") diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index 0e0c49320da07..87418f39d90af 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -44,6 +44,8 @@ import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.Function; @@ -189,6 +191,81 @@ public void testAllocatorAllocateFromHeapSegment() { } } + // Invariant checking tests for the SegmentAllocator method: + // MemorySegment allocateFrom(ValueLayout elementLayout, + // MemorySegment source, + // ValueLayout sourceElementLayout, + // long sourceOffset, + // long elementCount) { + @Test + public void testAllocatorAllocateFromArguments() { + try (Arena arena = Arena.ofConfined()) { + var sourceElements = 2; + var source = arena.allocate(ValueLayout.JAVA_LONG, sourceElements); + var elementLayout = ValueLayout.JAVA_INT; + var sourceElementLayout = ValueLayout.JAVA_INT; + + // IllegalArgumentException if {@code elementLayout.byteSize() != sourceElementLayout.byteSize()} + assertThrows(IllegalArgumentException.class, () -> + arena.allocateFrom(elementLayout, source, ValueLayout.JAVA_BYTE, 0, 1) + ); + + // IllegalArgumentException if source segment/offset + // are incompatible with the alignment constraint + // in the source element layout + assertThrows(IllegalArgumentException.class, () -> + arena.allocateFrom(elementLayout, source.asSlice(1), sourceElementLayout, 0, 1) + ); + assertThrows(IllegalArgumentException.class, () -> + arena.allocateFrom(elementLayout, source, sourceElementLayout, 1, 1) + ); + + // IllegalArgumentException if {@code elementLayout.byteAlignment() > elementLayout.byteSize()} + assertThrows(IllegalArgumentException.class, () -> + arena.allocateFrom(elementLayout.withByteAlignment(elementLayout.byteAlignment() * 2), source, sourceElementLayout, 1, 1) + ); + + // IllegalStateException if the {@linkplain MemorySegment#scope() scope} associated + // with {@code source} is not {@linkplain MemorySegment.Scope#isAlive() alive} + // This is tested in TestScopedOperations + + // WrongThreadException if this method is called from a thread {@code T}, + // such that {@code source.isAccessibleBy(T) == false} + CompletableFuture future = CompletableFuture.supplyAsync(Arena::ofConfined); + try { + Arena otherThreadArena = future.get(); + assertThrows(WrongThreadException.class, () -> + otherThreadArena.allocateFrom(elementLayout, source, sourceElementLayout, 0, 1) + ); + } catch (ExecutionException | InterruptedException e) { + fail("Unable to create arena", e); + } + + // IllegalArgumentException if {@code elementCount * sourceElementLayout.byteSize()} overflows + assertThrows(IllegalArgumentException.class, () -> + arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, Long.MAX_VALUE) + ); + + // IndexOutOfBoundsException if {@code sourceOffset > source.byteSize() - (elementCount * sourceElementLayout.byteSize())} + assertThrows(IndexOutOfBoundsException.class, () -> + arena.allocateFrom(elementLayout, source, sourceElementLayout, source.byteSize() - (1 * sourceElementLayout.byteAlignment()) + elementLayout.byteSize(), 1) + ); + + // IndexOutOfBoundsException if {@code sourceOffset < 0} + assertThrows(IndexOutOfBoundsException.class, () -> + arena.allocateFrom(elementLayout, source, sourceElementLayout, -elementLayout.byteSize(), 1) + ); + + // IllegalArgumentException if {@code elementCount < 0} + assertThrows(IllegalArgumentException.class, () -> + arena.allocateFrom(elementLayout, source, sourceElementLayout, 0, -1) + ); + + + } + } + + @Test public void testArrayAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index 414cd0a8451d9..88636bf5420ce 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -145,6 +145,66 @@ public void testHyperAlignedDst() { MemorySegment.copy(segment, JAVA_BYTE.withByteAlignment(2), 0, segment, 0, 4); } + @Test + public void testCopy5ArgWithNegativeValues() { + MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, -1, dst, 0, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, 0, dst, -1, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, 0, dst, 0, -1) + ); + } + + @Test + public void testCopy7ArgWithNegativeValues() { + MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, JAVA_BYTE, -1, dst, JAVA_BYTE, 0, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, JAVA_BYTE, 0, dst, JAVA_BYTE, -1, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, JAVA_BYTE, 0, dst, JAVA_BYTE, 0, -1) + ); + } + + @Test + public void testCopyFromArrayWithNegativeValues() { + MemorySegment src = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + byte[] dst = new byte[] {1, 2, 3, 4}; + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, JAVA_BYTE, -1, dst, 0, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, JAVA_BYTE, 0, dst, -1, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, JAVA_BYTE, 0, dst, 0, -1) + ); + } + + @Test + public void testCopyToArrayWithNegativeValues() { + byte[] src = new byte[] {1, 2, 3, 4}; + MemorySegment dst = MemorySegment.ofArray(new byte[] {1, 2, 3, 4}); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, -1, dst, JAVA_BYTE, 0, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, 0, dst, JAVA_BYTE, -1, 4) + ); + assertThrows(IndexOutOfBoundsException.class, () -> + MemorySegment.copy(src, 0, dst, JAVA_BYTE, 0, -1) + ); + } + enum Type { // Byte BYTE(byte.class, JAVA_BYTE, i -> (byte)i), diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index 94b49eb7e594c..44ecd12ba5ebd 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -43,6 +43,7 @@ import java.util.function.Supplier; import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; import static org.testng.Assert.*; public class TestSegments { @@ -55,14 +56,13 @@ public void testBadAllocateAlign(long size, long align) { @Test public void testZeroLengthNativeSegment() { try (Arena arena = Arena.ofConfined()) { - Arena session = arena; - var segment = session.allocate(0, 1); + var segment = arena.allocate(0, 1); assertEquals(segment.byteSize(), 0); MemoryLayout seq = MemoryLayout.sequenceLayout(0, JAVA_INT); - segment = session.allocate(seq); + segment = arena.allocate(seq); assertEquals(segment.byteSize(), 0); assertEquals(segment.address() % seq.byteAlignment(), 0); - segment = session.allocate(0, 4); + segment = arena.allocate(0, 4); assertEquals(segment.byteSize(), 0); assertEquals(segment.address() % 4, 0); MemorySegment rawAddress = MemorySegment.ofAddress(segment.address()); @@ -133,8 +133,7 @@ public void testDerivedScopes(Supplier segmentSupplier) { @Test public void testEqualsOffHeap() { try (Arena arena = Arena.ofConfined()) { - Arena scope1 = arena; - MemorySegment segment = scope1.allocate(100, 1); + MemorySegment segment = arena.allocate(100, 1); assertEquals(segment, segment.asReadOnly()); assertEquals(segment, segment.asSlice(0, 100)); assertNotEquals(segment, segment.asSlice(10, 90)); From a40d397d5d785d29a2d5e848f872d11dab3bf80c Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 8 Jan 2024 09:01:33 +0000 Subject: [PATCH 040/112] 8323110: Eliminate -Wparentheses warnings in ppc code Reviewed-by: dholmes --- src/hotspot/cpu/ppc/frame_ppc.inline.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp index e7dca45b3c35a..861c6adc491e4 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp @@ -78,8 +78,8 @@ inline void frame::setup() { // Continuation frames on the java heap are not aligned. // When thawing interpreted frames the sp can be unaligned (see new_stack_frame()). assert(_on_heap || - (is_aligned(_sp, alignment_in_bytes) || is_interpreted_frame()) && - (is_aligned(_fp, alignment_in_bytes) || !is_fully_initialized()), + ((is_aligned(_sp, alignment_in_bytes) || is_interpreted_frame()) && + (is_aligned(_fp, alignment_in_bytes) || !is_fully_initialized())), "invalid alignment sp:" PTR_FORMAT " unextended_sp:" PTR_FORMAT " fp:" PTR_FORMAT, p2i(_sp), p2i(_unextended_sp), p2i(_fp)); } From eb9e754b3a439cc3ce36c2c9393bc8b250343844 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 8 Jan 2024 10:27:00 +0000 Subject: [PATCH 041/112] 8323065: Unneccesary CodeBlob lookup in CompiledIC::internal_set_ic_destination Reviewed-by: dlong, thartmann --- src/hotspot/share/code/compiledIC.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index b493df73ba88c..28c02d8578c55 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -128,11 +128,13 @@ void CompiledIC::internal_set_ic_destination(address entry_point, bool is_icstub tty->cr(); } +#ifdef ASSERT { CodeBlob* cb = CodeCache::find_blob(_call->instruction_address()); assert(cb != nullptr && cb->is_compiled(), "must be compiled"); - _call->set_destination_mt_safe(entry_point); } +#endif + _call->set_destination_mt_safe(entry_point); if (is_optimized() || is_icstub) { // Optimized call sites don't have a cache value and ICStub call From 09c6c4ff021b7dc719c0b1e0dfb041b03bba1b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Mon, 8 Jan 2024 11:41:51 +0000 Subject: [PATCH 042/112] 8322489: 22-b27: Up to 7% regression in all Footprint3-*-G1/ZGC Reviewed-by: egahlin --- src/hotspot/share/jfr/jfr.cpp | 4 +++- .../checkpoint/jfrCheckpointManager.cpp | 8 +++---- .../checkpoint/jfrCheckpointWriter.hpp | 1 + .../share/jfr/recorder/jfrRecorder.cpp | 24 +++++++++++++------ .../share/jfr/recorder/jfrRecorder.hpp | 1 + .../jfr/support/jfrDeprecationManager.cpp | 4 +++- 6 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp index 45848fb024311..03b47bcd21dc5 100644 --- a/src/hotspot/share/jfr/jfr.cpp +++ b/src/hotspot/share/jfr/jfr.cpp @@ -67,7 +67,9 @@ void Jfr::on_create_vm_3() { } void Jfr::on_unloading_classes() { - JfrCheckpointManager::on_unloading_classes(); + if (JfrRecorder::is_created() || JfrRecorder::is_started_on_commandline()) { + JfrCheckpointManager::on_unloading_classes(); + } } bool Jfr::is_excluded(Thread* t) { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index 799d6ef899d03..0aed916702e79 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -117,16 +117,16 @@ bool JfrCheckpointManager::initialize_early() { assert(_thread_local_mspace == nullptr, "invariant"); _thread_local_mspace = new JfrThreadLocalCheckpointMspace(); if (_thread_local_mspace == nullptr || !_thread_local_mspace->initialize(thread_local_buffer_size, - thread_local_buffer_prealloc_count, - thread_local_buffer_prealloc_count)) { + thread_local_buffer_prealloc_count, + thread_local_buffer_prealloc_count)) { return false; } assert(_virtual_thread_local_mspace == nullptr, "invariant"); _virtual_thread_local_mspace = new JfrThreadLocalCheckpointMspace(); if (_virtual_thread_local_mspace == nullptr || !_virtual_thread_local_mspace->initialize(virtual_thread_local_buffer_size, - JFR_MSPACE_UNLIMITED_CACHE_SIZE, - virtual_thread_local_buffer_prealloc_count)) { + JFR_MSPACE_UNLIMITED_CACHE_SIZE, + virtual_thread_local_buffer_prealloc_count)) { return false; } return true; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp index f99159b3a51c9..a8ec2fd70f538 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointWriter.hpp @@ -55,6 +55,7 @@ struct JfrCheckpointContext { class JfrCheckpointWriter : public JfrCheckpointWriterBase { friend class JfrCheckpointManager; + friend class JfrDeprecationManager; friend class JfrSerializerRegistration; friend class JfrTypeManager; private: diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp index 40c3d7a8c4f4d..cc460f8c2aad6 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp @@ -86,9 +86,6 @@ bool JfrRecorder::create_oop_storages() { return ObjectSampler::create_oop_storage(); } -// Subsystem -static JfrCheckpointManager* _checkpoint_manager = nullptr; - bool JfrRecorder::on_create_vm_1() { if (!is_disabled()) { if (FlightRecorder || is_started_on_commandline()) { @@ -99,9 +96,10 @@ bool JfrRecorder::on_create_vm_1() { return false; } - _checkpoint_manager = JfrCheckpointManager::create(); - if (_checkpoint_manager == nullptr || !_checkpoint_manager->initialize_early()) { - return false; + if (is_started_on_commandline()) { + if (!create_checkpoint_manager()) { + return false; + } } // fast time initialization @@ -292,7 +290,7 @@ bool JfrRecorder::create_components() { if (!create_storage()) { return false; } - if (!create_checkpoint_manager()) { + if (!initialize_checkpoint_manager()) { return false; } if (!create_stacktrace_repository()) { @@ -321,6 +319,7 @@ static JfrStackTraceRepository* _stack_trace_repository; static JfrStringPool* _stringpool = nullptr; static JfrOSInterface* _os_interface = nullptr; static JfrThreadSampling* _thread_sampling = nullptr; +static JfrCheckpointManager* _checkpoint_manager = nullptr; bool JfrRecorder::create_java_event_writer() { return JfrJavaEventWriter::initialize(); @@ -357,6 +356,17 @@ bool JfrRecorder::create_storage() { } bool JfrRecorder::create_checkpoint_manager() { + assert(_checkpoint_manager == nullptr, "invariant"); + _checkpoint_manager = JfrCheckpointManager::create(); + return _checkpoint_manager != nullptr && _checkpoint_manager->initialize_early(); +} + +bool JfrRecorder::initialize_checkpoint_manager() { + if (_checkpoint_manager == nullptr) { + if (!create_checkpoint_manager()) { + return false; + } + } assert(_checkpoint_manager != nullptr, "invariant"); assert(_repository != nullptr, "invariant"); return _checkpoint_manager->initialize(&_repository->chunkwriter()); diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp index 3e2541fad98ef..9f4969b01872a 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.hpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.hpp @@ -42,6 +42,7 @@ class JfrRecorder : public JfrCHeapObj { static bool on_create_vm_2(); static bool on_create_vm_3(); static bool create_checkpoint_manager(); + static bool initialize_checkpoint_manager(); static bool create_chunk_repository(); static bool create_java_event_writer(); static bool create_jvmti_agent(); diff --git a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp index a36b85dbb7eb1..5f5c87d239c7f 100644 --- a/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp +++ b/src/hotspot/share/jfr/support/jfrDeprecationManager.cpp @@ -371,8 +371,10 @@ void JfrDeprecationManager::write_edges(JfrChunkWriter& cw, Thread* thread, bool void JfrDeprecationManager::on_type_set(JfrCheckpointWriter& writer, JfrChunkWriter* cw, Thread* thread) { assert(_pending_list.is_empty(), "invariant"); - if (writer.has_data() && _pending_head != nullptr) { + if (_pending_head != nullptr) { save_type_set_blob(writer); + } else { + writer.cancel(); } if (cw != nullptr) { write_edges(*cw, thread); From 71aac7a5fbb9a32181ada1a04b6a9622fe939c59 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 8 Jan 2024 11:45:18 +0000 Subject: [PATCH 043/112] 8276809: java/awt/font/JNICheck/FreeTypeScalerJNICheck.java shows JNI warning on Windows Reviewed-by: rschmelter, stuefe --- .../native/libawt/windows/awt_Win32GraphicsEnv.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp index 6c949b564e960..7dac7b17b1be4 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -126,9 +126,15 @@ BOOL DWMIsCompositionEnabled() { dwmIsCompositionEnabled = bRes; JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - JNU_CallStaticMethodByName(env, NULL, + jboolean hasException; + JNU_CallStaticMethodByName(env, &hasException, "sun/awt/Win32GraphicsEnvironment", "dwmCompositionChanged", "(Z)V", (jboolean)bRes); + if (hasException) { + J2dTraceLn(J2D_TRACE_INFO, "Exception occurred in DWMIsCompositionEnabled"); + env->ExceptionDescribe(); + env->ExceptionClear(); + } return bRes; } From 458e563cd994f5e0f590c2144e8ed35d020d53d6 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 8 Jan 2024 12:57:55 +0000 Subject: [PATCH 044/112] 8310711: [IR Framework] Remove safepoint while printing handling Reviewed-by: thartmann, epeter --- .../parser/hotspot/CompilePhaseBlock.java | 31 +--- .../irmatching/parser/hotspot/State.java | 18 +- .../parser/hotspot/WriterThread.java | 51 ------ .../parser/hotspot/WriterThreads.java | 50 ------ .../tests/TestSafepointWhilePrinting.java | 152 ---------------- .../safepoint_while_printing_hotspot_pid.log | 163 ------------------ 6 files changed, 4 insertions(+), 461 deletions(-) delete mode 100644 test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/WriterThread.java delete mode 100644 test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/WriterThreads.java delete mode 100644 test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSafepointWhilePrinting.java delete mode 100644 test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/safepoint_while_printing_hotspot_pid.log diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/CompilePhaseBlock.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/CompilePhaseBlock.java index 16cc62f9c57be..b97c56a57203c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/CompilePhaseBlock.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/CompilePhaseBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -29,7 +29,6 @@ * This class represents a single compile phase block of a {@link LoggedMethod}. */ class CompilePhaseBlock { - public static final String SAFEPOINT_WHILE_PRINTING_MESSAGE = ""; /** * Dummy object for a block that we do not need to parse. @@ -38,11 +37,6 @@ class CompilePhaseBlock { private final CompilePhase compilePhase; private final StringBuilder builder; - /** - * Stores an incomplete line that was interrupted by a safepoint. - * Needs to be merged with the immediately following line. - */ - private String incompleteLine = ""; public CompilePhaseBlock(CompilePhase compilePhase) { this.compilePhase = compilePhase; @@ -92,35 +86,14 @@ public static boolean isBlockEndLine(String line) { } public void addLine(String line) { - line = mergeWithIncompleteLine(line); - if (line.endsWith(SAFEPOINT_WHILE_PRINTING_MESSAGE)) { - line = removeSafepointMessage(line); - incompleteLine = line; - } else { - appendLine(line); - } - } - - private String mergeWithIncompleteLine(String line) { - if (!incompleteLine.isEmpty()) { - line = incompleteLine + line; - incompleteLine = ""; - } - return line; - } + builder.append(escapeXML(line)).append(System.lineSeparator()); - private static String removeSafepointMessage(String line) { - return line.substring(0, line.lastIndexOf(SAFEPOINT_WHILE_PRINTING_MESSAGE)); } public String content() { return builder.toString(); } - private void appendLine(String line) { - builder.append(escapeXML(line)).append(System.lineSeparator()); - } - private static String escapeXML(String line) { if (line.contains("&")) { line = line.replace("<", "<"); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/State.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/State.java index 75d6b060cb243..49f25674dbf6c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/State.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/State.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -29,8 +29,6 @@ * This class holds the current state of the parsing of the hotspot_pid* file. */ class State { - private final WriterThreads writerThreads; - private WriterThread writerThread; private final CompileQueueMessages compileQueueMessages; private final LoggedMethods loggedMethods; private LoggedMethod loggedMethod = LoggedMethod.DONT_CARE; @@ -38,7 +36,6 @@ class State { public State(String testClassName, TestMethods testMethods) { this.compileQueueMessages = new CompileQueueMessages(testClassName, testMethods); this.loggedMethods = new LoggedMethods(); - this.writerThreads = new WriterThreads(); } public LoggedMethods loggedMethods() { @@ -46,9 +43,7 @@ public LoggedMethods loggedMethods() { } public void update(String line) { - if (WriterThread.isWriterThreadLine(line)) { - processWriterThreadLine(line); - } else if (compileQueueMessages.isTestMethodQueuedLine(line)) { + if (compileQueueMessages.isTestMethodQueuedLine(line)) { processCompileQueueLine(line); } else if (CompilePhaseBlock.isBlockStartLine(line)) { processBlockStartLine(line); @@ -59,15 +54,6 @@ public void update(String line) { } } - private void processWriterThreadLine(String line) { - if (loggedMethod.hasActiveBlock()) { - // The current compile phase block was interrupted due to a safepoint. Save and restore later. - writerThread.saveLoggedMethod(loggedMethod); - } - writerThread = writerThreads.parse(line); - loggedMethod = writerThread.restoreLoggedMethod(); - } - private void processCompileQueueLine(String line) { String methodName = compileQueueMessages.parse(line); loggedMethods.registerMethod(methodName); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/WriterThread.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/WriterThread.java deleted file mode 100644 index 302bd203277e1..0000000000000 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/irmatching/parser/hotspot/WriterThread.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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. - */ - -package compiler.lib.ir_framework.driver.irmatching.parser.hotspot; - -/** - * This class represents a writer thread that emits log messages with LogCompilation. It saves and restores a currently - * parsed {@link LoggedMethod} if a {@link CompilePhaseBlock} was interrupted before reaching the block end tag. - * - * @see LoggedMethod - * @see CompilePhaseBlock - */ -class WriterThread { - private LoggedMethod loggedMethod = LoggedMethod.DONT_CARE; - - public static boolean isWriterThreadLine(String line) { - return line.startsWith(" mapIdToThread = new HashMap<>(); - - WriterThread parse(String line) { - int writerThreadId = parseWriterThreadId(line); - return mapIdToThread.computeIfAbsent(writerThreadId, c -> new WriterThread()); - } - - private static int parseWriterThreadId(String line) { - Pattern pattern = Pattern.compile("='(\\d+)'"); - Matcher matcher = pattern.matcher(line); - TestFramework.check(matcher.find(), "should find writer thread id"); - return Integer.parseInt(matcher.group(1)); - } -} diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSafepointWhilePrinting.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSafepointWhilePrinting.java deleted file mode 100644 index 99de3c1510ca7..0000000000000 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestSafepointWhilePrinting.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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. - */ - -package compiler.testlibrary_tests.ir_framework.tests; - -import compiler.lib.ir_framework.CompilePhase; -import compiler.lib.ir_framework.IR; -import compiler.lib.ir_framework.IRNode; -import compiler.lib.ir_framework.Test; -import compiler.lib.ir_framework.driver.irmatching.IRMatcher; -import compiler.lib.ir_framework.driver.irmatching.Matchable; -import compiler.lib.ir_framework.driver.irmatching.parser.TestClassParser; -import jdk.test.lib.Utils; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; - -/* - * @test - * @bug 8300273 - * @requires vm.debug == true & vm.flagless - * @summary Test TestClassParser such that it correctly parses the hotspot_pid* files with safepoint interruption messages - * @library /test/lib /testlibrary_tests / - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run junit/othervm -Xbootclasspath/a:. -DSkipWhiteBoxInstall=true -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:+WhiteBoxAPI compiler.testlibrary_tests.ir_framework.tests.TestSafepointWhilePrinting - */ -public class TestSafepointWhilePrinting { - static int iFld; - - @org.junit.Test - public void test() throws IOException { - String hotspotPidFileName = "safepoint_while_printing_hotspot_pid.log"; - Path hotspotPidFilePath = Paths.get(Utils.TEST_SRC).resolve(hotspotPidFileName); - // Copy file to current workdir - Files.copy(hotspotPidFilePath, Paths.get("").resolve(hotspotPidFileName), - StandardCopyOption.REPLACE_EXISTING); - - String irEncoding = - """ - ##### IRMatchRulesEncoding - used by TestFramework ##### - ,{comma separated applied @IR rule ids} - test1,1 - test2,1 - testSafepointInBlock,1 - testQueueInBlock1,1 - testQueueInBlock2,1 - testDoubleInterruptOuter,1 - testDoubleInterruptMiddle,1 - testDoubleInterruptInner,1 - testCompilePhaseBackToBackFirst,1 - testCompilePhaseBackToBackLast,1 - ----- END ----- - ##### IRMatchingVMInfo - used by TestFramework ##### - : - cpuFeatures:empty_cpu_info - MaxVectorSize:64 - MaxVectorSizeIsDefault:1 - LoopMaxUnroll:64 - UseAVX:1 - UseAVXIsDefault:1 - ----- END VMInfo ----- - """; - TestClassParser testClassParser = new TestClassParser(TestSafepointWhilePrinting.class); - Matchable testClassMatchable = testClassParser.parse(hotspotPidFileName, irEncoding); - IRMatcher matcher = new IRMatcher(testClassMatchable); - matcher.match(); - } - - @Test - @IR(counts = {IRNode.CMP_UL3, "1"}) - public void test1() { - iFld = 34; - } - - @Test - @IR(counts = {IRNode.CMP_UL3, "1"}) - public void test2() { - iFld = 34; - } - - @Test - @IR(counts = {"testSafepointInBlock @ bci:-1", "1"}, phase = CompilePhase.PRINT_IDEAL) - public void testSafepointInBlock() { - iFld = 34; - } - - @Test - @IR(counts = {"testQueueInBlock1 @ bci:-1", "1"}, phase = CompilePhase.PRINT_IDEAL) - public void testQueueInBlock1() { - iFld = 34; - } - - @Test - @IR(counts = {"testQueueInBlock2 @ bci:-1", "1"}, phase = CompilePhase.PRINT_IDEAL) - public void testQueueInBlock2() { - iFld = 34; - } - @Test - @IR(counts = {"!jvms: TestSafepointWhilePrinting::testDoubleInterruptOuter", "1"}, phase = CompilePhase.PRINT_IDEAL) - public void testDoubleInterruptOuter() { - iFld = 34; - } - - @Test - @IR(counts = {"testDoubleInterruptMiddle @ bci:-1", "1", IRNode.CMP_UL3, "1"}, phase = CompilePhase.PRINT_IDEAL) - public void testDoubleInterruptMiddle() { - iFld = 34; - } - - @Test - @IR(counts = {IRNode.CON_L, "1"}, phase = CompilePhase.PRINT_IDEAL) - public void testDoubleInterruptInner() { - iFld = 34; - } - - @Test - @IR(counts = {"(line 115)", "1", IRNode.CMP_UL3, "1"}, phase = {CompilePhase.AFTER_PARSING, CompilePhase.BEFORE_MATCHING}) - public void testCompilePhaseBackToBackFirst() { - iFld = 34; - } - - @Test - @IR(counts = {"(line 115)", "1", IRNode.CMP_UL3, "1"}, phase = {CompilePhase.AFTER_PARSING, CompilePhase.BEFORE_MATCHING}) - public void testCompilePhaseBackToBackLast() { - iFld = 34; - } -} diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/safepoint_while_printing_hotspot_pid.log b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/safepoint_while_printing_hotspot_pid.log deleted file mode 100644 index 2bdd2540f08a5..0000000000000 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/safepoint_while_printing_hotspot_pid.log +++ /dev/null @@ -1,163 +0,0 @@ - - 1682 967 b 3 jdk.test.lib.Asserts::assertEquals (7 bytes) - - - - - - - - - - 1716 995 3 compiler.testlibrary_tests.ir_framework.tests.TestSafepointWhilePrinting::compareLongWithImm5 (8 bytes) made not entrant - - 1716 1018 b 4 compiler.testlibrary_tests.ir_framework.tests.TestSafepointWhilePrinting::test1 (8 bytes) - - - - 1716 1008 b 3 java.util.Arrays::copyOfRange (90 bytes) - - 1716 1013 b 4 compiler.testlibrary_tests.ir_framework.tests.TestSafepointWhilePrinting::test2 (8 bytes) - - - - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 3 Start === 3 0 [[ 3 5 6 7 8 9 11 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:compiler/intrinsics/TestSafepointWhilePrinting:NotNull *, 6:long, 7:half} - 5 Parm === 3 [[ 26 ]] Control !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 6 Parm === 3 [[ 26 ]] I_O !jvms: - - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 3 Start === 3 0 [[ 3 5 6 7 8 9 11 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:compiler/intrinsics/TestSafepointWhilePrinting:NotNull *, 6:long, 7:half} - 5 Parm === 3 [[ 26 ]] Control !jvms: TestSafepointWhilePrinting::test2 @ bci:-1 (line 109) - 6 Parm === 3 [[ 26 ]] I_O !jvms: TestSafepointWhilePrinting::test2 @ bci:-1 (line 109) - 7 Parm === 3 [[ 26 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: TestSafepointWhilePrinting::test2 @ bci:-1 (line 109) - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::test2 @ bci:-1 (line 109) - 9 Parm === 3 [[ 26 ]] ReturnAdr !jvms: TestSafepointWhilePrinting::test2 @ bci:-1 (line 109) - 11 Parm === 3 [[ 25 ]] Parm1: long !jvms: TestSafepointWhilePrinting::test2 @ bci:-1 (line 109) - 24 ConL === 0 [[ 25 ]] #long:42 - 25 CmpUL3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test2 @ bci:4 (line 109) - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - - TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 7 Parm === 3 [[ 26 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 9 Parm === 3 [[ 26 ]] ReturnAdr !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 11 Parm === 3 [[ 25 ]] Parm1: long !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 24 ConL === 0 [[ 25 ]] #long:172032 - 25 CmpUL3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test1 @ bci:4 (line 115) - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - - - - 1784 993 3 compiler.intrinsics.TestCompareUnsigned::compareLongWithImm3 (8 bytes) made not entrant - 1784 1013 b 4 compiler.intrinsics.TestCompareUnsigned::compareLongWithImm1 (8 bytes) - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::testSafepointInBlock - @ bci:-1 (line 109) - 24 ConL === 0 [[ 25 ]] #long:42 - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - - - - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::testQueueInBlock1 - - - - @ bci:-1 (line 109) - 24 ConL === 0 [[ 25 ]] #long:42 - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::testQueueInBlock2 - @ bci:-1 (line 109) - 24 ConL === 0 [[ 25 ]] #long:42 - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - - - - - - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 3 Start === 3 0 [[ 3 5 6 7 8 9 11 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:compiler/intrinsics/TestSafepointWhilePrinting:NotNull *, 6:long, 7:half} - 6 Parm === 3 [[ 26 ]] I_O !jvms: - - -AFTER: print_ideal - 0 Root === 0 26 [[ 0 1 3 24 ]] inner - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::testDoubleInterruptMiddle - @ bci:-1 (line 109) - 25 Cmp - - - - - 24 ConL === 0 [[ 25 ]] #long:42 - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - -UL3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test2 @ bci:4 (line 109) - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - - TestSafepointWhilePrinting::testDoubleInterruptOuter @ bci:-1 (line 115) - 7 Parm === 3 [[ 26 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 8 Parm === 3 [[ 26 ]] FramePtr !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 9 Parm === 3 [[ 26 ]] ReturnAdr !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 11 Parm === 3 [[ 25 ]] Parm1: long !jvms: TestSafepointWhilePrinting::test1 @ bci:-1 (line 115) - 24 ConL === 0 [[ 25 ]] #long:172032 - 25 CmpUL3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test1 @ bci:4 (line 115) - 26 Return === 5 6 7 8 9 returns 25 [[ 0 ]] - - - - - - 24 ConL === 0 [[ 25 ]] #long:172032 - 25 CmpUL - - - - 24 ConL === 0 [[ 25 ]] #long:172032 - 25 CmpUL3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test1 @ bci:4 (line 115) - - - 24 ConL === 0 [[ 25 ]] #long:172032 - 25 CmpU - -3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test1 @ bci:4 ( - -L3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test1 @ bci:4 (line - -line 115) - - - - - - 24 ConL === 0 [[ 25 ]] #long:172032 - 25 CmpU - -115) - - -L3 === _ 11 24 [[ 26 ]] !jvms: TestSafepointWhilePrinting::test1 @ bci:4 (line 115) - \ No newline at end of file From fc047508170ab666857d740ccf541c2c3b612277 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Mon, 8 Jan 2024 13:30:23 +0000 Subject: [PATCH 045/112] 8321371: SpinPause() not implemented for bsd_aarch64/macOS Reviewed-by: eosterlund, dholmes, dcubed, eastigeevich, shade --- .../os_cpu/bsd_aarch64/os_bsd_aarch64.cpp | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp index df5a42fd118b9..fbd7c4eccd403 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp @@ -514,7 +514,39 @@ static inline void atomic_copy64(const volatile void *src, volatile void *dst) { extern "C" { int SpinPause() { - return 0; + // We don't use StubRoutines::aarch64::spin_wait stub in order to + // avoid a costly call to os::current_thread_enable_wx() on MacOS. + // We should return 1 if SpinPause is implemented, and since there + // will be a sequence of 11 instructions for NONE and YIELD and 12 + // instructions for NOP and ISB, SpinPause will always return 1. + uint64_t br_dst; + const int instructions_per_case = 2; + int64_t off = VM_Version::spin_wait_desc().inst() * instructions_per_case * Assembler::instruction_size; + + assert(VM_Version::spin_wait_desc().inst() >= SpinWait::NONE && + VM_Version::spin_wait_desc().inst() <= SpinWait::YIELD, "must be"); + assert(-1 == SpinWait::NONE, "must be"); + assert( 0 == SpinWait::NOP, "must be"); + assert( 1 == SpinWait::ISB, "must be"); + assert( 2 == SpinWait::YIELD, "must be"); + + asm volatile( + " adr %[d], 20 \n" // 20 == PC here + 5 instructions => address + // to entry for case SpinWait::NOP + " add %[d], %[d], %[o] \n" + " br %[d] \n" + " b SpinPause_return \n" // case SpinWait::NONE (-1) + " nop \n" // padding + " nop \n" // case SpinWait::NOP ( 0) + " b SpinPause_return \n" + " isb \n" // case SpinWait::ISB ( 1) + " b SpinPause_return \n" + " yield \n" // case SpinWait::YIELD ( 2) + "SpinPause_return: \n" + : [d]"=&r"(br_dst) + : [o]"r"(off) + : "memory"); + return 1; } void _Copy_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { From 29397d29baac3b29083b1b5d6b2cb06e456af0c3 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Mon, 8 Jan 2024 13:32:17 +0000 Subject: [PATCH 046/112] 8320317: ObjectMonitor NotRunnable is not really an optimization Reviewed-by: eosterlund, dholmes, shade, dcubed --- src/hotspot/share/runtime/objectMonitor.cpp | 67 --------------------- src/hotspot/share/runtime/objectMonitor.hpp | 1 - 2 files changed, 68 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 2214713aa4bf6..a8e2e571c5bbd 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1844,10 +1844,6 @@ int ObjectMonitor::TrySpin(JavaThread* current) { ctr = _SpinDuration; if (ctr <= 0) return 0; - if (NotRunnable(current, static_cast(owner_raw()))) { - return 0; - } - // We're good to spin ... spin ingress. // CONSIDER: use Prefetch::write() to avoid RTS->RTO upgrades // when preparing to LD...CAS _owner, etc and the CAS is likely @@ -1933,13 +1929,6 @@ int ObjectMonitor::TrySpin(JavaThread* current) { } prv = ox; - // Abort the spin if the owner is not executing. - // The owner must be executing in order to drop the lock. - // Spinning while the owner is OFFPROC is idiocy. - // Consider: ctr -= RunnablePenalty ; - if (NotRunnable(current, ox)) { - goto Abort; - } if (_succ == nullptr) { _succ = current; } @@ -1972,62 +1961,6 @@ int ObjectMonitor::TrySpin(JavaThread* current) { return 0; } -// NotRunnable() -- informed spinning -// -// Don't bother spinning if the owner is not eligible to drop the lock. -// Spin only if the owner thread is _thread_in_Java or _thread_in_vm. -// The thread must be runnable in order to drop the lock in timely fashion. -// If the _owner is not runnable then spinning will not likely be -// successful (profitable). -// -// Beware -- the thread referenced by _owner could have died -// so a simply fetch from _owner->_thread_state might trap. -// Instead, we use SafeFetchXX() to safely LD _owner->_thread_state. -// Because of the lifecycle issues, the _thread_state values -// observed by NotRunnable() might be garbage. NotRunnable must -// tolerate this and consider the observed _thread_state value -// as advisory. -// -// Beware too, that _owner is sometimes a BasicLock address and sometimes -// a thread pointer. -// Alternately, we might tag the type (thread pointer vs basiclock pointer) -// with the LSB of _owner. Another option would be to probabilistically probe -// the putative _owner->TypeTag value. -// -// Checking _thread_state isn't perfect. Even if the thread is -// in_java it might be blocked on a page-fault or have been preempted -// and sitting on a ready/dispatch queue. -// -// The return value from NotRunnable() is *advisory* -- the -// result is based on sampling and is not necessarily coherent. -// The caller must tolerate false-negative and false-positive errors. -// Spinning, in general, is probabilistic anyway. - - -int ObjectMonitor::NotRunnable(JavaThread* current, JavaThread* ox) { - // Check ox->TypeTag == 2BAD. - if (ox == nullptr) return 0; - - // Avoid transitive spinning ... - // Say T1 spins or blocks trying to acquire L. T1._Stalled is set to L. - // Immediately after T1 acquires L it's possible that T2, also - // spinning on L, will see L.Owner=T1 and T1._Stalled=L. - // This occurs transiently after T1 acquired L but before - // T1 managed to clear T1.Stalled. T2 does not need to abort - // its spin in this circumstance. - intptr_t BlockedOn = SafeFetchN((intptr_t *) &ox->_Stalled, intptr_t(1)); - - if (BlockedOn == 1) return 1; - if (BlockedOn != 0) { - return BlockedOn != intptr_t(this) && owner_raw() == ox; - } - - assert(sizeof(ox->_thread_state == sizeof(int)), "invariant"); - int jst = SafeFetch32((int *) &ox->_thread_state, -1);; - // consider also: jst != _thread_in_Java -- but that's overspecific. - return jst == _thread_blocked || jst == _thread_in_native; -} - // ----------------------------------------------------------------------------- // WaitSet management ... diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index ab48bd19b5e43..281067fe55c6b 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -353,7 +353,6 @@ class ObjectMonitor : public CHeapObj { void ReenterI(JavaThread* current, ObjectWaiter* current_node); void UnlinkAfterAcquire(JavaThread* current, ObjectWaiter* current_node); int TryLock(JavaThread* current); - int NotRunnable(JavaThread* current, JavaThread* Owner); int TrySpin(JavaThread* current); void ExitEpilog(JavaThread* current, ObjectWaiter* Wakee); From c90768c93b26771bb8f4bdbe855d054ad089b337 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 8 Jan 2024 13:47:43 +0000 Subject: [PATCH 047/112] 8318444: Write details about compilation bailouts into crash reports Reviewed-by: thartmann, chagedorn --- src/hotspot/share/c1/c1_Compilation.cpp | 8 +- src/hotspot/share/c1/c1_Compilation.hpp | 3 + src/hotspot/share/ci/ciEnv.hpp | 4 +- .../share/compiler/compilationFailureInfo.cpp | 121 ++++++++++++++++++ .../share/compiler/compilationFailureInfo.hpp | 57 +++++++++ .../share/compiler/compiler_globals.hpp | 4 + src/hotspot/share/opto/compile.cpp | 12 ++ src/hotspot/share/opto/compile.hpp | 7 +- src/hotspot/share/runtime/os.cpp | 19 ++- src/hotspot/share/runtime/os.hpp | 1 + src/hotspot/share/utilities/vmError.cpp | 7 + 11 files changed, 231 insertions(+), 12 deletions(-) create mode 100644 src/hotspot/share/compiler/compilationFailureInfo.cpp create mode 100644 src/hotspot/share/compiler/compilationFailureInfo.hpp diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index 53fb5fbcf9efe..4890cec5bfc7b 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -33,10 +33,12 @@ #include "c1/c1_ValueMap.hpp" #include "c1/c1_ValueStack.hpp" #include "code/debugInfoRec.hpp" +#include "compiler/compilationFailureInfo.hpp" #include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compilerDirectives.hpp" #include "compiler/compileLog.hpp" #include "compiler/compileTask.hpp" +#include "compiler/compiler_globals.hpp" #include "compiler/compilerDirectives.hpp" #include "memory/resourceArea.hpp" #include "runtime/sharedRuntime.hpp" @@ -582,6 +584,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho , _has_monitors(false) , _install_code(install_code) , _bailout_msg(nullptr) +, _first_failure_details(nullptr) , _exception_info_list(nullptr) , _allocator(nullptr) , _code(buffer_blob) @@ -626,7 +629,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho Compilation::~Compilation() { // simulate crash during compilation assert(CICrashAt < 0 || (uintx)_env->compile_id() != (uintx)CICrashAt, "just as planned"); - + delete _first_failure_details; _env->set_compiler_data(nullptr); } @@ -652,6 +655,9 @@ void Compilation::bailout(const char* msg) { // keep first bailout message if (PrintCompilation || PrintBailouts) tty->print_cr("compilation bailout: %s", msg); _bailout_msg = msg; + if (CaptureBailoutInformation) { + _first_failure_details = new CompilationFailureInfo(msg); + } } } diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp index b0753a94d1ba7..f344695509ee1 100644 --- a/src/hotspot/share/c1/c1_Compilation.hpp +++ b/src/hotspot/share/c1/c1_Compilation.hpp @@ -34,6 +34,7 @@ #include "memory/resourceArea.hpp" #include "runtime/deoptimization.hpp" +class CompilationFailureInfo; class CompilationResourceObj; class XHandlers; class ExceptionInfo; @@ -85,6 +86,7 @@ class Compilation: public StackObj { bool _has_monitors; // Fastpath monitors detection for Continuations bool _install_code; const char* _bailout_msg; + CompilationFailureInfo* _first_failure_details; // Details for the first failure happening during compilation bool _oom; ExceptionInfoList* _exception_info_list; ExceptionHandlerTable _exception_handler_table; @@ -212,6 +214,7 @@ class Compilation: public StackObj { void bailout(const char* msg); bool bailed_out() const { return _bailout_msg != nullptr; } const char* bailout_msg() const { return _bailout_msg; } + const CompilationFailureInfo* first_failure_details() const { return _first_failure_details; } static uint desired_max_code_buffer_size() { return (uint)NMethodSizeLimit; // default 64K diff --git a/src/hotspot/share/ci/ciEnv.hpp b/src/hotspot/share/ci/ciEnv.hpp index 5c39cb58f9ff1..fc12cc0259b71 100644 --- a/src/hotspot/share/ci/ciEnv.hpp +++ b/src/hotspot/share/ci/ciEnv.hpp @@ -362,7 +362,7 @@ class ciEnv : StackObj { // The compiler task which has created this env. // May be useful to find out compile_id, comp_level, etc. - CompileTask* task() { return _task; } + CompileTask* task() const { return _task; } // Handy forwards to the task: int comp_level(); // task()->comp_level() @@ -444,7 +444,7 @@ class ciEnv : StackObj { static ciEnv* current(CompilerThread *thread) { return thread->env(); } // Per-compiler data. (Used by C2 to publish the Compile* pointer.) - void* compiler_data() { return _compiler_data; } + void* compiler_data() const { return _compiler_data; } void set_compiler_data(void* x) { _compiler_data = x; } // Notice that a method has been inlined in the current compile; diff --git a/src/hotspot/share/compiler/compilationFailureInfo.cpp b/src/hotspot/share/compiler/compilationFailureInfo.cpp new file mode 100644 index 0000000000000..e3f3353589e54 --- /dev/null +++ b/src/hotspot/share/compiler/compilationFailureInfo.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Red Hat, Inc. and/or its affiliates. + * 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. + * + */ + +#include "precompiled.hpp" + +#if defined(COMPILER1) || defined(COMPILER2) + +#ifdef COMPILER1 +#include "c1/c1_Compilation.hpp" +#endif +#include "ci/ciEnv.hpp" +#include "compiler/abstractCompiler.hpp" +#include "compiler/compilationFailureInfo.hpp" +#include "compiler/compileTask.hpp" +#ifdef COMPILER2 +#include "opto/node.hpp" +#include "opto/compile.hpp" +#endif +#include "runtime/os.hpp" +#include "utilities/ostream.hpp" +#include "utilities/nativeCallStack.hpp" + +CompilationFailureInfo::CompilationFailureInfo(const char* failure_reason) : + _stack(2), + _failure_reason(os::strdup(failure_reason)), + _elapsed_seconds(os::elapsedTime()), + _compile_id(ciEnv::current()->task()->compile_id()) +{} + +CompilationFailureInfo::~CompilationFailureInfo() { + os::free(_failure_reason); +} + +void CompilationFailureInfo::print_on(outputStream* st) const { + st->print(" Time: "); + os::print_elapsed_time(st, _elapsed_seconds); + st->print_cr(" Compile id: %d", _compile_id); + st->print_cr(" Reason: '%s'", _failure_reason); + st->print_cr(" Callstack: "); + _stack.print_on(st); + st->cr(); +} + +// Convenience function to print current compile failure iff +// current thread is compiler thread and there is a pending failure. +// Otherwise prints nothing. +bool CompilationFailureInfo::print_pending_compilation_failure(outputStream* st) { + + const CompilationFailureInfo* info = nullptr; + + // Carefully tiptoeing because we are called from the error reporter and + // nothing is certain. + + const Thread* const t = Thread::current(); + if (t == nullptr || !t->is_Compiler_thread()) { + return false; + } + + const ciEnv* const env = ciEnv::current(); + if (env == nullptr) { + return false; + } + + const CompileTask* const task = env->task(); + if (task == nullptr) { + return false; + } + + const AbstractCompiler* const compiler = task->compiler(); + if (compiler == nullptr) { + return false; + } + +#ifdef COMPILER1 + if (compiler->type() == compiler_c1) { + const Compilation* const C = (Compilation*)env->compiler_data(); + if (C != nullptr) { + info = C->first_failure_details(); + } + } +#endif +#ifdef COMPILER2 + if (compiler->type() == compiler_c2) { + const Compile* const C = (Compile*)env->compiler_data(); + if (C != nullptr) { + info = C->first_failure_details(); + } + } +#endif + + if (info != nullptr) { + st->print_cr("Pending compilation failure details for thread " PTR_FORMAT ":", p2i(t)); + info->print_on(st); + } + + return true; +} + +#endif // defined(COMPILER1) || defined(COMPILER2) diff --git a/src/hotspot/share/compiler/compilationFailureInfo.hpp b/src/hotspot/share/compiler/compilationFailureInfo.hpp new file mode 100644 index 0000000000000..3de62eb69da5a --- /dev/null +++ b/src/hotspot/share/compiler/compilationFailureInfo.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Red Hat, Inc. and/or its affiliates. + * 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. + * + */ + +#ifndef SHARE_COMPILER_COMPILATIONFAILUREINFO_HPP +#define SHARE_COMPILER_COMPILATIONFAILUREINFO_HPP + +#if defined(COMPILER1) || defined(COMPILER2) + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/nativeCallStack.hpp" + +class outputStream; +class Symbol; + +class CompilationFailureInfo : public CHeapObj { + NativeCallStack _stack; + char* const _failure_reason; + const double _elapsed_seconds; + const int _compile_id; +public: + CompilationFailureInfo(const char* failure_reason); + ~CompilationFailureInfo(); + void print_on(outputStream* st) const; + + // Convenience function to print, safely, current compile failure iff + // current thread is compiler thread and there is an ongoing compilation + // and a pending failure. + // Otherwise prints nothing. + static bool print_pending_compilation_failure(outputStream* st); +}; + +#endif // defined(COMPILER1) || defined(COMPILER2) + +#endif // SHARE_COMPILER_COMPILATIONFAILUREINFO_HPP diff --git a/src/hotspot/share/compiler/compiler_globals.hpp b/src/hotspot/share/compiler/compiler_globals.hpp index 7f1f08b68ef65..71b475392cf69 100644 --- a/src/hotspot/share/compiler/compiler_globals.hpp +++ b/src/hotspot/share/compiler/compiler_globals.hpp @@ -379,6 +379,10 @@ "Don't compile methods larger than this if " \ "+DontCompileHugeMethods") \ \ + product(bool, CaptureBailoutInformation, trueInDebug, DIAGNOSTIC, \ + "If compilation is stopped with an error, capture diagnostic " \ + "information at the bailout point") \ + \ // end of COMPILER_FLAGS diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 522654803aa19..30701c03707e9 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -29,9 +29,11 @@ #include "classfile/javaClasses.hpp" #include "code/exceptionHandlerTable.hpp" #include "code/nmethod.hpp" +#include "compiler/compilationFailureInfo.hpp" #include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compileLog.hpp" +#include "compiler/compiler_globals.hpp" #include "compiler/disassembler.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSet.hpp" @@ -637,6 +639,7 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, _directive(directive), _log(ci_env->log()), _failure_reason(nullptr), + _first_failure_details(nullptr), _intrinsics (comp_arena(), 0, 0, nullptr), _macro_nodes (comp_arena(), 8, 0, nullptr), _parse_predicates (comp_arena(), 8, 0, nullptr), @@ -926,6 +929,7 @@ Compile::Compile( ciEnv* ci_env, _directive(directive), _log(ci_env->log()), _failure_reason(nullptr), + _first_failure_details(nullptr), _congraph(nullptr), NOT_PRODUCT(_igv_printer(nullptr) COMMA) _unique(0), @@ -989,6 +993,11 @@ Compile::Compile( ciEnv* ci_env, Code_Gen(); } +Compile::~Compile() { + delete _print_inlining_stream; + delete _first_failure_details; +}; + //------------------------------Init------------------------------------------- // Prepare for a single compilation void Compile::Init(bool aliasing) { @@ -4358,6 +4367,9 @@ void Compile::record_failure(const char* reason) { if (_failure_reason == nullptr) { // Record the first failure reason. _failure_reason = reason; + if (CaptureBailoutInformation) { + _first_failure_details = new CompilationFailureInfo(reason); + } } if (!C->failure_reason_is(C2Compiler::retry_no_subsuming_loads())) { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 01d0d727aa7b5..42f866df781c2 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -53,6 +53,7 @@ class Bundle; class CallGenerator; class CallStaticJavaNode; class CloneMap; +class CompilationFailureInfo; class ConnectionGraph; class IdealGraphPrinter; class InlineTree; @@ -363,6 +364,7 @@ class Compile : public Phase { DirectiveSet* _directive; // Compiler directive CompileLog* _log; // from CompilerThread const char* _failure_reason; // for record_failure/failing pattern + CompilationFailureInfo* _first_failure_details; // Details for the first failure happening during compilation GrowableArray _intrinsics; // List of intrinsics. GrowableArray _macro_nodes; // List of nodes which need to be expanded before matching. GrowableArray _parse_predicates; // List of Parse Predicates. @@ -809,6 +811,7 @@ class Compile : public Phase { CompileLog* log() const { return _log; } bool failing() const { return _env->failing() || _failure_reason != nullptr; } const char* failure_reason() const { return (_env->failing()) ? _env->failure_reason() : _failure_reason; } + const CompilationFailureInfo* first_failure_details() const { return _first_failure_details; } bool failure_reason_is(const char* r) const { return (r == _failure_reason) || (r != nullptr && _failure_reason != nullptr && strcmp(r, _failure_reason) == 0); @@ -1125,9 +1128,7 @@ class Compile : public Phase { int is_fancy_jump, bool pass_tls, bool return_pc, DirectiveSet* directive); - ~Compile() { - delete _print_inlining_stream; - }; + ~Compile(); // Are we compiling a method? bool has_method() { return method() != nullptr; } diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 0eb4015a24659..dad10a7b9b4d8 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -1105,10 +1105,11 @@ void os::print_summary_info(outputStream* st, char* buf, size_t buflen) { st->cr(); } +static constexpr int secs_per_day = 86400; +static constexpr int secs_per_hour = 3600; +static constexpr int secs_per_min = 60; + void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) { - const int secs_per_day = 86400; - const int secs_per_hour = 3600; - const int secs_per_min = 60; time_t tloc; (void)time(&tloc); @@ -1134,9 +1135,15 @@ void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) { } double t = os::elapsedTime(); + st->print(" elapsed time: "); + print_elapsed_time(st, t); + st->cr(); +} + +void os::print_elapsed_time(outputStream* st, double time) { // NOTE: a crash using printf("%f",...) on Linux was historically noted here. - int eltime = (int)t; // elapsed time in seconds - int eltimeFraction = (int) ((t - eltime) * 1000000); + int eltime = (int)time; // elapsed time in seconds + int eltimeFraction = (int) ((time - eltime) * 1000000); // print elapsed time in a human-readable format: int eldays = eltime / secs_per_day; @@ -1146,7 +1153,7 @@ void os::print_date_and_time(outputStream *st, char* buf, size_t buflen) { int elmins = (eltime - day_secs - hour_secs) / secs_per_min; int minute_secs = elmins * secs_per_min; int elsecs = (eltime - day_secs - hour_secs - minute_secs); - st->print_cr(" elapsed time: %d.%06d seconds (%dd %dh %dm %ds)", eltime, eltimeFraction, eldays, elhours, elmins, elsecs); + st->print("%d.%06d seconds (%dd %dh %dm %ds)", eltime, eltimeFraction, eldays, elhours, elmins, elsecs); } diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 8ecabde8ca144..f5346c9230753 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -789,6 +789,7 @@ class os: AllStatic { static void print_siginfo(outputStream* st, const void* siginfo); static void print_signal_handlers(outputStream* st, char* buf, size_t buflen); static void print_date_and_time(outputStream* st, char* buf, size_t buflen); + static void print_elapsed_time(outputStream* st, double time); static void print_user_info(outputStream* st); static void print_active_locale(outputStream* st); diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index d586c6f4eeacf..d40504d6d2008 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -27,6 +27,7 @@ #include "precompiled.hpp" #include "cds/metaspaceShared.hpp" #include "code/codeCache.hpp" +#include "compiler/compilationFailureInfo.hpp" #include "compiler/compileBroker.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/gcConfig.hpp" @@ -1053,6 +1054,12 @@ void VMError::report(outputStream* st, bool _verbose) { check_failing_cds_access(st, _siginfo); st->cr(); +#if defined(COMPILER1) || defined(COMPILER2) + STEP_IF("printing pending compilation failure", + _verbose && _thread != nullptr && _thread->is_Compiler_thread()) + CompilationFailureInfo::print_pending_compilation_failure(st); +#endif + STEP_IF("printing registers", _verbose && _context != nullptr) // printing registers os::print_context(st, _context); From 57a65fe436a3617d64bbf0b02d4c7f7c2551448f Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 8 Jan 2024 14:09:27 +0000 Subject: [PATCH 048/112] 8322003: JShell - Incorrect type inference in lists of records implementing interfaces Reviewed-by: vromero --- .../sun/tools/javac/parser/JavacParser.java | 24 ++-- .../share/classes/jdk/jshell/TaskFactory.java | 107 ++++++++++++++---- test/langtools/jdk/jshell/VariablesTest.java | 13 ++- 3 files changed, 110 insertions(+), 34 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index d83fb85b7f2c0..c962862e4bf7d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -967,6 +967,20 @@ public JCExpression parseType(boolean allowVar, List annotations) return result; } + protected JCExpression parseIntersectionType(int pos, JCExpression firstType) { + JCExpression t = firstType; + int pos1 = pos; + List targets = List.of(t); + while (token.kind == AMP) { + accept(AMP); + targets = targets.prepend(parseType()); + } + if (targets.length() > 1) { + t = toP(F.at(pos1).TypeIntersection(targets.reverse())); + } + return t; + } + public JCExpression unannotatedType(boolean allowVar) { return unannotatedType(allowVar, TYPE); } @@ -1337,15 +1351,7 @@ protected JCExpression term3() { case CAST: accept(LPAREN); selectTypeMode(); - int pos1 = pos; - List targets = List.of(t = parseType()); - while (token.kind == AMP) { - accept(AMP); - targets = targets.prepend(parseType()); - } - if (targets.length() > 1) { - t = toP(F.at(pos1).TypeIntersection(targets.reverse())); - } + t = parseIntersectionType(pos, parseType()); accept(RPAREN); selectExprMode(); JCExpression t1 = term3(); diff --git a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index ac777435102ba..5360e0d517fc7 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java @@ -80,8 +80,13 @@ import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.comp.Resolve; +import com.sun.tools.javac.parser.JavacParser; +import com.sun.tools.javac.parser.Lexer; import com.sun.tools.javac.parser.Parser; import com.sun.tools.javac.parser.ParserFactory; +import com.sun.tools.javac.parser.ScannerFactory; +import static com.sun.tools.javac.parser.Tokens.TokenKind.AMP; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; @@ -363,7 +368,7 @@ private ParseTask(SourceHandler sh, JavacTaskImpl task, DiagnosticCollector diagnostics, boolean forceExpression) { - super(sh, task, diagnostics); + super(sh, task, diagnostics, false); ReplParserFactory.preRegister(context, forceExpression); cuts = parse(); units = Util.stream(cuts) @@ -402,7 +407,7 @@ class AnalyzeTask extends BaseTask { private AnalyzeTask(SourceHandler sh, JavacTaskImpl task, DiagnosticCollector diagnostics) { - super(sh, task, diagnostics); + super(sh, task, diagnostics, true); cuts = analyze(); } @@ -440,7 +445,7 @@ class CompileTask extends BaseTask { CompileTask(SourceHandlersh, JavacTaskImpl jti, DiagnosticCollector diagnostics) { - super(sh, jti, diagnostics); + super(sh, jti, diagnostics, true); } boolean compile() { @@ -504,11 +509,15 @@ abstract class BaseTask { private BaseTask(SourceHandler sh, JavacTaskImpl task, - DiagnosticCollector diagnostics) { + DiagnosticCollector diagnostics, + boolean analyzeParserFactory) { this.sourceHandler = sh; this.task = task; context = task.getContext(); this.diagnostics = diagnostics; + if (analyzeParserFactory) { + JShellAnalyzeParserFactory.preRegister(context); + } } abstract Iterable cuTrees(); @@ -693,7 +702,7 @@ private void setVariableType(VarSnippet s) { Symtab syms = Symtab.instance(context); Names names = Names.instance(context); Log log = Log.instance(context); - ParserFactory parserFactory = ParserFactory.instance(context); + JShellAnalyzeParserFactory parserFactory = (JShellAnalyzeParserFactory) ParserFactory.instance(context); Attr attr = Attr.instance(context); Enter enter = Enter.instance(context); DisableAccessibilityResolve rs = (DisableAccessibilityResolve) Resolve.instance(context); @@ -709,26 +718,28 @@ private void setVariableType(VarSnippet s) { //ignore any errors: JavaFileObject prev = log.useSource(null); DiscardDiagnosticHandler h = new DiscardDiagnosticHandler(log); - try { - //parse the type as a cast, i.e. "() x". This is to support - //intersection types: - CharBuffer buf = CharBuffer.wrap(("(" + typeName +")x\u0000").toCharArray(), 0, typeName.length() + 3); - Parser parser = parserFactory.newParser(buf, false, false, false); - JCExpression expr = parser.parseExpression(); - if (expr.hasTag(Tag.TYPECAST)) { - //if parsed OK, attribute and set the type: - var2OriginalType.put(field, field.type); - - JCTypeCast tree = (JCTypeCast) expr; - rs.runWithoutAccessChecks(() -> { - field.type = attr.attribType(tree.clazz, - enter.getEnvs().iterator().next().enclClass.sym); - }); + parserFactory.runPermitIntersectionTypes(() -> { + try { + //parse the type as a cast, i.e. "() x". This is to support + //intersection types: + CharBuffer buf = CharBuffer.wrap(("(" + typeName +")x\u0000").toCharArray(), 0, typeName.length() + 3); + Parser parser = parserFactory.newParser(buf, false, false, false); + JCExpression expr = parser.parseExpression(); + if (expr.hasTag(Tag.TYPECAST)) { + //if parsed OK, attribute and set the type: + var2OriginalType.put(field, field.type); + + JCTypeCast tree = (JCTypeCast) expr; + rs.runWithoutAccessChecks(() -> { + field.type = attr.attribType(tree.clazz, + enter.getEnvs().iterator().next().enclClass.sym); + }); + } + } finally { + log.popDiagnosticHandler(h); + log.useSource(prev); } - } finally { - log.popDiagnosticHandler(h); - log.useSource(prev); - } + }); } } } @@ -777,4 +788,52 @@ public boolean isAccessible(Env env, Type site, Symbol sym, boolean private static final class Marker {} } + private static final class JShellAnalyzeParserFactory extends ParserFactory { + public static void preRegister(Context context) { + if (context.get(Marker.class) == null) { + context.put(parserFactoryKey, ((Factory) c -> new JShellAnalyzeParserFactory(c))); + context.put(Marker.class, new Marker()); + } + } + + private final ScannerFactory scannerFactory; + private boolean permitIntersectionTypes; + + public JShellAnalyzeParserFactory(Context context) { + super(context); + this.scannerFactory = ScannerFactory.instance(context); + } + + /**Run the given Runnable with intersection type permitted. + * + * @param r Runnnable to run + */ + public void runPermitIntersectionTypes(Runnable r) { + boolean prevPermitIntersectionTypes = permitIntersectionTypes; + try { + permitIntersectionTypes = true; + r.run(); + } finally { + permitIntersectionTypes = prevPermitIntersectionTypes; + } + } + + @Override + public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) { + com.sun.tools.javac.parser.Lexer lexer = scannerFactory.newScanner(input, keepDocComments); + return new JavacParser(this, lexer, keepDocComments, keepLineMap, keepEndPos, parseModuleInfo) { + @Override + public JCExpression parseType(boolean allowVar, com.sun.tools.javac.util.List annotations) { + int pos = token.pos; + JCExpression t = super.parseType(allowVar, annotations); + if (permitIntersectionTypes) { + t = parseIntersectionType(pos, t); + } + return t; + } + }; + } + + private static final class Marker {} + } } diff --git a/test/langtools/jdk/jshell/VariablesTest.java b/test/langtools/jdk/jshell/VariablesTest.java index 56546955e0829..98a543e77a9bf 100644 --- a/test/langtools/jdk/jshell/VariablesTest.java +++ b/test/langtools/jdk/jshell/VariablesTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 8322532 + * @bug 8144903 8177466 8191842 8211694 8213725 8239536 8257236 8252409 8294431 8322003 8322532 * @summary Tests for EvaluationState.variables * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -627,4 +627,15 @@ public void underscoreAsLambdaParameter() { //JDK-8322532 " int i;", true); } + public void intersectionTypeAsTypeArgument() { //JDK-8322003 + assertEval("interface Shape {}"); + assertEval("record Square(int edge) implements Shape {}"); + assertEval("record Circle(int radius) implements Shape {}"); + assertEval("java.util.function.Consumer printShape = System.out::println;"); + assertEval("Square square = new Square(1);"); + assertEval("Circle circle = new Circle(1);"); + assertEval("var shapes = java.util.List.of(square, circle);"); + assertEval("shapes.forEach(printShape);"); + } + } From c8fa3e21e6a4fd7846932b545a1748cc1dc6d9f1 Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Mon, 8 Jan 2024 14:55:17 +0000 Subject: [PATCH 049/112] 8320310: CompiledMethod::has_monitors flag can be incorrect Reviewed-by: vlivanov, thartmann --- src/hotspot/share/c1/c1_Compilation.cpp | 6 +--- src/hotspot/share/c1/c1_GraphBuilder.cpp | 22 ++++++------ src/hotspot/share/opto/locknode.cpp | 6 ---- src/hotspot/share/opto/parse1.cpp | 2 +- .../share/runtime/continuationFreezeThaw.cpp | 34 +++++++++---------- 5 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index 4890cec5bfc7b..bef1fae7f7496 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -390,10 +390,6 @@ int Compilation::compile_java_method() { BAILOUT_("mdo allocation failed", no_frame_size); } - if (method()->is_synchronized()) { - set_has_monitors(true); - } - { PhaseTraceTime timeit(_t_buildIR); build_hir(); @@ -581,7 +577,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho , _would_profile(false) , _has_method_handle_invokes(false) , _has_reserved_stack_access(method->has_reserved_stack_access()) -, _has_monitors(false) +, _has_monitors(method->is_synchronized() || method->has_monitor_bytecodes()) , _install_code(install_code) , _bailout_msg(nullptr) , _first_failure_details(nullptr) diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index fb2aa28ec86a3..fe9a8a478365d 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -2316,7 +2316,6 @@ void GraphBuilder::instance_of(int klass_index) { void GraphBuilder::monitorenter(Value x, int bci) { // save state before locking in case of deoptimization after a NullPointerException ValueStack* state_before = copy_state_for_exception_with_bci(bci); - compilation()->set_has_monitors(true); append_with_bci(new MonitorEnter(x, state()->lock(x), state_before), bci); kill_all(); } @@ -3510,6 +3509,15 @@ int GraphBuilder::recursive_inline_level(ciMethod* cur_callee) const { return recur_level; } +static void set_flags_for_inlined_callee(Compilation* compilation, ciMethod* callee) { + if (callee->has_reserved_stack_access()) { + compilation->set_has_reserved_stack_access(true); + } + if (callee->is_synchronized() || callee->has_monitor_bytecodes()) { + compilation->set_has_monitors(true); + } +} + bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_return, Bytecodes::Code bc, Value receiver) { const char* msg = nullptr; @@ -3526,9 +3534,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_r // method handle invokes if (callee->is_method_handle_intrinsic()) { if (try_method_handle_inline(callee, ignore_return)) { - if (callee->has_reserved_stack_access()) { - compilation()->set_has_reserved_stack_access(true); - } + set_flags_for_inlined_callee(compilation(), callee); return true; } return false; @@ -3539,9 +3545,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_r callee->check_intrinsic_candidate()) { if (try_inline_intrinsics(callee, ignore_return)) { print_inlining(callee, "intrinsic"); - if (callee->has_reserved_stack_access()) { - compilation()->set_has_reserved_stack_access(true); - } + set_flags_for_inlined_callee(compilation(), callee); return true; } // try normal inlining @@ -3559,9 +3563,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, bool ignore_r bc = code(); } if (try_inline_full(callee, holder_known, ignore_return, bc, receiver)) { - if (callee->has_reserved_stack_access()) { - compilation()->set_has_reserved_stack_access(true); - } + set_flags_for_inlined_callee(compilation(), callee); return true; } diff --git a/src/hotspot/share/opto/locknode.cpp b/src/hotspot/share/opto/locknode.cpp index 640109e6c42a4..6354df1ec5914 100644 --- a/src/hotspot/share/opto/locknode.cpp +++ b/src/hotspot/share/opto/locknode.cpp @@ -179,8 +179,6 @@ void FastLockNode::create_rtm_lock_counter(JVMState* state) { void Parse::do_monitor_enter() { kill_dead_locals(); - C->set_has_monitors(true); - // Null check; get casted pointer. Node* obj = null_check(peek()); // Check for locking null object @@ -198,10 +196,6 @@ void Parse::do_monitor_enter() { void Parse::do_monitor_exit() { kill_dead_locals(); - // need to set it for monitor exit as well. - // OSR compiled methods can start with lock taken - C->set_has_monitors(true); - pop(); // Pop oop to unlock // Because monitors are guaranteed paired (else we bail out), we know // the matching Lock for this Unlock. Hence we know there is no need diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index d784f3f3240a3..96db18f774fe7 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -423,7 +423,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) C->set_has_reserved_stack_access(true); } - if (parse_method->is_synchronized()) { + if (parse_method->is_synchronized() || parse_method->has_monitor_bytecodes()) { C->set_has_monitors(true); } diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 969e14f150e17..26c915852e589 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -1498,21 +1498,21 @@ static void jvmti_yield_cleanup(JavaThread* thread, ContinuationWrapper& cont) { #endif // INCLUDE_JVMTI #ifdef ASSERT -// static bool monitors_on_stack(JavaThread* thread) { -// ContinuationEntry* ce = thread->last_continuation(); -// RegisterMap map(thread, -// RegisterMap::UpdateMap::include, -// RegisterMap::ProcessFrames::include, -// RegisterMap::WalkContinuation::skip); -// map.set_include_argument_oops(false); -// for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { -// if ((f.is_interpreted_frame() && ContinuationHelper::InterpretedFrame::is_owning_locks(f)) || -// (f.is_compiled_frame() && ContinuationHelper::CompiledFrame::is_owning_locks(map.thread(), &map, f))) { -// return true; -// } -// } -// return false; -// } +static bool monitors_on_stack(JavaThread* thread) { + ContinuationEntry* ce = thread->last_continuation(); + RegisterMap map(thread, + RegisterMap::UpdateMap::include, + RegisterMap::ProcessFrames::include, + RegisterMap::WalkContinuation::skip); + map.set_include_argument_oops(false); + for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { + if ((f.is_interpreted_frame() && ContinuationHelper::InterpretedFrame::is_owning_locks(f)) || + (f.is_compiled_frame() && ContinuationHelper::CompiledFrame::is_owning_locks(map.thread(), &map, f))) { + return true; + } + } + return false; +} bool FreezeBase::interpreted_native_or_deoptimized_on_stack() { ContinuationEntry* ce = _thread->last_continuation(); @@ -1575,8 +1575,8 @@ static inline int freeze_internal(JavaThread* current, intptr_t* const sp) { assert(entry->is_virtual_thread() == (entry->scope(current) == java_lang_VirtualThread::vthread_scope()), ""); - // assert(monitors_on_stack(current) == ((current->held_monitor_count() - current->jni_monitor_count()) > 0), - // "Held monitor count and locks on stack invariant: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); + assert(monitors_on_stack(current) == ((current->held_monitor_count() - current->jni_monitor_count()) > 0), + "Held monitor count and locks on stack invariant: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); if (entry->is_pinned() || current->held_monitor_count() > 0) { log_develop_debug(continuations)("PINNED due to critical section/hold monitor"); From 2acb5bd9924511b58b0e57ea9eb6c2dee9fd3ee8 Mon Sep 17 00:00:00 2001 From: Ilya Gavrilin Date: Mon, 8 Jan 2024 15:53:58 +0000 Subject: [PATCH 050/112] 8322790: RISC-V: Tune costs for shuffles with no conversion Reviewed-by: rehn, fyang --- src/hotspot/cpu/riscv/riscv.ad | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index d5a95b2e3ba5b..7e1291f49d74c 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1001,6 +1001,7 @@ definitions %{ int_def LOAD_COST ( 300, 3 * DEFAULT_COST); // load, fpload int_def STORE_COST ( 100, 1 * DEFAULT_COST); // store, fpstore int_def XFER_COST ( 300, 3 * DEFAULT_COST); // mfc, mtc, fcvt, fmove, fcmp + int_def FMVX_COST ( 100, 1 * DEFAULT_COST); // shuffles with no conversion int_def BRANCH_COST ( 200, 2 * DEFAULT_COST); // branch, jmp, call int_def IMUL_COST ( 1000, 10 * DEFAULT_COST); // imul int_def IDIVSI_COST ( 3400, 34 * DEFAULT_COST); // idivsi @@ -8674,7 +8675,7 @@ instruct MoveF2I_reg_reg(iRegINoSp dst, fRegF src) %{ effect(DEF dst, USE src); - ins_cost(XFER_COST); + ins_cost(FMVX_COST); format %{ "fmv.x.w $dst, $src\t#@MoveF2I_reg_reg" %} @@ -8692,7 +8693,7 @@ instruct MoveI2F_reg_reg(fRegF dst, iRegI src) %{ effect(DEF dst, USE src); - ins_cost(XFER_COST); + ins_cost(FMVX_COST); format %{ "fmv.w.x $dst, $src\t#@MoveI2F_reg_reg" %} @@ -8710,7 +8711,7 @@ instruct MoveD2L_reg_reg(iRegLNoSp dst, fRegD src) %{ effect(DEF dst, USE src); - ins_cost(XFER_COST); + ins_cost(FMVX_COST); format %{ "fmv.x.d $dst, $src\t#@MoveD2L_reg_reg" %} @@ -8728,7 +8729,7 @@ instruct MoveL2D_reg_reg(fRegD dst, iRegL src) %{ effect(DEF dst, USE src); - ins_cost(XFER_COST); + ins_cost(FMVX_COST); format %{ "fmv.d.x $dst, $src\t#@MoveL2D_reg_reg" %} From 827c71dac9a5732f70bc7341743bce314cad302f Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 8 Jan 2024 16:10:21 +0000 Subject: [PATCH 051/112] 8310190: C2 SuperWord: AlignVector is broken, generates misaligned packs Co-authored-by: Christian Hagedorn Reviewed-by: kvn, chagedorn --- src/hotspot/cpu/aarch64/aarch64.ad | 20 +- src/hotspot/cpu/x86/x86.ad | 15 + src/hotspot/share/adlc/formssel.cpp | 3 +- src/hotspot/share/opto/c2_globals.hpp | 6 +- src/hotspot/share/opto/c2compiler.cpp | 10 +- src/hotspot/share/opto/chaitin.cpp | 16 +- src/hotspot/share/opto/classes.hpp | 3 +- src/hotspot/share/opto/compile.cpp | 27 +- src/hotspot/share/opto/machnode.cpp | 9 +- src/hotspot/share/opto/node.hpp | 1 + src/hotspot/share/opto/superword.cpp | 859 ++-- src/hotspot/share/opto/superword.hpp | 39 +- src/hotspot/share/opto/vectorization.cpp | 675 ++- src/hotspot/share/opto/vectorization.hpp | 451 +- src/hotspot/share/opto/vectornode.hpp | 43 +- .../TestVectorizationMismatchedAccess.java | 17 +- .../lib/ir_framework/TestFramework.java | 3 +- .../loopopts/superword/TestAlignVector.java | 1479 ++++++ .../superword/TestAlignVectorFuzzer.java | 1353 +++++ .../superword/TestDependencyOffsets.java | 4489 ++++++++++++++--- .../superword/TestMovingLoadBeforeStore.java | 3 +- .../loopopts/superword/TestMulAddS2I.java | 18 +- .../TestBufferVectorization.java | 314 +- 23 files changed, 8530 insertions(+), 1323 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java create mode 100644 test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 233f9b6af7c14..f637648b2279c 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, 2021, Red Hat, Inc. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -8237,6 +8237,24 @@ instruct popCountL_mem(iRegINoSp dst, memory8 mem, vRegD tmp) %{ ins_pipe(pipe_class_default); %} +// ============================================================================ +// VerifyVectorAlignment Instruction + +instruct verify_vector_alignment(iRegP addr, immL_positive_bitmaskI mask, rFlagsReg cr) %{ + match(Set addr (VerifyVectorAlignment addr mask)); + effect(KILL cr); + format %{ "verify_vector_alignment $addr $mask \t! verify alignment" %} + ins_encode %{ + Label Lskip; + // check if masked bits of addr are zero + __ tst($addr$$Register, $mask$$constant); + __ br(Assembler::EQ, Lskip); + __ stop("verify_vector_alignment found a misaligned vector memory access"); + __ bind(Lskip); + %} + ins_pipe(pipe_slow); +%} + // ============================================================================ // MemBar Instruction diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 8d656c136aa89..caa82aab99c2d 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -8965,6 +8965,21 @@ instruct vmasked_store_evex(memory mem, vec src, kReg mask) %{ %} #ifdef _LP64 +instruct verify_vector_alignment(rRegP addr, immL32 mask, rFlagsReg cr) %{ + match(Set addr (VerifyVectorAlignment addr mask)); + effect(KILL cr); + format %{ "verify_vector_alignment $addr $mask \t! verify alignment" %} + ins_encode %{ + Label Lskip; + // check if masked bits of addr are zero + __ testq($addr$$Register, $mask$$constant); + __ jccb(Assembler::equal, Lskip); + __ stop("verify_vector_alignment found a misaligned vector memory access"); + __ bind(Lskip); + %} + ins_pipe(pipe_slow); +%} + instruct vmask_cmp_node(rRegI dst, vec src1, vec src2, kReg mask, kReg ktmp1, kReg ktmp2, rFlagsReg cr) %{ match(Set dst (VectorCmpMasked src1 (Binary src2 mask))); effect(TEMP_DEF dst, TEMP ktmp1, TEMP ktmp2, KILL cr); diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 8e2366e5d09ff..ecbf472c59ef4 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -794,6 +794,7 @@ bool InstructForm::captures_bottom_type(FormDict &globals) const { !strcmp(_matrule->_rChild->_opType,"StrInflatedCopy") || !strcmp(_matrule->_rChild->_opType,"VectorCmpMasked")|| !strcmp(_matrule->_rChild->_opType,"VectorMaskGen")|| + !strcmp(_matrule->_rChild->_opType,"VerifyVectorAlignment")|| !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeP") || !strcmp(_matrule->_rChild->_opType,"CompareAndExchangeN"))) return true; else if ( is_ideal_load() == Form::idealP ) return true; diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index dc629de1bdfdb..885c0dd75a784 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -93,6 +93,10 @@ product(bool, AlignVector, true, \ "Perform vector store/load alignment in loop") \ \ + develop(bool, VerifyAlignVector, false, \ + "Check that vector stores/loads are aligned if AlignVector" \ + "is enabled.") \ + \ product(intx, NumberOfLoopInstrToAlign, 4, \ "Number of first instructions in a loop to align") \ range(0, max_jint) \ diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index ba383a679e182..b7c761d9b9845 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -34,6 +34,7 @@ #include "opto/output.hpp" #include "opto/runtime.hpp" #include "runtime/stubRoutines.hpp" +#include "runtime/globals_extension.hpp" #include "utilities/macros.hpp" @@ -64,6 +65,13 @@ void compiler_stubs_init(bool in_compiler_thread); bool C2Compiler::init_c2_runtime() { +#ifdef ASSERT + if (!AlignVector && VerifyAlignVector) { + warning("VerifyAlignVector disabled because AlignVector is not enabled."); + FLAG_SET_CMDLINE(VerifyAlignVector, false); + } +#endif + // Check assumptions used while running ADLC Compile::adlc_verification(); assert(REG_COUNT <= ConcreteRegisterImpl::number_of_registers, "incompatible register counts"); diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index 2f13a8bbd5721..97c45f508445e 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -1789,10 +1789,20 @@ void PhaseChaitin::fixup_spills() { // Helper to stretch above; recursively discover the base Node for a // given derived Node. Easy for AddP-related machine nodes, but needs // to be recursive for derived Phis. -Node *PhaseChaitin::find_base_for_derived( Node **derived_base_map, Node *derived, uint &maxlrg ) { +Node* PhaseChaitin::find_base_for_derived(Node** derived_base_map, Node* derived, uint& maxlrg) { // See if already computed; if so return it - if( derived_base_map[derived->_idx] ) + if (derived_base_map[derived->_idx]) { return derived_base_map[derived->_idx]; + } + +#ifdef ASSERT + if (derived->is_Mach() && derived->as_Mach()->ideal_Opcode() == Op_VerifyVectorAlignment) { + // Bypass the verification node + Node* base = find_base_for_derived(derived_base_map, derived->in(1), maxlrg); + derived_base_map[derived->_idx] = base; + return base; + } +#endif // See if this happens to be a base. // NOTE: we use TypePtr instead of TypeOopPtr because we can have diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 7d1a2cd1db0e8..f1da18f464e46 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -449,6 +449,7 @@ macro(StoreVectorScatter) macro(StoreVectorScatterMasked) macro(LoadVectorMasked) macro(StoreVectorMasked) +macro(VerifyVectorAlignment) macro(VectorCmpMasked) macro(VectorMaskGen) macro(VectorMaskOp) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 30701c03707e9..acce455b7265d 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -1065,7 +1065,7 @@ void Compile::Init(bool aliasing) { set_has_monitors(false); if (AllowVectorizeOnDemand) { - if (has_method() && (_directive->VectorizeOption || _directive->VectorizeDebugOption)) { + if (has_method() && _directive->VectorizeOption) { set_do_vector_loop(true); NOT_PRODUCT(if (do_vector_loop() && Verbose) {tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());}) } else if (has_method() && method()->name() != 0 && @@ -3707,6 +3707,31 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f case Op_LoadVector: case Op_StoreVector: +#ifdef ASSERT + // Add VerifyVectorAlignment node between adr and load / store. + if (VerifyAlignVector && Matcher::has_match_rule(Op_VerifyVectorAlignment)) { + bool must_verify_alignment = n->is_LoadVector() ? n->as_LoadVector()->must_verify_alignment() : + n->as_StoreVector()->must_verify_alignment(); + if (must_verify_alignment) { + jlong vector_width = n->is_LoadVector() ? n->as_LoadVector()->memory_size() : + n->as_StoreVector()->memory_size(); + // The memory access should be aligned to the vector width in bytes. + // However, the underlying array is possibly less well aligned, but at least + // to ObjectAlignmentInBytes. Hence, even if multiple arrays are accessed in + // a loop we can expect at least the following alignment: + jlong guaranteed_alignment = MIN2(vector_width, (jlong)ObjectAlignmentInBytes); + assert(2 <= guaranteed_alignment && guaranteed_alignment <= 64, "alignment must be in range"); + assert(is_power_of_2(guaranteed_alignment), "alignment must be power of 2"); + // Create mask from alignment. e.g. 0b1000 -> 0b0111 + jlong mask = guaranteed_alignment - 1; + Node* mask_con = ConLNode::make(mask); + VerifyVectorAlignmentNode* va = new VerifyVectorAlignmentNode(n->in(MemNode::Address), mask_con); + n->set_req(MemNode::Address, va); + } + } +#endif + break; + case Op_LoadVectorGather: case Op_StoreVectorScatter: case Op_LoadVectorGatherMasked: diff --git a/src/hotspot/share/opto/machnode.cpp b/src/hotspot/share/opto/machnode.cpp index 61042dfe71eff..173a38fa9d854 100644 --- a/src/hotspot/share/opto/machnode.cpp +++ b/src/hotspot/share/opto/machnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -357,6 +357,13 @@ const class TypePtr *MachNode::adr_type() const { return adr_type; // get_base_and_disp has the answer } +#ifdef ASSERT + if (base != nullptr && base->is_Mach() && base->as_Mach()->ideal_Opcode() == Op_VerifyVectorAlignment) { + // For VerifyVectorAlignment we just pass the type through + return base->bottom_type()->is_ptr(); + } +#endif + // Direct addressing modes have no base node, simply an indirect // offset, which is always to raw memory. // %%%%% Someday we'd like to allow constant oop offsets which diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 7e9c5196942fb..015bf5d5c72ca 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -178,6 +178,7 @@ class StoreVectorMaskedNode; class LoadVectorGatherNode; class StoreVectorNode; class StoreVectorScatterNode; +class VerifyVectorAlignmentNode; class VectorMaskCmpNode; class VectorUnboxNode; class VectorSet; diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index c3f0a60af20ff..4b1d9e5457291 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -557,14 +557,22 @@ bool SuperWord::SLP_extract() { // Attempt vectorization find_adjacent_refs(); - if (align_to_ref() == nullptr) { - return false; // Did not find memory reference to align vectors + if (_packset.length() == 0) { +#ifndef PRODUCT + if (TraceSuperWord) { + tty->print_cr("\nNo pair packs generated, abort SuperWord."); + tty->cr(); + } +#endif + return false; } extend_packlist(); combine_packs(); + filter_packs_for_alignment(); + construct_my_pack_map(); filter_packs(); @@ -578,9 +586,9 @@ bool SuperWord::SLP_extract() { //------------------------------find_adjacent_refs--------------------------- // Find the adjacent memory references and create pack pairs for them. -// This is the initial set of packs that will then be extended by -// following use->def and def->use links. The align positions are -// assigned relative to the reference "align_to_ref" +// We can find adjacent memory references by comparing their relative +// alignment. Whether the final vectors can be aligned is determined later +// once all vectors are extended and combined. void SuperWord::find_adjacent_refs() { // Get list of memory operations Node_List memops; @@ -598,25 +606,22 @@ void SuperWord::find_adjacent_refs() { tty->print_cr("\nfind_adjacent_refs found %d memops", memops.size()); } - Node_List align_to_refs; int max_idx; - int best_iv_adjustment = 0; - MemNode* best_align_to_mem_ref = nullptr; + + // Take the first mem_ref as the reference to align to. The pre-loop trip count is + // modified to align this reference to a vector-aligned address. If strict alignment + // is required, we may change the reference later (see filter_packs_for_alignment()). + MemNode* align_to_mem_ref = nullptr; while (memops.size() != 0) { // Find a memory reference to align to. MemNode* mem_ref = find_align_to_ref(memops, max_idx); if (mem_ref == nullptr) break; - align_to_refs.push(mem_ref); int iv_adjustment = get_iv_adjustment(mem_ref); - if (best_align_to_mem_ref == nullptr) { - // Set memory reference which is the best from all memory operations - // to be used for alignment. The pre-loop trip count is modified to align - // this reference to a vector-aligned address. - best_align_to_mem_ref = mem_ref; - best_iv_adjustment = iv_adjustment; - NOT_PRODUCT(find_adjacent_refs_trace_1(best_align_to_mem_ref, best_iv_adjustment);) + if (align_to_mem_ref == nullptr) { + align_to_mem_ref = mem_ref; + set_align_to_ref(align_to_mem_ref); } VPointer align_to_ref_p(mem_ref, phase(), lpt(), nullptr, false); @@ -633,90 +638,26 @@ void SuperWord::find_adjacent_refs() { } } - if (mem_ref_has_no_alignment_violation(mem_ref, iv_adjustment, align_to_ref_p, - best_align_to_mem_ref, best_iv_adjustment, - align_to_refs)) { - // Create initial pack pairs of memory operations for which alignment was set. - for (uint i = 0; i < memops.size(); i++) { - Node* s1 = memops.at(i); - int align = alignment(s1); - if (align == top_align) continue; - for (uint j = 0; j < memops.size(); j++) { - Node* s2 = memops.at(j); - if (alignment(s2) == top_align) continue; - if (s1 != s2 && are_adjacent_refs(s1, s2)) { - if (stmts_can_pack(s1, s2, align)) { - Node_List* pair = new Node_List(); - pair->push(s1); - pair->push(s2); - if (!_do_vector_loop || same_origin_idx(s1, s2)) { - _packset.append(pair); - } - } - } - } - } - } else { - // Cannot create pairs for mem_ref. Reject all related memops forever. - - // First, remove remaining memory ops of the same memory slice from the list. - for (int i = memops.size() - 1; i >= 0; i--) { - MemNode* s = memops.at(i)->as_Mem(); - if (same_memory_slice(s, mem_ref) || same_velt_type(s, mem_ref)) { - memops.remove(i); - } - } - - // Second, remove already constructed packs of the same memory slice. - for (int i = _packset.length() - 1; i >= 0; i--) { - Node_List* p = _packset.at(i); - MemNode* s = p->at(0)->as_Mem(); - if (same_memory_slice(s, mem_ref) || same_velt_type(s, mem_ref)) { - remove_pack_at(i); - } - } - - // If needed find the best memory reference for loop alignment again. - if (same_memory_slice(mem_ref, best_align_to_mem_ref) || same_velt_type(mem_ref, best_align_to_mem_ref)) { - // Put memory ops from remaining packs back on memops list for - // the best alignment search. - uint orig_msize = memops.size(); - for (int i = 0; i < _packset.length(); i++) { - Node_List* p = _packset.at(i); - MemNode* s = p->at(0)->as_Mem(); - assert(!same_velt_type(s, mem_ref), "sanity"); - memops.push(s); - } - best_align_to_mem_ref = find_align_to_ref(memops, max_idx); - if (best_align_to_mem_ref == nullptr) { - if (TraceSuperWord) { - tty->print_cr("SuperWord::find_adjacent_refs(): best_align_to_mem_ref == nullptr"); - } - // best_align_to_mem_ref will be used for adjusting the pre-loop limit in - // SuperWord::align_initial_loop_index. Find one with the biggest vector size, - // smallest data size and smallest iv offset from memory ops from remaining packs. - if (_packset.length() > 0) { - if (orig_msize == 0) { - best_align_to_mem_ref = memops.at(max_idx)->as_Mem(); - } else { - for (uint i = 0; i < orig_msize; i++) { - memops.remove(0); - } - best_align_to_mem_ref = find_align_to_ref(memops, max_idx); - assert(best_align_to_mem_ref == nullptr, "sanity"); - best_align_to_mem_ref = memops.at(max_idx)->as_Mem(); + // Create initial pack pairs of memory operations for which alignment was set. + for (uint i = 0; i < memops.size(); i++) { + Node* s1 = memops.at(i); + int align = alignment(s1); + if (align == top_align) continue; + for (uint j = 0; j < memops.size(); j++) { + Node* s2 = memops.at(j); + if (alignment(s2) == top_align) continue; + if (s1 != s2 && are_adjacent_refs(s1, s2)) { + if (stmts_can_pack(s1, s2, align)) { + Node_List* pair = new Node_List(); + pair->push(s1); + pair->push(s2); + if (!_do_vector_loop || same_origin_idx(s1, s2)) { + _packset.append(pair); } - assert(best_align_to_mem_ref != nullptr, "sanity"); } - break; } - best_iv_adjustment = get_iv_adjustment(best_align_to_mem_ref); - NOT_PRODUCT(find_adjacent_refs_trace_1(best_align_to_mem_ref, best_iv_adjustment);) - // Restore list. - while (memops.size() > orig_msize) - (void)memops.pop(); } - } // unaligned memory accesses + } // Remove used mem nodes. for (int i = memops.size() - 1; i >= 0; i--) { @@ -725,66 +666,17 @@ void SuperWord::find_adjacent_refs() { memops.remove(i); } } + } // while (memops.size() != 0) - } // while (memops.size() != 0 - set_align_to_ref(best_align_to_mem_ref); + assert(_packset.is_empty() || align_to_mem_ref != nullptr, + "packset empty or we find the alignment reference"); +#ifndef PRODUCT if (TraceSuperWord) { tty->print_cr("\nAfter find_adjacent_refs"); print_packset(); } -} - -#ifndef PRODUCT -void SuperWord::find_adjacent_refs_trace_1(Node* best_align_to_mem_ref, int best_iv_adjustment) { - if (is_trace_adjacent()) { - tty->print("SuperWord::find_adjacent_refs best_align_to_mem_ref = %d, best_iv_adjustment = %d", - best_align_to_mem_ref->_idx, best_iv_adjustment); - best_align_to_mem_ref->dump(); - } -} #endif - -// If strict memory alignment is required (vectors_should_be_aligned), then check if -// mem_ref is aligned with best_align_to_mem_ref. -bool SuperWord::mem_ref_has_no_alignment_violation(MemNode* mem_ref, int iv_adjustment, VPointer& align_to_ref_p, - MemNode* best_align_to_mem_ref, int best_iv_adjustment, - Node_List &align_to_refs) { - if (!vectors_should_be_aligned()) { - // Alignment is not required by the hardware. No violation possible. - return true; - } - - // All vectors need to be memory aligned, modulo their vector_width. This is more strict - // than the hardware probably requires. Most hardware at most requires 4-byte alignment. - // - // In the pre-loop, we align best_align_to_mem_ref to its vector_length. To ensure that - // all mem_ref's are memory aligned modulo their vector_width, we only need to check that - // they are all aligned to best_align_to_mem_ref, modulo their vector_width. For that, - // we check the following 3 conditions. - - // (1) All packs are aligned with best_align_to_mem_ref. - if (memory_alignment(mem_ref, best_iv_adjustment) != 0) { - return false; - } - // (2) All other vectors have vector_size less or equal to that of best_align_to_mem_ref. - int vw = vector_width(mem_ref); - int vw_best = vector_width(best_align_to_mem_ref); - if (vw > vw_best) { - // We only align to vector_width of best_align_to_mem_ref during pre-loop. - // A mem_ref with a larger vector_width might thus not be vector_width aligned. - return false; - } - // (3) Ensure that all vectors have the same invariant. We model memory accesses like this - // address = base + k*iv + constant [+ invar] - // memory_alignment ignores the invariant. - VPointer p2(best_align_to_mem_ref, phase(), lpt(), nullptr, false); - if (!align_to_ref_p.invar_equals(p2)) { - // Do not vectorize memory accesses with different invariants - // if unaligned memory accesses are not allowed. - return false; - } - return true; } //------------------------------find_align_to_ref--------------------------- @@ -798,12 +690,6 @@ MemNode* SuperWord::find_align_to_ref(Node_List &memops, int &idx) { for (uint i = 0; i < memops.size(); i++) { MemNode* s1 = memops.at(i)->as_Mem(); VPointer p1(s1, phase(), lpt(), nullptr, false); - // Only discard unalignable memory references if vector memory references - // should be aligned on this platform. - if (vectors_should_be_aligned() && !ref_is_alignable(p1)) { - *cmp_ct.adr_at(i) = 0; - continue; - } for (uint j = i+1; j < memops.size(); j++) { MemNode* s2 = memops.at(j)->as_Mem(); if (isomorphic(s1, s2)) { @@ -892,95 +778,6 @@ MemNode* SuperWord::find_align_to_ref(Node_List &memops, int &idx) { return nullptr; } -//------------------span_works_for_memory_size----------------------------- -static bool span_works_for_memory_size(MemNode* mem, int span, int mem_size, int offset) { - bool span_matches_memory = false; - if ((mem_size == type2aelembytes(T_BYTE) || mem_size == type2aelembytes(T_SHORT)) - && ABS(span) == type2aelembytes(T_INT)) { - // There is a mismatch on span size compared to memory. - for (DUIterator_Fast jmax, j = mem->fast_outs(jmax); j < jmax; j++) { - Node* use = mem->fast_out(j); - if (!VectorNode::is_type_transition_to_int(use)) { - return false; - } - } - // If all uses transition to integer, it means that we can successfully align even on mismatch. - return true; - } - else { - span_matches_memory = ABS(span) == mem_size; - } - return span_matches_memory && (ABS(offset) % mem_size) == 0; -} - -//------------------------------ref_is_alignable--------------------------- -// Can the preloop align the reference to position zero in the vector? -bool SuperWord::ref_is_alignable(VPointer& p) { - if (!p.has_iv()) { - return true; // no induction variable - } - CountedLoopEndNode* pre_end = lp()->pre_loop_end(); - assert(pre_end->stride_is_con(), "pre loop stride is constant"); - int preloop_stride = pre_end->stride_con(); - - int span = preloop_stride * p.scale_in_bytes(); - int mem_size = p.memory_size(); - int offset = p.offset_in_bytes(); - // Stride one accesses are alignable if offset is aligned to memory operation size. - // Offset can be unaligned when UseUnalignedAccesses is used. - if (span_works_for_memory_size(p.mem(), span, mem_size, offset)) { - return true; - } - // If the initial offset from start of the object is computable, - // check if the pre-loop can align the final offset accordingly. - // - // In other words: Can we find an i such that the offset - // after i pre-loop iterations is aligned to vw? - // (init_offset + pre_loop) % vw == 0 (1) - // where - // pre_loop = i * span - // is the number of bytes added to the offset by i pre-loop iterations. - // - // For this to hold we need pre_loop to increase init_offset by - // pre_loop = vw - (init_offset % vw) - // - // This is only possible if pre_loop is divisible by span because each - // pre-loop iteration increases the initial offset by 'span' bytes: - // (vw - (init_offset % vw)) % span == 0 - // - int vw = vector_width_in_bytes(p.mem()); - assert(vw > 1, "sanity"); - Node* init_nd = pre_end->init_trip(); - if (init_nd->is_Con() && p.invar() == nullptr) { - int init = init_nd->bottom_type()->is_int()->get_con(); - int init_offset = init * p.scale_in_bytes() + offset; - if (init_offset < 0) { // negative offset from object start? - return false; // may happen in dead loop - } - if (vw % span == 0) { - // If vm is a multiple of span, we use formula (1). - if (span > 0) { - return (vw - (init_offset % vw)) % span == 0; - } else { - assert(span < 0, "nonzero stride * scale"); - return (init_offset % vw) % -span == 0; - } - } else if (span % vw == 0) { - // If span is a multiple of vw, we can simplify formula (1) to: - // (init_offset + i * span) % vw == 0 - // => - // (init_offset % vw) + ((i * span) % vw) == 0 - // => - // init_offset % vw == 0 - // - // Because we add a multiple of vw to the initial offset, the final - // offset is a multiple of vw if and only if init_offset is a multiple. - // - return (init_offset % vw) == 0; - } - } - return false; -} //---------------------------get_vw_bytes_special------------------------ int SuperWord::get_vw_bytes_special(MemNode* s) { // Get the vector width in bytes. @@ -1026,10 +823,6 @@ int SuperWord::get_iv_adjustment(MemNode* mem_ref) { // several iterations are needed to align memory operations in main-loop even // if offset is 0. int iv_adjustment_in_bytes = (stride_sign * vw - (offset % vw)); - // iv_adjustment_in_bytes must be a multiple of elt_size if vector memory - // references should be aligned on this platform. - assert((ABS(iv_adjustment_in_bytes) % elt_size) == 0 || !vectors_should_be_aligned(), - "(%d) should be divisible by (%d)", iv_adjustment_in_bytes, elt_size); iv_adjustment = iv_adjustment_in_bytes/elt_size; } else { // This memory op is not dependent on iv (scale == 0) @@ -1707,6 +1500,12 @@ int SuperWord::unpack_cost(int ct) { return ct; } //------------------------------combine_packs--------------------------- // Combine packs A and B with A.last == B.first into A.first..,A.last,B.second,..B.last void SuperWord::combine_packs() { +#ifdef ASSERT + for (int i = 0; i < _packset.length(); i++) { + assert(_packset.at(i) != nullptr, "no nullptr in packset"); + } +#endif + bool changed = true; // Combine packs regardless max vector size. while (changed) { @@ -1802,18 +1601,123 @@ void SuperWord::combine_packs() { } } - // Compress list. - for (int i = _packset.length() - 1; i >= 0; i--) { - Node_List* p1 = _packset.at(i); - if (p1 == nullptr) { - _packset.remove_at(i); - } - } + // Remove all nullptr from packset + compress_packset(); +#ifndef PRODUCT if (TraceSuperWord) { tty->print_cr("\nAfter combine_packs"); print_packset(); } +#endif +} + +// Find the set of alignment solutions for load/store pack. +const AlignmentSolution* SuperWord::pack_alignment_solution(Node_List* pack) { + assert(pack != nullptr && (pack->at(0)->is_Load() || pack->at(0)->is_Store()), "only load/store packs"); + + const MemNode* mem_ref = pack->at(0)->as_Mem(); + VPointer mem_ref_p(mem_ref, phase(), lpt(), nullptr, false); + const CountedLoopEndNode* pre_end = lp()->pre_loop_end(); + assert(pre_end->stride_is_con(), "pre loop stride is constant"); + + AlignmentSolver solver(pack->at(0)->as_Mem(), + pack->size(), + mem_ref_p.base(), + mem_ref_p.offset_in_bytes(), + mem_ref_p.invar(), + mem_ref_p.invar_factor(), + mem_ref_p.scale_in_bytes(), + pre_end->init_trip(), + pre_end->stride_con(), + iv_stride() + DEBUG_ONLY(COMMA is_trace_align_vector())); + return solver.solve(); +} + +// Ensure all packs are aligned, if AlignVector is on. +// Find an alignment solution: find the set of pre_iter that memory align all packs. +// Start with the maximal set (pre_iter >= 0) and filter it with the constraints +// that the packs impose. Remove packs that do not have a compatible solution. +void SuperWord::filter_packs_for_alignment() { + // We do not need to filter if no alignment is required. + if (!vectors_should_be_aligned()) { + return; + } + +#ifndef PRODUCT + if (TraceSuperWord || is_trace_align_vector()) { + tty->print_cr("\nfilter_packs_for_alignment:"); + } +#endif + + ResourceMark rm; + + // Start with trivial (unconstrained) solution space + AlignmentSolution const* current = new TrivialAlignmentSolution(); + int mem_ops_count = 0; + int mem_ops_rejected = 0; + for (int i = 0; i < _packset.length(); i++) { + Node_List* p = _packset.at(i); + if (p != nullptr) { + if (p->at(0)->is_Load() || p->at(0)->is_Store()) { + mem_ops_count++; + // Find solution for pack p, and filter with current solution. + const AlignmentSolution* s = pack_alignment_solution(p); + const AlignmentSolution* intersect = current->filter(s); + +#ifndef PRODUCT + if (is_trace_align_vector()) { + tty->print(" solution for pack: "); + s->print(); + tty->print(" intersection with current: "); + intersect->print(); + } +#endif + + if (intersect->is_empty()) { + // Solution failed or is not compatible, remove pack i. + _packset.at_put(i, nullptr); + mem_ops_rejected++; + } else { + // Solution is compatible. + current = intersect; + } + } + } + } + +#ifndef PRODUCT + if (TraceSuperWord || is_trace_align_vector()) { + tty->print("\n final solution: "); + current->print(); + tty->print_cr(" rejected mem_ops packs: %d of %d", mem_ops_rejected, mem_ops_count); + tty->cr(); + } +#endif + + assert(!current->is_empty(), "solution must be non-empty"); + if (current->is_constrained()) { + // Solution is constrained (not trivial) + // -> must change pre-limit to achieve alignment + set_align_to_ref(current->as_constrained()->mem_ref()); + } + + // Remove all nullptr from packset + compress_packset(); +} + +// Compress packset, such that it has no nullptr entries +void SuperWord::compress_packset() { + int j = 0; + for (int i = 0; i < _packset.length(); i++) { + Node_List* p = _packset.at(i); + if (p != nullptr) { + _packset.at_put(j, p); + j++; + } + } + _packset.trunc_to(j); } //-----------------------------construct_my_pack_map-------------------------- @@ -2493,9 +2397,7 @@ bool SuperWord::output() { #endif _phase->C->print_method(PHASE_SUPERWORD2_BEFORE_OUTPUT, 4, cl); - // Ensure main loop's initial value is properly aligned - // (iv_initial_value + min_iv_offset) % vector_width_in_bytes() == 0 - align_initial_loop_index(align_to_ref()); + adjust_pre_loop_limit_to_align_main_loop_vectors(); // Insert extract (unpack) operations for scalar uses for (int i = 0; i < _packset.length(); i++) { @@ -2768,6 +2670,17 @@ bool SuperWord::output() { return false; // bailout } +#ifdef ASSERT + // Mark Load/Store Vector for alignment verification + if (VerifyAlignVector) { + if (vn->Opcode() == Op_LoadVector) { + vn->as_LoadVector()->set_must_verify_alignment(); + } else if (vn->Opcode() == Op_StoreVector) { + vn->as_StoreVector()->set_must_verify_alignment(); + } + } +#endif + _block.at_put(i, vn); _igvn.register_new_node_with_optimizer(vn); _phase->set_ctrl(vn, _phase->get_ctrl(first)); @@ -3553,167 +3466,337 @@ LoadNode::ControlDependency SuperWord::control_dependency(Node_List* p) { return dep; } +#define TRACE_ALIGN_VECTOR_NODE(node) { \ + DEBUG_ONLY( \ + if (is_trace_align_vector()) { \ + tty->print(" " #node ": "); \ + node->dump(); \ + } \ + ) \ +} \ + +// Ensure that the main loop vectors are aligned by adjusting the pre loop limit. We memory-align +// the address of "align_to_ref" to the maximal possible vector width. We adjust the pre-loop +// iteration count by adjusting the pre-loop limit. +void SuperWord::adjust_pre_loop_limit_to_align_main_loop_vectors() { + const MemNode* align_to_ref = _align_to_ref; + assert(align_to_ref != nullptr, "align_to_ref must be set"); + assert(lp()->is_main_loop(), "can only do alignment for main loop"); -//----------------------------align_initial_loop_index--------------------------- -// Adjust pre-loop limit so that in main loop, a load/store reference -// to align_to_ref will be a position zero in the vector. -// (iv + k) mod vector_align == 0 -void SuperWord::align_initial_loop_index(MemNode* align_to_ref) { - assert(lp()->is_main_loop(), ""); - CountedLoopEndNode* pre_end = lp()->pre_loop_end(); - Node* pre_opaq1 = pre_end->limit(); - assert(pre_opaq1->Opcode() == Op_Opaque1, ""); - Opaque1Node* pre_opaq = (Opaque1Node*)pre_opaq1; - Node* lim0 = pre_opaq->in(1); + // The opaque node for the limit, where we adjust the input + Opaque1Node* pre_opaq = lp()->pre_loop_end()->limit()->as_Opaque1(); - // Where we put new limit calculations + // Current pre-loop limit. + Node* old_limit = pre_opaq->in(1); + + // Where we put new limit calculations. Node* pre_ctrl = lp()->pre_loop_head()->in(LoopNode::EntryControl); - // Ensure the original loop limit is available from the - // pre-loop Opaque1 node. + // Ensure the original loop limit is available from the pre-loop Opaque1 node. Node* orig_limit = pre_opaq->original_loop_limit(); assert(orig_limit != nullptr && _igvn.type(orig_limit) != Type::TOP, ""); VPointer align_to_ref_p(align_to_ref, phase(), lpt(), nullptr, false); assert(align_to_ref_p.valid(), "sanity"); - // Given: - // lim0 == original pre loop limit - // V == v_align (power of 2) - // invar == extra invariant piece of the address expression - // e == offset [ +/- invar ] + // For the main-loop, we want the address of align_to_ref to be memory aligned + // with some alignment width (aw, a power of 2). When we enter the main-loop, + // we know that iv is equal to the pre-loop limit. If we adjust the pre-loop + // limit by executing adjust_pre_iter many extra iterations, we can change the + // alignment of the address. // - // When reassociating expressions involving '%' the basic rules are: - // (a - b) % k == 0 => a % k == b % k - // and: - // (a + b) % k == 0 => a % k == (k - b) % k + // adr = base + offset + invar + scale * iv (1) + // adr % aw = 0 (2) // - // For stride > 0 && scale > 0, - // Derive the new pre-loop limit "lim" such that the two constraints: - // (1) lim = lim0 + N (where N is some positive integer < V) - // (2) (e + lim) % V == 0 - // are true. + // Note, that we are defining the modulo operator "%" such that the remainder is + // always positive, see AlignmentSolution::mod(i, q). Since we are only computing + // modulo with powers of 2, we can instead simply use the last log2(q) bits of + // a number i, to get "i % q". This is performed with a bitmask. // - // Substituting (1) into (2), - // (e + lim0 + N) % V == 0 - // solve for N: - // N = (V - (e + lim0)) % V - // substitute back into (1), so that new limit - // lim = lim0 + (V - (e + lim0)) % V + // The limit of the pre-loop needs to be adjusted: // - // For stride > 0 && scale < 0 - // Constraints: - // lim = lim0 + N - // (e - lim) % V == 0 - // Solving for lim: - // (e - lim0 - N) % V == 0 - // N = (e - lim0) % V - // lim = lim0 + (e - lim0) % V + // old_limit: current pre-loop limit + // new_limit: new pre-loop limit + // adjust_pre_iter: additional pre-loop iterations for alignment adjustment // - // For stride < 0 && scale > 0 - // Constraints: - // lim = lim0 - N - // (e + lim) % V == 0 - // Solving for lim: - // (e + lim0 - N) % V == 0 - // N = (e + lim0) % V - // lim = lim0 - (e + lim0) % V + // We want to find adjust_pre_iter, such that the address is aligned when entering + // the main-loop: // - // For stride < 0 && scale < 0 - // Constraints: - // lim = lim0 - N - // (e - lim) % V == 0 - // Solving for lim: - // (e - lim0 + N) % V == 0 - // N = (V - (e - lim0)) % V - // lim = lim0 - (V - (e - lim0)) % V - - int vw = vector_width_in_bytes(align_to_ref); - int stride = iv_stride(); - int scale = align_to_ref_p.scale_in_bytes(); - int elt_size = align_to_ref_p.memory_size(); - int v_align = vw / elt_size; - assert(v_align > 1, "sanity"); - int offset = align_to_ref_p.offset_in_bytes() / elt_size; - Node *offsn = _igvn.intcon(offset); - - Node *e = offsn; - if (align_to_ref_p.invar() != nullptr) { - // incorporate any extra invariant piece producing (offset +/- invar) >>> log2(elt) - Node* log2_elt = _igvn.intcon(exact_log2(elt_size)); - Node* invar = align_to_ref_p.invar(); + // iv = new_limit = old_limit + adjust_pre_iter (3a, stride > 0) + // iv = new_limit = old_limit - adjust_pre_iter (3b, stride < 0) + // + // We define boi as: + // + // boi = base + offset + invar (4) + // + // And now we can simplify the address using (1), (3), and (4): + // + // adr = boi + scale * new_limit + // adr = boi + scale * (old_limit + adjust_pre_iter) (5a, stride > 0) + // adr = boi + scale * (old_limit - adjust_pre_iter) (5b, stride < 0) + // + // And hence we can restate (2) with (5), and solve the equation for adjust_pre_iter: + // + // (boi + scale * (old_limit + adjust_pre_iter) % aw = 0 (6a, stride > 0) + // (boi + scale * (old_limit - adjust_pre_iter) % aw = 0 (6b, stride < 0) + // + // In most cases, scale is the element size, for example: + // + // for (i = 0; i < a.length; i++) { a[i] = ...; } + // + // It is thus reasonable to assume that both abs(scale) and abs(stride) are + // strictly positive powers of 2. Further, they can be assumed to be non-zero, + // otherwise the address does not depend on iv, and the alignment cannot be + // affected by adjusting the pre-loop limit. + // + // Further, if abs(scale) >= aw, then adjust_pre_iter has no effect on alignment, and + // we are not able to affect the alignment at all. Hence, we require abs(scale) < aw. + // + // Moreover, for alignment to be achievable, boi must be a multiple of scale. If strict + // alignment is required (i.e. -XX:+AlignVector), this is guaranteed by the filtering + // done with the AlignmentSolver / AlignmentSolution. If strict alignment is not + // required, then alignment is still preferable for performance, but not necessary. + // In many cases boi will be a multiple of scale, but if it is not, then the adjustment + // does not guarantee alignment, but the code is still correct. + // + // Hence, in what follows we assume that boi is a multiple of scale, and in fact all + // terms in (6) are multiples of scale. Therefore we divide all terms by scale: + // + // AW = aw / abs(scale) (power of 2) (7) + // BOI = boi / abs(scale) (8) + // + // and restate (6), using (7) and (8), i.e. we divide (6) by abs(scale): + // + // (BOI + sign(scale) * (old_limit + adjust_pre_iter) % AW = 0 (9a, stride > 0) + // (BOI + sign(scale) * (old_limit - adjust_pre_iter) % AW = 0 (9b, stride < 0) + // + // where: sign(scale) = scale / abs(scale) = (scale > 0 ? 1 : -1) + // + // Note, (9) allows for periodic solutions of adjust_pre_iter, with periodicity AW. + // But we would like to spend as few iterations in the pre-loop as possible, + // hence we want the smallest adjust_pre_iter, and so: + // + // 0 <= adjust_pre_iter < AW (10) + // + // We solve (9) for adjust_pre_iter, in the following 4 cases: + // + // Case A: scale > 0 && stride > 0 (i.e. sign(scale) = 1) + // (BOI + old_limit + adjust_pre_iter) % AW = 0 + // adjust_pre_iter = (-BOI - old_limit) % AW (11a) + // + // Case B: scale < 0 && stride > 0 (i.e. sign(scale) = -1) + // (BOI - old_limit - adjust_pre_iter) % AW = 0 + // adjust_pre_iter = (BOI - old_limit) % AW (11b) + // + // Case C: scale > 0 && stride < 0 (i.e. sign(scale) = 1) + // (BOI + old_limit - adjust_pre_iter) % AW = 0 + // adjust_pre_iter = (BOI + old_limit) % AW (11c) + // + // Case D: scale < 0 && stride < 0 (i.e. sign(scale) = -1) + // (BOI - old_limit + adjust_pre_iter) % AW = 0 + // adjust_pre_iter = (-BOI + old_limit) % AW (11d) + // + // We now generalize the equations (11*) by using: + // + // OP: (stride > 0) ? SUB : ADD + // XBOI: (stride * scale > 0) ? -BOI : BOI + // + // which gives us the final pre-loop limit adjustment: + // + // adjust_pre_iter = (XBOI OP old_limit) % AW (12) + // + // We can construct XBOI by additionally defining: + // + // xboi = (stride * scale > 0) ? -boi : boi (13) + // + // which gives us: + // + // XBOI = (stride * scale > 0) ? -BOI : BOI + // = (stride * scale > 0) ? -boi / abs(scale) : boi / abs(scale) + // = xboi / abs(scale) (14) + // + // When we have computed adjust_pre_iter, we update the pre-loop limit + // with (3a, b). However, we have to make sure that the adjust_pre_iter + // additional pre-loop iterations do not lead the pre-loop to execute + // iterations that would step over the original limit (orig_limit) of + // the loop. Hence, we must constrain the updated limit as follows: + // + // constrained_limit = MIN(old_limit + adjust_pre_iter, orig_limit) + // = MIN(new_limit, orig_limit) (15a, stride > 0) + // constrained_limit = MAX(old_limit - adjust_pre_iter, orig_limit) + // = MAX(new_limit, orig_limit) (15a, stride < 0) + + // We chose an aw that is the maximal possible vector width for the type of + // align_to_ref. + const int aw = vector_width_in_bytes(align_to_ref); + const int stride = iv_stride(); + const int scale = align_to_ref_p.scale_in_bytes(); + const int offset = align_to_ref_p.offset_in_bytes(); + Node* base = align_to_ref_p.adr(); + Node* invar = align_to_ref_p.invar(); + +#ifdef ASSERT + if (is_trace_align_vector()) { + tty->print_cr("\nadjust_pre_loop_limit_to_align_main_loop_vectors:"); + tty->print(" align_to_ref:"); + align_to_ref->dump(); + tty->print_cr(" aw: %d", aw); + tty->print_cr(" stride: %d", stride); + tty->print_cr(" scale: %d", scale); + tty->print_cr(" offset: %d", offset); + tty->print(" base:"); + base->dump(); + if (invar == nullptr) { + tty->print_cr(" invar: null"); + } else { + tty->print(" invar:"); + invar->dump(); + } + tty->print(" old_limit: "); + old_limit->dump(); + tty->print(" orig_limit: "); + orig_limit->dump(); + } +#endif + + if (stride == 0 || !is_power_of_2(abs(stride)) || + scale == 0 || !is_power_of_2(abs(scale)) || + abs(scale) >= aw) { +#ifdef ASSERT + if (is_trace_align_vector()) { + tty->print_cr(" Alignment cannot be affected by changing pre-loop limit because"); + tty->print_cr(" stride or scale are not power of 2, or abs(scale) >= aw."); + } +#endif + // Cannot affect alignment, abort. + return; + } + + assert(stride != 0 && is_power_of_2(abs(stride)) && + scale != 0 && is_power_of_2(abs(scale)) && + abs(scale) < aw, "otherwise we cannot affect alignment with pre-loop"); + + const int AW = aw / abs(scale); + +#ifdef ASSERT + if (is_trace_align_vector()) { + tty->print_cr(" AW = aw(%d) / abs(scale(%d)) = %d", aw, scale, AW); + } +#endif + + // 1: Compute (13a, b): + // xboi = -boi = (-base - offset - invar) (stride * scale > 0) + // xboi = +boi = (+base + offset + invar) (stride * scale < 0) + const bool is_sub = scale * stride > 0; + + // 1.1: offset + Node* xboi = _igvn.intcon(is_sub ? -offset : offset); + TRACE_ALIGN_VECTOR_NODE(xboi); + + // 1.2: invar (if it exists) + if (invar != nullptr) { if (_igvn.type(invar)->isa_long()) { // Computations are done % (vector width/element size) so it's // safe to simply convert invar to an int and loose the upper 32 // bit half. invar = new ConvL2INode(invar); _igvn.register_new_node_with_optimizer(invar); + TRACE_ALIGN_VECTOR_NODE(invar); + } + if (is_sub) { + xboi = new SubINode(xboi, invar); + } else { + xboi = new AddINode(xboi, invar); } - Node* aref = new URShiftINode(invar, log2_elt); - _igvn.register_new_node_with_optimizer(aref); - _phase->set_ctrl(aref, pre_ctrl); - e = new AddINode(e, aref); - _igvn.register_new_node_with_optimizer(e); - _phase->set_ctrl(e, pre_ctrl); + _igvn.register_new_node_with_optimizer(xboi); + _phase->set_ctrl(xboi, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(xboi); } - if (vw > ObjectAlignmentInBytes || align_to_ref_p.base()->is_top()) { - // incorporate base e +/- base && Mask >>> log2(elt) - Node* xbase = new CastP2XNode(nullptr, align_to_ref_p.adr()); + + // 1.3: base (unless base is guaranteed aw aligned) + if (aw > ObjectAlignmentInBytes || align_to_ref_p.base()->is_top()) { + // The base is only aligned with ObjectAlignmentInBytes with arrays. + // When the base() is top, we have no alignment guarantee at all. + // Hence, we must now take the base into account for the calculation. + Node* xbase = new CastP2XNode(nullptr, base); _igvn.register_new_node_with_optimizer(xbase); + TRACE_ALIGN_VECTOR_NODE(xbase); #ifdef _LP64 xbase = new ConvL2INode(xbase); _igvn.register_new_node_with_optimizer(xbase); + TRACE_ALIGN_VECTOR_NODE(xbase); #endif - Node* mask = _igvn.intcon(vw-1); - Node* masked_xbase = new AndINode(xbase, mask); - _igvn.register_new_node_with_optimizer(masked_xbase); - Node* log2_elt = _igvn.intcon(exact_log2(elt_size)); - Node* bref = new URShiftINode(masked_xbase, log2_elt); - _igvn.register_new_node_with_optimizer(bref); - _phase->set_ctrl(bref, pre_ctrl); - e = new AddINode(e, bref); - _igvn.register_new_node_with_optimizer(e); - _phase->set_ctrl(e, pre_ctrl); - } - - // compute e +/- lim0 - if (scale < 0) { - e = new SubINode(e, lim0); + if (is_sub) { + xboi = new SubINode(xboi, xbase); + } else { + xboi = new AddINode(xboi, xbase); + } + _igvn.register_new_node_with_optimizer(xboi); + _phase->set_ctrl(xboi, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(xboi); + } + + // 2: Compute (14): + // XBOI = xboi / abs(scale) + // The division is executed as shift + Node* log2_abs_scale = _igvn.intcon(exact_log2(abs(scale))); + Node* XBOI = new URShiftINode(xboi, log2_abs_scale); + _igvn.register_new_node_with_optimizer(XBOI); + _phase->set_ctrl(XBOI, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(log2_abs_scale); + TRACE_ALIGN_VECTOR_NODE(XBOI); + + // 3: Compute (12): + // adjust_pre_iter = (XBOI OP old_limit) % AW + // + // 3.1: XBOI_OP_old_limit = XBOI OP old_limit + Node* XBOI_OP_old_limit = nullptr; + if (stride > 0) { + XBOI_OP_old_limit = new SubINode(XBOI, old_limit); } else { - e = new AddINode(e, lim0); - } - _igvn.register_new_node_with_optimizer(e); - _phase->set_ctrl(e, pre_ctrl); - - if (stride * scale > 0) { - // compute V - (e +/- lim0) - Node* va = _igvn.intcon(v_align); - e = new SubINode(va, e); - _igvn.register_new_node_with_optimizer(e); - _phase->set_ctrl(e, pre_ctrl); - } - // compute N = (exp) % V - Node* va_msk = _igvn.intcon(v_align - 1); - Node* N = new AndINode(e, va_msk); - _igvn.register_new_node_with_optimizer(N); - _phase->set_ctrl(N, pre_ctrl); - - // substitute back into (1), so that new limit - // lim = lim0 + N - Node* lim; + XBOI_OP_old_limit = new AddINode(XBOI, old_limit); + } + _igvn.register_new_node_with_optimizer(XBOI_OP_old_limit); + _phase->set_ctrl(XBOI_OP_old_limit, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(XBOI_OP_old_limit); + + // 3.2: Compute: + // adjust_pre_iter = (XBOI OP old_limit) % AW + // = XBOI_OP_old_limit % AW + // = XBOI_OP_old_limit AND (AW - 1) + // Since AW is a power of 2, the modulo operation can be replaced with + // a bitmask operation. + Node* mask_AW = _igvn.intcon(AW-1); + Node* adjust_pre_iter = new AndINode(XBOI_OP_old_limit, mask_AW); + _igvn.register_new_node_with_optimizer(adjust_pre_iter); + _phase->set_ctrl(adjust_pre_iter, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(mask_AW); + TRACE_ALIGN_VECTOR_NODE(adjust_pre_iter); + + // 4: Compute (3a, b): + // new_limit = old_limit + adjust_pre_iter (stride > 0) + // new_limit = old_limit - adjust_pre_iter (stride < 0) + Node* new_limit = nullptr; if (stride < 0) { - lim = new SubINode(lim0, N); + new_limit = new SubINode(old_limit, adjust_pre_iter); } else { - lim = new AddINode(lim0, N); - } - _igvn.register_new_node_with_optimizer(lim); - _phase->set_ctrl(lim, pre_ctrl); - Node* constrained = - (stride > 0) ? (Node*) new MinINode(lim, orig_limit) - : (Node*) new MaxINode(lim, orig_limit); - _igvn.register_new_node_with_optimizer(constrained); - _phase->set_ctrl(constrained, pre_ctrl); - _igvn.replace_input_of(pre_opaq, 1, constrained); + new_limit = new AddINode(old_limit, adjust_pre_iter); + } + _igvn.register_new_node_with_optimizer(new_limit); + _phase->set_ctrl(new_limit, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(new_limit); + + // 5: Compute (15a, b): + // Prevent pre-loop from going past the original limit of the loop. + Node* constrained_limit = + (stride > 0) ? (Node*) new MinINode(new_limit, orig_limit) + : (Node*) new MaxINode(new_limit, orig_limit); + _igvn.register_new_node_with_optimizer(constrained_limit); + _phase->set_ctrl(constrained_limit, pre_ctrl); + TRACE_ALIGN_VECTOR_NODE(constrained_limit); + + // 6: Hack the pre-loop limit + _igvn.replace_input_of(pre_opaq, 1, constrained_limit); } //------------------------------init--------------------------- diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 2319636c99abc..db7101b26cb53 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -247,7 +247,7 @@ class SuperWord : public ResourceObj { GrowableArray _mem_slice_tail; // Memory slice tail nodes GrowableArray _node_info; // Info needed per node CloneMap& _clone_map; // map of nodes created in cloning - MemNode* _align_to_ref; // Memory reference that pre-loop will align to + MemNode const* _align_to_ref; // Memory reference that pre-loop will align to GrowableArray _disjoint_ptrs; // runtime disambiguated pointer pairs @@ -281,6 +281,7 @@ class SuperWord : public ResourceObj { bool is_trace_loop() { return (_vector_loop_debug & 8) > 0; } bool is_trace_adjacent() { return (_vector_loop_debug & 16) > 0; } bool is_trace_cmov() { return (_vector_loop_debug & 32) > 0; } + bool is_trace_align_vector() { return (_vector_loop_debug & 128) > 0; } #endif bool do_vector_loop() { return _do_vector_loop; } @@ -315,17 +316,17 @@ class SuperWord : public ResourceObj { } int iv_stride() const { return lp()->stride_con(); } - int vector_width(Node* n) { + int vector_width(const Node* n) const { BasicType bt = velt_basic_type(n); return MIN2(ABS(iv_stride()), Matcher::max_vector_size(bt)); } - int vector_width_in_bytes(Node* n) { + int vector_width_in_bytes(const Node* n) const { BasicType bt = velt_basic_type(n); return vector_width(n)*type2aelembytes(bt); } int get_vw_bytes_special(MemNode* s); - MemNode* align_to_ref() { return _align_to_ref; } - void set_align_to_ref(MemNode* m) { _align_to_ref = m; } + const MemNode* align_to_ref() const { return _align_to_ref; } + void set_align_to_ref(const MemNode* m) { _align_to_ref = m; } const Node* ctrl(const Node* n) const { return _phase->has_ctrl(n) ? _phase->get_ctrl(n) : n; } @@ -360,8 +361,8 @@ class SuperWord : public ResourceObj { void set_depth(Node* n, int d) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_depth = d; } // vector element type - const Type* velt_type(Node* n) { return _node_info.adr_at(bb_idx(n))->_velt_type; } - BasicType velt_basic_type(Node* n) { return velt_type(n)->array_element_basic_type(); } + const Type* velt_type(const Node* n) const { return _node_info.adr_at(bb_idx(n))->_velt_type; } + BasicType velt_basic_type(const Node* n) const { return velt_type(n)->array_element_basic_type(); } void set_velt_type(Node* n, const Type* t) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_velt_type = t; } bool same_velt_type(Node* n1, Node* n2); bool same_memory_slice(MemNode* best_align_to_mem_ref, MemNode* mem_ref) const; @@ -441,21 +442,10 @@ class SuperWord : public ResourceObj { bool SLP_extract(); // Find the adjacent memory references and create pack pairs for them. void find_adjacent_refs(); - // Tracing support - #ifndef PRODUCT - void find_adjacent_refs_trace_1(Node* best_align_to_mem_ref, int best_iv_adjustment); - #endif - // If strict memory alignment is required (vectors_should_be_aligned), then check if - // mem_ref is aligned with best_align_to_mem_ref. - bool mem_ref_has_no_alignment_violation(MemNode* mem_ref, int iv_adjustment, VPointer& align_to_ref_p, - MemNode* best_align_to_mem_ref, int best_iv_adjustment, - Node_List &align_to_refs); // Find a memory reference to align the loop induction variable to. MemNode* find_align_to_ref(Node_List &memops, int &idx); // Calculate loop's iv adjustment for this memory ops. int get_iv_adjustment(MemNode* mem); - // Can the preloop align the reference to position zero in the vector? - bool ref_is_alignable(VPointer& p); // Construct dependency graph. void dependence_graph(); // Return a memory slice (node list) in predecessor order starting at "start" @@ -497,6 +487,12 @@ class SuperWord : public ResourceObj { int unpack_cost(int ct); // Combine packs A and B with A.last == B.first into A.first..,A.last,B.second,..B.last void combine_packs(); + // Ensure all packs are aligned, if AlignVector is on. + void filter_packs_for_alignment(); + // Find the set of alignment solutions for load/store pack. + const AlignmentSolution* pack_alignment_solution(Node_List* pack); + // Compress packset, such that it has no nullptr entries. + void compress_packset(); // Construct the map from nodes to packs. void construct_my_pack_map(); // Remove packs that are not implemented or not profitable. @@ -544,9 +540,8 @@ class SuperWord : public ResourceObj { int memory_alignment(MemNode* s, int iv_adjust); // Smallest type containing range of values const Type* container_type(Node* n); - // Adjust pre-loop limit so that in main loop, a load/store reference - // to align_to_ref will be a position zero in the vector. - void align_initial_loop_index(MemNode* align_to_ref); + // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. + void adjust_pre_loop_limit_to_align_main_loop_vectors(); // Is the use of d1 in u1 at the same operand position as d2 in u2? bool opnd_positions_match(Node* d1, Node* u1, Node* d2, Node* u2); void init(); diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index 7158f40092928..4794140ab0e45 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -35,7 +35,8 @@ int VPointer::Tracer::_depth = 0; #endif -VPointer::VPointer(MemNode* mem, PhaseIdealLoop* phase, IdealLoopTree* lpt, +VPointer::VPointer(const MemNode* mem, + PhaseIdealLoop* phase, IdealLoopTree* lpt, Node_Stack* nstack, bool analyze_only) : _mem(mem), _phase(phase), _lpt(lpt), _iv(lpt->_head->as_CountedLoop()->phi()->as_Phi()), @@ -119,6 +120,22 @@ VPointer::VPointer(VPointer* p) : #endif {} +// Biggest detectable factor of the invariant. +int VPointer::invar_factor() const { + Node* n = invar(); + if (n == nullptr) { + return 0; + } + int opc = n->Opcode(); + if (opc == Op_LShiftI && n->in(2)->is_Con()) { + return 1 << n->in(2)->get_int(); + } else if (opc == Op_LShiftL && n->in(2)->is_Con()) { + return 1 << n->in(2)->get_int(); + } + // All our best-effort has failed. + return 1; +} + bool VPointer::is_loop_member(Node* n) const { Node* n_c = phase()->get_ctrl(n); return lpt()->is_member(phase()->get_loop(n_c)); @@ -417,7 +434,7 @@ void VPointer::Tracer::print_depth() const { } } -void VPointer::Tracer::ctor_1(Node* mem) { +void VPointer::Tracer::ctor_1(const Node* mem) { if (_is_trace_alignment) { print_depth(); tty->print(" %d VPointer::VPointer: start alignment analysis", mem->_idx); mem->dump(); } @@ -459,7 +476,7 @@ void VPointer::Tracer::ctor_5(Node* adr, Node* base, int i) { } } -void VPointer::Tracer::ctor_6(Node* mem) { +void VPointer::Tracer::ctor_6(const Node* mem) { if (_is_trace_alignment) { //restore_depth(); print_depth(); tty->print_cr(" %d (adr) VPointer::VPointer: stop analysis", mem->_idx); @@ -685,5 +702,655 @@ void VPointer::Tracer::offset_plus_k_11(Node* n) { print_depth(); tty->print_cr(" %d VPointer::offset_plus_k: FAILED", n->_idx); } } +#endif + + +AlignmentSolution* AlignmentSolver::solve() const { + DEBUG_ONLY( trace_start_solve(); ) + + // Out of simplicity: non power-of-2 stride not supported. + if (!is_power_of_2(abs(_pre_stride))) { + return new EmptyAlignmentSolution("non power-of-2 stride not supported"); + } + assert(is_power_of_2(abs(_main_stride)), "main_stride is power of 2"); + assert(_aw > 0 && is_power_of_2(_aw), "aw must be power of 2"); + + // Out of simplicity: non power-of-2 scale not supported. + if (abs(_scale) == 0 || !is_power_of_2(abs(_scale))) { + return new EmptyAlignmentSolution("non power-of-2 scale not supported"); + } + + // We analyze the address of mem_ref. The idea is to disassemble it into a linear + // expression, where we can use the constant factors as the basis for ensuring the + // alignment of vector memory accesses. + // + // The Simple form of the address is disassembled by VPointer into: + // + // adr = base + offset + invar + scale * iv + // + // Where the iv can be written as: + // + // iv = init + pre_stride * pre_iter + main_stride * main_iter + // + // init: value before pre-loop + // pre_stride: increment per pre-loop iteration + // pre_iter: number of pre-loop iterations (adjustable via pre-loop limit) + // main_stride: increment per main-loop iteration (= pre_stride * unroll_factor) + // main_iter: number of main-loop iterations (main_iter >= 0) + // + // In the following, we restate the Simple form of the address expression, by first + // expanding the iv variable. In a second step, we reshape the expression again, and + // state it as a linear expression, consisting of 6 terms. + // + // Simple form Expansion of iv variable Reshaped with constants Comments for terms + // ----------- ------------------------ ----------------------- ------------------ + // adr = base = base = base (base % aw = 0) + // + offset + offset + C_const (sum of constant terms) + // + invar + invar_factor * var_invar + C_invar * var_invar (term for invariant) + // / + scale * init + C_init * var_init (term for variable init) + // + scale * iv -> | + scale * pre_stride * pre_iter + C_pre * pre_iter (adjustable pre-loop term) + // \ + scale * main_stride * main_iter + C_main * main_iter (main-loop term) + // + // We describe the 6 terms: + // 1) The "base" of the address is the address of a Java object (e.g. array), + // and as such ObjectAlignmentInBytes (a power of 2) aligned. We have + // defined aw = MIN(vector_width, ObjectAlignmentInBytes), which is also + // a power of 2. And hence we know that "base" is thus also aw-aligned: + // + // base % ObjectAlignmentInBytes = 0 ==> base % aw = 0 + // + // 2) The "C_const" term is the sum of all constant terms. This is "offset", + // plus "scale * init" if it is constant. + // 3) The "C_invar * var_invar" is the factorization of "invar" into a constant + // and variable term. If there is no invariant, then "C_invar" is zero. + // + // invar = C_invar * var_invar (FAC_INVAR) + // + // 4) The "C_init * var_init" is the factorization of "scale * init" into a + // constant and a variable term. If "init" is constant, then "C_init" is + // zero, and "C_const" accounts for "init" instead. + // + // scale * init = C_init * var_init + scale * C_const_init (FAC_INIT) + // C_init = (init is constant) ? 0 : scale + // C_const_init = (init is constant) ? init : 0 + // + // 5) The "C_pre * pre_iter" term represents how much the iv is incremented + // during the "pre_iter" pre-loop iterations. This term can be adjusted + // by changing the pre-loop limit, which defines how many pre-loop iterations + // are executed. This allows us to adjust the alignment of the main-loop + // memory reference. + // 6) The "C_main * main_iter" term represents how much the iv is increased + // during "main_iter" main-loop iterations. + + // Attribute init (i.e. _init_node) either to C_const or to C_init term. + const int C_const_init = _init_node->is_ConI() ? _init_node->as_ConI()->get_int() : 0; + const int C_const = _offset + C_const_init * _scale; + + // Set C_invar depending on if invar is present + const int C_invar = (_invar == nullptr) ? 0 : abs(_invar_factor); + + const int C_init = _init_node->is_ConI() ? 0 : _scale; + const int C_pre = _scale * _pre_stride; + const int C_main = _scale * _main_stride; + + DEBUG_ONLY( trace_reshaped_form(C_const, C_const_init, C_invar, C_init, C_pre, C_main); ) + + // We must find a pre_iter, such that adr is aw aligned: adr % aw = 0. Note, that we are defining the + // modulo operator "%" such that the remainder is always positive, see AlignmentSolution::mod(i, q). + // + // Since "base % aw = 0", we only need to ensure alignment of the other 5 terms: + // + // (C_const + C_invar * var_invar + C_init * var_init + C_pre * pre_iter + C_main * main_iter) % aw = 0 (1) + // + // Alignment must be maintained over all main-loop iterations, i.e. for any main_iter >= 0, we require: + // + // C_main % aw = 0 (2) + // + const int C_main_mod_aw = AlignmentSolution::mod(C_main, _aw); + + DEBUG_ONLY( trace_main_iteration_alignment(C_const, C_invar, C_init, C_pre, C_main, C_main_mod_aw); ) + + if (C_main_mod_aw != 0) { + return new EmptyAlignmentSolution("EQ(2) not satisfied (cannot align across main-loop iterations)"); + } + + // In what follows, we need to show that the C_const, init and invar terms can be aligned by + // adjusting the pre-loop iteration count (pre_iter), which is controlled by the pre-loop + // limit. + // + // (C_const + C_invar * var_invar + C_init * var_init + C_pre * pre_iter) % aw = 0 (3) + // + // We strengthen the constraints by splitting the equation into 3 equations, where we + // want to find integer solutions for pre_iter_C_const, pre_iter_C_invar, and + // pre_iter_C_init, which means that the C_const, init and invar terms can be aligned + // independently: + // + // (C_const + C_pre * pre_iter_C_const) % aw = 0 (4a) + // (C_invar * var_invar + C_pre * pre_iter_C_invar) % aw = 0 (4b) + // (C_init * var_init + C_pre * pre_iter_C_init ) % aw = 0 (4c) + // + // We now prove that (4a, b, c) are sufficient as well as necessary to guarantee (3) + // for any runtime value of var_invar and var_init (i.e. for any invar and init). + // This tells us that the "strengthening" does not restrict the algorithm more than + // necessary. + // + // Sufficient (i.e (4a, b, c) imply (3)): + // + // pre_iter = pre_iter_C_const + pre_iter_C_invar + pre_iter_C_init + // + // Adding up (4a, b, c): + // + // 0 = ( C_const + C_pre * pre_iter_C_const + // + C_invar * var_invar + C_pre * pre_iter_C_invar + // + C_init * var_init + C_pre * pre_iter_C_init ) % aw + // + // = ( C_const + C_invar * var_invar + C_init * var_init + // + C_pre * (pre_iter_C_const + pre_iter_C_invar + pre_iter_C_init)) % aw + // + // = ( C_const + C_invar * var_invar + C_init * var_init + // + C_pre * pre_iter) % aw + // + // Necessary (i.e. (3) implies (4a, b, c)): + // (4a): Set var_invar = var_init = 0 at runtime. Applying this to (3), we get: + // + // 0 = + // = (C_const + C_invar * var_invar + C_init * var_init + C_pre * pre_iter) % aw + // = (C_const + C_invar * 0 + C_init * 0 + C_pre * pre_iter) % aw + // = (C_const + C_pre * pre_iter) % aw + // + // This is of the same form as (4a), and we have a solution: + // pre_iter_C_const = pre_iter + // + // (4b): Set var_init = 0, and assume (4a), which we just proved is implied by (3). + // Subtract (4a) from (3): + // + // 0 = + // = (C_const + C_invar * var_invar + C_init * var_init + C_pre * pre_iter) % aw + // - (C_const + C_pre * pre_iter_C_const) % aw + // = (C_invar * var_invar + C_init * var_init + C_pre * pre_iter - C_pre * pre_iter_C_const) % aw + // = (C_invar * var_invar + C_init * 0 + C_pre * (pre_iter - pre_iter_C_const)) % aw + // = (C_invar * var_invar + + C_pre * (pre_iter - pre_iter_C_const)) % aw + // + // This is of the same form as (4b), and we have a solution: + // pre_iter_C_invar = pre_iter - pre_iter_C_const + // + // (4c): Set var_invar = 0, and assume (4a), which we just proved is implied by (3). + // Subtract (4a) from (3): + // + // 0 = + // = (C_const + C_invar * var_invar + C_init * var_init + C_pre * pre_iter) % aw + // - (C_const + C_pre * pre_iter_C_const) % aw + // = (C_invar * var_invar + C_init * var_init + C_pre * pre_iter - C_pre * pre_iter_C_const) % aw + // = (C_invar * 0 + C_init * var_init + C_pre * (pre_iter - pre_iter_C_const)) % aw + // = ( + C_init * var_init + C_pre * (pre_iter - pre_iter_C_const)) % aw + // + // This is of the same form as (4c), and we have a solution: + // pre_iter_C_invar = pre_iter - pre_iter_C_const + // + // The solutions of Equations (4a, b, c) for pre_iter_C_const, pre_iter_C_invar, and pre_iter_C_init + // respectively, can have one of these states: + // + // trivial: The solution can be any integer. + // constrained: There is a (periodic) solution, but it is not trivial. + // empty: Statically we cannot guarantee a solution for all var_invar and var_init. + // + // We look at (4a): + // + // abs(C_pre) >= aw + // -> Since abs(C_pre) is a power of two, we have C_pre % aw = 0. Therefore: + // + // For any pre_iter_C_const: (C_pre * pre_iter_C_const) % aw = 0 + // + // (C_const + C_pre * pre_iter_C_const) % aw = 0 + // C_const % aw = 0 + // + // Hence, we can only satisfy (4a) if C_Const is aw aligned: + // + // C_const % aw == 0: + // -> (4a) has a trivial solution since we can choose any value for pre_iter_C_const. + // + // C_const % aw != 0: + // -> (4a) has an empty solution since no pre_iter_C_const can achieve aw alignment. + // + // abs(C_pre) < aw: + // -> Since both abs(C_pre) and aw are powers of two, we know: + // + // There exists integer x > 1: aw = abs(C_pre) * x + // + // C_const % abs(C_pre) == 0: + // -> There exists integer z: C_const = C_pre * z + // + // (C_const + C_pre * pre_iter_C_const) % aw = 0 + // ==> + // (C_pre * z + C_pre * pre_iter_C_const) % aw = 0 + // ==> + // (C_pre * z + C_pre * pre_iter_C_const) % (abs(C_pre) * x) = 0 + // ==> + // ( z + pre_iter_C_const) % x = 0 + // ==> + // for any m: pre_iter_C_const = m * x - z + // + // Hence, pre_iter_C_const has a non-trivial (because x > 1) periodic (periodicity x) + // solution, i.e. it has a constrained solution. + // + // C_const % abs(C_pre) != 0: + // There exists integer x > 1: aw = abs(C_pre) * x + // + // C_const % abs(C_pre) != 0 + // ==> + // (C_const + C_pre * pre_iter_C_const) % abs(C_pre) != 0 + // ==> + // (C_const + C_pre * pre_iter_C_const) % (abs(C_pre) * x) != 0 + // ==> + // (C_const + C_pre * pre_iter_C_const) % aw != 0 + // + // This is in contradiction with (4a), and therefore there cannot be any solution, + // i.e. we have an empty solution. + // + // In summary, for (4a): + // + // abs(C_pre) >= aw AND C_const % aw == 0 -> trivial + // abs(C_pre) >= aw AND C_const % aw != 0 -> empty + // abs(C_pre) < aw AND C_const % abs(C_pre) == 0 -> constrained + // abs(C_pre) < aw AND C_const % abs(C_pre) != 0 -> empty + // + // With analogue argumentation for (4b): + // + // abs(C_pre) >= aw AND C_invar % aw == 0 -> trivial + // abs(C_pre) >= aw AND C_invar % aw != 0 -> empty + // abs(C_pre) < aw AND C_invar % abs(C_pre) == 0 -> constrained + // abs(C_pre) < aw AND C_invar % abs(C_pre) != 0 -> empty + // + // With analogue argumentation for (4c): + // + // abs(C_pre) >= aw AND C_init % aw == 0 -> trivial + // abs(C_pre) >= aw AND C_init % aw != 0 -> empty + // abs(C_pre) < aw AND C_init % abs(C_pre) == 0 -> constrained + // abs(C_pre) < aw AND C_init % abs(C_pre) != 0 -> empty + // + // Out of these states follows the state for the solution of pre_iter: + // + // Trivial: If (4a, b, c) are all trivial. + // Empty: If any of (4a, b, c) is empty, because then we cannot guarantee a solution + // for pre_iter, for all possible invar and init values. + // Constrained: Else. Incidentally, (4a, b, c) are all constrained themselves, as we argue below. + + const EQ4 eq4(C_const, C_invar, C_init, C_pre, _aw); + const EQ4::State eq4a_state = eq4.eq4a_state(); + const EQ4::State eq4b_state = eq4.eq4b_state(); + const EQ4::State eq4c_state = eq4.eq4c_state(); + +#ifdef ASSERT + if (is_trace()) { + eq4.trace(); + } +#endif + + // If (4a, b, c) are all trivial, then also the solution for pre_iter is trivial: + if (eq4a_state == EQ4::State::TRIVIAL && + eq4b_state == EQ4::State::TRIVIAL && + eq4c_state == EQ4::State::TRIVIAL) { + return new TrivialAlignmentSolution(); + } + + // If any of (4a, b, c) is empty, then we also cannot guarantee a solution for pre_iter, for + // any init and invar, hence the solution for pre_iter is empty: + if (eq4a_state == EQ4::State::EMPTY || + eq4b_state == EQ4::State::EMPTY || + eq4c_state == EQ4::State::EMPTY) { + return new EmptyAlignmentSolution("EQ(4a, b, c) not all non-empty: cannot align const, invar and init terms individually"); + } + + // If abs(C_pre) >= aw, then the solutions to (4a, b, c) are all either trivial or empty, and + // hence we would have found the solution to pre_iter above as either trivial or empty. Thus + // we now know that: + // + // abs(C_pre) < aw + // + assert(abs(C_pre) < _aw, "implied by constrained case"); + + // And since abs(C_pre) < aw, the solutions of (4a, b, c) can now only be constrained or empty. + // But since we already handled the empty case, the solutions are now all constrained. + assert(eq4a_state == EQ4::State::CONSTRAINED && + eq4a_state == EQ4::State::CONSTRAINED && + eq4a_state == EQ4::State::CONSTRAINED, "all must be constrained now"); + + // And since they are all constrained, we must have: + // + // C_const % abs(C_pre) = 0 (5a) + // C_invar % abs(C_pre) = 0 (5b) + // C_init % abs(C_pre) = 0 (5c) + // + assert(AlignmentSolution::mod(C_const, abs(C_pre)) == 0, "EQ(5a): C_const must be alignable"); + assert(AlignmentSolution::mod(C_invar, abs(C_pre)) == 0, "EQ(5b): C_invar must be alignable"); + assert(AlignmentSolution::mod(C_init, abs(C_pre)) == 0, "EQ(5c): C_init must be alignable"); + + // With (5a, b, c), we know that there are integers X, Y, Z: + // + // C_const = X * abs(C_pre) ==> X = C_const / abs(C_pre) (6a) + // C_invar = Y * abs(C_pre) ==> Y = C_invar / abs(C_pre) (6b) + // C_init = Z * abs(C_pre) ==> Z = C_init / abs(C_pre) (6c) + // + // Further, we define: + // + // sign(C_pre) = C_pre / abs(C_pre) = (C_pre > 0) ? 1 : -1, (7) + // + // We know that abs(C_pre) as well as aw are powers of 2, and since (5) we can define integer q: + // + // q = aw / abs(C_pre) (8) + // + const int q = _aw / abs(C_pre); + + assert(q >= 2, "implied by constrained solution"); + + // We now know that all terms in (4a, b, c) are divisible by abs(C_pre): + // + // (C_const / abs(C_pre) + C_pre * pre_iter_C_const / abs(C_pre)) % (aw / abs(C_pre)) = + // (X * abs(C_pre) / abs(C_pre) + C_pre * pre_iter_C_const / abs(C_pre)) % (aw / abs(C_pre)) = + // (X + pre_iter_C_const * sign(C_pre)) % q = 0 (9a) + // + // -> pre_iter_C_const * sign(C_pre) = mx1 * q - X + // -> pre_iter_C_const = mx2 * q - sign(C_pre) * X (10a) + // (for any integers mx1, mx2) + // + // (C_invar * var_invar / abs(C_pre) + C_pre * pre_iter_C_invar / abs(C_pre)) % (aw / abs(C_pre)) = + // (Y * abs(C_pre) * var_invar / abs(C_pre) + C_pre * pre_iter_C_invar / abs(C_pre)) % (aw / abs(C_pre)) = + // (Y * var_invar + pre_iter_C_invar * sign(C_pre)) % q = 0 (9b) + // + // -> pre_iter_C_invar * sign(C_pre) = my1 * q - Y * var_invar + // -> pre_iter_C_invar = my2 * q - sign(C_pre) * Y * var_invar (10b) + // (for any integers my1, my2) + // + // (C_init * var_init / abs(C_pre) + C_pre * pre_iter_C_init / abs(C_pre)) % (aw / abs(C_pre)) = + // (Z * abs(C_pre) * var_init / abs(C_pre) + C_pre * pre_iter_C_init / abs(C_pre)) % (aw / abs(C_pre)) = + // (Z * var_init + pre_iter_C_init * sign(C_pre)) % q = 0 (9c) + // + // -> pre_iter_C_init * sign(C_pre) = mz1 * q - Z * var_init + // -> pre_iter_C_init = mz2 * q - sign(C_pre) * Z * var_init (10c) + // (for any integers mz1, mz2) + // + // + // Having solved the equations using the division, we can re-substitute X, Y, and Z, and apply (FAC_INVAR) as + // well as (FAC_INIT). We use the fact that sign(x) == 1 / sign(x) and sign(x) * abs(x) == x: + // + // pre_iter_C_const = mx2 * q - sign(C_pre) * X + // = mx2 * q - sign(C_pre) * C_const / abs(C_pre) + // = mx2 * q - C_const / C_pre + // = mx2 * q - C_const / (scale * pre_stride) (11a) + // + // If there is an invariant: + // + // pre_iter_C_invar = my2 * q - sign(C_pre) * Y * var_invar + // = my2 * q - sign(C_pre) * C_invar * var_invar / abs(C_pre) + // = my2 * q - sign(C_pre) * invar / abs(C_pre) + // = my2 * q - invar / C_pre + // = my2 * q - invar / (scale * pre_stride) (11b, with invar) + // + // If there is no invariant (i.e. C_invar = 0 ==> Y = 0): + // + // pre_iter_C_invar = my2 * q (11b, no invar) + // + // If init is variable (i.e. C_init = scale, init = var_init): + // + // pre_iter_C_init = mz2 * q - sign(C_pre) * Z * var_init + // = mz2 * q - sign(C_pre) * C_init * var_init / abs(C_pre) + // = mz2 * q - sign(C_pre) * scale * init / abs(C_pre) + // = mz2 * q - scale * init / C_pre + // = mz2 * q - scale * init / (scale * pre_stride) + // = mz2 * q - init / pre_stride (11c, variable init) + // + // If init is constant (i.e. C_init = 0 ==> Z = 0): + // + // pre_iter_C_init = mz2 * q (11c, constant init) + // + // Note, that the solutions found by (11a, b, c) are all periodic with periodicity q. We combine them, + // with m = mx2 + my2 + mz2: + // + // pre_iter = pre_iter_C_const + pre_iter_C_invar + pre_iter_C_init + // = mx2 * q - C_const / (scale * pre_stride) + // + my2 * q [- invar / (scale * pre_stride) ] + // + mz2 * q [- init / pre_stride ] + // + // = m * q (periodic part) + // - C_const / (scale * pre_stride) (align constant term) + // [- invar / (scale * pre_stride) ] (align invariant term, if present) + // [- init / pre_stride ] (align variable init term, if present) (12) + // + // We can further simplify this solution by introducing integer 0 <= r < q: + // + // r = (-C_const / (scale * pre_stride)) % q (13) + // + const int r = AlignmentSolution::mod(-C_const / (_scale * _pre_stride), q); + // + // pre_iter = m * q + r + // [- invar / (scale * pre_stride) ] + // [- init / pre_stride ] (14) + // + // We thus get a solution that can be stated in terms of: + // + // q (periodicity), r (constant alignment), invar, scale, pre_stride, init + // + // However, pre_stride and init are shared by all mem_ref in the loop, hence we do not need to provide + // them in the solution description. + + DEBUG_ONLY( trace_constrained_solution(C_const, C_invar, C_init, C_pre, q, r); ) + + return new ConstrainedAlignmentSolution(_mem_ref, q, r, _invar, _scale); + + // APPENDIX: + // We can now verify the success of the solution given by (12): + // + // adr % aw = + // + // -> Simple form + // (base + offset + invar + scale * iv) % aw = + // + // -> Expand iv + // (base + offset + invar + scale * (init + pre_stride * pre_iter + main_stride * main_iter)) % aw = + // + // -> Reshape + // (base + offset + invar + // + scale * init + // + scale * pre_stride * pre_iter + // + scale * main_stride * main_iter)) % aw = + // + // -> base aligned: base % aw = 0 + // -> main-loop iterations aligned (2): C_main % aw = (scale * main_stride) % aw = 0 + // (offset + invar + scale * init + scale * pre_stride * pre_iter) % aw = + // + // -> apply (12) + // (offset + invar + scale * init + // + scale * pre_stride * (m * q - C_const / (scale * pre_stride) + // [- invar / (scale * pre_stride) ] + // [- init / pre_stride ] + // ) + // ) % aw = + // + // -> expand C_const = offset [+ init * scale] (if init const) + // (offset + invar + scale * init + // + scale * pre_stride * (m * q - offset / (scale * pre_stride) + // [- init / pre_stride ] (if init constant) + // [- invar / (scale * pre_stride) ] (if invar present) + // [- init / pre_stride ] (if init variable) + // ) + // ) % aw = + // + // -> assuming invar = 0 if it is not present + // -> merge the two init terms (variable or constant) + // -> apply (8): q = aw / (abs(C_pre)) = aw / abs(scale * pre_stride) + // -> and hence: (scale * pre_stride * q) % aw = 0 + // -> all terms are canceled out + // (offset + invar + scale * init + // + scale * pre_stride * m * q -> aw aligned + // - scale * pre_stride * offset / (scale * pre_stride) -> = offset + // - scale * pre_stride * init / pre_stride -> = scale * init + // - scale * pre_stride * invar / (scale * pre_stride) -> = invar + // ) % aw = 0 + // + // The solution given by (12) does indeed guarantee alignment. +} +#ifdef ASSERT +void print_con_or_idx(const Node* n) { + if (n == nullptr) { + tty->print("(0)"); + } else if (n->is_ConI()) { + jint val = n->as_ConI()->get_int(); + tty->print("(%d)", val); + } else { + tty->print("[%d]", n->_idx); + } +} + +void AlignmentSolver::trace_start_solve() const { + if (is_trace()) { + tty->print(" vector mem_ref:"); + _mem_ref->dump(); + tty->print_cr(" vector_width = vector_length(%d) * element_size(%d) = %d", + _vector_length, _element_size, _vector_width); + tty->print_cr(" aw = alignment_width = min(vector_width(%d), ObjectAlignmentInBytes(%d)) = %d", + _vector_width, ObjectAlignmentInBytes, _aw); + + if (!_init_node->is_ConI()) { + tty->print(" init:"); + _init_node->dump(); + } + + if (_invar != nullptr) { + tty->print(" invar:"); + _invar->dump(); + } + + tty->print_cr(" invar_factor = %d", _invar_factor); + + // iv = init + pre_iter * pre_stride + main_iter * main_stride + tty->print(" iv = init"); + print_con_or_idx(_init_node); + tty->print_cr(" + pre_iter * pre_stride(%d) + main_iter * main_stride(%d)", + _pre_stride, _main_stride); + + // adr = base + offset + invar + scale * iv + tty->print(" adr = base"); + print_con_or_idx(_base); + tty->print(" + offset(%d) + invar", _offset); + print_con_or_idx(_invar); + tty->print_cr(" + scale(%d) * iv", _scale); + } +} + +void AlignmentSolver::trace_reshaped_form(const int C_const, + const int C_const_init, + const int C_invar, + const int C_init, + const int C_pre, + const int C_main) const +{ + if (is_trace()) { + tty->print(" = base[%d] + ", _base->_idx); + tty->print_cr("C_const(%d) + C_invar(%d) * var_invar + C_init(%d) * var_init + C_pre(%d) * pre_iter + C_main(%d) * main_iter", + C_const, C_invar, C_init, C_pre, C_main); + if (_init_node->is_ConI()) { + tty->print_cr(" init is constant:"); + tty->print_cr(" C_const_init = %d", C_const_init); + tty->print_cr(" C_init = %d", C_init); + } else { + tty->print_cr(" init is variable:"); + tty->print_cr(" C_const_init = %d", C_const_init); + tty->print_cr(" C_init = abs(scale)= %d", C_init); + } + if (_invar != nullptr) { + tty->print_cr(" invariant present:"); + tty->print_cr(" C_invar = abs(invar_factor) = %d", C_invar); + } else { + tty->print_cr(" no invariant:"); + tty->print_cr(" C_invar = %d", C_invar); + } + tty->print_cr(" C_const = offset(%d) + scale(%d) * C_const_init(%d) = %d", + _offset, _scale, C_const_init, C_const); + tty->print_cr(" C_pre = scale(%d) * pre_stride(%d) = %d", + _scale, _pre_stride, C_pre); + tty->print_cr(" C_main = scale(%d) * main_stride(%d) = %d", + _scale, _main_stride, C_main); + } +} + +void AlignmentSolver::trace_main_iteration_alignment(const int C_const, + const int C_invar, + const int C_init, + const int C_pre, + const int C_main, + const int C_main_mod_aw) const +{ + if (is_trace()) { + tty->print(" EQ(1 ): (C_const(%d) + C_invar(%d) * var_invar + C_init(%d) * var_init", + C_const, C_invar, C_init); + tty->print(" + C_pre(%d) * pre_iter + C_main(%d) * main_iter) %% aw(%d) = 0", + C_pre, C_main, _aw); + tty->print_cr(" (given base aligned -> align rest)"); + tty->print(" EQ(2 ): C_main(%d) %% aw(%d) = %d = 0", + C_main, _aw, C_main_mod_aw); + tty->print_cr(" (alignment across iterations)"); + } +} + +void AlignmentSolver::EQ4::trace() const { + tty->print_cr(" EQ(4a): (C_const(%3d) + C_pre(%d) * pre_iter_C_const) %% aw(%d) = 0 (align const term individually)", + _C_const, _C_pre, _aw); + tty->print_cr(" -> %s", state_to_str(eq4a_state())); + + tty->print_cr(" EQ(4b): (C_invar(%3d) * var_invar + C_pre(%d) * pre_iter_C_invar) %% aw(%d) = 0 (align invar term individually)", + _C_invar, _C_pre, _aw); + tty->print_cr(" -> %s", state_to_str(eq4b_state())); + + tty->print_cr(" EQ(4c): (C_init( %3d) * var_init + C_pre(%d) * pre_iter_C_init ) %% aw(%d) = 0 (align init term individually)", + _C_init, _C_pre, _aw); + tty->print_cr(" -> %s", state_to_str(eq4c_state())); +} + +void AlignmentSolver::trace_constrained_solution(const int C_const, + const int C_invar, + const int C_init, + const int C_pre, + const int q, + const int r) const +{ + if (is_trace()) { + tty->print_cr(" EQ(4a, b, c) all constrained, hence:"); + tty->print_cr(" EQ(5a): C_const(%3d) %% abs(C_pre(%d)) = 0", C_const, C_pre); + tty->print_cr(" EQ(5b): C_invar(%3d) %% abs(C_pre(%d)) = 0", C_invar, C_pre); + tty->print_cr(" EQ(5c): C_init( %3d) %% abs(C_pre(%d)) = 0", C_init, C_pre); + + tty->print_cr(" All terms in EQ(4a, b, c) are divisible by abs(C_pre(%d)).", C_pre); + const int X = C_const / abs(C_pre); + const int Y = C_invar / abs(C_pre); + const int Z = C_init / abs(C_pre); + const int sign = (C_pre > 0) ? 1 : -1; + tty->print_cr(" X = C_const(%3d) / abs(C_pre(%d)) = %d (6a)", C_const, C_pre, X); + tty->print_cr(" Y = C_invar(%3d) / abs(C_pre(%d)) = %d (6b)", C_invar, C_pre, Y); + tty->print_cr(" Z = C_init( %3d) / abs(C_pre(%d)) = %d (6c)", C_init , C_pre, Z); + tty->print_cr(" q = aw( %3d) / abs(C_pre(%d)) = %d (8)", _aw, C_pre, q); + tty->print_cr(" sign(C_pre) = (C_pre(%d) > 0) ? 1 : -1 = %d (7)", C_pre, sign); + + tty->print_cr(" EQ(9a): (X(%3d) + pre_iter_C_const * sign(C_pre)) %% q(%d) = 0", X, q); + tty->print_cr(" EQ(9b): (Y(%3d) * var_invar + pre_iter_C_invar * sign(C_pre)) %% q(%d) = 0", Y, q); + tty->print_cr(" EQ(9c): (Z(%3d) * var_init + pre_iter_C_init * sign(C_pre)) %% q(%d) = 0", Z, q); + + tty->print_cr(" EQ(10a): pre_iter_C_const = mx2 * q(%d) - sign(C_pre) * X(%d)", q, X); + tty->print_cr(" EQ(10b): pre_iter_C_invar = my2 * q(%d) - sign(C_pre) * Y(%d) * var_invar", q, Y); + tty->print_cr(" EQ(10c): pre_iter_C_init = mz2 * q(%d) - sign(C_pre) * Z(%d) * var_init ", q, Z); + + tty->print_cr(" r = (-C_const(%d) / (scale(%d) * pre_stride(%d)) %% q(%d) = %d", + C_const, _scale, _pre_stride, q, r); + + tty->print_cr(" EQ(14): pre_iter = m * q(%3d) - r(%d)", q, r); + if (_invar != nullptr) { + tty->print_cr(" - invar / (scale(%d) * pre_stride(%d))", + _scale, _pre_stride); + } + if (!_init_node->is_ConI()) { + tty->print_cr(" - init / pre_stride(%d)", + _pre_stride); + } + } +} #endif diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index 8df5d0c9a821f..8e63b40d5ac48 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,7 +36,7 @@ // operation in a counted loop for vectorizable analysis. class VPointer : public ArenaObj { protected: - MemNode* _mem; // My memory reference node + const MemNode* _mem; // My memory reference node PhaseIdealLoop* _phase; // PhaseIdealLoop handle IdealLoopTree* _lpt; // Current IdealLoopTree PhiNode* _iv; // The loop induction variable @@ -80,23 +80,27 @@ class VPointer : public ArenaObj { NotComparable = (Less | Greater | Equal) }; - VPointer(MemNode* mem, PhaseIdealLoop* phase, IdealLoopTree* lpt, - Node_Stack* nstack, bool analyze_only); + VPointer(const MemNode* mem, + PhaseIdealLoop* phase, IdealLoopTree* lpt, + Node_Stack* nstack, bool analyze_only); // Following is used to create a temporary object during // the pattern match of an address expression. VPointer(VPointer* p); - bool valid() { return _adr != nullptr; } - bool has_iv() { return _scale != 0; } + bool valid() const { return _adr != nullptr; } + bool has_iv() const { return _scale != 0; } - Node* base() { return _base; } - Node* adr() { return _adr; } - MemNode* mem() { return _mem; } - int scale_in_bytes() { return _scale; } - Node* invar() { return _invar; } - int offset_in_bytes() { return _offset; } - int memory_size() { return _mem->memory_size(); } - Node_Stack* node_stack() { return _nstack; } + Node* base() const { return _base; } + Node* adr() const { return _adr; } + const MemNode* mem() const { return _mem; } + int scale_in_bytes() const { return _scale; } + Node* invar() const { return _invar; } + int offset_in_bytes() const { return _offset; } + int memory_size() const { return _mem->memory_size(); } + Node_Stack* node_stack() const { return _nstack; } + + // Biggest detectable factor of the invariant. + int invar_factor() const; // Comparable? bool invar_equals(VPointer& q) { @@ -165,12 +169,12 @@ class VPointer : public ArenaObj { Tracer(bool is_trace_alignment) : _is_trace_alignment(is_trace_alignment) {} // tracing functions - void ctor_1(Node* mem); + void ctor_1(const Node* mem); void ctor_2(Node* adr); void ctor_3(Node* adr, int i); void ctor_4(Node* adr, int i); void ctor_5(Node* adr, Node* base, int i); - void ctor_6(Node* mem); + void ctor_6(const Node* mem); void scaled_iv_plus_offset_1(Node* n); void scaled_iv_plus_offset_2(Node* n); @@ -259,4 +263,419 @@ class VectorElementSizeStats { } }; +// When alignment is required, we must adjust the pre-loop iteration count pre_iter, +// such that the address is aligned for any main_iter >= 0: +// +// adr = base + offset + invar + scale * init +// + scale * pre_stride * pre_iter +// + scale * main_stride * main_iter +// +// The AlignmentSolver generates solutions of the following forms: +// 1. Empty: No pre_iter guarantees alignment. +// 2. Trivial: Any pre_iter guarantees alignment. +// 3. Constrained: There is a periodic solution, but it is not trivial. +// +// The Constrained solution is of the following form: +// +// pre_iter = m * q + r (for any integer m) +// [- invar / (scale * pre_stride) ] (if there is an invariant) +// [- init / pre_stride ] (if init is variable) +// +// The solution is periodic with periodicity q, which is guaranteed to be a power of 2. +// This periodic solution is "rotated" by three alignment terms: one for constants (r), +// one for the invariant (if present), and one for init (if it is variable). +// +// The "filter" method combines the solutions of two mem_refs, such that the new set of +// values for pre_iter guarantees alignment for both mem_refs. +// +class EmptyAlignmentSolution; +class TrivialAlignmentSolution; +class ConstrainedAlignmentSolution; + +class AlignmentSolution : public ResourceObj { +public: + virtual bool is_empty() const = 0; + virtual bool is_trivial() const = 0; + virtual bool is_constrained() const = 0; + + virtual const ConstrainedAlignmentSolution* as_constrained() const { + assert(is_constrained(), "must be constrained"); + return nullptr; + } + + // Implemented by each subclass + virtual const AlignmentSolution* filter(const AlignmentSolution* other) const = 0; + virtual void print() const = 0; + + // Compute modulo and ensure that we get a positive remainder + static int mod(int i, int q) { + assert(q >= 1, "modulo value must be large enough"); + + // Modulo operator: Get positive 0 <= r < q for positive i, but + // get negative 0 >= r > -q for negative i. + int r = i % q; + + // Make negative r into positive ones: + r = (r >= 0) ? r : r + q; + + assert(0 <= r && r < q, "remainder must fit in modulo space"); + return r; + } +}; + +class EmptyAlignmentSolution : public AlignmentSolution { +private: + const char* _reason; +public: + EmptyAlignmentSolution(const char* reason) : _reason(reason) {} + virtual bool is_empty() const override final { return true; } + virtual bool is_trivial() const override final { return false; } + virtual bool is_constrained() const override final { return false; } + const char* reason() const { return _reason; } + + virtual const AlignmentSolution* filter(const AlignmentSolution* other) const override final { + // If "this" cannot be guaranteed to be aligned, then we also cannot guarantee to align + // "this" and "other" together. + return new EmptyAlignmentSolution("empty solution input to filter"); + } + + virtual void print() const override final { + tty->print_cr("empty solution: %s", reason()); + }; +}; + +class TrivialAlignmentSolution : public AlignmentSolution { +public: + TrivialAlignmentSolution() {} + virtual bool is_empty() const override final { return false; } + virtual bool is_trivial() const override final { return true; } + virtual bool is_constrained() const override final { return false; } + + virtual const AlignmentSolution* filter(const AlignmentSolution* other) const override final { + if (other->is_empty()) { + // If "other" cannot be guaranteed to be aligned, then we also cannot guarantee to align + // "this" and "other". + return new EmptyAlignmentSolution("empty solution input to filter"); + } + // Since "this" is trivial (no constraints), the solution of "other" guarantees alignment + // of both. + return other; + } + + virtual void print() const override final { + tty->print_cr("pre_iter >= 0 (trivial)"); + }; +}; + +class ConstrainedAlignmentSolution : public AlignmentSolution { +private: + const MemNode* _mem_ref; + const int _q; + const int _r; + const Node* _invar; + const int _scale; +public: + ConstrainedAlignmentSolution(const MemNode* mem_ref, + const int q, + const int r, + const Node* invar, + int scale) : + _mem_ref(mem_ref), + _q(q), + _r(r), + _invar(invar), + _scale(scale) { + assert(q > 1 && is_power_of_2(q), "q must be power of 2"); + assert(0 <= r && r < q, "r must be in modulo space of q"); + assert(_mem_ref != nullptr, "must have mem_ref"); + } + + virtual bool is_empty() const override final { return false; } + virtual bool is_trivial() const override final { return false; } + virtual bool is_constrained() const override final { return true; } + + const MemNode* mem_ref() const { return _mem_ref; } + + virtual const ConstrainedAlignmentSolution* as_constrained() const override final { return this; } + + virtual const AlignmentSolution* filter(const AlignmentSolution* other) const override final { + if (other->is_empty()) { + // If "other" cannot be guaranteed to be aligned, then we also cannot guarantee to align + // "this" and "other" together. + return new EmptyAlignmentSolution("empty solution input to filter"); + } + // Since "other" is trivial (no constraints), the solution of "this" guarantees alignment + // of both. + if (other->is_trivial()) { + return this; + } + + // Both solutions are constrained: + ConstrainedAlignmentSolution const* s1 = this; + ConstrainedAlignmentSolution const* s2 = other->as_constrained(); + + // Thus, pre_iter is the intersection of two sets, i.e. constrained by these two equations, + // for any integers m1 and m2: + // + // pre_iter = m1 * q1 + r1 + // [- invar1 / (scale1 * pre_stride) ] + // [- init / pre_stride ] + // + // pre_iter = m2 * q2 + r2 + // [- invar2 / (scale2 * pre_stride) ] + // [- init / pre_stride ] + // + // Note: pre_stride and init are identical for all mem_refs in the loop. + // + // The init alignment term either does not exist for both mem_refs, or exists identically + // for both. The init alignment term is thus trivially identical. + // + // The invar alignment term is identical if either: + // - both mem_refs have no invariant. + // - both mem_refs have the same invariant and the same scale. + // + if (s1->_invar != s2->_invar) { + return new EmptyAlignmentSolution("invar not identical"); + } + if (s1->_invar != nullptr && s1->_scale != s2->_scale) { + return new EmptyAlignmentSolution("has invar with different scale"); + } + + // Now, we have reduced the problem to: + // + // pre_iter = m1 * q1 + r1 [- x] (S1) + // pre_iter = m2 * q2 + r2 [- x] (S2) + // + + // Make s2 the bigger modulo space, i.e. has larger periodicity q. + // This guarantees that S2 is either identical to, a subset of, + // or disjunct from S1 (but cannot be a strict superset of S1). + if (s1->_q > s2->_q) { + swap(s1, s2); + } + assert(s1->_q <= s2->_q, "s1 is a smaller modulo space than s2"); + + // Is S2 subset of (or equal to) S1? + // + // for any m2, there are integers a, b, m1: m2 * q2 + r2 = + // m2 * a * q1 + b * q1 + r1 = + // (m2 * a + b) * q1 + r1 + // + // Since q1 and q2 are both powers of 2, and q1 <= q2, we know there + // is an integer a: a * q1 = q2. Thus, it remains to check if there + // is an integer b: b * q1 + r1 = r2. This is equivalent to checking: + // + // r1 = r1 % q1 = r2 % q1 + // + if (mod(s2->_r, s1->_q) != s1->_r) { + // Neither is subset of the other -> no intersection + return new EmptyAlignmentSolution("empty intersection (r and q)"); + } + + // Now we know: "s1 = m1 * q1 + r1" is a superset of "s2 = m2 * q2 + r2" + // Hence, any solution of S2 guarantees alignment for both mem_refs. + return s2; // return the subset + } + + virtual void print() const override final { + tty->print("m * q(%d) + r(%d)", _q, _r); + if (_invar != nullptr) { + tty->print(" - invar[%d] / (scale(%d) * pre_stride)", _invar->_idx, _scale); + } + tty->print_cr(" [- init / pre_stride], mem_ref[%d]", mem_ref()->_idx); + }; +}; + +// When strict alignment is required (e.g. -XX:+AlignVector), then we must ensure +// that all vector memory accesses can be aligned. We achieve this alignment by +// adjusting the pre-loop limit, which adjusts the number of iterations executed +// in the pre-loop. +// +// This is how the pre-loop and unrolled main-loop look like for a memref (adr): +// +// iv = init +// i = 0 // single-iteration counter +// +// pre-loop: +// iv = init + i * pre_stride +// adr = base + offset + invar + scale * iv +// adr = base + offset + invar + scale * (init + i * pre_stride) +// iv += pre_stride +// i++ +// +// pre_iter = i // number of iterations in the pre-loop +// iv = init + pre_iter * pre_stride +// +// main_iter = 0 // main-loop iteration counter +// main_stride = unroll_factor * pre_stride +// +// main-loop: +// i = pre_iter + main_iter * unroll_factor +// iv = init + i * pre_stride = init + pre_iter * pre_stride + main_iter * unroll_factor * pre_stride +// = init + pre_iter * pre_stride + main_iter * main_stride +// adr = base + offset + invar + scale * iv // must be aligned +// iv += main_stride +// i += unroll_factor +// main_iter++ +// +// For each vector memory access, we can find the set of pre_iter (number of pre-loop +// iterations) which would align its address. The AlignmentSolver finds such an +// AlignmentSolution. We can then check which solutions are compatible, and thus +// decide if we have to (partially) reject vectorization if not all vectors have +// a compatible solutions. +class AlignmentSolver { +private: + const MemNode* _mem_ref; // first element + const uint _vector_length; // number of elements in vector + const int _element_size; + const int _vector_width; // in bytes + + // All vector loads and stores need to be memory aligned. The alignment width (aw) in + // principle is the vector_width. But when vector_width > ObjectAlignmentInBytes this is + // too strict, since any memory object is only guaranteed to be ObjectAlignmentInBytes + // aligned. For example, the relative offset between two arrays is only guaranteed to + // be divisible by ObjectAlignmentInBytes. + const int _aw; + + // We analyze the address of mem_ref. The idea is to disassemble it into a linear + // expression, where we can use the constant factors as the basis for ensuring the + // alignment of vector memory accesses. + // + // The Simple form of the address is disassembled by VPointer into: + // + // adr = base + offset + invar + scale * iv + // + // Where the iv can be written as: + // + // iv = init + pre_stride * pre_iter + main_stride * main_iter + // + // pre_iter: number of pre-loop iterations (adjustable via pre-loop limit) + // main_iter: number of main-loop iterations (main_iter >= 0) + // + const Node* _base; // base of address (e.g. Java array object, aw-aligned) + const int _offset; + const Node* _invar; + const int _invar_factor; // known constant factor of invar + const int _scale; + const Node* _init_node; // value of iv before pre-loop + const int _pre_stride; // address increment per pre-loop iteration + const int _main_stride; // address increment per main-loop iteration + + DEBUG_ONLY( const bool _is_trace; ); + + static const MemNode* mem_ref_not_null(const MemNode* mem_ref) { + assert(mem_ref != nullptr, "not nullptr"); + return mem_ref; + } + +public: + AlignmentSolver(const MemNode* mem_ref, + const uint vector_length, + const Node* base, + const int offset, + const Node* invar, + const int invar_factor, + const int scale, + const Node* init_node, + const int pre_stride, + const int main_stride + DEBUG_ONLY( COMMA const bool is_trace) + ) : + _mem_ref( mem_ref_not_null(mem_ref)), + _vector_length( vector_length), + _element_size( _mem_ref->memory_size()), + _vector_width( _vector_length * _element_size), + _aw( MIN2(_vector_width, ObjectAlignmentInBytes)), + _base( base), + _offset( offset), + _invar( invar), + _invar_factor( invar_factor), + _scale( scale), + _init_node( init_node), + _pre_stride( pre_stride), + _main_stride( main_stride) + DEBUG_ONLY( COMMA _is_trace(is_trace) ) + { + assert(_mem_ref != nullptr && + (_mem_ref->is_Load() || _mem_ref->is_Store()), + "only load or store vectors allowed"); + } + + AlignmentSolution* solve() const; + +private: + class EQ4 { + private: + const int _C_const; + const int _C_invar; + const int _C_init; + const int _C_pre; + const int _aw; + + public: + EQ4(const int C_const, const int C_invar, const int C_init, const int C_pre, const int aw) : + _C_const(C_const), _C_invar(C_invar), _C_init(C_init), _C_pre(C_pre), _aw(aw) {} + + enum State { TRIVIAL, CONSTRAINED, EMPTY }; + + State eq4a_state() const { + return (abs(_C_pre) >= _aw) ? ( (C_const_mod_aw() == 0 ) ? TRIVIAL : EMPTY) + : ( (C_const_mod_abs_C_pre() == 0) ? CONSTRAINED : EMPTY); + } + + State eq4b_state() const { + return (abs(_C_pre) >= _aw) ? ( (C_invar_mod_aw() == 0 ) ? TRIVIAL : EMPTY) + : ( (C_invar_mod_abs_C_pre() == 0) ? CONSTRAINED : EMPTY); + } + + State eq4c_state() const { + return (abs(_C_pre) >= _aw) ? ( (C_init_mod_aw() == 0 ) ? TRIVIAL : EMPTY) + : ( (C_init_mod_abs_C_pre() == 0) ? CONSTRAINED : EMPTY); + } + + private: + int C_const_mod_aw() const { return AlignmentSolution::mod(_C_const, _aw); } + int C_invar_mod_aw() const { return AlignmentSolution::mod(_C_invar, _aw); } + int C_init_mod_aw() const { return AlignmentSolution::mod(_C_init, _aw); } + int C_const_mod_abs_C_pre() const { return AlignmentSolution::mod(_C_const, abs(_C_pre)); } + int C_invar_mod_abs_C_pre() const { return AlignmentSolution::mod(_C_invar, abs(_C_pre)); } + int C_init_mod_abs_C_pre() const { return AlignmentSolution::mod(_C_init, abs(_C_pre)); } + +#ifdef ASSERT + public: + void trace() const; + + private: + static const char* state_to_str(State s) { + if (s == TRIVIAL) { return "trivial"; } + if (s == CONSTRAINED) { return "constrained"; } + return "empty"; + } +#endif + }; + +#ifdef ASSERT + bool is_trace() const { return _is_trace; } + void trace_start_solve() const; + void trace_reshaped_form(const int C_const, + const int C_const_init, + const int C_invar, + const int C_init, + const int C_pre, + const int C_main) const; + void trace_main_iteration_alignment(const int C_const, + const int C_invar, + const int C_init, + const int C_pre, + const int C_main, + const int C_main_mod_aw) const; + void trace_constrained_solution(const int C_const, + const int C_invar, + const int C_init, + const int C_pre, + const int q, + const int r) const; +#endif +}; + #endif // SHARE_OPTO_VECTORIZATION_HPP diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 6992f3516aac8..e4d3d013cd384 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -847,6 +847,8 @@ class ExpandVNode: public VectorNode { //------------------------------LoadVectorNode--------------------------------- // Load Vector from memory class LoadVectorNode : public LoadNode { + private: + DEBUG_ONLY( bool _must_verify_alignment = false; ); public: LoadVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeVect* vt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest) : LoadNode(c, mem, adr, at, vt, MemNode::unordered, control_dependency) { @@ -871,6 +873,17 @@ class LoadVectorNode : public LoadNode { uint vlen, BasicType bt, ControlDependency control_dependency = LoadNode::DependsOnlyOnTest); uint element_size(void) { return type2aelembytes(vect_type()->element_basic_type()); } + + // Needed for proper cloning. + virtual uint size_of() const { return sizeof(*this); } + +#ifdef ASSERT + // When AlignVector is enabled, SuperWord only creates aligned vector loads and stores. + // VerifyAlignVector verifies this. We need to mark the nodes created in SuperWord, + // because nodes created elsewhere (i.e. VectorAPI) may still be misaligned. + bool must_verify_alignment() const { return _must_verify_alignment; } + void set_must_verify_alignment() { _must_verify_alignment = true; } +#endif }; //------------------------------LoadVectorGatherNode------------------------------ @@ -894,6 +907,7 @@ class LoadVectorGatherNode : public LoadVectorNode { class StoreVectorNode : public StoreNode { private: const TypeVect* _vect_type; + DEBUG_ONLY( bool _must_verify_alignment = false; ); public: StoreVectorNode(Node* c, Node* mem, Node* adr, const TypePtr* at, Node* val) : StoreNode(c, mem, adr, at, val, MemNode::unordered), _vect_type(val->bottom_type()->is_vect()) { @@ -918,6 +932,14 @@ class StoreVectorNode : public StoreNode { // Needed for proper cloning. virtual uint size_of() const { return sizeof(*this); } + +#ifdef ASSERT + // When AlignVector is enabled, SuperWord only creates aligned vector loads and stores. + // VerifyAlignVector verifies this. We need to mark the nodes created in SuperWord, + // because nodes created elsewhere (i.e. VectorAPI) may still be misaligned. + bool must_verify_alignment() const { return _must_verify_alignment; } + void set_must_verify_alignment() { _must_verify_alignment = true; } +#endif }; //------------------------------StoreVectorScatterNode------------------------------ @@ -1017,6 +1039,25 @@ class StoreVectorScatterMaskedNode : public StoreVectorNode { idx == MemNode::ValueIn + 2; } }; +// Verify that memory address (adr) is aligned. The mask specifies the +// least significant bits which have to be zero in the address. +// +// if (adr & mask == 0) { +// return adr +// } else { +// stop("verify_vector_alignment found a misaligned vector memory access") +// } +// +// This node is used just before a vector load/store with -XX:+VerifyAlignVector +class VerifyVectorAlignmentNode : public Node { + virtual uint hash() const { return NO_HASH; }; +public: + VerifyVectorAlignmentNode(Node* adr, Node* mask) : Node(nullptr, adr, mask) {} + virtual int Opcode() const; + virtual uint size_of() const { return sizeof(*this); } + virtual const Type *bottom_type() const { return in(1)->bottom_type(); } +}; + //------------------------------VectorCmpMaskedNode-------------------------------- // Vector Comparison under the influence of a predicate register(mask). class VectorCmpMaskedNode : public TypeNode { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java index 3b7bf23173051..b68ddfe2799ce 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizationMismatchedAccess.java @@ -50,13 +50,10 @@ public class TestVectorizationMismatchedAccess { private final static WhiteBox wb = WhiteBox.getWhiteBox(); public static void main(String[] args) { - Object alignVector = wb.getVMFlag("AlignVector"); - if (alignVector != null && !((Boolean)alignVector)) { - if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { - throw new RuntimeException("fix test that was written for a little endian platform"); - } - TestFramework.runWithFlags("--add-modules", "java.base", "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + throw new RuntimeException("fix test that was written for a little endian platform"); } + TestFramework.runWithFlags("--add-modules", "java.base", "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED"); } static int size = 1024; @@ -189,7 +186,9 @@ public static void testByteLong3_runner() { } @Test - @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }) + @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + applyIf = {"AlignVector", "false"}) + // AlignVector cannot guarantee that invar is aligned. public static void testByteLong4(byte[] dest, long[] src, int start, int stop) { for (int i = start; i < stop; i++) { UNSAFE.putLongUnaligned(dest, 8 * i + baseOffset, src[i]); @@ -323,7 +322,9 @@ public static void testOffHeapLong3_runner() { } @Test - @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }) + @IR(counts = { IRNode.LOAD_VECTOR_L, ">=1", IRNode.STORE_VECTOR, ">=1" }, + applyIf = {"AlignVector", "false"}) + // AlignVector cannot guarantee that invar is aligned. public static void testOffHeapLong4(long dest, long[] src, int start, int stop) { for (int i = start; i < stop; i++) { UNSAFE.putLongUnaligned(null, dest + 8 * i + baseOffset, src[i]); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index be508bbb81e1a..67fadbc4eac31 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -135,6 +135,7 @@ public class TestFramework { "CompileThreshold", "Xmixed", "server", + "AlignVector", "UseAVX", "UseSSE", "UseSVE", diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java new file mode 100644 index 0000000000000..fe873770ab44d --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java @@ -0,0 +1,1479 @@ +/* + * Copyright (c) 2024, 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.loopopts.superword; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Utils; +import jdk.test.whitebox.WhiteBox; +import jdk.internal.misc.Unsafe; +import java.lang.reflect.Array; +import java.util.Map; +import java.util.HashMap; +import java.util.Random; +import java.nio.ByteOrder; + +/* + * @test id=NoAlignVector + * @bug 8310190 + * @summary Test AlignVector with various loop init, stride, scale, invar, etc. + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver compiler.loopopts.superword.TestAlignVector NoAlignVector + */ + +/* + * @test id=AlignVector + * @bug 8310190 + * @summary Test AlignVector with various loop init, stride, scale, invar, etc. + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver compiler.loopopts.superword.TestAlignVector AlignVector + */ + +/* + * @test id=VerifyAlignVector + * @bug 8310190 + * @summary Test AlignVector with various loop init, stride, scale, invar, etc. + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver compiler.loopopts.superword.TestAlignVector VerifyAlignVector + */ + +public class TestAlignVector { + static int RANGE = 1024*8; + static int RANGE_FINAL = 1024*8; + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + private static final Random RANDOM = Utils.getRandomInstance(); + + // Inputs + byte[] aB; + byte[] bB; + byte mB = (byte)31; + short[] aS; + short[] bS; + short mS = (short)0xF0F0; + int[] aI; + int[] bI; + int mI = 0xF0F0F0F0; + long[] aL; + long[] bL; + long mL = 0xF0F0F0F0F0F0F0F0L; + + // List of tests + Map tests = new HashMap(); + + // List of gold, the results from the first run before compilation + Map golds = new HashMap(); + + interface TestFunction { + Object[] run(); + } + + public static void main(String[] args) { + TestFramework framework = new TestFramework(TestAlignVector.class); + framework.addFlags("--add-modules", "java.base", "--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED", + "-XX:LoopUnrollLimit=250"); + + switch (args[0]) { + case "NoAlignVector" -> { framework.addFlags("-XX:-AlignVector"); } + case "AlignVector" -> { framework.addFlags("-XX:+AlignVector"); } + case "VerifyAlignVector" -> { framework.addFlags("-XX:+AlignVector", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+VerifyAlignVector"); } + default -> { throw new RuntimeException("Test argument not recognized: " + args[0]); } + } + framework.start(); + } + + public TestAlignVector() { + // Generate input once + aB = generateB(); + bB = generateB(); + aS = generateS(); + bS = generateS(); + aI = generateI(); + bI = generateI(); + aL = generateL(); + bL = generateL(); + + // Add all tests to list + tests.put("test0", () -> { return test0(aB.clone(), bB.clone(), mB); }); + tests.put("test1", () -> { return test1(aB.clone(), bB.clone(), mB); }); + tests.put("test2", () -> { return test2(aB.clone(), bB.clone(), mB); }); + tests.put("test3", () -> { return test3(aB.clone(), bB.clone(), mB); }); + tests.put("test4", () -> { return test4(aB.clone(), bB.clone(), mB); }); + tests.put("test5", () -> { return test5(aB.clone(), bB.clone(), mB, 0); }); + tests.put("test6", () -> { return test6(aB.clone(), bB.clone(), mB); }); + tests.put("test7", () -> { return test7(aS.clone(), bS.clone(), mS); }); + tests.put("test8", () -> { return test8(aB.clone(), bB.clone(), mB, 0); }); + tests.put("test8", () -> { return test8(aB.clone(), bB.clone(), mB, 1); }); + tests.put("test9", () -> { return test9(aB.clone(), bB.clone(), mB); }); + + tests.put("test10a", () -> { return test10a(aB.clone(), bB.clone(), mB); }); + tests.put("test10b", () -> { return test10b(aB.clone(), bB.clone(), mB); }); + tests.put("test10c", () -> { return test10c(aS.clone(), bS.clone(), mS); }); + tests.put("test10d", () -> { return test10d(aS.clone(), bS.clone(), mS); }); + + tests.put("test11aB", () -> { return test11aB(aB.clone(), bB.clone(), mB); }); + tests.put("test11aS", () -> { return test11aS(aS.clone(), bS.clone(), mS); }); + tests.put("test11aI", () -> { return test11aI(aI.clone(), bI.clone(), mI); }); + tests.put("test11aL", () -> { return test11aL(aL.clone(), bL.clone(), mL); }); + + tests.put("test11bB", () -> { return test11bB(aB.clone(), bB.clone(), mB); }); + tests.put("test11bS", () -> { return test11bS(aS.clone(), bS.clone(), mS); }); + tests.put("test11bI", () -> { return test11bI(aI.clone(), bI.clone(), mI); }); + tests.put("test11bL", () -> { return test11bL(aL.clone(), bL.clone(), mL); }); + + tests.put("test11cB", () -> { return test11cB(aB.clone(), bB.clone(), mB); }); + tests.put("test11cS", () -> { return test11cS(aS.clone(), bS.clone(), mS); }); + tests.put("test11cI", () -> { return test11cI(aI.clone(), bI.clone(), mI); }); + tests.put("test11cL", () -> { return test11cL(aL.clone(), bL.clone(), mL); }); + + tests.put("test11dB", () -> { return test11dB(aB.clone(), bB.clone(), mB, 0); }); + tests.put("test11dS", () -> { return test11dS(aS.clone(), bS.clone(), mS, 0); }); + tests.put("test11dI", () -> { return test11dI(aI.clone(), bI.clone(), mI, 0); }); + tests.put("test11dL", () -> { return test11dL(aL.clone(), bL.clone(), mL, 0); }); + + tests.put("test12", () -> { return test12(aB.clone(), bB.clone(), mB); }); + + tests.put("test13aIL", () -> { return test13aIL(aI.clone(), aL.clone()); }); + tests.put("test13aIB", () -> { return test13aIB(aI.clone(), aB.clone()); }); + tests.put("test13aIS", () -> { return test13aIS(aI.clone(), aS.clone()); }); + tests.put("test13aBSIL", () -> { return test13aBSIL(aB.clone(), aS.clone(), aI.clone(), aL.clone()); }); + + tests.put("test13bIL", () -> { return test13bIL(aI.clone(), aL.clone()); }); + tests.put("test13bIB", () -> { return test13bIB(aI.clone(), aB.clone()); }); + tests.put("test13bIS", () -> { return test13bIS(aI.clone(), aS.clone()); }); + tests.put("test13bBSIL", () -> { return test13bBSIL(aB.clone(), aS.clone(), aI.clone(), aL.clone()); }); + + tests.put("test14aB", () -> { return test14aB(aB.clone()); }); + tests.put("test14bB", () -> { return test14bB(aB.clone()); }); + tests.put("test14cB", () -> { return test14cB(aB.clone()); }); + + tests.put("test15aB", () -> { return test15aB(aB.clone()); }); + tests.put("test15bB", () -> { return test15bB(aB.clone()); }); + tests.put("test15cB", () -> { return test15cB(aB.clone()); }); + + tests.put("test16a", () -> { return test16a(aB.clone(), aS.clone()); }); + tests.put("test16b", () -> { return test16b(aB.clone()); }); + + tests.put("test17a", () -> { return test17a(aL.clone()); }); + tests.put("test17b", () -> { return test17b(aL.clone()); }); + tests.put("test17c", () -> { return test17c(aL.clone()); }); + tests.put("test17d", () -> { return test17d(aL.clone()); }); + + tests.put("test18a", () -> { return test18a(aB.clone(), aI.clone()); }); + tests.put("test18b", () -> { return test18b(aB.clone(), aI.clone()); }); + + tests.put("test19", () -> { return test19(aI.clone(), bI.clone()); }); + tests.put("test20", () -> { return test20(aB.clone()); }); + + // Compute gold value for all test methods before compilation + for (Map.Entry entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + Object[] gold = test.run(); + golds.put(name, gold); + } + } + + @Warmup(100) + @Run(test = {"test0", + "test1", + "test2", + "test3", + "test4", + "test5", + "test6", + "test7", + "test8", + "test9", + "test10a", + "test10b", + "test10c", + "test10d", + "test11aB", + "test11aS", + "test11aI", + "test11aL", + "test11bB", + "test11bS", + "test11bI", + "test11bL", + "test11cB", + "test11cS", + "test11cI", + "test11cL", + "test11dB", + "test11dS", + "test11dI", + "test11dL", + "test12", + "test13aIL", + "test13aIB", + "test13aIS", + "test13aBSIL", + "test13bIL", + "test13bIB", + "test13bIS", + "test13bBSIL", + "test14aB", + "test14bB", + "test14cB", + "test15aB", + "test15bB", + "test15cB", + "test16a", + "test16b", + "test17a", + "test17b", + "test17c", + "test17d", + "test18a", + "test18b", + "test19", + "test20"}) + public void runTests() { + for (Map.Entry entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + // Recall gold value from before compilation + Object[] gold = golds.get(name); + // Compute new result + Object[] result = test.run(); + // Compare gold and new result + verify(name, gold, result); + } + } + + static byte[] generateB() { + byte[] a = new byte[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = (byte)RANDOM.nextInt(); + } + return a; + } + + static short[] generateS() { + short[] a = new short[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = (short)RANDOM.nextInt(); + } + return a; + } + + static int[] generateI() { + int[] a = new int[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = RANDOM.nextInt(); + } + return a; + } + + static long[] generateL() { + long[] a = new long[RANGE]; + for (int i = 0; i < a.length; i++) { + a[i] = RANDOM.nextLong(); + } + return a; + } + + static void verify(String name, Object[] gold, Object[] result) { + if (gold.length != result.length) { + throw new RuntimeException("verify " + name + ": not the same number of outputs: gold.length = " + + gold.length + ", result.length = " + result.length); + } + for (int i = 0; i < gold.length; i++) { + Object g = gold[i]; + Object r = result[i]; + if (g.getClass() != r.getClass() || !g.getClass().isArray() || !r.getClass().isArray()) { + throw new RuntimeException("verify " + name + ": must both be array of same type:" + + " gold[" + i + "].getClass() = " + g.getClass().getSimpleName() + + " result[" + i + "].getClass() = " + r.getClass().getSimpleName()); + } + if (g == r) { + throw new RuntimeException("verify " + name + ": should be two separate arrays (with identical content):" + + " gold[" + i + "] == result[" + i + "]"); + } + if (Array.getLength(g) != Array.getLength(r)) { + throw new RuntimeException("verify " + name + ": arrays must have same length:" + + " gold[" + i + "].length = " + Array.getLength(g) + + " result[" + i + "].length = " + Array.getLength(r)); + } + Class c = g.getClass().getComponentType(); + if (c == byte.class) { + verifyB(name, i, (byte[])g, (byte[])r); + } else if (c == short.class) { + verifyS(name, i, (short[])g, (short[])r); + } else if (c == int.class) { + verifyI(name, i, (int[])g, (int[])r); + } else if (c == long.class) { + verifyL(name, i, (long[])g, (long[])r); + } else { + throw new RuntimeException("verify " + name + ": array type not supported for verify:" + + " gold[" + i + "].getClass() = " + g.getClass().getSimpleName() + + " result[" + i + "].getClass() = " + r.getClass().getSimpleName()); + } + } + } + + static void verifyB(String name, int i, byte[] g, byte[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyS(String name, int i, short[] g, short[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyI(String name, int i, int[] g, int[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyL(String name, int i, long[] g, long[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verify " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test0(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE; i+=8) { + // Safe to vectorize with AlignVector + b[i+0] = (byte)(a[i+0] & mask); // offset 0, align 0 + b[i+1] = (byte)(a[i+1] & mask); + b[i+2] = (byte)(a[i+2] & mask); + b[i+3] = (byte)(a[i+3] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.AND_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test1(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE; i+=8) { + // Safe to vectorize with AlignVector + b[i+0] = (byte)(a[i+0] & mask); // offset 0, align 0 + b[i+1] = (byte)(a[i+1] & mask); + b[i+2] = (byte)(a[i+2] & mask); + b[i+3] = (byte)(a[i+3] & mask); + b[i+4] = (byte)(a[i+4] & mask); + b[i+5] = (byte)(a[i+5] & mask); + b[i+6] = (byte)(a[i+6] & mask); + b[i+7] = (byte)(a[i+7] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test2(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE; i+=8) { + // Cannot align with AlignVector: 3 + x * 8 % 8 = 3 + b[i+3] = (byte)(a[i+3] & mask); // at alignment 3 + b[i+4] = (byte)(a[i+4] & mask); + b[i+5] = (byte)(a[i+5] & mask); + b[i+6] = (byte)(a[i+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test3(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE; i+=8) { + // Cannot align with AlignVector: 3 + x * 8 % 8 = 3 + + // Problematic for AlignVector + b[i+0] = (byte)(a[i+0] & mask); // best_memref, align 0 + + b[i+3] = (byte)(a[i+3] & mask); // pack at offset 3 bytes + b[i+4] = (byte)(a[i+4] & mask); + b[i+5] = (byte)(a[i+5] & mask); + b[i+6] = (byte)(a[i+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_8, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_8, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=16"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_8, "= 0",// unaligned + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_8, "= 0",// unaligned + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">=16"}) + static Object[] test4(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE/16; i++) { + // Problematic for AlignVector + b[i*16 + 0 ] = (byte)(a[i*16 + 0 ] & mask); // 4 pack, 0 aligned + b[i*16 + 1 ] = (byte)(a[i*16 + 1 ] & mask); + b[i*16 + 2 ] = (byte)(a[i*16 + 2 ] & mask); + b[i*16 + 3 ] = (byte)(a[i*16 + 3 ] & mask); + + b[i*16 + 5 ] = (byte)(a[i*16 + 5 ] & mask); // 8 pack, 5 aligned + b[i*16 + 6 ] = (byte)(a[i*16 + 6 ] & mask); + b[i*16 + 7 ] = (byte)(a[i*16 + 7 ] & mask); + b[i*16 + 8 ] = (byte)(a[i*16 + 8 ] & mask); + b[i*16 + 9 ] = (byte)(a[i*16 + 9 ] & mask); + b[i*16 + 10] = (byte)(a[i*16 + 10] & mask); + b[i*16 + 11] = (byte)(a[i*16 + 11] & mask); + b[i*16 + 12] = (byte)(a[i*16 + 12] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test5(byte[] a, byte[] b, byte mask, int inv) { + for (int i = 0; i < RANGE; i+=8) { + // Cannot align with AlignVector because of invariant + b[i+inv+0] = (byte)(a[i+inv+0] & mask); + + b[i+inv+3] = (byte)(a[i+inv+3] & mask); + b[i+inv+4] = (byte)(a[i+inv+4] & mask); + b[i+inv+5] = (byte)(a[i+inv+5] & mask); + b[i+inv+6] = (byte)(a[i+inv+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test6(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE/8; i+=2) { + // Cannot align with AlignVector because offset is odd + b[i*4+0] = (byte)(a[i*4+0] & mask); + + b[i*4+3] = (byte)(a[i*4+3] & mask); + b[i*4+4] = (byte)(a[i*4+4] & mask); + b[i*4+5] = (byte)(a[i*4+5] & mask); + b[i*4+6] = (byte)(a[i*4+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VS, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=16"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_S, "= 0", + IRNode.AND_VS, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test7(short[] a, short[] b, short mask) { + for (int i = 0; i < RANGE/8; i+=2) { + // Cannot align with AlignVector because offset is odd + b[i*4+0] = (short)(a[i*4+0] & mask); + + b[i*4+3] = (short)(a[i*4+3] & mask); + b[i*4+4] = (short)(a[i*4+4] & mask); + b[i*4+5] = (short)(a[i*4+5] & mask); + b[i*4+6] = (short)(a[i*4+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test8(byte[] a, byte[] b, byte mask, int init) { + for (int i = init; i < RANGE; i+=8) { + // Cannot align with AlignVector because of invariant (variable init becomes invar) + b[i+0] = (byte)(a[i+0] & mask); + + b[i+3] = (byte)(a[i+3] & mask); + b[i+4] = (byte)(a[i+4] & mask); + b[i+5] = (byte)(a[i+5] & mask); + b[i+6] = (byte)(a[i+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"MaxVectorSize", ">=8"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test9(byte[] a, byte[] b, byte mask) { + // known non-zero init value does not affect offset, but has implicit effect on iv + for (int i = 13; i < RANGE-8; i+=8) { + b[i+0] = (byte)(a[i+0] & mask); + + b[i+3] = (byte)(a[i+3] & mask); + b[i+4] = (byte)(a[i+4] & mask); + b[i+5] = (byte)(a[i+5] & mask); + b[i+6] = (byte)(a[i+6] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test10a(byte[] a, byte[] b, byte mask) { + // This is not alignable with pre-loop, because of odd init. + for (int i = 3; i < RANGE-8; i+=8) { + b[i+0] = (byte)(a[i+0] & mask); + b[i+1] = (byte)(a[i+1] & mask); + b[i+2] = (byte)(a[i+2] & mask); + b[i+3] = (byte)(a[i+3] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VB, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=8"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test10b(byte[] a, byte[] b, byte mask) { + // This is not alignable with pre-loop, because of odd init. + // Seems not correctly handled. + for (int i = 13; i < RANGE-8; i+=8) { + b[i+0] = (byte)(a[i+0] & mask); + b[i+1] = (byte)(a[i+1] & mask); + b[i+2] = (byte)(a[i+2] & mask); + b[i+3] = (byte)(a[i+3] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VS, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=16"}) + @IR(counts = {IRNode.LOAD_VECTOR_S, "= 0", + IRNode.AND_VS, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test10c(short[] a, short[] b, short mask) { + // This is not alignable with pre-loop, because of odd init. + // Seems not correctly handled with MaxVectorSize >= 32. + for (int i = 13; i < RANGE-8; i+=8) { + b[i+0] = (short)(a[i+0] & mask); + b[i+1] = (short)(a[i+1] & mask); + b[i+2] = (short)(a[i+2] & mask); + b[i+3] = (short)(a[i+3] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.AND_VS, IRNode.VECTOR_SIZE_4, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"MaxVectorSize", ">=16"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test10d(short[] a, short[] b, short mask) { + for (int i = 13; i < RANGE-16; i+=8) { + // init + offset -> aligned + b[i+0+3] = (short)(a[i+0+3] & mask); + b[i+1+3] = (short)(a[i+1+3] & mask); + b[i+2+3] = (short)(a[i+2+3] & mask); + b[i+3+3] = (short)(a[i+3+3] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.AND_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11aB(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE; i++) { + // always alignable + b[i+0] = (byte)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", + IRNode.AND_VS, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11aS(short[] a, short[] b, short mask) { + for (int i = 0; i < RANGE; i++) { + // always alignable + b[i+0] = (short)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.AND_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11aI(int[] a, int[] b, int mask) { + for (int i = 0; i < RANGE; i++) { + // always alignable + b[i+0] = (int)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", + IRNode.AND_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11aL(long[] a, long[] b, long mask) { + for (int i = 0; i < RANGE; i++) { + // always alignable + b[i+0] = (long)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.AND_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11bB(byte[] a, byte[] b, byte mask) { + for (int i = 1; i < RANGE; i++) { + // always alignable + b[i+0] = (byte)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", + IRNode.AND_VS, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11bS(short[] a, short[] b, short mask) { + for (int i = 1; i < RANGE; i++) { + // always alignable + b[i+0] = (short)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.AND_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11bI(int[] a, int[] b, int mask) { + for (int i = 1; i < RANGE; i++) { + // always alignable + b[i+0] = (int)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", + IRNode.AND_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11bL(long[] a, long[] b, long mask) { + for (int i = 1; i < RANGE; i++) { + // always alignable + b[i+0] = (long)(a[i+0] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.AND_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test11cB(byte[] a, byte[] b, byte mask) { + for (int i = 1; i < RANGE-1; i++) { + // 1 byte offset -> not alignable with AlignVector + b[i+0] = (byte)(a[i+1] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", + IRNode.AND_VS, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_S, "= 0", + IRNode.AND_VS, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test11cS(short[] a, short[] b, short mask) { + for (int i = 1; i < RANGE-1; i++) { + // 2 byte offset -> not alignable with AlignVector + b[i+0] = (short)(a[i+1] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.AND_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_I, "= 0", + IRNode.AND_VI, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test11cI(int[] a, int[] b, int mask) { + for (int i = 1; i < RANGE-1; i++) { + // 4 byte offset -> not alignable with AlignVector + b[i+0] = (int)(a[i+1] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", + IRNode.AND_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11cL(long[] a, long[] b, long mask) { + for (int i = 1; i < RANGE-1; i++) { + // always alignable (8 byte offset) + b[i+0] = (long)(a[i+1] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.AND_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11dB(byte[] a, byte[] b, byte mask, int invar) { + for (int i = 0; i < RANGE; i++) { + b[i+0+invar] = (byte)(a[i+0+invar] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", + IRNode.AND_VS, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11dS(short[] a, short[] b, short mask, int invar) { + for (int i = 0; i < RANGE; i++) { + b[i+0+invar] = (short)(a[i+0+invar] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.AND_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11dI(int[] a, int[] b, int mask, int invar) { + for (int i = 0; i < RANGE; i++) { + b[i+0+invar] = (int)(a[i+0+invar] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", + IRNode.AND_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test11dL(long[] a, long[] b, long mask, int invar) { + for (int i = 0; i < RANGE; i++) { + b[i+0+invar] = (long)(a[i+0+invar] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.AND_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test12(byte[] a, byte[] b, byte mask) { + for (int i = 0; i < RANGE/16; i++) { + // Currently does not vectorize at all + b[i*6 + 0 ] = (byte)(a[i*6 + 0 ] & mask); + b[i*6 + 1 ] = (byte)(a[i*6 + 1 ] & mask); + b[i*6 + 2 ] = (byte)(a[i*6 + 2 ] & mask); + b[i*6 + 3 ] = (byte)(a[i*6 + 3 ] & mask); + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VI, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VL, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true"}) + // require avx to ensure vectors are larger than what unrolling produces + static Object[] test13aIL(int[] a, long[] b) { + for (int i = 0; i < RANGE; i++) { + a[i]++; + b[i]++; + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test13aIB(int[] a, byte[] b) { + for (int i = 0; i < RANGE; i++) { + a[i]++; + b[i]++; + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.LOAD_VECTOR_S, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.ADD_VS, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test13aIS(int[] a, short[] b) { + for (int i = 0; i < RANGE; i++) { + a[i]++; + b[i]++; + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.LOAD_VECTOR_S, "> 0", + IRNode.LOAD_VECTOR_I, "> 0", + IRNode.LOAD_VECTOR_L, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.ADD_VS, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.ADD_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test13aBSIL(byte[] a, short[] b, int[] c, long[] d) { + for (int i = 0; i < RANGE; i++) { + a[i]++; + b[i]++; + c[i]++; + d[i]++; + } + return new Object[]{ a, b, c, d }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VI, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.ADD_VL, IRNode.VECTOR_SIZE + "min(max_int, max_long)", "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true"}) + // require avx to ensure vectors are larger than what unrolling produces + static Object[] test13bIL(int[] a, long[] b) { + for (int i = 1; i < RANGE; i++) { + a[i]++; + b[i]++; + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.LOAD_VECTOR_I, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test13bIB(int[] a, byte[] b) { + for (int i = 1; i < RANGE; i++) { + a[i]++; + b[i]++; + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", + IRNode.LOAD_VECTOR_S, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.ADD_VS, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test13bIS(int[] a, short[] b) { + for (int i = 1; i < RANGE; i++) { + a[i]++; + b[i]++; + } + return new Object[]{ a, b }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.LOAD_VECTOR_S, "> 0", + IRNode.LOAD_VECTOR_I, "> 0", + IRNode.LOAD_VECTOR_L, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.ADD_VS, "> 0", + IRNode.ADD_VI, "> 0", + IRNode.ADD_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + static Object[] test13bBSIL(byte[] a, short[] b, int[] c, long[] d) { + for (int i = 1; i < RANGE; i++) { + a[i]++; + b[i]++; + c[i]++; + d[i]++; + } + return new Object[]{ a, b, c, d }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test14aB(byte[] a) { + // non-power-of-2 stride + for (int i = 0; i < RANGE-20; i+=9) { + a[i+0]++; + a[i+1]++; + a[i+2]++; + a[i+3]++; + a[i+4]++; + a[i+5]++; + a[i+6]++; + a[i+7]++; + a[i+8]++; + a[i+9]++; + a[i+10]++; + a[i+11]++; + a[i+12]++; + a[i+13]++; + a[i+14]++; + a[i+15]++; + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test14bB(byte[] a) { + // non-power-of-2 stride + for (int i = 0; i < RANGE-20; i+=3) { + a[i+0]++; + a[i+1]++; + a[i+2]++; + a[i+3]++; + a[i+4]++; + a[i+5]++; + a[i+6]++; + a[i+7]++; + a[i+8]++; + a[i+9]++; + a[i+10]++; + a[i+11]++; + a[i+12]++; + a[i+13]++; + a[i+14]++; + a[i+15]++; + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", + IRNode.ADD_VB, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "false"}) + @IR(counts = {IRNode.LOAD_VECTOR_B, "= 0", + IRNode.ADD_VB, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test14cB(byte[] a) { + // non-power-of-2 stride + for (int i = 0; i < RANGE-20; i+=5) { + a[i+0]++; + a[i+1]++; + a[i+2]++; + a[i+3]++; + a[i+4]++; + a[i+5]++; + a[i+6]++; + a[i+7]++; + a[i+8]++; + a[i+9]++; + a[i+10]++; + a[i+11]++; + a[i+12]++; + a[i+13]++; + a[i+14]++; + a[i+15]++; + } + return new Object[]{ a }; + } + + @Test + // IR rules difficult because of modulo wrapping with offset after peeling. + static Object[] test15aB(byte[] a) { + // non-power-of-2 scale + for (int i = 0; i < RANGE/64-20; i++) { + a[53*i+0]++; + a[53*i+1]++; + a[53*i+2]++; + a[53*i+3]++; + a[53*i+4]++; + a[53*i+5]++; + a[53*i+6]++; + a[53*i+7]++; + a[53*i+8]++; + a[53*i+9]++; + a[53*i+10]++; + a[53*i+11]++; + a[53*i+12]++; + a[53*i+13]++; + a[53*i+14]++; + a[53*i+15]++; + } + return new Object[]{ a }; + } + + @Test + // IR rules difficult because of modulo wrapping with offset after peeling. + static Object[] test15bB(byte[] a) { + // non-power-of-2 scale + for (int i = 0; i < RANGE/64-20; i++) { + a[25*i+0]++; + a[25*i+1]++; + a[25*i+2]++; + a[25*i+3]++; + a[25*i+4]++; + a[25*i+5]++; + a[25*i+6]++; + a[25*i+7]++; + a[25*i+8]++; + a[25*i+9]++; + a[25*i+10]++; + a[25*i+11]++; + a[25*i+12]++; + a[25*i+13]++; + a[25*i+14]++; + a[25*i+15]++; + } + return new Object[]{ a }; + } + + @Test + // IR rules difficult because of modulo wrapping with offset after peeling. + static Object[] test15cB(byte[] a) { + // non-power-of-2 scale + for (int i = 0; i < RANGE/64-20; i++) { + a[19*i+0]++; + a[19*i+1]++; + a[19*i+2]++; + a[19*i+3]++; + a[19*i+4]++; + a[19*i+5]++; + a[19*i+6]++; + a[19*i+7]++; + a[19*i+8]++; + a[19*i+9]++; + a[19*i+10]++; + a[19*i+11]++; + a[19*i+12]++; + a[19*i+13]++; + a[19*i+14]++; + a[19*i+15]++; + } + return new Object[]{ a }; + } + + @Test + static Object[] test16a(byte[] a, short[] b) { + // infinite loop issues + for (int i = 0; i < RANGE/2-20; i++) { + a[2*i+0]++; + a[2*i+1]++; + a[2*i+2]++; + a[2*i+3]++; + a[2*i+4]++; + a[2*i+5]++; + a[2*i+6]++; + a[2*i+7]++; + a[2*i+8]++; + a[2*i+9]++; + a[2*i+10]++; + a[2*i+11]++; + a[2*i+12]++; + a[2*i+13]++; + a[2*i+14]++; + + b[2*i+0]++; + b[2*i+1]++; + b[2*i+2]++; + b[2*i+3]++; + } + return new Object[]{ a, b }; + } + + @Test + static Object[] test16b(byte[] a) { + // infinite loop issues + for (int i = 0; i < RANGE/2-20; i++) { + a[2*i+0]++; + a[2*i+1]++; + a[2*i+2]++; + a[2*i+3]++; + a[2*i+4]++; + a[2*i+5]++; + a[2*i+6]++; + a[2*i+7]++; + a[2*i+8]++; + a[2*i+9]++; + a[2*i+10]++; + a[2*i+11]++; + a[2*i+12]++; + a[2*i+13]++; + a[2*i+14]++; + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", + IRNode.ADD_VL, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test17a(long[] a) { + // Unsafe: vectorizes with profiling (not xcomp) + for (int i = 0; i < RANGE; i++) { + int adr = UNSAFE.ARRAY_LONG_BASE_OFFSET + 8 * i; + long v = UNSAFE.getLongUnaligned(a, adr); + UNSAFE.putLongUnaligned(a, adr, v + 1); + } + return new Object[]{ a }; + } + + @Test + // Difficult to write good IR rule. Modulo calculus overflow can create non-power-of-2 packs. + static Object[] test17b(long[] a) { + // Not alignable + for (int i = 0; i < RANGE-1; i++) { + int adr = UNSAFE.ARRAY_LONG_BASE_OFFSET + 8 * i + 1; + long v = UNSAFE.getLongUnaligned(a, adr); + UNSAFE.putLongUnaligned(a, adr, v + 1); + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE_2, "> 0", + IRNode.ADD_VL, IRNode.VECTOR_SIZE_2, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIf = {"MaxVectorSize", ">=32"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + static Object[] test17c(long[] a) { + // Unsafe: aligned vectorizes + for (int i = 0; i < RANGE-1; i+=4) { + int adr = UNSAFE.ARRAY_LONG_BASE_OFFSET + 8 * i; + long v0 = UNSAFE.getLongUnaligned(a, adr + 0); + long v1 = UNSAFE.getLongUnaligned(a, adr + 8); + UNSAFE.putLongUnaligned(a, adr + 0, v0 + 1); + UNSAFE.putLongUnaligned(a, adr + 8, v1 + 1); + } + return new Object[]{ a }; + } + + @Test + @IR(counts = {IRNode.LOAD_VECTOR_L, IRNode.VECTOR_SIZE_2, "> 0", + IRNode.ADD_VL, IRNode.VECTOR_SIZE_2, "> 0", + IRNode.STORE_VECTOR, "> 0"}, + applyIfCPUFeatureOr = {"avx512", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">=64"}) + // Ensure vector width is large enough to fit 64 byte for longs: + // The offsets are: 25, 33, 57, 65 + // In modulo 32: 25, 1, 25, 1 -> does not vectorize + // In modulo 64: 25, 33, 57, 1 -> at least first pair vectorizes + // This problem is because we compute modulo vector width in memory_alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "= 0", + IRNode.ADD_VL, "= 0", + IRNode.STORE_VECTOR, "= 0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIfPlatform = {"64-bit", "true"}, + applyIf = {"AlignVector", "true"}) + static Object[] test17d(long[] a) { + // Not alignable + for (int i = 0; i < RANGE-1; i+=4) { + int adr = UNSAFE.ARRAY_LONG_BASE_OFFSET + 8 * i + 1; + long v0 = UNSAFE.getLongUnaligned(a, adr + 0); + long v1 = UNSAFE.getLongUnaligned(a, adr + 8); + UNSAFE.putLongUnaligned(a, adr + 0, v0 + 1); + UNSAFE.putLongUnaligned(a, adr + 8, v1 + 1); + } + return new Object[]{ a }; + } + + @Test + static Object[] test18a(byte[] a, int[] b) { + // scale = 0 --> no iv + for (int i = 0; i < RANGE; i++) { + a[0] = 1; + b[i] = 2; + a[1] = 1; + } + return new Object[]{ a, b }; + } + + @Test + static Object[] test18b(byte[] a, int[] b) { + // scale = 0 --> no iv + for (int i = 0; i < RANGE; i++) { + a[1] = 1; + b[i] = 2; + a[2] = 1; + } + return new Object[]{ a, b }; + } + + @Test + static Object[] test19(int[] a, int[] b) { + for (int i = 5000; i > 0; i--) { + a[RANGE_FINAL - i] = b[RANGE_FINAL - i]; + } + return new Object[]{ a, b }; + } + + @Test + static Object[] test20(byte[] a) { + // Example where it is easy to pass alignment check, + // but used to fail the alignment calculation + for (int i = 1; i < RANGE/2-50; i++) { + a[2*i+0+30]++; + a[2*i+1+30]++; + a[2*i+2+30]++; + a[2*i+3+30]++; + } + return new Object[]{ a }; + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java new file mode 100644 index 0000000000000..478cfbcb2c522 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVectorFuzzer.java @@ -0,0 +1,1353 @@ +/* + * Copyright (c) 2024, 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 id=Vanilla + * @bug 8253191 + * @summary Fuzzing loops with different (random) init, limit, stride, scale etc. Do not force alignment. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @requires vm.compiler2.enabled + * @key randomness + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:LoopUnrollLimit=250 + * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* + * compiler.loopopts.superword.TestAlignVectorFuzzer + */ + +/* + * @test id=VerifyAlignVector + * @bug 8253191 + * @summary Fuzzing loops with different (random) init, limit, stride, scale etc. Verify AlignVector. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @requires vm.compiler2.enabled + * @key randomness + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:+AlignVector -XX:+VerifyAlignVector + * -XX:LoopUnrollLimit=250 + * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* + * compiler.loopopts.superword.TestAlignVectorFuzzer + */ + +/* + * @test id=VerifyAlignVector-Align16 + * @bug 8253191 + * @summary Fuzzing loops with different (random) init, limit, stride, scale etc. Verify AlignVector. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @requires vm.compiler2.enabled + * @requires vm.bits == 64 + * @key randomness + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:+AlignVector -XX:+VerifyAlignVector + * -XX:LoopUnrollLimit=250 + * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* + * -XX:ObjectAlignmentInBytes=16 + * compiler.loopopts.superword.TestAlignVectorFuzzer + */ + +/* + * @test id=VerifyAlignVector-NoTieredCompilation-Xbatch + * @bug 8253191 + * @summary Fuzzing loops with different (random) init, limit, stride, scale etc. Verify AlignVector. + * @modules java.base/jdk.internal.misc + * @library /test/lib + * @requires vm.compiler2.enabled + * @key randomness + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:+AlignVector -XX:+VerifyAlignVector + * -XX:LoopUnrollLimit=250 + * -XX:CompileCommand=printcompilation,compiler.loopopts.superword.TestAlignVectorFuzzer::* + * -XX:-TieredCompilation -Xbatch + * compiler.loopopts.superword.TestAlignVectorFuzzer + */ + +package compiler.loopopts.superword; + +import java.lang.reflect.Array; +import java.util.Map; +import java.util.HashMap; +import java.lang.invoke.*; +import java.util.Random; +import jdk.test.lib.Utils; +import jdk.internal.misc.Unsafe; + +public class TestAlignVectorFuzzer { + static final int ITERATIONS_MAX = 5; // time allowance may lead to fewer iterations + static final int RANGE_CON = 1024 * 8; + static int ZERO = 0; + + private static final Random random = Utils.getRandomInstance(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + interface TestFunction { + Object[] run(); + } + + // Setup for variable compile-time constants: + private static final CallSite INIT_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite LIMIT_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite STRIDE_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite SCALE_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite OFFSET1_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite OFFSET2_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite OFFSET3_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final MethodHandle INIT_MH = INIT_CS.dynamicInvoker(); + private static final MethodHandle LIMIT_MH = LIMIT_CS.dynamicInvoker(); + private static final MethodHandle STRIDE_MH = STRIDE_CS.dynamicInvoker(); + private static final MethodHandle SCALE_MH = SCALE_CS.dynamicInvoker(); + private static final MethodHandle OFFSET1_MH = OFFSET1_CS.dynamicInvoker(); + private static final MethodHandle OFFSET2_MH = OFFSET2_CS.dynamicInvoker(); + private static final MethodHandle OFFSET3_MH = OFFSET3_CS.dynamicInvoker(); + + // Toggle if init, limit and offset are constants or variables + private static final CallSite INIT_IS_CON_CS = new MutableCallSite(MethodType.methodType(boolean.class)); + private static final CallSite LIMIT_IS_CON_CS = new MutableCallSite(MethodType.methodType(boolean.class)); + private static final CallSite OFFSET1_IS_CON_CS = new MutableCallSite(MethodType.methodType(boolean.class)); + private static final CallSite OFFSET2_IS_CON_CS = new MutableCallSite(MethodType.methodType(boolean.class)); + private static final CallSite OFFSET3_IS_CON_CS = new MutableCallSite(MethodType.methodType(boolean.class)); + private static final MethodHandle INIT_IS_CON_MH = INIT_IS_CON_CS.dynamicInvoker(); + private static final MethodHandle LIMIT_IS_CON_MH = LIMIT_IS_CON_CS.dynamicInvoker(); + private static final MethodHandle OFFSET1_IS_CON_MH = OFFSET1_IS_CON_CS.dynamicInvoker(); + private static final MethodHandle OFFSET2_IS_CON_MH = OFFSET2_IS_CON_CS.dynamicInvoker(); + private static final MethodHandle OFFSET3_IS_CON_MH = OFFSET3_IS_CON_CS.dynamicInvoker(); + + // Hand-Unrolling compile-constants + private static final CallSite HAND_UNROLLING1_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite HAND_UNROLLING2_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final CallSite HAND_UNROLLING3_CS = new MutableCallSite(MethodType.methodType(int.class)); + private static final MethodHandle HAND_UNROLLING1_MH = HAND_UNROLLING1_CS.dynamicInvoker(); + private static final MethodHandle HAND_UNROLLING2_MH = HAND_UNROLLING2_CS.dynamicInvoker(); + private static final MethodHandle HAND_UNROLLING3_MH = HAND_UNROLLING3_CS.dynamicInvoker(); + + static void setConstant(CallSite cs, int value) { + MethodHandle constant = MethodHandles.constant(int.class, value); + cs.setTarget(constant); + } + + static void setConstant(CallSite cs, boolean value) { + MethodHandle constant = MethodHandles.constant(boolean.class, value); + cs.setTarget(constant); + } + + static int init_con() { // compile-time constant + try { + return (int) INIT_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static boolean init_is_con() { // compile-time constant + try { + return (boolean) INIT_IS_CON_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int init_con_or_var() { + int init = init_con(); + if (!init_is_con()) { // branch constant folds to true or false + init += ZERO; // LoadI + } + return init; + } + + static int limit_con() { // compile-time constant + try { + return (int) LIMIT_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static boolean limit_is_con() { // compile-time constant + try { + return (boolean) LIMIT_IS_CON_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int limit_con_or_var() { + int limit = limit_con(); + if (!limit_is_con()) { // branch constant folds to true or false + limit -= ZERO; // LoadI + } + return limit; + } + + static int stride_con() { // compile-time constant + try { + return (int) STRIDE_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int scale_con() { // compile-time constant + try { + return (int) SCALE_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int offset1_con() { // compile-time constant + try { + return (int) OFFSET1_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int offset2_con() { // compile-time constant + try { + return (int) OFFSET2_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int offset3_con() { // compile-time constant + try { + return (int) OFFSET3_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static boolean offset1_is_con() { // compile-time constant + try { + return (boolean) OFFSET1_IS_CON_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static boolean offset2_is_con() { // compile-time constant + try { + return (boolean) OFFSET2_IS_CON_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static boolean offset3_is_con() { // compile-time constant + try { + return (boolean) OFFSET3_IS_CON_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int offset1_con_or_var() { + int offset = offset1_con(); + if (!offset1_is_con()) { // branch constant folds to true or false + offset += ZERO; // LoadI + } + return offset; + } + + static int offset2_con_or_var() { + int offset = offset2_con(); + if (!offset2_is_con()) { // branch constant folds to true or false + offset += ZERO; // LoadI + } + return offset; + } + + static int offset3_con_or_var() { + int offset = offset3_con(); + if (!offset3_is_con()) { // branch constant folds to true or false + offset += ZERO; // LoadI + } + return offset; + } + + static int opposite_direction_offset1_con_or_var() { + // When indexing in the opposite direction to i, we Want to have: + // + // a[x - i * scale] + // + // So we want to fulfill these constraints: + // + // x - init * scale = offset + limit * scale + // x - limit * scale = offset + init * scale + // + // Hence: + // + // x = offset + limit * scale + init * scale; + + int offset = offset1_con_or_var(); + int init = init_con(); + int limit = limit_con(); + int scale = scale_con(); + return offset + limit * scale + init * scale; + } + + static int opposite_direction_offset2_con_or_var() { + int offset = offset2_con_or_var(); + int init = init_con(); + int limit = limit_con(); + int scale = scale_con(); + return offset + limit * scale + init * scale; + } + + static int opposite_direction_offset3_con_or_var() { + int offset = offset3_con_or_var(); + int init = init_con(); + int limit = limit_con(); + int scale = scale_con(); + return offset + limit * scale + init * scale; + } + + static int hand_unrolling1_con() { // compile-time constant + try { + return (int) HAND_UNROLLING1_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int hand_unrolling2_con() { // compile-time constant + try { + return (int) HAND_UNROLLING2_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int hand_unrolling3_con() { // compile-time constant + try { + return (int) HAND_UNROLLING3_MH.invokeExact(); + } catch (Throwable t) { + throw new InternalError(t); // should NOT happen + } + } + + static int randomStride() { + return switch (random.nextInt(6)) { + case 0 -> random.nextInt(64) + 1; // [1..64] + case 1, 2, 3 -> 1; + default -> 1 << random.nextInt(7); // powers of 2: 1..64 + }; + } + + static int randomScale() { + return switch (random.nextInt(6)) { + case 0 -> random.nextInt(64) + 1; // [1..64] + case 1, 2, 3 -> 1; + default -> 1 << random.nextInt(7); // powers of 2: 1..64 + }; + } + + static int randomOffsetDiff() { + return switch (random.nextInt(6)) { + case 0 -> random.nextInt(256) + 128; + case 1, 2, 3 -> 0; + case 4 -> +(1 << random.nextInt(8)); // powers of 2: 1..128 + default -> -(1 << random.nextInt(8)); // powers of 2: -1..-128 + }; + } + + static int randomHandUnrolling() { + return switch (random.nextInt(2)) { + case 0 -> random.nextInt(16) + 1; // [1..16] + default -> 1 << random.nextInt(5); // powers of 2: 1..16 + }; + } + + static void setRandomConstants() { + // We want to create random constants for a loop, but they should never go out of bounds. + // We constrain i to be in the range [init..limit], with init < limit. For simplicity, we + // always generate: + // + // 1 <= scale <= 64 + // 1 <= stride <= 64 + // + // We work with this reference memory access: + // + // a[offset + i * scale] + // + // It is up to the test function to re-arrange the the given terms to iterate upward or + // downward, to hand-unroll etc. + // + // We must ensure that the first and last indices are in range: + // + // 0 + error <= offset + init * scale + // offset + limit * scale < range - error + // + // The "error" term is there such that the test functions have the freedom to slightly + // diverge from the reference memory access pattern (for example modify the offset). + // + // The values for scale and range are already fixed. We now want to generate values for + // offset, init and limit. + // + // (1) Fix offset: + // + // init >= (error - offset) / scale + // limit < (range - error - offset) / scale + // + // (2) Fix init: + // + // offset >= error - init * scale + // limit < (range - error - offset) / scale + // + // (3) Fix limit: + // + // offset < range - error - limit * scale + // init >= (error - offset) / scale + // + // We can still slightly perturb the results in the direction permitted by the inequality. + + int stride = randomStride(); + int scale = randomScale(); + int range = RANGE_CON; + int error = 1024; // generous + int init; + int limit; + int offset1; + switch(random.nextInt(3)) { + case 0 -> { + offset1 = random.nextInt(2_000_000) - 1_000_000; + init = (error - offset1) / scale + random.nextInt(64); + limit = (range - error - offset1) / scale - random.nextInt(64); + } + case 1 -> { + init = random.nextInt(2_000_000) - 1_000_000; + offset1 = error - init * scale + random.nextInt(64); + limit = (range - error - offset1) / scale - random.nextInt(64); + } + default -> { + limit = random.nextInt(2_000_000) - 1_000_000; + offset1 = range - error - limit * scale - random.nextInt(64); + init = (error - offset1) / scale + random.nextInt(64); + } + } + + int offset2 = offset1 + randomOffsetDiff(); + int offset3 = offset1 + randomOffsetDiff(); + + // We can toggle the init, limit and offset to either be constant or variable: + boolean init_is_con = random.nextInt(3) != 0; + boolean limit_is_con = random.nextInt(3) != 0; + boolean offset1_is_con = random.nextInt(3) != 0; + boolean offset2_is_con = random.nextInt(3) != 0; + boolean offset3_is_con = random.nextInt(3) != 0; + + int hand_unrolling1 = randomHandUnrolling(); + int hand_unrolling2 = randomHandUnrolling(); + int hand_unrolling3 = randomHandUnrolling(); + +// Overwrite the fuzzed values below to reproduce a specific failure: +// +// init = 1; +// limit = init + 3000; +// offset1 = 0; +// offset2 = 0; +// offset3 = 32 - 2*init; +// stride = 1; +// scale = 2; +// hand_unrolling1 = 0; +// hand_unrolling2 = 0; +// hand_unrolling3 = 4; +// +// init_is_con = true; +// limit_is_con = true; +// offset1_is_con = true; +// offset2_is_con = true; +// offset3_is_con = true; + + System.out.println(" init: " + init + " (con: " + init_is_con + ")"); + System.out.println(" limit: " + limit + " (con: " + limit_is_con + ")"); + System.out.println(" offset1: " + offset1 + " (con: " + offset1_is_con + ")"); + System.out.println(" offset2: " + offset2 + " (con: " + offset2_is_con + ")"); + System.out.println(" offset3: " + offset3 + " (con: " + offset3_is_con + ")"); + System.out.println(" stride: " + stride); + System.out.println(" scale: " + scale); + System.out.println(" hand_unrolling1: " + hand_unrolling1); + System.out.println(" hand_unrolling2: " + hand_unrolling2); + System.out.println(" hand_unrolling3: " + hand_unrolling3); + setConstant(INIT_CS, init); + setConstant(LIMIT_CS, limit); + setConstant(STRIDE_CS, stride); + setConstant(SCALE_CS, scale); + setConstant(OFFSET1_CS, offset1); + setConstant(OFFSET2_CS, offset2); + setConstant(OFFSET3_CS, offset3); + setConstant(INIT_IS_CON_CS, init_is_con); + setConstant(LIMIT_IS_CON_CS, limit_is_con); + setConstant(OFFSET1_IS_CON_CS, offset1_is_con); + setConstant(OFFSET2_IS_CON_CS, offset2_is_con); + setConstant(OFFSET3_IS_CON_CS, offset3_is_con); + setConstant(HAND_UNROLLING1_CS, hand_unrolling1); + setConstant(HAND_UNROLLING2_CS, hand_unrolling2); + setConstant(HAND_UNROLLING3_CS, hand_unrolling3); + } + + public static void main(String[] args) { + byte[] aB = generateB(); + byte[] bB = generateB(); + byte[] cB = generateB(); + short[] aS = generateS(); + short[] bS = generateS(); + short[] cS = generateS(); + char[] aC = generateC(); + char[] bC = generateC(); + char[] cC = generateC(); + int[] aI = generateI(); + int[] bI = generateI(); + int[] cI = generateI(); + long[] aL = generateL(); + long[] bL = generateL(); + long[] cL = generateL(); + float[] aF = generateF(); + float[] bF = generateF(); + float[] cF = generateF(); + double[] aD = generateD(); + double[] bD = generateD(); + double[] cD = generateD(); + + // Add all tests to list + Map tests = new HashMap(); + tests.put("testUUB", () -> { return testUUB(aB.clone()); }); + tests.put("testDDB", () -> { return testDDB(aB.clone()); }); + tests.put("testUDB", () -> { return testUDB(aB.clone()); }); + tests.put("testDUB", () -> { return testDUB(aB.clone()); }); + + tests.put("testUUBH", () -> { return testUUBH(aB.clone()); }); + + tests.put("testUUBBB", () -> { return testUUBBB(aB.clone(), bB.clone(), cB.clone()); }); + tests.put("testUUBSI", () -> { return testUUBSI(aB.clone(), bS.clone(), cI.clone()); }); + + tests.put("testUUBBBH", () -> { return testUUBBBH(aB.clone(), bB.clone(), cB.clone()); }); + + tests.put("testUUBCFH", () -> { return testUUBCFH(aB.clone(), bC.clone(), cF.clone()); }); + tests.put("testDDBCFH", () -> { return testDDBCFH(aB.clone(), bC.clone(), cF.clone()); }); + tests.put("testUDBCFH", () -> { return testUDBCFH(aB.clone(), bC.clone(), cF.clone()); }); + tests.put("testDUBCFH", () -> { return testDUBCFH(aB.clone(), bC.clone(), cF.clone()); }); + + tests.put("testMMSFD", () -> { return testMMSFD(aS.clone(), bF.clone(), cD.clone()); }); + + tests.put("testUU_unsafe_BasI", () -> { return testUU_unsafe_BasI(aB.clone()); }); + tests.put("testUU_unsafe_BasIH", () -> { return testUU_unsafe_BasIH(aB.clone(), bB.clone(), cB.clone()); }); + + + // Only run for 90% of the time, and subtract some margin. This ensures the shutdown has sufficient time, + // even for very slow runs. + long test_time_allowance = System.currentTimeMillis() + + (long)(Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT) * 0.9) - + 20_000; + long test_hard_timeout = System.currentTimeMillis() + + Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT); + + for (int i = 1; i <= ITERATIONS_MAX; i++) { + setRandomConstants(); + for (Map.Entry entry : tests.entrySet()) { + String name = entry.getKey(); + TestFunction test = entry.getValue(); + long allowance = test_time_allowance - System.currentTimeMillis(); + long until_timeout = test_hard_timeout - System.currentTimeMillis(); + System.out.println("ITERATION " + i + " of " + ITERATIONS_MAX + ". Test " + name + + ", time allowance: " + allowance + ", until timeout: " + until_timeout); + + // Compute gold value, probably deopt first if constants have changed. + Object[] gold = test.run(); + + // Have enough iterations to (re)compile + for (int j = 0; j < 10_000; j++) { + Object[] result = test.run(); + verify(name, gold, result); + } + + if (System.currentTimeMillis() > test_time_allowance) { + allowance = test_time_allowance - System.currentTimeMillis(); + until_timeout = test_hard_timeout - System.currentTimeMillis(); + System.out.println("TEST PASSED: hit maximal time allownance during iteration " + i + + ", time allowance: " + allowance + ", until timeout: " + until_timeout); + return; + } + } + } + long allowance = test_time_allowance - System.currentTimeMillis(); + long until_timeout = test_hard_timeout - System.currentTimeMillis(); + System.out.println("TEST PASSED, time allowance: " + allowance + ", until timeout: " + until_timeout); + } + + // Test names: + // test + // {U: i goes up, D: i goes down, M: mixed} + // {U: indexing goes up, D: indexing goes down, M: mixed} + // BSCILFD (types used) + + // -------------------- BASIC SINGLE -------------------- + + static Object[] testUUB(byte[] a) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset = offset1_con_or_var(); + + for (int i = init; i < limit; i += stride) { + a[offset + i * scale]++; + } + return new Object[]{ a }; + } + + static Object[] testDDB(byte[] a) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset = offset1_con_or_var(); + + for (int i = limit; i > init; i -= stride) { + a[offset + i * scale]++; + } + return new Object[]{ a }; + } + + static Object[] testUDB(byte[] a) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int x = opposite_direction_offset1_con_or_var(); + + for (int i = init; i < limit; i += stride) { + a[x - i * scale]++; + } + return new Object[]{ a }; + } + + static Object[] testDUB(byte[] a) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int x = opposite_direction_offset1_con_or_var(); + + for (int i = limit; i > init; i -= stride) { + a[x - i * scale]++; + } + return new Object[]{ a }; + } + + // -------------------- BASIC HAND UNROLL -------------------- + + static Object[] testUUBH(byte[] a) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset = offset1_con_or_var(); + + // All if statements with constant h fold to true or false + int h = hand_unrolling1_con(); + + for (int i = init; i < limit; i += stride) { + if (h >= 1) { a[offset + i * scale + 0]++; } + if (h >= 2) { a[offset + i * scale + 1]++; } + if (h >= 3) { a[offset + i * scale + 2]++; } + if (h >= 4) { a[offset + i * scale + 3]++; } + if (h >= 5) { a[offset + i * scale + 4]++; } + if (h >= 6) { a[offset + i * scale + 5]++; } + if (h >= 7) { a[offset + i * scale + 6]++; } + if (h >= 8) { a[offset + i * scale + 7]++; } + if (h >= 9) { a[offset + i * scale + 8]++; } + if (h >= 10) { a[offset + i * scale + 9]++; } + if (h >= 11) { a[offset + i * scale + 10]++; } + if (h >= 12) { a[offset + i * scale + 11]++; } + if (h >= 13) { a[offset + i * scale + 12]++; } + if (h >= 14) { a[offset + i * scale + 13]++; } + if (h >= 15) { a[offset + i * scale + 14]++; } + if (h >= 16) { a[offset + i * scale + 15]++; } + } + return new Object[]{ a }; + } + + // -------------------- BASIC TRIPPLE -------------------- + + static Object[] testUUBBB(byte[] a, byte[] b, byte[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + for (int i = init; i < limit; i += stride) { + a[offset1 + i * scale]++; + b[offset2 + i * scale]++; + c[offset3 + i * scale]++; + } + return new Object[]{ a, b, c }; + } + + static Object[] testUUBSI(byte[] a, short[] b, int[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + for (int i = init; i < limit; i += stride) { + a[offset1 + i * scale]++; + b[offset2 + i * scale]++; + c[offset3 + i * scale]++; + } + return new Object[]{ a, b, c }; + } + + // -------------------- HAND UNROLL TRIPPLE -------------------- + + static Object[] testUUBBBH(byte[] a, byte[] b, byte[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + int h1 = hand_unrolling1_con(); + int h2 = hand_unrolling2_con(); + int h3 = hand_unrolling3_con(); + + for (int i = init; i < limit; i += stride) { + if (h1 >= 1) { a[offset1 + i * scale + 0]++; } + if (h1 >= 2) { a[offset1 + i * scale + 1]++; } + if (h1 >= 3) { a[offset1 + i * scale + 2]++; } + if (h1 >= 4) { a[offset1 + i * scale + 3]++; } + if (h1 >= 5) { a[offset1 + i * scale + 4]++; } + if (h1 >= 6) { a[offset1 + i * scale + 5]++; } + if (h1 >= 7) { a[offset1 + i * scale + 6]++; } + if (h1 >= 8) { a[offset1 + i * scale + 7]++; } + if (h1 >= 9) { a[offset1 + i * scale + 8]++; } + if (h1 >= 10) { a[offset1 + i * scale + 9]++; } + if (h1 >= 11) { a[offset1 + i * scale + 10]++; } + if (h1 >= 12) { a[offset1 + i * scale + 11]++; } + if (h1 >= 13) { a[offset1 + i * scale + 12]++; } + if (h1 >= 14) { a[offset1 + i * scale + 13]++; } + if (h1 >= 15) { a[offset1 + i * scale + 14]++; } + if (h1 >= 16) { a[offset1 + i * scale + 15]++; } + + if (h2 >= 1) { b[offset2 + i * scale + 0]++; } + if (h2 >= 2) { b[offset2 + i * scale + 1]++; } + if (h2 >= 3) { b[offset2 + i * scale + 2]++; } + if (h2 >= 4) { b[offset2 + i * scale + 3]++; } + if (h2 >= 5) { b[offset2 + i * scale + 4]++; } + if (h2 >= 6) { b[offset2 + i * scale + 5]++; } + if (h2 >= 7) { b[offset2 + i * scale + 6]++; } + if (h2 >= 8) { b[offset2 + i * scale + 7]++; } + if (h2 >= 9) { b[offset2 + i * scale + 8]++; } + if (h2 >= 10) { b[offset2 + i * scale + 9]++; } + if (h2 >= 11) { b[offset2 + i * scale + 10]++; } + if (h2 >= 12) { b[offset2 + i * scale + 11]++; } + if (h2 >= 13) { b[offset2 + i * scale + 12]++; } + if (h2 >= 14) { b[offset2 + i * scale + 13]++; } + if (h2 >= 15) { b[offset2 + i * scale + 14]++; } + if (h2 >= 16) { b[offset2 + i * scale + 15]++; } + + if (h3 >= 1) { c[offset3 + i * scale + 0]++; } + if (h3 >= 2) { c[offset3 + i * scale + 1]++; } + if (h3 >= 3) { c[offset3 + i * scale + 2]++; } + if (h3 >= 4) { c[offset3 + i * scale + 3]++; } + if (h3 >= 5) { c[offset3 + i * scale + 4]++; } + if (h3 >= 6) { c[offset3 + i * scale + 5]++; } + if (h3 >= 7) { c[offset3 + i * scale + 6]++; } + if (h3 >= 8) { c[offset3 + i * scale + 7]++; } + if (h3 >= 9) { c[offset3 + i * scale + 8]++; } + if (h3 >= 10) { c[offset3 + i * scale + 9]++; } + if (h3 >= 11) { c[offset3 + i * scale + 10]++; } + if (h3 >= 12) { c[offset3 + i * scale + 11]++; } + if (h3 >= 13) { c[offset3 + i * scale + 12]++; } + if (h3 >= 14) { c[offset3 + i * scale + 13]++; } + if (h3 >= 15) { c[offset3 + i * scale + 14]++; } + if (h3 >= 16) { c[offset3 + i * scale + 15]++; } + } + return new Object[]{ a, b, c }; + } + + static Object[] testUUBCFH(byte[] a, char[] b, float[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + int h1 = hand_unrolling1_con(); + int h2 = hand_unrolling2_con(); + int h3 = hand_unrolling3_con(); + + for (int i = init; i < limit; i += stride) { + if (h1 >= 1) { a[offset1 + i * scale + 0]++; } + if (h1 >= 2) { a[offset1 + i * scale + 1]++; } + if (h1 >= 3) { a[offset1 + i * scale + 2]++; } + if (h1 >= 4) { a[offset1 + i * scale + 3]++; } + if (h1 >= 5) { a[offset1 + i * scale + 4]++; } + if (h1 >= 6) { a[offset1 + i * scale + 5]++; } + if (h1 >= 7) { a[offset1 + i * scale + 6]++; } + if (h1 >= 8) { a[offset1 + i * scale + 7]++; } + if (h1 >= 9) { a[offset1 + i * scale + 8]++; } + if (h1 >= 10) { a[offset1 + i * scale + 9]++; } + if (h1 >= 11) { a[offset1 + i * scale + 10]++; } + if (h1 >= 12) { a[offset1 + i * scale + 11]++; } + if (h1 >= 13) { a[offset1 + i * scale + 12]++; } + if (h1 >= 14) { a[offset1 + i * scale + 13]++; } + if (h1 >= 15) { a[offset1 + i * scale + 14]++; } + if (h1 >= 16) { a[offset1 + i * scale + 15]++; } + + if (h2 >= 1) { b[offset2 + i * scale + 0]++; } + if (h2 >= 2) { b[offset2 + i * scale + 1]++; } + if (h2 >= 3) { b[offset2 + i * scale + 2]++; } + if (h2 >= 4) { b[offset2 + i * scale + 3]++; } + if (h2 >= 5) { b[offset2 + i * scale + 4]++; } + if (h2 >= 6) { b[offset2 + i * scale + 5]++; } + if (h2 >= 7) { b[offset2 + i * scale + 6]++; } + if (h2 >= 8) { b[offset2 + i * scale + 7]++; } + if (h2 >= 9) { b[offset2 + i * scale + 8]++; } + if (h2 >= 10) { b[offset2 + i * scale + 9]++; } + if (h2 >= 11) { b[offset2 + i * scale + 10]++; } + if (h2 >= 12) { b[offset2 + i * scale + 11]++; } + if (h2 >= 13) { b[offset2 + i * scale + 12]++; } + if (h2 >= 14) { b[offset2 + i * scale + 13]++; } + if (h2 >= 15) { b[offset2 + i * scale + 14]++; } + if (h2 >= 16) { b[offset2 + i * scale + 15]++; } + + if (h3 >= 1) { c[offset3 + i * scale + 0]++; } + if (h3 >= 2) { c[offset3 + i * scale + 1]++; } + if (h3 >= 3) { c[offset3 + i * scale + 2]++; } + if (h3 >= 4) { c[offset3 + i * scale + 3]++; } + if (h3 >= 5) { c[offset3 + i * scale + 4]++; } + if (h3 >= 6) { c[offset3 + i * scale + 5]++; } + if (h3 >= 7) { c[offset3 + i * scale + 6]++; } + if (h3 >= 8) { c[offset3 + i * scale + 7]++; } + if (h3 >= 9) { c[offset3 + i * scale + 8]++; } + if (h3 >= 10) { c[offset3 + i * scale + 9]++; } + if (h3 >= 11) { c[offset3 + i * scale + 10]++; } + if (h3 >= 12) { c[offset3 + i * scale + 11]++; } + if (h3 >= 13) { c[offset3 + i * scale + 12]++; } + if (h3 >= 14) { c[offset3 + i * scale + 13]++; } + if (h3 >= 15) { c[offset3 + i * scale + 14]++; } + if (h3 >= 16) { c[offset3 + i * scale + 15]++; } + } + return new Object[]{ a, b, c }; + } + + static Object[] testDDBCFH(byte[] a, char[] b, float[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + int h1 = hand_unrolling1_con(); + int h2 = hand_unrolling2_con(); + int h3 = hand_unrolling3_con(); + + for (int i = limit; i > init; i -= stride) { + if (h1 >= 1) { a[offset1 + i * scale + 0]++; } + if (h1 >= 2) { a[offset1 + i * scale + 1]++; } + if (h1 >= 3) { a[offset1 + i * scale + 2]++; } + if (h1 >= 4) { a[offset1 + i * scale + 3]++; } + if (h1 >= 5) { a[offset1 + i * scale + 4]++; } + if (h1 >= 6) { a[offset1 + i * scale + 5]++; } + if (h1 >= 7) { a[offset1 + i * scale + 6]++; } + if (h1 >= 8) { a[offset1 + i * scale + 7]++; } + if (h1 >= 9) { a[offset1 + i * scale + 8]++; } + if (h1 >= 10) { a[offset1 + i * scale + 9]++; } + if (h1 >= 11) { a[offset1 + i * scale + 10]++; } + if (h1 >= 12) { a[offset1 + i * scale + 11]++; } + if (h1 >= 13) { a[offset1 + i * scale + 12]++; } + if (h1 >= 14) { a[offset1 + i * scale + 13]++; } + if (h1 >= 15) { a[offset1 + i * scale + 14]++; } + if (h1 >= 16) { a[offset1 + i * scale + 15]++; } + + if (h2 >= 1) { b[offset2 + i * scale + 0]++; } + if (h2 >= 2) { b[offset2 + i * scale + 1]++; } + if (h2 >= 3) { b[offset2 + i * scale + 2]++; } + if (h2 >= 4) { b[offset2 + i * scale + 3]++; } + if (h2 >= 5) { b[offset2 + i * scale + 4]++; } + if (h2 >= 6) { b[offset2 + i * scale + 5]++; } + if (h2 >= 7) { b[offset2 + i * scale + 6]++; } + if (h2 >= 8) { b[offset2 + i * scale + 7]++; } + if (h2 >= 9) { b[offset2 + i * scale + 8]++; } + if (h2 >= 10) { b[offset2 + i * scale + 9]++; } + if (h2 >= 11) { b[offset2 + i * scale + 10]++; } + if (h2 >= 12) { b[offset2 + i * scale + 11]++; } + if (h2 >= 13) { b[offset2 + i * scale + 12]++; } + if (h2 >= 14) { b[offset2 + i * scale + 13]++; } + if (h2 >= 15) { b[offset2 + i * scale + 14]++; } + if (h2 >= 16) { b[offset2 + i * scale + 15]++; } + + if (h3 >= 1) { c[offset3 + i * scale + 0]++; } + if (h3 >= 2) { c[offset3 + i * scale + 1]++; } + if (h3 >= 3) { c[offset3 + i * scale + 2]++; } + if (h3 >= 4) { c[offset3 + i * scale + 3]++; } + if (h3 >= 5) { c[offset3 + i * scale + 4]++; } + if (h3 >= 6) { c[offset3 + i * scale + 5]++; } + if (h3 >= 7) { c[offset3 + i * scale + 6]++; } + if (h3 >= 8) { c[offset3 + i * scale + 7]++; } + if (h3 >= 9) { c[offset3 + i * scale + 8]++; } + if (h3 >= 10) { c[offset3 + i * scale + 9]++; } + if (h3 >= 11) { c[offset3 + i * scale + 10]++; } + if (h3 >= 12) { c[offset3 + i * scale + 11]++; } + if (h3 >= 13) { c[offset3 + i * scale + 12]++; } + if (h3 >= 14) { c[offset3 + i * scale + 13]++; } + if (h3 >= 15) { c[offset3 + i * scale + 14]++; } + if (h3 >= 16) { c[offset3 + i * scale + 15]++; } + } + return new Object[]{ a, b, c }; + } + + static Object[] testUDBCFH(byte[] a, char[] b, float[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int x1 = opposite_direction_offset1_con_or_var(); + int x2 = opposite_direction_offset2_con_or_var(); + int x3 = opposite_direction_offset3_con_or_var(); + + int h1 = hand_unrolling1_con(); + int h2 = hand_unrolling2_con(); + int h3 = hand_unrolling3_con(); + + for (int i = init; i < limit; i += stride) { + if (h1 >= 1) { a[x1 - i * scale + 0]++; } + if (h1 >= 2) { a[x1 - i * scale + 1]++; } + if (h1 >= 3) { a[x1 - i * scale + 2]++; } + if (h1 >= 4) { a[x1 - i * scale + 3]++; } + if (h1 >= 5) { a[x1 - i * scale + 4]++; } + if (h1 >= 6) { a[x1 - i * scale + 5]++; } + if (h1 >= 7) { a[x1 - i * scale + 6]++; } + if (h1 >= 8) { a[x1 - i * scale + 7]++; } + if (h1 >= 9) { a[x1 - i * scale + 8]++; } + if (h1 >= 10) { a[x1 - i * scale + 9]++; } + if (h1 >= 11) { a[x1 - i * scale + 10]++; } + if (h1 >= 12) { a[x1 - i * scale + 11]++; } + if (h1 >= 13) { a[x1 - i * scale + 12]++; } + if (h1 >= 14) { a[x1 - i * scale + 13]++; } + if (h1 >= 15) { a[x1 - i * scale + 14]++; } + if (h1 >= 16) { a[x1 - i * scale + 15]++; } + + if (h2 >= 1) { b[x2 - i * scale + 0]++; } + if (h2 >= 2) { b[x2 - i * scale + 1]++; } + if (h2 >= 3) { b[x2 - i * scale + 2]++; } + if (h2 >= 4) { b[x2 - i * scale + 3]++; } + if (h2 >= 5) { b[x2 - i * scale + 4]++; } + if (h2 >= 6) { b[x2 - i * scale + 5]++; } + if (h2 >= 7) { b[x2 - i * scale + 6]++; } + if (h2 >= 8) { b[x2 - i * scale + 7]++; } + if (h2 >= 9) { b[x2 - i * scale + 8]++; } + if (h2 >= 10) { b[x2 - i * scale + 9]++; } + if (h2 >= 11) { b[x2 - i * scale + 10]++; } + if (h2 >= 12) { b[x2 - i * scale + 11]++; } + if (h2 >= 13) { b[x2 - i * scale + 12]++; } + if (h2 >= 14) { b[x2 - i * scale + 13]++; } + if (h2 >= 15) { b[x2 - i * scale + 14]++; } + if (h2 >= 16) { b[x2 - i * scale + 15]++; } + + if (h3 >= 1) { c[x3 - i * scale + 0]++; } + if (h3 >= 2) { c[x3 - i * scale + 1]++; } + if (h3 >= 3) { c[x3 - i * scale + 2]++; } + if (h3 >= 4) { c[x3 - i * scale + 3]++; } + if (h3 >= 5) { c[x3 - i * scale + 4]++; } + if (h3 >= 6) { c[x3 - i * scale + 5]++; } + if (h3 >= 7) { c[x3 - i * scale + 6]++; } + if (h3 >= 8) { c[x3 - i * scale + 7]++; } + if (h3 >= 9) { c[x3 - i * scale + 8]++; } + if (h3 >= 10) { c[x3 - i * scale + 9]++; } + if (h3 >= 11) { c[x3 - i * scale + 10]++; } + if (h3 >= 12) { c[x3 - i * scale + 11]++; } + if (h3 >= 13) { c[x3 - i * scale + 12]++; } + if (h3 >= 14) { c[x3 - i * scale + 13]++; } + if (h3 >= 15) { c[x3 - i * scale + 14]++; } + if (h3 >= 16) { c[x3 - i * scale + 15]++; } + } + return new Object[]{ a, b, c }; + } + + static Object[] testDUBCFH(byte[] a, char[] b, float[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int x1 = opposite_direction_offset1_con_or_var(); + int x2 = opposite_direction_offset2_con_or_var(); + int x3 = opposite_direction_offset3_con_or_var(); + + int h1 = hand_unrolling1_con(); + int h2 = hand_unrolling2_con(); + int h3 = hand_unrolling3_con(); + + for (int i = limit; i > init; i -= stride) { + if (h1 >= 1) { a[x1 - i * scale + 0]++; } + if (h1 >= 2) { a[x1 - i * scale + 1]++; } + if (h1 >= 3) { a[x1 - i * scale + 2]++; } + if (h1 >= 4) { a[x1 - i * scale + 3]++; } + if (h1 >= 5) { a[x1 - i * scale + 4]++; } + if (h1 >= 6) { a[x1 - i * scale + 5]++; } + if (h1 >= 7) { a[x1 - i * scale + 6]++; } + if (h1 >= 8) { a[x1 - i * scale + 7]++; } + if (h1 >= 9) { a[x1 - i * scale + 8]++; } + if (h1 >= 10) { a[x1 - i * scale + 9]++; } + if (h1 >= 11) { a[x1 - i * scale + 10]++; } + if (h1 >= 12) { a[x1 - i * scale + 11]++; } + if (h1 >= 13) { a[x1 - i * scale + 12]++; } + if (h1 >= 14) { a[x1 - i * scale + 13]++; } + if (h1 >= 15) { a[x1 - i * scale + 14]++; } + if (h1 >= 16) { a[x1 - i * scale + 15]++; } + + if (h2 >= 1) { b[x2 - i * scale + 0]++; } + if (h2 >= 2) { b[x2 - i * scale + 1]++; } + if (h2 >= 3) { b[x2 - i * scale + 2]++; } + if (h2 >= 4) { b[x2 - i * scale + 3]++; } + if (h2 >= 5) { b[x2 - i * scale + 4]++; } + if (h2 >= 6) { b[x2 - i * scale + 5]++; } + if (h2 >= 7) { b[x2 - i * scale + 6]++; } + if (h2 >= 8) { b[x2 - i * scale + 7]++; } + if (h2 >= 9) { b[x2 - i * scale + 8]++; } + if (h2 >= 10) { b[x2 - i * scale + 9]++; } + if (h2 >= 11) { b[x2 - i * scale + 10]++; } + if (h2 >= 12) { b[x2 - i * scale + 11]++; } + if (h2 >= 13) { b[x2 - i * scale + 12]++; } + if (h2 >= 14) { b[x2 - i * scale + 13]++; } + if (h2 >= 15) { b[x2 - i * scale + 14]++; } + if (h2 >= 16) { b[x2 - i * scale + 15]++; } + + if (h3 >= 1) { c[x3 - i * scale + 0]++; } + if (h3 >= 2) { c[x3 - i * scale + 1]++; } + if (h3 >= 3) { c[x3 - i * scale + 2]++; } + if (h3 >= 4) { c[x3 - i * scale + 3]++; } + if (h3 >= 5) { c[x3 - i * scale + 4]++; } + if (h3 >= 6) { c[x3 - i * scale + 5]++; } + if (h3 >= 7) { c[x3 - i * scale + 6]++; } + if (h3 >= 8) { c[x3 - i * scale + 7]++; } + if (h3 >= 9) { c[x3 - i * scale + 8]++; } + if (h3 >= 10) { c[x3 - i * scale + 9]++; } + if (h3 >= 11) { c[x3 - i * scale + 10]++; } + if (h3 >= 12) { c[x3 - i * scale + 11]++; } + if (h3 >= 13) { c[x3 - i * scale + 12]++; } + if (h3 >= 14) { c[x3 - i * scale + 13]++; } + if (h3 >= 15) { c[x3 - i * scale + 14]++; } + if (h3 >= 16) { c[x3 - i * scale + 15]++; } + } + return new Object[]{ a, b, c }; + } + + // -------------------- MIXED DIRECTION TRIPPLE -------------------- + + static Object[] testMMSFD(short[] a, float[] b, double[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = opposite_direction_offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + for (int i = init; i < limit; i += stride) { + a[offset1 + i * scale]++; + b[offset2 - i * scale]++; + c[offset3 + i * scale]++; + } + return new Object[]{ a, b, c }; + } + + // -------------------- UNSAFE -------------------- + + static Object[] testUU_unsafe_BasI(byte[] a) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset = offset1_con_or_var(); + + for (int i = init; i < limit; i += stride) { + int adr = UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset + i * scale; + int v = UNSAFE.getIntUnaligned(a, adr); + UNSAFE.putIntUnaligned(a, adr, v + 1); + } + return new Object[]{ a }; + } + + static Object[] testUU_unsafe_BasIH(byte[] a, byte[] b, byte[] c) { + int init = init_con_or_var(); + int limit = limit_con_or_var(); + int stride = stride_con(); + int scale = scale_con(); + int offset1 = offset1_con_or_var(); + int offset2 = offset2_con_or_var(); + int offset3 = offset3_con_or_var(); + + int h1 = hand_unrolling1_con(); + int h2 = hand_unrolling2_con(); + int h3 = hand_unrolling3_con(); + + for (int i = init; i < limit; i += stride) { + int adr1 = UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset1 + i * scale; + int adr2 = UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset2 + i * scale; + int adr3 = UNSAFE.ARRAY_BYTE_BASE_OFFSET + offset3 + i * scale; + + if (h1 >= 1) { UNSAFE.putIntUnaligned(a, adr1 + 0*4, UNSAFE.getIntUnaligned(a, adr1 + 0*4) + 1); } + if (h1 >= 2) { UNSAFE.putIntUnaligned(a, adr1 + 1*4, UNSAFE.getIntUnaligned(a, adr1 + 1*4) + 1); } + if (h1 >= 3) { UNSAFE.putIntUnaligned(a, adr1 + 2*4, UNSAFE.getIntUnaligned(a, adr1 + 2*4) + 1); } + if (h1 >= 4) { UNSAFE.putIntUnaligned(a, adr1 + 3*4, UNSAFE.getIntUnaligned(a, adr1 + 3*4) + 1); } + if (h1 >= 5) { UNSAFE.putIntUnaligned(a, adr1 + 4*4, UNSAFE.getIntUnaligned(a, adr1 + 4*4) + 1); } + if (h1 >= 6) { UNSAFE.putIntUnaligned(a, adr1 + 5*4, UNSAFE.getIntUnaligned(a, adr1 + 5*4) + 1); } + if (h1 >= 7) { UNSAFE.putIntUnaligned(a, adr1 + 6*4, UNSAFE.getIntUnaligned(a, adr1 + 6*4) + 1); } + if (h1 >= 8) { UNSAFE.putIntUnaligned(a, adr1 + 7*4, UNSAFE.getIntUnaligned(a, adr1 + 7*4) + 1); } + if (h1 >= 9) { UNSAFE.putIntUnaligned(a, adr1 + 8*4, UNSAFE.getIntUnaligned(a, adr1 + 8*4) + 1); } + if (h1 >= 10) { UNSAFE.putIntUnaligned(a, adr1 + 9*4, UNSAFE.getIntUnaligned(a, adr1 + 9*4) + 1); } + if (h1 >= 11) { UNSAFE.putIntUnaligned(a, adr1 + 10*4, UNSAFE.getIntUnaligned(a, adr1 + 10*4) + 1); } + if (h1 >= 12) { UNSAFE.putIntUnaligned(a, adr1 + 11*4, UNSAFE.getIntUnaligned(a, adr1 + 11*4) + 1); } + if (h1 >= 13) { UNSAFE.putIntUnaligned(a, adr1 + 12*4, UNSAFE.getIntUnaligned(a, adr1 + 12*4) + 1); } + if (h1 >= 14) { UNSAFE.putIntUnaligned(a, adr1 + 13*4, UNSAFE.getIntUnaligned(a, adr1 + 13*4) + 1); } + if (h1 >= 15) { UNSAFE.putIntUnaligned(a, adr1 + 14*4, UNSAFE.getIntUnaligned(a, adr1 + 14*4) + 1); } + if (h1 >= 16) { UNSAFE.putIntUnaligned(a, adr1 + 15*4, UNSAFE.getIntUnaligned(a, adr1 + 15*4) + 1); } + + if (h2 >= 1) { UNSAFE.putIntUnaligned(b, adr2 + 0*4, UNSAFE.getIntUnaligned(b, adr2 + 0*4) + 1); } + if (h2 >= 2) { UNSAFE.putIntUnaligned(b, adr2 + 1*4, UNSAFE.getIntUnaligned(b, adr2 + 1*4) + 1); } + if (h2 >= 3) { UNSAFE.putIntUnaligned(b, adr2 + 2*4, UNSAFE.getIntUnaligned(b, adr2 + 2*4) + 1); } + if (h2 >= 4) { UNSAFE.putIntUnaligned(b, adr2 + 3*4, UNSAFE.getIntUnaligned(b, adr2 + 3*4) + 1); } + if (h2 >= 5) { UNSAFE.putIntUnaligned(b, adr2 + 4*4, UNSAFE.getIntUnaligned(b, adr2 + 4*4) + 1); } + if (h2 >= 6) { UNSAFE.putIntUnaligned(b, adr2 + 5*4, UNSAFE.getIntUnaligned(b, adr2 + 5*4) + 1); } + if (h2 >= 7) { UNSAFE.putIntUnaligned(b, adr2 + 6*4, UNSAFE.getIntUnaligned(b, adr2 + 6*4) + 1); } + if (h2 >= 8) { UNSAFE.putIntUnaligned(b, adr2 + 7*4, UNSAFE.getIntUnaligned(b, adr2 + 7*4) + 1); } + if (h2 >= 9) { UNSAFE.putIntUnaligned(b, adr2 + 8*4, UNSAFE.getIntUnaligned(b, adr2 + 8*4) + 1); } + if (h2 >= 10) { UNSAFE.putIntUnaligned(b, adr2 + 9*4, UNSAFE.getIntUnaligned(b, adr2 + 9*4) + 1); } + if (h2 >= 11) { UNSAFE.putIntUnaligned(b, adr2 + 10*4, UNSAFE.getIntUnaligned(b, adr2 + 10*4) + 1); } + if (h2 >= 12) { UNSAFE.putIntUnaligned(b, adr2 + 11*4, UNSAFE.getIntUnaligned(b, adr2 + 11*4) + 1); } + if (h2 >= 13) { UNSAFE.putIntUnaligned(b, adr2 + 12*4, UNSAFE.getIntUnaligned(b, adr2 + 12*4) + 1); } + if (h2 >= 14) { UNSAFE.putIntUnaligned(b, adr2 + 13*4, UNSAFE.getIntUnaligned(b, adr2 + 13*4) + 1); } + if (h2 >= 15) { UNSAFE.putIntUnaligned(b, adr2 + 14*4, UNSAFE.getIntUnaligned(b, adr2 + 14*4) + 1); } + if (h2 >= 16) { UNSAFE.putIntUnaligned(b, adr2 + 15*4, UNSAFE.getIntUnaligned(b, adr2 + 15*4) + 1); } + + if (h3 >= 1) { UNSAFE.putIntUnaligned(c, adr3 + 0*4, UNSAFE.getIntUnaligned(c, adr3 + 0*4) + 1); } + if (h3 >= 2) { UNSAFE.putIntUnaligned(c, adr3 + 1*4, UNSAFE.getIntUnaligned(c, adr3 + 1*4) + 1); } + if (h3 >= 3) { UNSAFE.putIntUnaligned(c, adr3 + 2*4, UNSAFE.getIntUnaligned(c, adr3 + 2*4) + 1); } + if (h3 >= 4) { UNSAFE.putIntUnaligned(c, adr3 + 3*4, UNSAFE.getIntUnaligned(c, adr3 + 3*4) + 1); } + if (h3 >= 5) { UNSAFE.putIntUnaligned(c, adr3 + 4*4, UNSAFE.getIntUnaligned(c, adr3 + 4*4) + 1); } + if (h3 >= 6) { UNSAFE.putIntUnaligned(c, adr3 + 5*4, UNSAFE.getIntUnaligned(c, adr3 + 5*4) + 1); } + if (h3 >= 7) { UNSAFE.putIntUnaligned(c, adr3 + 6*4, UNSAFE.getIntUnaligned(c, adr3 + 6*4) + 1); } + if (h3 >= 8) { UNSAFE.putIntUnaligned(c, adr3 + 7*4, UNSAFE.getIntUnaligned(c, adr3 + 7*4) + 1); } + if (h3 >= 9) { UNSAFE.putIntUnaligned(c, adr3 + 8*4, UNSAFE.getIntUnaligned(c, adr3 + 8*4) + 1); } + if (h3 >= 10) { UNSAFE.putIntUnaligned(c, adr3 + 9*4, UNSAFE.getIntUnaligned(c, adr3 + 9*4) + 1); } + if (h3 >= 11) { UNSAFE.putIntUnaligned(c, adr3 + 10*4, UNSAFE.getIntUnaligned(c, adr3 + 10*4) + 1); } + if (h3 >= 12) { UNSAFE.putIntUnaligned(c, adr3 + 11*4, UNSAFE.getIntUnaligned(c, adr3 + 11*4) + 1); } + if (h3 >= 13) { UNSAFE.putIntUnaligned(c, adr3 + 12*4, UNSAFE.getIntUnaligned(c, adr3 + 12*4) + 1); } + if (h3 >= 14) { UNSAFE.putIntUnaligned(c, adr3 + 13*4, UNSAFE.getIntUnaligned(c, adr3 + 13*4) + 1); } + if (h3 >= 15) { UNSAFE.putIntUnaligned(c, adr3 + 14*4, UNSAFE.getIntUnaligned(c, adr3 + 14*4) + 1); } + if (h3 >= 16) { UNSAFE.putIntUnaligned(c, adr3 + 15*4, UNSAFE.getIntUnaligned(c, adr3 + 15*4) + 1); } + } + return new Object[]{ a, b, c }; + } + + static byte[] generateB() { + byte[] a = new byte[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = (byte)random.nextInt(); + } + return a; + } + + static char[] generateC() { + char[] a = new char[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = (char)random.nextInt(); + } + return a; + } + + static short[] generateS() { + short[] a = new short[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = (short)random.nextInt(); + } + return a; + } + + static int[] generateI() { + int[] a = new int[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = random.nextInt(); + } + return a; + } + + static long[] generateL() { + long[] a = new long[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = random.nextLong(); + } + return a; + } + + static float[] generateF() { + float[] a = new float[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = Float.intBitsToFloat(random.nextInt()); + } + return a; + } + + static double[] generateD() { + double[] a = new double[RANGE_CON]; + for (int i = 0; i < a.length; i++) { + a[i] = Double.longBitsToDouble(random.nextLong()); + } + return a; + } + + static void verify(String name, Object[] gold, Object[] result) { + if (gold.length != result.length) { + throw new RuntimeException("verify " + name + ": not the same number of outputs: gold.length = " + + gold.length + ", result.length = " + result.length); + } + for (int i = 0; i < gold.length; i++) { + Object g = gold[i]; + Object r = result[i]; + if (g.getClass() != r.getClass() || !g.getClass().isArray() || !r.getClass().isArray()) { + throw new RuntimeException("verify " + name + ": must both be array of same type:" + + " gold[" + i + "].getClass() = " + g.getClass().getSimpleName() + + " result[" + i + "].getClass() = " + r.getClass().getSimpleName()); + } + if (g == r) { + throw new RuntimeException("verify " + name + ": should be two separate arrays (with identical content):" + + " gold[" + i + "] == result[" + i + "]"); + } + if (Array.getLength(g) != Array.getLength(r)) { + throw new RuntimeException("verify " + name + ": arrays must have same length:" + + " gold[" + i + "].length = " + Array.getLength(g) + + " result[" + i + "].length = " + Array.getLength(r)); + } + Class c = g.getClass().getComponentType(); + if (c == byte.class) { + verifyB(name, i, (byte[])g, (byte[])r); + } else if (c == char.class) { + verifyC(name, i, (char[])g, (char[])r); + } else if (c == short.class) { + verifyS(name, i, (short[])g, (short[])r); + } else if (c == int.class) { + verifyI(name, i, (int[])g, (int[])r); + } else if (c == long.class) { + verifyL(name, i, (long[])g, (long[])r); + } else if (c == float.class) { + verifyF(name, i, (float[])g, (float[])r); + } else if (c == double.class) { + verifyD(name, i, (double[])g, (double[])r); + } else { + throw new RuntimeException("verify " + name + ": array type not supported for verify:" + + " gold[" + i + "].getClass() = " + g.getClass().getSimpleName() + + " result[" + i + "].getClass() = " + r.getClass().getSimpleName()); + } + } + } + + static void verifyB(String name, int i, byte[] g, byte[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verifyB " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyC(String name, int i, char[] g, char[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verifyC " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyS(String name, int i, short[] g, short[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verifyS " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyI(String name, int i, int[] g, int[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verifyI " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyL(String name, int i, long[] g, long[] r) { + for (int j = 0; j < g.length; j++) { + if (g[j] != r[j]) { + throw new RuntimeException("verifyL " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + g[j] + + " result[" + i + "][" + j + "] = " + r[j]); + } + } + } + + static void verifyF(String name, int i, float[] g, float[] r) { + for (int j = 0; j < g.length; j++) { + int gv = UNSAFE.getInt(g, UNSAFE.ARRAY_FLOAT_BASE_OFFSET + 4 * j); + int rv = UNSAFE.getInt(r, UNSAFE.ARRAY_FLOAT_BASE_OFFSET + 4 * j); + if (gv != rv) { + throw new RuntimeException("verifyF " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + gv + + " result[" + i + "][" + j + "] = " + rv); + } + } + } + + static void verifyD(String name, int i, double[] g, double[] r) { + for (int j = 0; j < g.length; j++) { + long gv = UNSAFE.getLong(g, UNSAFE.ARRAY_DOUBLE_BASE_OFFSET + 8 * j); + long rv = UNSAFE.getLong(r, UNSAFE.ARRAY_DOUBLE_BASE_OFFSET + 8 * j); + if (gv != rv) { + throw new RuntimeException("verifyF " + name + ": arrays must have same content:" + + " gold[" + i + "][" + j + "] = " + gv + + " result[" + i + "][" + j + "] = " + rv); + } + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java index 105b07b875874..1e48ae071069f 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -27,7 +27,7 @@ * and various MaxVectorSize values, and +- AlignVector. * * Note: this test is auto-generated. Please modify / generate with script: - * https://bugs.openjdk.org/browse/JDK-8312570 + * https://bugs.openjdk.org/browse/JDK-8310190 * * Types: int, long, short, char, byte, float, double * Offsets: 0, -1, 1, -2, 2, -3, 3, -4, 4, -7, 7, -8, 8, -14, 14, -16, 16, -18, 18, -20, 20, -31, 31, -32, 32, -63, 63, -64, 64, -65, 65, -128, 128, -129, 129, -192, 192 @@ -49,8 +49,7 @@ * Note: sizeofop(type) = sizeof(type), except sizeofop(char) = 2 * * Different types can lead to different vector_width. This depends on - * the CPU-features. Thus, we have a positive and negative IR rule per - * CPU-feature for each test. + * the CPU-features. * * Definition: * MaxVectorSize: limit through flag @@ -66,31 +65,53 @@ * or some additional optimization collapses some Loads, and suddenly cyclic * dependency disappears, and we can vectorize. * - * With '-XX:+AlignVector', we would like to check that we vectorize exactly iff: - * byte_offset % actual_vector_width == 0 - * Because all vector_widths are powers of 2, this is equivalent to: - * pow2_factor(byte_offset) >= actual_vector_width - * where pow2_factor computes the largest power of 2 that is a factor of the number. + * With '-XX:+AlignVector' we do the following: * - * Under these assumptions, we know there must be vectorization: - * pow2_factor(byte_offset) >= vector_width + * Must vectorize cleanly if: + * 1) guaranteed no misalignment AND + * 2) guaratneed no cyclic dependency + * + * Must not vectorize at all if: + * 1) guaranteed misalignment AND + * 2) guaranteed no cyclic dependency + * + * We could imagine a case with cyclic dependency, where C2 detects + * that only the first load is needed, and so no vectorization is + * required for it, and hence the store vector can be aligned. + * + * The alignment criteria is + * byte_offset % aw == 0 + * where align width (aw) is + * aw = min(actual_vector_width, ObjectAlignmentInBytes) + * For simplicity, we assume that ObjectAlignmentInBytes == 8, + * which currently can only be changed manually and then no IR + * rule is run. + * This allows us to do the computation statically. + * Further, we define: + * aw_min = min(min_vector_width, ObjectAlignmentInBytes) + * aw_max = min(vector_width, ObjectAlignmentInBytes) + * aw_min <= aw <= aw_max + * + * Again, we have no cyclic dependency, except when: + * byte_offset > 0 and p.vector_width > byte_offset + * Here we must ensure that: + * byte_offset >= MaxVectorSize + * + * Guaranteed no misalignment: + * byte_offset % aw_max == 0 * implies - * pow2_factor(byte_offset) >= actual_vector_width - * MaxVectorSize >= min_vector_size - * else any vectorization is impossible. + * byte_offset % aw == 0 * - * And under the following conditions no vectorization is possible: - * byte_offset < 0: No cyclic dependency. - * Cyclic dependency could lead to Load removals, then only the store is vectorized. - * byte_offset % min_vector_width != 0 + * Guaranteed misalignment: + * byte_offset % aw_min != 0 * implies - * byte_offset % actual_vector_width != 0 + * byte_offset % aw != 0 * */ /* * @test id=vanilla-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @library /test/lib / @@ -99,7 +120,7 @@ /* * @test id=vanilla-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @library /test/lib / @@ -108,7 +129,7 @@ /* * @test id=sse4-v016-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -119,7 +140,7 @@ /* * @test id=sse4-v016-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -130,7 +151,7 @@ /* * @test id=sse4-v008-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -141,7 +162,7 @@ /* * @test id=sse4-v008-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -152,7 +173,7 @@ /* * @test id=sse4-v004-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -163,7 +184,7 @@ /* * @test id=sse4-v004-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -174,7 +195,7 @@ /* * @test id=sse4-v002-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -185,7 +206,7 @@ /* * @test id=sse4-v002-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -196,7 +217,7 @@ /* * @test id=avx1-v032-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -207,7 +228,7 @@ /* * @test id=avx1-v032-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -218,7 +239,7 @@ /* * @test id=avx1-v016-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -229,7 +250,7 @@ /* * @test id=avx1-v016-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -240,7 +261,7 @@ /* * @test id=avx2-v032-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -251,7 +272,7 @@ /* * @test id=avx2-v032-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -262,7 +283,7 @@ /* * @test id=avx2-v016-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -273,7 +294,7 @@ /* * @test id=avx2-v016-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -284,7 +305,7 @@ /* * @test id=avx512-v064-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -295,7 +316,7 @@ /* * @test id=avx512-v064-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -306,7 +327,7 @@ /* * @test id=avx512-v032-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -317,7 +338,7 @@ /* * @test id=avx512-v032-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -328,7 +349,7 @@ /* * @test id=avx512bw-v064-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -339,7 +360,7 @@ /* * @test id=avx512bw-v064-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -350,7 +371,7 @@ /* * @test id=avx512bw-v032-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -361,7 +382,7 @@ /* * @test id=avx512bw-v032-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -372,7 +393,7 @@ /* * @test id=vec-v064-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -382,7 +403,7 @@ /* * @test id=vec-v064-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -392,7 +413,7 @@ /* * @test id=vec-v032-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -402,7 +423,7 @@ /* * @test id=vec-v032-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -412,7 +433,7 @@ /* * @test id=vec-v016-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -422,7 +443,7 @@ /* * @test id=vec-v016-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -432,7 +453,7 @@ /* * @test id=vec-v008-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -442,7 +463,7 @@ /* * @test id=vec-v008-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -452,7 +473,7 @@ /* * @test id=vec-v004-A - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -462,7 +483,7 @@ /* * @test id=vec-v004-U - * @bug 8298935 8308606 8310308 8312570 + * @bug 8298935 8308606 8310308 8312570 8310190 * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -1392,22 +1413,42 @@ public static void main(String args[]) { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP0(int[] data) { for (int j = 0; j < RANGE; j++) { data[j + 0] = (int)(data[j] * (int)-11); @@ -1428,7 +1469,7 @@ public static void runIntP0() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -1436,7 +1477,7 @@ public static void runIntP0() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -1444,7 +1485,7 @@ public static void runIntP0() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -1452,7 +1493,7 @@ public static void runIntP0() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -1460,7 +1501,7 @@ public static void runIntP0() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -1483,18 +1524,38 @@ public static void runIntM1() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP1(int[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (int)(data[j] * (int)-11); @@ -1515,22 +1576,42 @@ public static void runIntP1() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM2(int[] data) { for (int j = 2; j < RANGE; j++) { data[j + -2] = (int)(data[j] * (int)-11); @@ -1550,27 +1631,47 @@ public static void runIntM2() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeature = {"sve", "true"}) public static void testIntP2(int[] data) { for (int j = 0; j < RANGE - 2; j++) { @@ -1592,7 +1693,7 @@ public static void runIntP2() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -1600,7 +1701,7 @@ public static void runIntP2() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -1608,7 +1709,7 @@ public static void runIntP2() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -1616,7 +1717,7 @@ public static void runIntP2() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -1624,7 +1725,7 @@ public static void runIntP2() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -1649,26 +1750,46 @@ public static void runIntM3() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP3(int[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (int)(data[j] * (int)-11); @@ -1689,22 +1810,42 @@ public static void runIntP3() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM4(int[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (int)(data[j] * (int)-11); @@ -1725,7 +1866,7 @@ public static void runIntM4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -1734,16 +1875,24 @@ public static void runIntM4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -1752,6 +1901,10 @@ public static void runIntM4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP4(int[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (int)(data[j] * (int)-11); @@ -1772,7 +1925,7 @@ public static void runIntP4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -1780,7 +1933,7 @@ public static void runIntP4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -1788,7 +1941,7 @@ public static void runIntP4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -1796,7 +1949,7 @@ public static void runIntP4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -1804,7 +1957,7 @@ public static void runIntP4() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -1828,25 +1981,45 @@ public static void runIntM7() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 28"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 28"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 28"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 28"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP7(int[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (int)(data[j] * (int)-11); @@ -1867,22 +2040,42 @@ public static void runIntP7() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM8(int[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (int)(data[j] * (int)-11); @@ -1903,7 +2096,7 @@ public static void runIntM8() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -1911,7 +2104,7 @@ public static void runIntM8() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -1920,11 +2113,15 @@ public static void runIntM8() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -1933,6 +2130,10 @@ public static void runIntM8() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP8(int[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (int)(data[j] * (int)-11); @@ -1953,22 +2154,42 @@ public static void runIntP8() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM14(int[] data) { for (int j = 14; j < RANGE; j++) { data[j + -14] = (int)(data[j] * (int)-11); @@ -1989,24 +2210,44 @@ public static void runIntM14() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP14(int[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (int)(data[j] * (int)-11); @@ -2027,22 +2268,42 @@ public static void runIntP14() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM16(int[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (int)(data[j] * (int)-11); @@ -2063,7 +2324,7 @@ public static void runIntM16() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2071,7 +2332,7 @@ public static void runIntM16() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2079,7 +2340,7 @@ public static void runIntM16() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2087,7 +2348,7 @@ public static void runIntM16() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2096,6 +2357,10 @@ public static void runIntM16() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP16(int[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (int)(data[j] * (int)-11); @@ -2116,22 +2381,42 @@ public static void runIntP16() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM18(int[] data) { for (int j = 18; j < RANGE; j++) { data[j + -18] = (int)(data[j] * (int)-11); @@ -2152,23 +2437,43 @@ public static void runIntM18() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 72 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 72"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 72"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP18(int[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (int)(data[j] * (int)-11); @@ -2189,22 +2494,42 @@ public static void runIntP18() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM20(int[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (int)(data[j] * (int)-11); @@ -2225,7 +2550,7 @@ public static void runIntM20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2233,15 +2558,23 @@ public static void runIntM20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2250,6 +2583,10 @@ public static void runIntM20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 80"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 80"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP20(int[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (int)(data[j] * (int)-11); @@ -2270,7 +2607,7 @@ public static void runIntP20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2278,7 +2615,7 @@ public static void runIntP20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2286,7 +2623,7 @@ public static void runIntP20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2294,7 +2631,7 @@ public static void runIntP20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2302,7 +2639,7 @@ public static void runIntP20() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -2326,23 +2663,43 @@ public static void runIntM31() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 124 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 124"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 124"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP31(int[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (int)(data[j] * (int)-11); @@ -2363,22 +2720,42 @@ public static void runIntP31() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM32(int[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (int)(data[j] * (int)-11); @@ -2399,7 +2776,7 @@ public static void runIntM32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2407,7 +2784,7 @@ public static void runIntM32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2415,7 +2792,7 @@ public static void runIntM32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2423,7 +2800,7 @@ public static void runIntM32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2432,6 +2809,10 @@ public static void runIntM32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP32(int[] data) { for (int j = 0; j < RANGE - 32; j++) { data[j + 32] = (int)(data[j] * (int)-11); @@ -2452,7 +2833,7 @@ public static void runIntP32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2460,7 +2841,7 @@ public static void runIntP32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2468,7 +2849,7 @@ public static void runIntP32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2476,7 +2857,7 @@ public static void runIntP32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2484,7 +2865,7 @@ public static void runIntP32() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -2508,23 +2889,43 @@ public static void runIntM63() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 - // positive byte_offset 252 can lead to cyclic dependency + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 + // positive byte_offset 252 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 252"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 252"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP63(int[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (int)(data[j] * (int)-11); @@ -2545,22 +2946,42 @@ public static void runIntP63() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM64(int[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (int)(data[j] * (int)-11); @@ -2581,7 +3002,7 @@ public static void runIntM64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2589,7 +3010,7 @@ public static void runIntM64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2597,7 +3018,7 @@ public static void runIntM64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2605,7 +3026,7 @@ public static void runIntM64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2613,7 +3034,7 @@ public static void runIntM64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) @@ -2637,7 +3058,7 @@ public static void runIntP64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2645,7 +3066,7 @@ public static void runIntP64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2653,7 +3074,7 @@ public static void runIntP64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2661,7 +3082,7 @@ public static void runIntP64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2669,7 +3090,7 @@ public static void runIntP64() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -2693,22 +3114,42 @@ public static void runIntM65() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP65(int[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (int)(data[j] * (int)-11); @@ -2729,22 +3170,42 @@ public static void runIntP65() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM128(int[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (int)(data[j] * (int)-11); @@ -2765,7 +3226,7 @@ public static void runIntM128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2773,7 +3234,7 @@ public static void runIntM128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2781,7 +3242,7 @@ public static void runIntM128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2789,7 +3250,7 @@ public static void runIntM128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2797,7 +3258,7 @@ public static void runIntM128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) @@ -2821,7 +3282,7 @@ public static void runIntP128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2829,7 +3290,7 @@ public static void runIntP128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2837,7 +3298,7 @@ public static void runIntP128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2845,7 +3306,7 @@ public static void runIntP128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2853,7 +3314,7 @@ public static void runIntP128() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -2877,22 +3338,42 @@ public static void runIntM129() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_I, IRNode.MUL_VI, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntP129(int[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (int)(data[j] * (int)-11); @@ -2913,22 +3394,42 @@ public static void runIntP129() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testIntM192(int[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (int)(data[j] * (int)-11); @@ -2949,7 +3450,7 @@ public static void runIntM192() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -2957,7 +3458,7 @@ public static void runIntM192() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -2965,7 +3466,7 @@ public static void runIntM192() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -2973,7 +3474,7 @@ public static void runIntM192() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -2981,7 +3482,7 @@ public static void runIntM192() { @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0", IRNode.MUL_VI, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) @@ -3005,22 +3506,42 @@ public static void runIntP192() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP0(long[] data) { for (int j = 0; j < RANGE; j++) { data[j + 0] = (long)(data[j] + (long)-11); @@ -3041,41 +3562,41 @@ public static void runLongP0() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM1(long[] data) { for (int j = 1; j < RANGE; j++) { @@ -3096,18 +3617,28 @@ public static void runLongM1() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 2 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: asimd -> vector_width: 16 -> elements in vector: 2 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. public static void testLongP1(long[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (long)(data[j] + (long)-11); @@ -3128,22 +3659,42 @@ public static void runLongP1() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM2(long[] data) { for (int j = 2; j < RANGE; j++) { data[j + -2] = (long)(data[j] + (long)-11); @@ -3164,32 +3715,44 @@ public static void runLongM2() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 16"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 16"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "16"}, + applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 16"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "16"}, + applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongP2(long[] data) { for (int j = 0; j < RANGE - 2; j++) { @@ -3211,41 +3774,41 @@ public static void runLongP2() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM3(long[] data) { for (int j = 3; j < RANGE; j++) { @@ -3267,25 +3830,45 @@ public static void runLongM3() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 // positive byte_offset 24 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 24 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 24 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP3(long[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (long)(data[j] + (long)-11); @@ -3306,22 +3889,42 @@ public static void runLongP3() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM4(long[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (long)(data[j] + (long)-11); @@ -3342,7 +3945,7 @@ public static void runLongM4() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -3350,7 +3953,7 @@ public static void runLongM4() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -3359,11 +3962,15 @@ public static void runLongM4() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -3372,6 +3979,10 @@ public static void runLongM4() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP4(long[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (long)(data[j] + (long)-11); @@ -3392,41 +4003,41 @@ public static void runLongP4() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM7(long[] data) { for (int j = 7; j < RANGE; j++) { @@ -3448,24 +4059,44 @@ public static void runLongM7() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP7(long[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (long)(data[j] + (long)-11); @@ -3486,22 +4117,42 @@ public static void runLongP7() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM8(long[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (long)(data[j] + (long)-11); @@ -3522,7 +4173,7 @@ public static void runLongM8() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -3530,7 +4181,7 @@ public static void runLongM8() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -3538,7 +4189,7 @@ public static void runLongM8() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -3546,7 +4197,7 @@ public static void runLongM8() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -3555,6 +4206,10 @@ public static void runLongM8() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP8(long[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (long)(data[j] + (long)-11); @@ -3575,22 +4230,42 @@ public static void runLongP8() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM14(long[] data) { for (int j = 14; j < RANGE; j++) { data[j + -14] = (long)(data[j] + (long)-11); @@ -3611,7 +4286,7 @@ public static void runLongM14() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -3619,15 +4294,23 @@ public static void runLongM14() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -3636,6 +4319,10 @@ public static void runLongM14() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 112"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 112"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP14(long[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (long)(data[j] + (long)-11); @@ -3656,22 +4343,42 @@ public static void runLongP14() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM16(long[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (long)(data[j] + (long)-11); @@ -3692,7 +4399,7 @@ public static void runLongM16() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -3700,7 +4407,7 @@ public static void runLongM16() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -3708,7 +4415,7 @@ public static void runLongM16() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -3716,7 +4423,7 @@ public static void runLongM16() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -3725,6 +4432,10 @@ public static void runLongM16() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP16(long[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (long)(data[j] + (long)-11); @@ -3745,22 +4456,42 @@ public static void runLongP16() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM18(long[] data) { for (int j = 18; j < RANGE; j++) { data[j + -18] = (long)(data[j] + (long)-11); @@ -3781,7 +4512,7 @@ public static void runLongM18() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -3789,15 +4520,23 @@ public static void runLongM18() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -3806,6 +4545,10 @@ public static void runLongM18() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 144"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 144"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP18(long[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (long)(data[j] + (long)-11); @@ -3826,22 +4569,42 @@ public static void runLongP18() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM20(long[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (long)(data[j] + (long)-11); @@ -3862,7 +4625,7 @@ public static void runLongM20() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -3870,7 +4633,7 @@ public static void runLongM20() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -3878,11 +4641,15 @@ public static void runLongM20() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -3891,6 +4658,10 @@ public static void runLongM20() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 160"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 160"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP20(long[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (long)(data[j] + (long)-11); @@ -3911,41 +4682,41 @@ public static void runLongP20() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM31(long[] data) { for (int j = 31; j < RANGE; j++) { @@ -3967,23 +4738,43 @@ public static void runLongM31() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 248 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 248"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 248"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP31(long[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (long)(data[j] + (long)-11); @@ -4004,22 +4795,42 @@ public static void runLongP31() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM32(long[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (long)(data[j] + (long)-11); @@ -4040,7 +4851,7 @@ public static void runLongM32() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -4048,7 +4859,7 @@ public static void runLongM32() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -4056,7 +4867,7 @@ public static void runLongM32() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -4064,7 +4875,7 @@ public static void runLongM32() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -4072,7 +4883,7 @@ public static void runLongM32() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -4096,41 +4907,41 @@ public static void runLongP32() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM63(long[] data) { for (int j = 63; j < RANGE; j++) { @@ -4152,22 +4963,42 @@ public static void runLongM63() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP63(long[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (long)(data[j] + (long)-11); @@ -4188,22 +5019,42 @@ public static void runLongP63() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM64(long[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (long)(data[j] + (long)-11); @@ -4224,7 +5075,7 @@ public static void runLongM64() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -4232,7 +5083,7 @@ public static void runLongM64() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -4240,7 +5091,7 @@ public static void runLongM64() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -4248,7 +5099,7 @@ public static void runLongM64() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -4256,7 +5107,7 @@ public static void runLongM64() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -4280,41 +5131,41 @@ public static void runLongP64() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM65(long[] data) { for (int j = 65; j < RANGE; j++) { @@ -4336,22 +5187,42 @@ public static void runLongM65() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP65(long[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (long)(data[j] + (long)-11); @@ -4372,22 +5243,42 @@ public static void runLongP65() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM128(long[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (long)(data[j] + (long)-11); @@ -4408,7 +5299,7 @@ public static void runLongM128() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -4416,7 +5307,7 @@ public static void runLongM128() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -4424,7 +5315,7 @@ public static void runLongM128() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -4432,7 +5323,7 @@ public static void runLongM128() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -4440,7 +5331,7 @@ public static void runLongM128() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -4464,41 +5355,41 @@ public static void runLongP128() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_L, IRNode.ADD_VL, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testLongM129(long[] data) { for (int j = 129; j < RANGE; j++) { @@ -4520,22 +5411,42 @@ public static void runLongM129() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongP129(long[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (long)(data[j] + (long)-11); @@ -4556,22 +5467,42 @@ public static void runLongP129() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testLongM192(long[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (long)(data[j] + (long)-11); @@ -4592,7 +5523,7 @@ public static void runLongM192() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -4600,7 +5531,7 @@ public static void runLongM192() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512", "false"}) @@ -4608,7 +5539,7 @@ public static void runLongM192() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -4616,7 +5547,7 @@ public static void runLongM192() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -4624,7 +5555,7 @@ public static void runLongM192() { @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_L, "> 0", IRNode.ADD_VL, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -4648,22 +5579,42 @@ public static void runLongP192() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP0(short[] data) { for (int j = 0; j < RANGE; j++) { data[j + 0] = (short)(data[j] * (short)-11); @@ -4684,7 +5635,7 @@ public static void runShortP0() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -4692,7 +5643,7 @@ public static void runShortP0() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -4700,7 +5651,7 @@ public static void runShortP0() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -4708,7 +5659,7 @@ public static void runShortP0() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -4716,7 +5667,7 @@ public static void runShortP0() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -4739,18 +5690,38 @@ public static void runShortM1() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP1(short[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (short)(data[j] * (short)-11); @@ -4771,22 +5742,27 @@ public static void runShortP1() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testShortM2(short[] data) { for (int j = 2; j < RANGE; j++) { data[j + -2] = (short)(data[j] * (short)-11); @@ -4806,28 +5782,33 @@ public static void runShortM2() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testShortP2(short[] data) { for (int j = 0; j < RANGE - 2; j++) { data[j + 2] = (short)(data[j] * (short)-11); @@ -4848,7 +5829,7 @@ public static void runShortP2() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -4856,7 +5837,7 @@ public static void runShortP2() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -4864,7 +5845,7 @@ public static void runShortP2() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -4872,7 +5853,7 @@ public static void runShortP2() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -4880,7 +5861,7 @@ public static void runShortP2() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -4905,26 +5886,46 @@ public static void runShortM3() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP3(short[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (short)(data[j] * (short)-11); @@ -4945,22 +5946,42 @@ public static void runShortP3() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM4(short[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (short)(data[j] * (short)-11); @@ -4982,26 +6003,46 @@ public static void runShortM4() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP4(short[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (short)(data[j] * (short)-11); @@ -5022,7 +6063,7 @@ public static void runShortP4() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5030,7 +6071,7 @@ public static void runShortP4() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5038,7 +6079,7 @@ public static void runShortP4() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -5046,7 +6087,7 @@ public static void runShortP4() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5054,7 +6095,7 @@ public static void runShortP4() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -5079,26 +6120,46 @@ public static void runShortM7() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP7(short[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (short)(data[j] * (short)-11); @@ -5119,22 +6180,42 @@ public static void runShortP7() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM8(short[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (short)(data[j] * (short)-11); @@ -5155,7 +6236,7 @@ public static void runShortM8() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5164,16 +6245,24 @@ public static void runShortM8() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5182,6 +6271,10 @@ public static void runShortM8() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP8(short[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (short)(data[j] * (short)-11); @@ -5202,22 +6295,27 @@ public static void runShortP8() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testShortM14(short[] data) { for (int j = 14; j < RANGE; j++) { data[j + -14] = (short)(data[j] * (short)-11); @@ -5238,25 +6336,30 @@ public static void runShortM14() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 28"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testShortP14(short[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (short)(data[j] * (short)-11); @@ -5277,22 +6380,42 @@ public static void runShortP14() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM16(short[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (short)(data[j] * (short)-11); @@ -5313,7 +6436,7 @@ public static void runShortM16() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5321,7 +6444,7 @@ public static void runShortM16() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5330,11 +6453,15 @@ public static void runShortM16() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5343,6 +6470,10 @@ public static void runShortM16() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP16(short[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (short)(data[j] * (short)-11); @@ -5363,22 +6494,27 @@ public static void runShortP16() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testShortM18(short[] data) { for (int j = 18; j < RANGE; j++) { data[j + -18] = (short)(data[j] * (short)-11); @@ -5399,24 +6535,29 @@ public static void runShortM18() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 36 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 36"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 36 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 36"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testShortP18(short[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (short)(data[j] * (short)-11); @@ -5437,22 +6578,42 @@ public static void runShortP18() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM20(short[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (short)(data[j] * (short)-11); @@ -5473,24 +6634,44 @@ public static void runShortM20() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 40 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 40 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP20(short[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (short)(data[j] * (short)-11); @@ -5511,7 +6692,7 @@ public static void runShortP20() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5519,7 +6700,7 @@ public static void runShortP20() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5527,7 +6708,7 @@ public static void runShortP20() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -5535,7 +6716,7 @@ public static void runShortP20() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5543,7 +6724,7 @@ public static void runShortP20() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -5567,24 +6748,44 @@ public static void runShortM31() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 62 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 62"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 62"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 62 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 62"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 62"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP31(short[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (short)(data[j] * (short)-11); @@ -5605,22 +6806,42 @@ public static void runShortP31() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM32(short[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (short)(data[j] * (short)-11); @@ -5641,7 +6862,7 @@ public static void runShortM32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5649,7 +6870,7 @@ public static void runShortM32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5657,7 +6878,7 @@ public static void runShortM32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -5665,7 +6886,7 @@ public static void runShortM32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5674,6 +6895,10 @@ public static void runShortM32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP32(short[] data) { for (int j = 0; j < RANGE - 32; j++) { data[j + 32] = (short)(data[j] * (short)-11); @@ -5694,7 +6919,7 @@ public static void runShortP32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5702,7 +6927,7 @@ public static void runShortP32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5710,7 +6935,7 @@ public static void runShortP32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -5718,7 +6943,7 @@ public static void runShortP32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5726,7 +6951,7 @@ public static void runShortP32() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -5750,23 +6975,43 @@ public static void runShortM63() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 126 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 126"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 126"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP63(short[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (short)(data[j] * (short)-11); @@ -5787,22 +7032,42 @@ public static void runShortP63() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM64(short[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (short)(data[j] * (short)-11); @@ -5823,7 +7088,7 @@ public static void runShortM64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5831,7 +7096,7 @@ public static void runShortM64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5839,7 +7104,7 @@ public static void runShortM64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -5847,7 +7112,7 @@ public static void runShortM64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5856,6 +7121,10 @@ public static void runShortM64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP64(short[] data) { for (int j = 0; j < RANGE - 64; j++) { data[j + 64] = (short)(data[j] * (short)-11); @@ -5876,7 +7145,7 @@ public static void runShortP64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -5884,7 +7153,7 @@ public static void runShortP64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -5892,7 +7161,7 @@ public static void runShortP64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -5900,7 +7169,7 @@ public static void runShortP64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -5908,7 +7177,7 @@ public static void runShortP64() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -5932,23 +7201,43 @@ public static void runShortM65() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 130 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 130"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 130"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP65(short[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (short)(data[j] * (short)-11); @@ -5969,22 +7258,42 @@ public static void runShortP65() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM128(short[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (short)(data[j] * (short)-11); @@ -6005,7 +7314,7 @@ public static void runShortM128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6013,7 +7322,7 @@ public static void runShortM128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6021,7 +7330,7 @@ public static void runShortM128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -6029,7 +7338,7 @@ public static void runShortM128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6037,7 +7346,7 @@ public static void runShortM128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) @@ -6061,7 +7370,7 @@ public static void runShortP128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6069,7 +7378,7 @@ public static void runShortP128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6077,7 +7386,7 @@ public static void runShortP128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -6085,7 +7394,7 @@ public static void runShortP128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6093,7 +7402,7 @@ public static void runShortP128() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -6117,22 +7426,42 @@ public static void runShortM129() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_S, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP129(short[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (short)(data[j] * (short)-11); @@ -6153,22 +7482,42 @@ public static void runShortP129() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortM192(short[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (short)(data[j] * (short)-11); @@ -6189,7 +7538,7 @@ public static void runShortM192() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6197,7 +7546,7 @@ public static void runShortM192() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6205,7 +7554,7 @@ public static void runShortM192() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -6213,7 +7562,7 @@ public static void runShortM192() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6221,6 +7570,10 @@ public static void runShortM192() { @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_S, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testShortP192(short[] data) { for (int j = 0; j < RANGE - 192; j++) { data[j + 192] = (short)(data[j] * (short)-11); @@ -6241,24 +7594,44 @@ public static void runShortP192() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - public static void testCharP0(char[] data) { - for (int j = 0; j < RANGE; j++) { + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) + public static void testCharP0(char[] data) { + for (int j = 0; j < RANGE; j++) { data[j + 0] = (char)(data[j] * (char)-11); } } @@ -6277,7 +7650,7 @@ public static void runCharP0() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6285,7 +7658,7 @@ public static void runCharP0() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6293,7 +7666,7 @@ public static void runCharP0() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -6301,7 +7674,7 @@ public static void runCharP0() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6309,7 +7682,7 @@ public static void runCharP0() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -6332,18 +7705,38 @@ public static void runCharM1() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP1(char[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (char)(data[j] * (char)-11); @@ -6364,22 +7757,27 @@ public static void runCharP1() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testCharM2(char[] data) { for (int j = 2; j < RANGE; j++) { data[j + -2] = (char)(data[j] * (char)-11); @@ -6399,28 +7797,33 @@ public static void runCharM2() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testCharP2(char[] data) { for (int j = 0; j < RANGE - 2; j++) { data[j + 2] = (char)(data[j] * (char)-11); @@ -6441,7 +7844,7 @@ public static void runCharP2() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6449,7 +7852,7 @@ public static void runCharP2() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6457,7 +7860,7 @@ public static void runCharP2() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -6465,7 +7868,7 @@ public static void runCharP2() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6473,7 +7876,7 @@ public static void runCharP2() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -6498,26 +7901,46 @@ public static void runCharM3() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 6 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 6"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 6"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP3(char[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (char)(data[j] * (char)-11); @@ -6538,22 +7961,42 @@ public static void runCharP3() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM4(char[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (char)(data[j] * (char)-11); @@ -6575,26 +8018,46 @@ public static void runCharM4() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP4(char[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (char)(data[j] * (char)-11); @@ -6615,7 +8078,7 @@ public static void runCharP4() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6623,7 +8086,7 @@ public static void runCharP4() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6631,7 +8094,7 @@ public static void runCharP4() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -6639,7 +8102,7 @@ public static void runCharP4() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6647,7 +8110,7 @@ public static void runCharP4() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -6672,26 +8135,46 @@ public static void runCharM7() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP7(char[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (char)(data[j] * (char)-11); @@ -6712,22 +8195,42 @@ public static void runCharP7() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM8(char[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (char)(data[j] * (char)-11); @@ -6748,7 +8251,7 @@ public static void runCharM8() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6757,16 +8260,24 @@ public static void runCharM8() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6775,6 +8286,10 @@ public static void runCharM8() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP8(char[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (char)(data[j] * (char)-11); @@ -6795,22 +8310,27 @@ public static void runCharP8() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testCharM14(char[] data) { for (int j = 14; j < RANGE; j++) { data[j + -14] = (char)(data[j] * (char)-11); @@ -6831,25 +8351,30 @@ public static void runCharM14() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 28"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testCharP14(char[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (char)(data[j] * (char)-11); @@ -6870,22 +8395,42 @@ public static void runCharP14() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM16(char[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (char)(data[j] * (char)-11); @@ -6906,7 +8451,7 @@ public static void runCharM16() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -6914,7 +8459,7 @@ public static void runCharM16() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -6923,11 +8468,15 @@ public static void runCharM16() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -6936,6 +8485,10 @@ public static void runCharM16() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP16(char[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (char)(data[j] * (char)-11); @@ -6956,22 +8509,27 @@ public static void runCharP16() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testCharM18(char[] data) { for (int j = 18; j < RANGE; j++) { data[j + -18] = (char)(data[j] * (char)-11); @@ -6992,24 +8550,29 @@ public static void runCharM18() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 36 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 36"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 36 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 36"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testCharP18(char[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (char)(data[j] * (char)-11); @@ -7030,22 +8593,42 @@ public static void runCharP18() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM20(char[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (char)(data[j] * (char)-11); @@ -7066,24 +8649,44 @@ public static void runCharM20() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 40 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 40 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 40"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP20(char[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (char)(data[j] * (char)-11); @@ -7104,7 +8707,7 @@ public static void runCharP20() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7112,7 +8715,7 @@ public static void runCharP20() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7120,7 +8723,7 @@ public static void runCharP20() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7128,7 +8731,7 @@ public static void runCharP20() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7136,7 +8739,7 @@ public static void runCharP20() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -7160,24 +8763,44 @@ public static void runCharM31() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 // positive byte_offset 62 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 62"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 62"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 62 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 62"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 62"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP31(char[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (char)(data[j] * (char)-11); @@ -7198,22 +8821,42 @@ public static void runCharP31() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM32(char[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (char)(data[j] * (char)-11); @@ -7234,7 +8877,7 @@ public static void runCharM32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7242,7 +8885,7 @@ public static void runCharM32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7250,7 +8893,7 @@ public static void runCharM32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7258,7 +8901,7 @@ public static void runCharM32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7267,6 +8910,10 @@ public static void runCharM32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP32(char[] data) { for (int j = 0; j < RANGE - 32; j++) { data[j + 32] = (char)(data[j] * (char)-11); @@ -7287,7 +8934,7 @@ public static void runCharP32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7295,7 +8942,7 @@ public static void runCharP32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7303,7 +8950,7 @@ public static void runCharP32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7311,7 +8958,7 @@ public static void runCharP32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7319,7 +8966,7 @@ public static void runCharP32() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -7343,23 +8990,43 @@ public static void runCharM63() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 126 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 126"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 126"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP63(char[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (char)(data[j] * (char)-11); @@ -7380,22 +9047,42 @@ public static void runCharP63() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM64(char[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (char)(data[j] * (char)-11); @@ -7416,7 +9103,7 @@ public static void runCharM64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7424,7 +9111,7 @@ public static void runCharM64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7432,7 +9119,7 @@ public static void runCharM64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7440,7 +9127,7 @@ public static void runCharM64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7449,6 +9136,10 @@ public static void runCharM64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP64(char[] data) { for (int j = 0; j < RANGE - 64; j++) { data[j + 64] = (char)(data[j] * (char)-11); @@ -7469,7 +9160,7 @@ public static void runCharP64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7477,7 +9168,7 @@ public static void runCharP64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7485,7 +9176,7 @@ public static void runCharP64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7493,7 +9184,7 @@ public static void runCharP64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7501,7 +9192,7 @@ public static void runCharP64() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -7525,23 +9216,43 @@ public static void runCharM65() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 // positive byte_offset 130 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 130"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 130"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP65(char[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (char)(data[j] * (char)-11); @@ -7562,22 +9273,42 @@ public static void runCharP65() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM128(char[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (char)(data[j] * (char)-11); @@ -7598,7 +9329,7 @@ public static void runCharM128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7606,7 +9337,7 @@ public static void runCharM128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7614,7 +9345,7 @@ public static void runCharM128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7622,7 +9353,7 @@ public static void runCharM128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7630,7 +9361,7 @@ public static void runCharM128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) @@ -7654,7 +9385,7 @@ public static void runCharP128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7662,7 +9393,7 @@ public static void runCharP128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7670,7 +9401,7 @@ public static void runCharP128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7678,7 +9409,7 @@ public static void runCharP128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7686,7 +9417,7 @@ public static void runCharP128() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -7710,22 +9441,42 @@ public static void runCharM129() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_C, IRNode.MUL_VS, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP129(char[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (char)(data[j] * (char)-11); @@ -7746,22 +9497,42 @@ public static void runCharP129() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 128 @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharM192(char[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (char)(data[j] * (char)-11); @@ -7782,7 +9553,7 @@ public static void runCharM192() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7790,7 +9561,7 @@ public static void runCharM192() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7798,7 +9569,7 @@ public static void runCharM192() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7806,7 +9577,7 @@ public static void runCharM192() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7814,6 +9585,10 @@ public static void runCharM192() { @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_C, "> 0", IRNode.MUL_VS, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testCharP192(char[] data) { for (int j = 0; j < RANGE - 192; j++) { data[j + 192] = (char)(data[j] * (char)-11); @@ -7834,22 +9609,42 @@ public static void runCharP192() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP0(byte[] data) { for (int j = 0; j < RANGE; j++) { data[j + 0] = (byte)(data[j] * (byte)11); @@ -7870,7 +9665,7 @@ public static void runByteP0() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7878,7 +9673,7 @@ public static void runByteP0() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7886,7 +9681,7 @@ public static void runByteP0() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7894,7 +9689,7 @@ public static void runByteP0() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7902,7 +9697,7 @@ public static void runByteP0() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -7925,18 +9720,38 @@ public static void runByteM1() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 1 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 1"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 1 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 1"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 1 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 1"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 1 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 1"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 1 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 1"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP1(byte[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (byte)(data[j] * (byte)11); @@ -7957,7 +9772,7 @@ public static void runByteP1() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -7965,7 +9780,7 @@ public static void runByteP1() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -7973,7 +9788,7 @@ public static void runByteP1() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -7981,7 +9796,7 @@ public static void runByteP1() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -7989,7 +9804,7 @@ public static void runByteP1() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8012,18 +9827,38 @@ public static void runByteM2() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 2 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 2"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP2(byte[] data) { for (int j = 0; j < RANGE - 2; j++) { data[j + 2] = (byte)(data[j] * (byte)11); @@ -8044,7 +9879,7 @@ public static void runByteP2() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8052,7 +9887,7 @@ public static void runByteP2() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8060,7 +9895,7 @@ public static void runByteP2() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -8068,7 +9903,7 @@ public static void runByteP2() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8076,7 +9911,7 @@ public static void runByteP2() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8099,18 +9934,38 @@ public static void runByteM3() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 3 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 3"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 3 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 3"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 3 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 3"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 3 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 3"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 3 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 3"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP3(byte[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (byte)(data[j] * (byte)11); @@ -8131,22 +9986,27 @@ public static void runByteP3() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testByteM4(byte[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (byte)(data[j] * (byte)11); @@ -8166,28 +10026,33 @@ public static void runByteM4() { // CPU: sse4.1 to avx -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 4 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 4"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testByteP4(byte[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (byte)(data[j] * (byte)11); @@ -8208,7 +10073,7 @@ public static void runByteP4() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8216,7 +10081,7 @@ public static void runByteP4() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8224,7 +10089,7 @@ public static void runByteP4() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -8232,7 +10097,7 @@ public static void runByteP4() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8240,7 +10105,7 @@ public static void runByteP4() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8265,26 +10130,46 @@ public static void runByteM7() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 7"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 7"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 7 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 7"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 7"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 7 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 7"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 7"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 7 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 7"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 7"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 7 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 7"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 7"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP7(byte[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (byte)(data[j] * (byte)11); @@ -8305,22 +10190,42 @@ public static void runByteP7() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteM8(byte[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (byte)(data[j] * (byte)11); @@ -8342,26 +10247,46 @@ public static void runByteM8() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP8(byte[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (byte)(data[j] * (byte)11); @@ -8382,7 +10307,7 @@ public static void runByteP8() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8390,7 +10315,7 @@ public static void runByteP8() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8398,7 +10323,7 @@ public static void runByteP8() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -8406,7 +10331,7 @@ public static void runByteP8() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8414,7 +10339,7 @@ public static void runByteP8() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8439,26 +10364,46 @@ public static void runByteM14() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 14 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 14"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 14"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP14(byte[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (byte)(data[j] * (byte)11); @@ -8479,22 +10424,42 @@ public static void runByteP14() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteM16(byte[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (byte)(data[j] * (byte)11); @@ -8515,7 +10480,7 @@ public static void runByteM16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8524,16 +10489,24 @@ public static void runByteM16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8542,6 +10515,10 @@ public static void runByteM16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP16(byte[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (byte)(data[j] * (byte)11); @@ -8562,7 +10539,7 @@ public static void runByteP16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8570,7 +10547,7 @@ public static void runByteP16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8578,7 +10555,7 @@ public static void runByteP16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -8586,7 +10563,7 @@ public static void runByteP16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8594,7 +10571,7 @@ public static void runByteP16() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8618,25 +10595,45 @@ public static void runByteM18() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 18 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 18"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 18"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 18 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 18"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 18"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 18 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 18"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 18"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP18(byte[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (byte)(data[j] * (byte)11); @@ -8657,22 +10654,27 @@ public static void runByteP18() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testByteM20(byte[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (byte)(data[j] * (byte)11); @@ -8693,25 +10695,30 @@ public static void runByteM20() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 20 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 20"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 20 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 20"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 20 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 20"}, applyIfCPUFeature = {"sve", "true"}) + // Alignment unclear -> no IR rule for -XX:+AlignVector. public static void testByteP20(byte[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (byte)(data[j] * (byte)11); @@ -8732,7 +10739,7 @@ public static void runByteP20() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8740,7 +10747,7 @@ public static void runByteP20() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8748,7 +10755,7 @@ public static void runByteP20() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -8756,7 +10763,7 @@ public static void runByteP20() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8764,7 +10771,7 @@ public static void runByteP20() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8788,25 +10795,45 @@ public static void runByteM31() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 // positive byte_offset 31 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 31"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 31"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 31 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 31"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 31"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 31 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 31"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 31"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP31(byte[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (byte)(data[j] * (byte)11); @@ -8827,22 +10854,42 @@ public static void runByteP31() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteM32(byte[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (byte)(data[j] * (byte)11); @@ -8863,7 +10910,7 @@ public static void runByteM32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8871,7 +10918,7 @@ public static void runByteM32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8880,11 +10927,15 @@ public static void runByteM32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8893,6 +10944,10 @@ public static void runByteM32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP32(byte[] data) { for (int j = 0; j < RANGE - 32; j++) { data[j + 32] = (byte)(data[j] * (byte)11); @@ -8913,7 +10968,7 @@ public static void runByteP32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -8921,7 +10976,7 @@ public static void runByteP32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -8929,7 +10984,7 @@ public static void runByteP32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -8937,7 +10992,7 @@ public static void runByteP32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -8945,7 +11000,7 @@ public static void runByteP32() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -8969,24 +11024,44 @@ public static void runByteM63() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 // positive byte_offset 63 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 63"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 63"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 63 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 63"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 63"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP63(byte[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (byte)(data[j] * (byte)11); @@ -9007,22 +11082,42 @@ public static void runByteP63() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteM64(byte[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (byte)(data[j] * (byte)11); @@ -9043,7 +11138,7 @@ public static void runByteM64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -9051,7 +11146,7 @@ public static void runByteM64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -9059,7 +11154,7 @@ public static void runByteM64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -9067,7 +11162,7 @@ public static void runByteM64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9076,6 +11171,10 @@ public static void runByteM64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP64(byte[] data) { for (int j = 0; j < RANGE - 64; j++) { data[j + 64] = (byte)(data[j] * (byte)11); @@ -9096,7 +11195,7 @@ public static void runByteP64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -9104,7 +11203,7 @@ public static void runByteP64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -9112,7 +11211,7 @@ public static void runByteP64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -9120,7 +11219,7 @@ public static void runByteP64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9128,7 +11227,7 @@ public static void runByteP64() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -9152,23 +11251,43 @@ public static void runByteM65() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 65 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 65"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 65"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP65(byte[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (byte)(data[j] * (byte)11); @@ -9189,22 +11308,42 @@ public static void runByteP65() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteM128(byte[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (byte)(data[j] * (byte)11); @@ -9225,7 +11364,7 @@ public static void runByteM128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -9233,7 +11372,7 @@ public static void runByteM128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -9241,7 +11380,7 @@ public static void runByteM128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -9249,7 +11388,7 @@ public static void runByteM128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9258,6 +11397,10 @@ public static void runByteM128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP128(byte[] data) { for (int j = 0; j < RANGE - 128; j++) { data[j + 128] = (byte)(data[j] * (byte)11); @@ -9278,7 +11421,7 @@ public static void runByteP128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -9286,7 +11429,7 @@ public static void runByteP128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -9294,7 +11437,7 @@ public static void runByteP128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -9302,7 +11445,7 @@ public static void runByteP128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9310,7 +11453,7 @@ public static void runByteP128() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -9334,23 +11477,43 @@ public static void runByteM129() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 // positive byte_offset 129 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 129"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_B, IRNode.MUL_VB, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 129"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP129(byte[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (byte)(data[j] * (byte)11); @@ -9371,22 +11534,42 @@ public static void runByteP129() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) // CPU: avx2 to avx512 without avx512bw -> vector_width: 32 -> elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) // CPU: avx512bw -> vector_width: 64 -> elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"avx512bw", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 256 @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteM192(byte[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (byte)(data[j] * (byte)11); @@ -9407,7 +11590,7 @@ public static void runByteM192() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "false"}) @@ -9415,7 +11598,7 @@ public static void runByteM192() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx512bw", "false"}) @@ -9423,7 +11606,7 @@ public static void runByteM192() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeature = {"avx512bw", "true"}) @@ -9431,7 +11614,7 @@ public static void runByteM192() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9440,6 +11623,10 @@ public static void runByteM192() { @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 192"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_B, "> 0", IRNode.MUL_VB, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 4", "MaxVectorSize", "<= 192"}, + applyIfCPUFeature = {"sve", "true"}) public static void testByteP192(byte[] data) { for (int j = 0; j < RANGE - 192; j++) { data[j + 192] = (byte)(data[j] * (byte)11); @@ -9460,21 +11647,41 @@ public static void runByteP192() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) public static void testFloatP0(float[] data) { for (int j = 0; j < RANGE; j++) { @@ -9496,7 +11703,7 @@ public static void runFloatP0() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -9504,7 +11711,7 @@ public static void runFloatP0() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -9512,7 +11719,7 @@ public static void runFloatP0() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -9520,7 +11727,7 @@ public static void runFloatP0() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9528,7 +11735,7 @@ public static void runFloatP0() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -9551,18 +11758,38 @@ public static void runFloatM1() { // CPU: sse4.1 -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 4 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 4"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP1(float[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (float)(data[j] * (float)1.001f); @@ -9583,22 +11810,42 @@ public static void runFloatP1() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM2(float[] data) { for (int j = 2; j < RANGE; j++) { data[j + -2] = (float)(data[j] * (float)1.001f); @@ -9618,27 +11865,47 @@ public static void runFloatM2() { // CPU: sse4.1 -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 8 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 8"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "8"}, + applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "8"}, applyIfCPUFeature = {"sve", "true"}) public static void testFloatP2(float[] data) { for (int j = 0; j < RANGE - 2; j++) { @@ -9660,7 +11927,7 @@ public static void runFloatP2() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -9668,7 +11935,7 @@ public static void runFloatP2() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -9676,7 +11943,7 @@ public static void runFloatP2() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -9684,7 +11951,7 @@ public static void runFloatP2() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9692,7 +11959,7 @@ public static void runFloatP2() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -9717,26 +11984,46 @@ public static void runFloatM3() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 12 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 12"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 12"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP3(float[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (float)(data[j] * (float)1.001f); @@ -9757,22 +12044,42 @@ public static void runFloatP3() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM4(float[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (float)(data[j] * (float)1.001f); @@ -9793,7 +12100,7 @@ public static void runFloatM4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -9802,16 +12109,24 @@ public static void runFloatM4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9820,6 +12135,10 @@ public static void runFloatM4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP4(float[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (float)(data[j] * (float)1.001f); @@ -9840,7 +12159,7 @@ public static void runFloatP4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -9848,7 +12167,7 @@ public static void runFloatP4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -9856,7 +12175,7 @@ public static void runFloatP4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -9864,7 +12183,7 @@ public static void runFloatP4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -9872,7 +12191,7 @@ public static void runFloatP4() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -9896,25 +12215,45 @@ public static void runFloatM7() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 28"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 28"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 28"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 28 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 28"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 28"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP7(float[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (float)(data[j] * (float)1.001f); @@ -9935,22 +12274,42 @@ public static void runFloatP7() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM8(float[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (float)(data[j] * (float)1.001f); @@ -9971,7 +12330,7 @@ public static void runFloatM8() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -9979,7 +12338,7 @@ public static void runFloatM8() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -9988,11 +12347,15 @@ public static void runFloatM8() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10001,6 +12364,10 @@ public static void runFloatM8() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP8(float[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (float)(data[j] * (float)1.001f); @@ -10021,22 +12388,42 @@ public static void runFloatP8() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM14(float[] data) { for (int j = 14; j < RANGE; j++) { data[j + -14] = (float)(data[j] * (float)1.001f); @@ -10057,24 +12444,44 @@ public static void runFloatM14() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP14(float[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (float)(data[j] * (float)1.001f); @@ -10095,22 +12502,42 @@ public static void runFloatP14() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM16(float[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (float)(data[j] * (float)1.001f); @@ -10131,7 +12558,7 @@ public static void runFloatM16() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10139,7 +12566,7 @@ public static void runFloatM16() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10147,7 +12574,7 @@ public static void runFloatM16() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10155,7 +12582,7 @@ public static void runFloatM16() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10164,6 +12591,10 @@ public static void runFloatM16() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP16(float[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (float)(data[j] * (float)1.001f); @@ -10184,22 +12615,42 @@ public static void runFloatP16() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM18(float[] data) { for (int j = 18; j < RANGE; j++) { data[j + -18] = (float)(data[j] * (float)1.001f); @@ -10220,23 +12671,43 @@ public static void runFloatM18() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 72 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 72"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 72"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP18(float[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (float)(data[j] * (float)1.001f); @@ -10257,22 +12728,42 @@ public static void runFloatP18() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM20(float[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (float)(data[j] * (float)1.001f); @@ -10293,7 +12784,7 @@ public static void runFloatM20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10301,15 +12792,23 @@ public static void runFloatM20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10318,6 +12817,10 @@ public static void runFloatM20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 80"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 80"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP20(float[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (float)(data[j] * (float)1.001f); @@ -10338,7 +12841,7 @@ public static void runFloatP20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10346,7 +12849,7 @@ public static void runFloatP20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10354,7 +12857,7 @@ public static void runFloatP20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10362,7 +12865,7 @@ public static void runFloatP20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10370,7 +12873,7 @@ public static void runFloatP20() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -10394,23 +12897,43 @@ public static void runFloatM31() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 124 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 124"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 124"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP31(float[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (float)(data[j] * (float)1.001f); @@ -10431,22 +12954,42 @@ public static void runFloatP31() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM32(float[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (float)(data[j] * (float)1.001f); @@ -10467,7 +13010,7 @@ public static void runFloatM32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10475,7 +13018,7 @@ public static void runFloatM32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10483,7 +13026,7 @@ public static void runFloatM32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10491,7 +13034,7 @@ public static void runFloatM32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10500,6 +13043,10 @@ public static void runFloatM32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP32(float[] data) { for (int j = 0; j < RANGE - 32; j++) { data[j + 32] = (float)(data[j] * (float)1.001f); @@ -10520,7 +13067,7 @@ public static void runFloatP32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10528,7 +13075,7 @@ public static void runFloatP32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10536,7 +13083,7 @@ public static void runFloatP32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10544,7 +13091,7 @@ public static void runFloatP32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10552,7 +13099,7 @@ public static void runFloatP32() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -10576,23 +13123,43 @@ public static void runFloatM63() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 // positive byte_offset 252 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8", "MaxVectorSize", "<= 252"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "<= 252"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP63(float[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (float)(data[j] * (float)1.001f); @@ -10613,22 +13180,42 @@ public static void runFloatP63() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM64(float[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (float)(data[j] * (float)1.001f); @@ -10649,7 +13236,7 @@ public static void runFloatM64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10657,7 +13244,7 @@ public static void runFloatM64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10665,7 +13252,7 @@ public static void runFloatM64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10673,7 +13260,7 @@ public static void runFloatM64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10681,7 +13268,7 @@ public static void runFloatM64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) @@ -10705,7 +13292,7 @@ public static void runFloatP64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10713,7 +13300,7 @@ public static void runFloatP64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10721,7 +13308,7 @@ public static void runFloatP64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10729,7 +13316,7 @@ public static void runFloatP64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10737,7 +13324,7 @@ public static void runFloatP64() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -10761,22 +13348,42 @@ public static void runFloatM65() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP65(float[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (float)(data[j] * (float)1.001f); @@ -10797,22 +13404,42 @@ public static void runFloatP65() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM128(float[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (float)(data[j] * (float)1.001f); @@ -10833,7 +13460,7 @@ public static void runFloatM128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10841,7 +13468,7 @@ public static void runFloatM128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10849,7 +13476,7 @@ public static void runFloatM128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10857,7 +13484,7 @@ public static void runFloatM128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10865,7 +13492,7 @@ public static void runFloatM128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) @@ -10889,7 +13516,7 @@ public static void runFloatP128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -10897,7 +13524,7 @@ public static void runFloatP128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -10905,7 +13532,7 @@ public static void runFloatP128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"avx512", "true"}) @@ -10913,7 +13540,7 @@ public static void runFloatP128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -10921,7 +13548,7 @@ public static void runFloatP128() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. + // Expect misalignment. @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, applyIf = {"AlignVector", "true"}, applyIfCPUFeature = {"sve", "true"}) @@ -10945,22 +13572,42 @@ public static void runFloatM129() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect misalignment. + @IR(failOn = {IRNode.LOAD_VECTOR_F, IRNode.MUL_VF, IRNode.STORE_VECTOR}, + applyIf = {"AlignVector", "true"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatP129(float[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (float)(data[j] * (float)1.001f); @@ -10981,22 +13628,42 @@ public static void runFloatP129() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 16 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 64 @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, + applyIfCPUFeature = {"sve", "true"}) public static void testFloatM192(float[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (float)(data[j] * (float)1.001f); @@ -11017,7 +13684,7 @@ public static void runFloatM192() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11025,7 +13692,7 @@ public static void runFloatM192() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -11033,7 +13700,7 @@ public static void runFloatM192() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"avx512", "true"}) @@ -11041,7 +13708,7 @@ public static void runFloatM192() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11049,7 +13716,7 @@ public static void runFloatM192() { @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_F, "> 0", IRNode.MUL_VF, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 8"}, applyIfCPUFeature = {"sve", "true"}) @@ -11073,22 +13740,42 @@ public static void runFloatP192() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP0(double[] data) { for (int j = 0; j < RANGE; j++) { data[j + 0] = (double)(data[j] * (double)1.001); @@ -11109,41 +13796,41 @@ public static void runDoubleP0() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM1(double[] data) { for (int j = 1; j < RANGE; j++) { @@ -11164,18 +13851,28 @@ public static void runDoubleM1() { // CPU: sse4.1 -> vector_width: 16 -> elements in vector: 2 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: asimd -> vector_width: 16 -> elements in vector: 2 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 8 can lead to cyclic dependency // No positive IR rule: conditions impossible. + // Expect alignment. + // No positive IR rule: conditions impossible. public static void testDoubleP1(double[] data) { for (int j = 0; j < RANGE - 1; j++) { data[j + 1] = (double)(data[j] * (double)1.001); @@ -11196,22 +13893,42 @@ public static void runDoubleP1() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM2(double[] data) { for (int j = 2; j < RANGE; j++) { data[j + -2] = (double)(data[j] * (double)1.001); @@ -11232,32 +13949,44 @@ public static void runDoubleM2() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 16"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 16"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "16"}, + applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 16 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, - applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 16"}, + applyIfAnd = {"AlignVector", "false", "MaxVectorSize", "16"}, + applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", "16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP2(double[] data) { for (int j = 0; j < RANGE - 2; j++) { @@ -11279,41 +14008,41 @@ public static void runDoubleP2() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM3(double[] data) { for (int j = 3; j < RANGE; j++) { @@ -11335,25 +14064,45 @@ public static void runDoubleM3() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 // positive byte_offset 24 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 24 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 24 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 24"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP3(double[] data) { for (int j = 0; j < RANGE - 3; j++) { data[j + 3] = (double)(data[j] * (double)1.001); @@ -11374,22 +14123,42 @@ public static void runDoubleP3() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM4(double[] data) { for (int j = 4; j < RANGE; j++) { data[j + -4] = (double)(data[j] * (double)1.001); @@ -11410,7 +14179,7 @@ public static void runDoubleM4() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11418,7 +14187,7 @@ public static void runDoubleM4() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -11427,11 +14196,15 @@ public static void runDoubleM4() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11440,6 +14213,10 @@ public static void runDoubleM4() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 32"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP4(double[] data) { for (int j = 0; j < RANGE - 4; j++) { data[j + 4] = (double)(data[j] * (double)1.001); @@ -11460,41 +14237,41 @@ public static void runDoubleP4() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM7(double[] data) { for (int j = 7; j < RANGE; j++) { @@ -11516,24 +14293,44 @@ public static void runDoubleM7() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 56 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 56"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP7(double[] data) { for (int j = 0; j < RANGE - 7; j++) { data[j + 7] = (double)(data[j] * (double)1.001); @@ -11554,22 +14351,42 @@ public static void runDoubleP7() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM8(double[] data) { for (int j = 8; j < RANGE; j++) { data[j + -8] = (double)(data[j] * (double)1.001); @@ -11590,7 +14407,7 @@ public static void runDoubleM8() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11598,7 +14415,7 @@ public static void runDoubleM8() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -11606,7 +14423,7 @@ public static void runDoubleM8() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -11614,7 +14431,7 @@ public static void runDoubleM8() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11623,6 +14440,10 @@ public static void runDoubleM8() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 64"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 64"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP8(double[] data) { for (int j = 0; j < RANGE - 8; j++) { data[j + 8] = (double)(data[j] * (double)1.001); @@ -11643,22 +14464,42 @@ public static void runDoubleP8() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM14(double[] data) { for (int j = 14; j < RANGE; j++) { data[j + -14] = (double)(data[j] * (double)1.001); @@ -11679,7 +14520,7 @@ public static void runDoubleM14() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11687,15 +14528,23 @@ public static void runDoubleM14() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11704,6 +14553,10 @@ public static void runDoubleM14() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 112"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 112"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP14(double[] data) { for (int j = 0; j < RANGE - 14; j++) { data[j + 14] = (double)(data[j] * (double)1.001); @@ -11724,22 +14577,42 @@ public static void runDoubleP14() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM16(double[] data) { for (int j = 16; j < RANGE; j++) { data[j + -16] = (double)(data[j] * (double)1.001); @@ -11760,7 +14633,7 @@ public static void runDoubleM16() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11768,7 +14641,7 @@ public static void runDoubleM16() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -11776,7 +14649,7 @@ public static void runDoubleM16() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -11784,7 +14657,7 @@ public static void runDoubleM16() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11793,6 +14666,10 @@ public static void runDoubleM16() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 128"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 128"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP16(double[] data) { for (int j = 0; j < RANGE - 16; j++) { data[j + 16] = (double)(data[j] * (double)1.001); @@ -11813,22 +14690,42 @@ public static void runDoubleP16() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM18(double[] data) { for (int j = 18; j < RANGE; j++) { data[j + -18] = (double)(data[j] * (double)1.001); @@ -11849,7 +14746,7 @@ public static void runDoubleM18() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11857,15 +14754,23 @@ public static void runDoubleM18() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11874,6 +14779,10 @@ public static void runDoubleM18() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 144"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 144"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP18(double[] data) { for (int j = 0; j < RANGE - 18; j++) { data[j + 18] = (double)(data[j] * (double)1.001); @@ -11894,22 +14803,42 @@ public static void runDoubleP18() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM20(double[] data) { for (int j = 20; j < RANGE; j++) { data[j + -20] = (double)(data[j] * (double)1.001); @@ -11930,7 +14859,7 @@ public static void runDoubleM20() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -11938,7 +14867,7 @@ public static void runDoubleM20() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -11946,11 +14875,15 @@ public static void runDoubleM20() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -11959,6 +14892,10 @@ public static void runDoubleM20() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 160"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 160"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP20(double[] data) { for (int j = 0; j < RANGE - 20; j++) { data[j + 20] = (double)(data[j] * (double)1.001); @@ -11979,41 +14916,41 @@ public static void runDoubleP20() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM31(double[] data) { for (int j = 31; j < RANGE; j++) { @@ -12035,23 +14972,43 @@ public static void runDoubleM31() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 // positive byte_offset 248 can lead to cyclic dependency @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 248"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16", "MaxVectorSize", "<= 248"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP31(double[] data) { for (int j = 0; j < RANGE - 31; j++) { data[j + 31] = (double)(data[j] * (double)1.001); @@ -12072,22 +15029,42 @@ public static void runDoubleP31() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM32(double[] data) { for (int j = 32; j < RANGE; j++) { data[j + -32] = (double)(data[j] * (double)1.001); @@ -12108,7 +15085,7 @@ public static void runDoubleM32() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -12116,7 +15093,7 @@ public static void runDoubleM32() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -12124,7 +15101,7 @@ public static void runDoubleM32() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -12132,7 +15109,7 @@ public static void runDoubleM32() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -12140,7 +15117,7 @@ public static void runDoubleM32() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -12164,41 +15141,41 @@ public static void runDoubleP32() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM63(double[] data) { for (int j = 63; j < RANGE; j++) { @@ -12220,22 +15197,42 @@ public static void runDoubleM63() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP63(double[] data) { for (int j = 0; j < RANGE - 63; j++) { data[j + 63] = (double)(data[j] * (double)1.001); @@ -12256,22 +15253,42 @@ public static void runDoubleP63() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM64(double[] data) { for (int j = 64; j < RANGE; j++) { data[j + -64] = (double)(data[j] * (double)1.001); @@ -12292,7 +15309,7 @@ public static void runDoubleM64() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -12300,7 +15317,7 @@ public static void runDoubleM64() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -12308,7 +15325,7 @@ public static void runDoubleM64() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -12316,7 +15333,7 @@ public static void runDoubleM64() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -12324,7 +15341,7 @@ public static void runDoubleM64() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -12348,41 +15365,41 @@ public static void runDoubleP64() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM65(double[] data) { for (int j = 65; j < RANGE; j++) { @@ -12404,22 +15421,42 @@ public static void runDoubleM65() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP65(double[] data) { for (int j = 0; j < RANGE - 65; j++) { data[j + 65] = (double)(data[j] * (double)1.001); @@ -12440,22 +15477,42 @@ public static void runDoubleP65() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM128(double[] data) { for (int j = 128; j < RANGE; j++) { data[j + -128] = (double)(data[j] * (double)1.001); @@ -12476,7 +15533,7 @@ public static void runDoubleM128() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -12484,7 +15541,7 @@ public static void runDoubleM128() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -12492,7 +15549,7 @@ public static void runDoubleM128() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -12500,7 +15557,7 @@ public static void runDoubleM128() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -12508,7 +15565,7 @@ public static void runDoubleM128() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) @@ -12532,41 +15589,41 @@ public static void runDoubleP128() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Strict alignment not possible. - @IR(failOn = {IRNode.LOAD_VECTOR_D, IRNode.MUL_VD, IRNode.STORE_VECTOR}, - applyIf = {"AlignVector", "true"}, + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM129(double[] data) { for (int j = 129; j < RANGE; j++) { @@ -12588,22 +15645,42 @@ public static void runDoubleM129() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleP129(double[] data) { for (int j = 0; j < RANGE - 129; j++) { data[j + 129] = (double)(data[j] * (double)1.001); @@ -12624,22 +15701,42 @@ public static void runDoubleP129() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) // CPU: avx and avx2 -> vector_width: 32 -> elements in vector: 4 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) // CPU: avx512 -> vector_width: 64 -> elements in vector: 8 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"avx512", "true"}) // CPU: asimd -> vector_width: 16 -> elements in vector: 2 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) // CPU: sve -> max vector_width: 256 -> max elements in vector: 32 @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) + // Expect alignment. + @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, + applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, + applyIfCPUFeature = {"sve", "true"}) public static void testDoubleM192(double[] data) { for (int j = 192; j < RANGE; j++) { data[j + -192] = (double)(data[j] * (double)1.001); @@ -12660,7 +15757,7 @@ public static void runDoubleM192() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"sse4.1", "true", "avx", "false"}) @@ -12668,7 +15765,7 @@ public static void runDoubleM192() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx512", "false"}) @@ -12676,7 +15773,7 @@ public static void runDoubleM192() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"avx512", "true"}) @@ -12684,7 +15781,7 @@ public static void runDoubleM192() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeatureAnd = {"asimd", "true", "sve", "false"}) @@ -12692,7 +15789,7 @@ public static void runDoubleM192() { @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "false", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) - // Vectorize when strict alignment guaranteed. + // Expect alignment. @IR(counts = {IRNode.LOAD_VECTOR_D, "> 0", IRNode.MUL_VD, "> 0", IRNode.STORE_VECTOR, "> 0"}, applyIfAnd = {"AlignVector", "true", "MaxVectorSize", ">= 16"}, applyIfCPUFeature = {"sve", "true"}) diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMovingLoadBeforeStore.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMovingLoadBeforeStore.java index 80922aeffe9cd..752c8010468a3 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMovingLoadBeforeStore.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMovingLoadBeforeStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -25,7 +25,6 @@ /** * @test * @requires vm.compiler2.enabled - * @requires vm.cpu.features ~= ".*avx2.*" * @bug 8316679 8316594 * @summary In SuperWord::output, LoadVector can be moved before StoreVector, but only if it is proven to be safe. * @key randomness diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java index 78e97f26817f8..e32da89b8cd58 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMulAddS2I.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, 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 @@ -24,7 +24,6 @@ /** * @test * @bug 8310886 - * @requires os.arch == "x86_64" | os.arch == "aarch64" * @summary Test MulAddS2I vectorization. * @library /test/lib / * @run driver compiler.loopopts.superword.TestMulAddS2I @@ -75,15 +74,14 @@ public static void compare(int[] out) { } @Test - @IR(applyIfCPUFeature = {"sse2", "true"}, applyIf = {"UseUnalignedLoadStores", "true"}, + @IR(applyIfCPUFeature = {"sse2", "true"}, + applyIfPlatform = {"64-bit", "true"}, counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) - @IR(applyIfCPUFeature = {"sse2", "true"}, applyIf = {"UseUnalignedLoadStores", "false"}, - failOn = {IRNode.MUL_ADD_VS2VI}, // Can only pack LoadS if UseUnalignedLoadStores is true (default if sse4.2) - counts = {IRNode.MUL_ADD_S2I, "> 0"}) - @IR(applyIfCPUFeature = {"asimd", "true"}, applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 - counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) - @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, applyIf = {"UseUnalignedLoadStores", "true"}, - counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) + @IR(applyIfCPUFeature = {"asimd", "true"}, + applyIf = {"MaxVectorSize", "16"}, // AD file requires vector_length = 16 + counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI, "> 0"}) + @IR(applyIfCPUFeature = {"avx512_vnni", "true"}, + counts = {IRNode.MUL_ADD_S2I, "> 0", IRNode.MUL_ADD_VS2VI_VNNI, "> 0"}) public static int[] test() { int[] out = new int[ITER]; int[] out2 = new int[ITER]; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java b/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java index 889cc68f876b6..76251ba99c8c3 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -23,24 +23,17 @@ /** * @test - * @bug 8257531 + * @bug 8257531 8310190 * @summary Test vectorization for Buffer operations. * @library /test/lib / - * - * @requires vm.flagless - * @requires vm.compiler2.enabled & vm.debug == true - * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" - * - * @run driver compiler.vectorization.TestBufferVectorization array - * @run driver compiler.vectorization.TestBufferVectorization arrayOffset - * @run driver compiler.vectorization.TestBufferVectorization buffer - * @run driver compiler.vectorization.TestBufferVectorization bufferHeap - * @run driver compiler.vectorization.TestBufferVectorization bufferDirect - * @run driver compiler.vectorization.TestBufferVectorization arrayView + * @requires vm.compiler2.enabled + * @run driver compiler.vectorization.TestBufferVectorization */ package compiler.vectorization; +import compiler.lib.ir_framework.*; + import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -48,205 +41,196 @@ import java.nio.ByteOrder; import java.nio.IntBuffer; -import jdk.test.lib.Platform; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; - public class TestBufferVectorization { - final static int N = 500; - final static int ITER = 1000; - final static IntBuffer buffer = IntBuffer.allocate(N); - final static int offset = buffer.arrayOffset(); - final static IntBuffer heap_buffer_byte_to_int = ByteBuffer.allocate(N * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer(); - final static IntBuffer direct_buffer_byte_to_int = ByteBuffer.allocateDirect(N * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer(); + final static int N = 1024*16; + static int offset = 0; final static VarHandle VH_arr_view = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.nativeOrder()).withInvokeExactBehavior(); - final static String arch = System.getProperty("os.arch"); - interface Test { - void init(); - void run(); - void verify(); + public static void main(String[] args) { + TestFramework.run(); } - static class TestArray implements Test { - final int[] array = new int[N]; + @Run(test = "testArray") + public static void runArray() { + int[] array = new int[N]; - public void init() { - for (int k = 0; k < array.length; k++) { - array[k] = k; - } + for (int k = 0; k < array.length; k++) { + array[k] = k; } - public void run() { - for(int k = 0; k < array.length; k++) { - array[k] += 1; + testArray(array); + + for(int k = 0; k < array.length; k++) { + if (array[k] != (k + 1)) { + throw new RuntimeException(" Invalid result: array[" + k + "]: " + array[k] + " != " + (k + 1)); } } + } - public void verify() { - init(); // reset - run(); // run compiled code - for(int k = 0; k < array.length; k++) { - if (array[k] != (k + 1)) { - throw new RuntimeException(" Invalid result: array[" + k + "]: " + array[k] + " != " + (k + 1)); - } - } + @Test + @IR(counts = {IRNode.REPLICATE_I, ">0", + IRNode.LOAD_VECTOR_I, ">0", + IRNode.ADD_VI, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + public static void testArray(int[] array) { + for(int k = 0; k < array.length; k++) { + array[k] += 1; } } - static class TestArrayOffset implements Test { - final int offset; - final int[] array = new int[N]; + @Run(test = "testArrayOffset") + public static void runArrayOffset() { + // Moving offset between 0..255 + offset = (offset + 1) % 256; - public TestArrayOffset(int off) { - offset = off; - } + int[] array = new int[N]; - public void init() { - for (int k = 0; k < array.length; k++) { - array[k] = k; - } + for (int k = 0; k < array.length; k++) { + array[k] = k; } - public void run() { - int l = array.length - offset; - for(int k = 0; k < l; k++) { - array[k + offset] += 1; - } - } + testArrayOffset(array, offset); - public void verify() { - init(); // reset - run(); // run compiled code - int l = array.length - offset; - for(int k = 0; k < l; k++) { - if (array[k] != (k + 1)) { - throw new RuntimeException(" Invalid result: arrayOffset[" + k + "]: " + array[k] + " != " + (k + 1)); - } + int l = array.length - offset; + for(int k = 0; k < offset; k++) { + if (array[k] != k) { + throw new RuntimeException(" Invalid result: arrayOffset[" + k + "]: " + array[k] + " != " + (k + 1)); } - for(int k = l; k < array.length; k++) { - if (array[k] != k) { - throw new RuntimeException(" Invalid result: arrayOffset[" + k + "]: " + array[k] + " != " + k); - } + } + for(int k = offset; k < array.length; k++) { + if (array[k] != (k + 1)) { + throw new RuntimeException(" Invalid result: arrayOffset[" + k + "]: " + array[k] + " != " + k); } } } - static class TestBuffer implements Test { - final IntBuffer buffer; - - public TestBuffer(IntBuffer buf) { - buffer = buf; - } - - public void init() { - for (int k = 0; k < buffer.limit(); k++) { - buffer.put(k, k); - } + @Test + @IR(counts = {IRNode.REPLICATE_I, ">0", + IRNode.LOAD_VECTOR_I, ">0", + IRNode.ADD_VI, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + public static void testArrayOffset(int[] array, int offset) { + int l = array.length - offset; + for(int k = 0; k < l; k++) { + array[k + offset] += 1; } + } - public void run() { - for (int k = 0; k < buffer.limit(); k++) { - buffer.put(k, buffer.get(k) + 1); - } - } + @Run(test = "testBuffer") + public static void runBuffer() { + IntBuffer buffer = IntBuffer.allocate(N); + initBuffer(buffer); + testBuffer(buffer); + verifyBuffer(buffer); + } - public void verify() { - init(); // reset - run(); // run compiled code - for(int k = 0; k < buffer.limit(); k++) { - if (buffer.get(k) != (k + 1)) { - throw new RuntimeException(" Invalid result: buffer.get(" + k + "): " + buffer.get(k) + " != " + (k + 1)); - } - } + @Test + @IR(counts = {IRNode.REPLICATE_I, ">0", + IRNode.LOAD_VECTOR_I, ">0", + IRNode.ADD_VI, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + public static void testBuffer(IntBuffer buffer) { + for (int k = 0; k < buffer.limit(); k++) { + buffer.put(k, buffer.get(k) + 1); } } - static class TestArrayView implements Test { - final byte[] b_arr = new byte[N * Integer.BYTES]; + @Run(test = "testBufferHeap") + public static void runBufferHeap() { + IntBuffer buffer = ByteBuffer.allocate(N * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer(); + initBuffer(buffer); + testBufferHeap(buffer); + verifyBuffer(buffer); + } - public void init() { - for (int k = 0; k < N; k++) { - VH_arr_view.set(b_arr, k, k); - } + @Test + @IR(counts = {IRNode.REPLICATE_I, IRNode.VECTOR_SIZE_ANY, ">0", + IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_ANY, ">0", + IRNode.ADD_VI, IRNode.VECTOR_SIZE_ANY, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}, + applyIf = {"AlignVector", "false"}, + applyIfPlatform = {"64-bit", "true"}) + // VECTOR_SIZE_ANY: Unrolling does not always seem to go far enough to reach maximum vector size. + // This looks like a BUG. + // AlignVector: Buffer get/put have an invariant that is in bytes (LoadL in ByteBufferAsIntBufferL::byteOffset). + // This makes sense: we are accessing a byte buffer. But to be able to align the 4 byte ints, + // we would require to know that the invariant is a multiple of 4. Without that, we cannot + // guarantee alignment by adjusting the limit of the pre-loop with a stride of 4 bytes. + // 64-bit: bufferHeap uses Long type for memory accesses which are not vectorized in 32-bit VM + public static void testBufferHeap(IntBuffer buffer) { + for (int k = 0; k < buffer.limit(); k++) { + buffer.put(k, buffer.get(k) + 1); } + } - public void run() { - for (int k = 0; k < b_arr.length; k += 4) { - int v = (int) VH_arr_view.get(b_arr, k); - VH_arr_view.set(b_arr, k, v + 1); - } + @Run(test = "testBufferDirect") + public static void runBufferDirect() { + IntBuffer buffer = ByteBuffer.allocateDirect(N * Integer.BYTES).order(ByteOrder.nativeOrder()).asIntBuffer(); + initBuffer(buffer); + testBufferDirect(buffer); + verifyBuffer(buffer); + } + + @Test + // bufferDirect uses Unsafe memory accesses which are not vectorized currently + // We find a CastX2P in pointer analysis (VPointer) + public static void testBufferDirect(IntBuffer buffer) { + for (int k = 0; k < buffer.limit(); k++) { + buffer.put(k, buffer.get(k) + 1); } + } - public void verify() { - init(); // reset - // Save initial INT values - final int[] i_arr = new int[N]; - for (int k = 0; k < i_arr.length; k++) { - i_arr[k] = (int) VH_arr_view.get(b_arr, k * Integer.BYTES); - } - run(); // run compiled code - for (int k = 0; k < i_arr.length; k++) { - int v = (int) VH_arr_view.get(b_arr, k * Integer.BYTES); - if (v != (i_arr[k] + 1)) { - throw new RuntimeException(" Invalid result: VH_arr_view.get(b_arr, " + (k * Integer.BYTES) + "): " + v + " != " + (i_arr[k] + 1)); - } - } + public static void initBuffer(IntBuffer buffer) { + for (int k = 0; k < buffer.limit(); k++) { + buffer.put(k, k); } } - public static void main(String[] args) { - if (args.length == 0) { - throw new RuntimeException(" Missing test name: array, arrayOffset, buffer, bufferHeap, bufferDirect, arrayView"); - } else if (args.length == 1) { - verify_vectors(args[0]); - } else { - Test te = switch (args[0]) { - case "array" -> new TestArray(); - case "arrayOffset" -> new TestArrayOffset(offset); - case "buffer" -> new TestBuffer(buffer); - case "bufferHeap" -> new TestBuffer(heap_buffer_byte_to_int); - case "bufferDirect" -> new TestBuffer(direct_buffer_byte_to_int); - case "arrayView" -> new TestArrayView(); - default -> throw new RuntimeException(" Unknown test: " + args[0]); - }; - - te.init(); - for (int i = 0; i < ITER; i++) { - te.run(); + public static void verifyBuffer(IntBuffer buffer) { + for(int k = 0; k < buffer.limit(); k++) { + if (buffer.get(k) != (k + 1)) { + throw new RuntimeException(" Invalid result: buffer.get(" + k + "): " + buffer.get(k) + " != " + (k + 1)); } - te.verify(); } - } - static void verify_vectors(String testName) { - ProcessBuilder pb; - OutputAnalyzer out; - try { - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:-BackgroundCompilation", - "-XX:+TraceNewVectors", - "compiler.vectorization.TestBufferVectorization", - testName, - "run"); - out = new OutputAnalyzer(pb.start()); - } catch (Exception e) { - throw new RuntimeException(" Exception launching Java process: " + e); - } + @Run(test = "testArrayView") + public static void runArrayView() { + byte[] b_arr = new byte[N * Integer.BYTES]; - out.shouldHaveExitValue(0); + for (int k = 0; k < N; k++) { + VH_arr_view.set(b_arr, k, k); + } - if (testName.equals("bufferDirect")) { - return; // bufferDirect uses Unsafe memory accesses which are not vectorized currently + // Save initial INT values + int[] i_arr = new int[N]; + for (int k = 0; k < i_arr.length; k++) { + i_arr[k] = (int) VH_arr_view.get(b_arr, k * Integer.BYTES); } + testArrayView(b_arr); - if (testName.equals("bufferHeap") && (Platform.is32bit())) { - return; // bufferHeap uses Long type for memory accesses which are not vectorized in 32-bit VM + for (int k = 0; k < i_arr.length; k++) { + int v = (int) VH_arr_view.get(b_arr, k * Integer.BYTES); + if (v != (i_arr[k] + 1)) { + throw new RuntimeException(" Invalid result: VH_arr_view.get(b_arr, " + (k * Integer.BYTES) + "): " + v + " != " + (i_arr[k] + 1)); + } } + } - out.shouldContain("Replicate"); - out.shouldContain("LoadVector"); - out.shouldContain("AddVI"); - out.shouldContain("StoreVector"); + @Test + @IR(counts = {IRNode.REPLICATE_I, ">0", + IRNode.LOAD_VECTOR_I, ">0", + IRNode.ADD_VI, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfCPUFeatureOr = {"sse4.1", "true", "asimd", "true"}) + public static void testArrayView(byte[] b_arr) { + for (int k = 0; k < b_arr.length; k += 4) { + int v = (int) VH_arr_view.get(b_arr, k); + VH_arr_view.set(b_arr, k, v + 1); + } } } From c4a83bd6f6c45e72bd776e929005be0aa9408867 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Mon, 8 Jan 2024 16:44:28 +0000 Subject: [PATCH 052/112] 8323086: Shenandoah: Heap could be corrupted by oom during evacuation Reviewed-by: kdnilsen, shade --- .../gc/shenandoah/shenandoahDegeneratedGC.cpp | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index d8398bb1ed8b3..e7cf402a52785 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -131,6 +131,27 @@ void ShenandoahDegenGC::op_degenerated() { // and we can do evacuation. Otherwise, it would be the shortcut cycle. if (heap->is_evacuation_in_progress()) { + if (_degen_point == _degenerated_evac) { + // Degeneration under oom-evac protocol allows the mutator LRB to expose + // references to from-space objects. This is okay, in theory, because we + // will come to the safepoint here to complete the evacuations and update + // the references. However, if the from-space reference is written to a + // region that was EC during final mark or was recycled after final mark + // it will not have TAMS or UWM updated. Such a region is effectively + // skipped during update references which can lead to crashes and corruption + // if the from-space reference is accessed. + if (UseTLAB) { + heap->labs_make_parsable(); + } + + for (size_t i = 0; i < heap->num_regions(); i++) { + ShenandoahHeapRegion* r = heap->get_region(i); + if (r->is_active() && r->top() > r->get_update_watermark()) { + r->set_update_watermark_at_safepoint(r->top()); + } + } + } + // Degeneration under oom-evac protocol might have left some objects in // collection set un-evacuated. Restart evacuation from the beginning to // capture all objects. For all the objects that are already evacuated, From 387828a3f7e4ec5b26954747e756aac212d579ae Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Mon, 8 Jan 2024 16:56:44 +0000 Subject: [PATCH 053/112] 8322980: Debug agent's dumpThread() API should update thread's name before printing it Reviewed-by: kevinw, sspitsyn --- .../share/native/libjdwp/threadControl.c | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c index 581de4305713e..5628f8b44db43 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -2623,15 +2623,58 @@ dumpThreadList(ThreadList *list) } } +#ifdef DEBUG_THREADNAME +static void +setThreadName(ThreadNode *node) +{ + /* + * Sometimes the debuggee changes the thread name, so we need to fetch + * and set it again. + */ + jvmtiThreadInfo info; + jvmtiError error; + + memset(&info, 0, sizeof(info)); + error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadInfo) + (gdata->jvmti, node->thread, &info); + if (info.name != NULL) { + strncpy(node->name, info.name, sizeof(node->name) - 1); + jvmtiDeallocate(info.name); + } +} +#endif + +#if 0 +static jint +getThreadState(ThreadNode *node) +{ + jint state = 0; + jvmtiError error = FUNC_PTR(gdata->jvmti,GetThreadState) + (gdata->jvmti, node->thread, &state); + return state; +} +#endif + static void dumpThread(ThreadNode *node) { - tty_message(" Thread: node = %p, jthread = %p", node, node->thread); + tty_message("Thread: node = %p, jthread = %p", node, node->thread); #ifdef DEBUG_THREADNAME + setThreadName(node); tty_message("\tname: %s", node->name); #endif // More fields can be printed here when needed. The amount of output is intentionally // kept small so it doesn't generate too much output. tty_message("\tsuspendCount: %d", node->suspendCount); +#if 0 + tty_message("\tsuspendAllCount: %d", suspendAllCount); + tty_message("\tthreadState: 0x%x", getThreadState(node)); + tty_message("\ttoBeResumed: %d", node->toBeResumed); + tty_message("\tis_vthread: %d", node->is_vthread); + tty_message("\tcurrentInvoke.pending: %d", node->currentInvoke.pending); + tty_message("\tcurrentInvoke.started: %d", node->currentInvoke.started); + tty_message("\tcurrentInvoke.available: %d", node->currentInvoke.available); + tty_message("\tobjID: %d", commonRef_refToID(getEnv(), node->thread)); +#endif } #endif /* DEBUG */ From d47393bd8225e818f0f9cd45192a5e656018af11 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 8 Jan 2024 18:53:41 +0000 Subject: [PATCH 054/112] 8320128: Clean up Parse constructor for OSR Reviewed-by: thartmann, shade --- src/hotspot/share/opto/parse.hpp | 7 +++-- src/hotspot/share/opto/parse1.cpp | 47 +++++++++++++++---------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp index 72929729812d1..40314ecc29d67 100644 --- a/src/hotspot/share/opto/parse.hpp +++ b/src/hotspot/share/opto/parse.hpp @@ -416,8 +416,11 @@ class Parse : public GraphKit { void set_block(Block* b) { _block = b; } // Derived accessors: - bool is_normal_parse() const { return _entry_bci == InvocationEntryBci; } - bool is_osr_parse() const { return _entry_bci != InvocationEntryBci; } + bool is_osr_parse() const { + assert(_entry_bci != UnknownBci, "uninitialized _entry_bci"); + return _entry_bci != InvocationEntryBci; + } + bool is_normal_parse() const { return !is_osr_parse(); } int osr_bci() const { assert(is_osr_parse(),""); return _entry_bci; } void set_parse_bci(int bci); diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index 96db18f774fe7..c1fe7acaa75a3 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -401,19 +401,17 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) _wrote_stable = false; _wrote_fields = false; _alloc_with_final = nullptr; - _entry_bci = InvocationEntryBci; - _tf = nullptr; _block = nullptr; _first_return = true; _replaced_nodes_for_exceptions = false; _new_idx = C->unique(); - debug_only(_block_count = -1); - debug_only(_blocks = (Block*)-1); + DEBUG_ONLY(_entry_bci = UnknownBci); + DEBUG_ONLY(_block_count = -1); + DEBUG_ONLY(_blocks = (Block*)-1); #ifndef PRODUCT if (PrintCompilation || PrintOpto) { // Make sure I have an inline tree, so I can print messages about it. - JVMState* ilt_caller = is_osr_parse() ? caller->caller() : caller; - InlineTree::find_subtree_from_root(C->ilt(), ilt_caller, parse_method); + InlineTree::find_subtree_from_root(C->ilt(), caller, parse_method); } _max_switch_depth = 0; _est_switch_depth = 0; @@ -427,19 +425,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) C->set_has_monitors(true); } - _tf = TypeFunc::make(method()); _iter.reset_to_method(method()); - _flow = method()->get_flow_analysis(); - if (_flow->failing()) { - assert(false, "type flow failed during parsing"); - C->record_method_not_compilable(_flow->failure_reason()); - } - -#ifndef PRODUCT - if (_flow->has_irreducible_entry()) { - C->set_parsed_irreducible_loop(true); - } -#endif C->set_has_loops(C->has_loops() || method()->has_loops()); if (_expected_uses <= 0) { @@ -507,14 +493,25 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) // Do some special top-level things. if (depth() == 1 && C->is_osr_compilation()) { + _tf = C->tf(); // the OSR entry type is different _entry_bci = C->entry_bci(); _flow = method()->get_osr_flow_analysis(osr_bci()); - if (_flow->failing()) { - assert(false, "type flow analysis failed for OSR compilation"); - C->record_method_not_compilable(_flow->failure_reason()); + } else { + _tf = TypeFunc::make(method()); + _entry_bci = InvocationEntryBci; + _flow = method()->get_flow_analysis(); + } + + if (_flow->failing()) { + assert(false, "type flow analysis failed during parsing"); + C->record_method_not_compilable(_flow->failure_reason()); #ifndef PRODUCT if (PrintOpto && (Verbose || WizardMode)) { - tty->print_cr("OSR @%d type flow bailout: %s", _entry_bci, _flow->failure_reason()); + if (is_osr_parse()) { + tty->print_cr("OSR @%d type flow bailout: %s", _entry_bci, _flow->failure_reason()); + } else { + tty->print_cr("type flow bailout: %s", _flow->failure_reason()); + } if (Verbose) { method()->print(); method()->print_codes(); @@ -522,8 +519,6 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) } } #endif - } - _tf = C->tf(); // the OSR entry type is different } #ifdef ASSERT @@ -535,6 +530,10 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) #endif #ifndef PRODUCT + if (_flow->has_irreducible_entry()) { + C->set_parsed_irreducible_loop(true); + } + methods_parsed++; // add method size here to guarantee that inlined methods are added too if (CITime) From 24823ba647d4bf412586372cd5076f35bbc131a5 Mon Sep 17 00:00:00 2001 From: Joshua Cao Date: Mon, 8 Jan 2024 19:46:04 +0000 Subject: [PATCH 055/112] 8323095: Expand TraceOptoParse block output abbreviations Reviewed-by: thartmann, chagedorn, xliu --- src/hotspot/share/opto/parse1.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp index c1fe7acaa75a3..8ee99ae9a65e3 100644 --- a/src/hotspot/share/opto/parse1.cpp +++ b/src/hotspot/share/opto/parse1.cpp @@ -1511,13 +1511,13 @@ void Parse::do_one_block() { int ns = b->num_successors(); int nt = b->all_successors(); - tty->print("Parsing block #%d at bci [%d,%d), successors: ", + tty->print("Parsing block #%d at bci [%d,%d), successors:", block()->rpo(), block()->start(), block()->limit()); for (int i = 0; i < nt; i++) { - tty->print((( i < ns) ? " %d" : " %d(e)"), b->successor_at(i)->rpo()); + tty->print((( i < ns) ? " %d" : " %d(exception block)"), b->successor_at(i)->rpo()); } if (b->is_loop_head()) { - tty->print(" lphd"); + tty->print(" loop head"); } if (b->is_irreducible_loop_entry()) { tty->print(" irreducible"); From d78e8dab93868c1212c95e165f556ad89a0b6920 Mon Sep 17 00:00:00 2001 From: Rajat Mahajan Date: Mon, 8 Jan 2024 19:58:32 +0000 Subject: [PATCH 056/112] 8322545: Declare newInsets as static in ThemeReader.cpp Reviewed-by: serb, aivanov --- .../windows/native/libawt/windows/ThemeReader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp b/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp index 12c2677e32a37..fad778dac4e0f 100644 --- a/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp +++ b/src/java.desktop/windows/native/libawt/windows/ThemeReader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -492,7 +492,7 @@ static void rescale(SIZE *size) { } } -jobject newInsets(JNIEnv *env, jint top, jint left, jint bottom, jint right) { +static jobject newInsets(JNIEnv *env, jint top, jint left, jint bottom, jint right) { if (env->EnsureLocalCapacity(2) < 0) { return NULL; } From 8a4dc79e1a40e7115e2971af81623b6b0368f41c Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Mon, 8 Jan 2024 20:17:29 +0000 Subject: [PATCH 057/112] 8274300: Address dsymutil warning by excluding platform specific files Reviewed-by: erikj --- make/test/BuildTestLibNative.gmk | 6 +++++- make/test/JtregNativeHotspot.gmk | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/make/test/BuildTestLibNative.gmk b/make/test/BuildTestLibNative.gmk index 00c7607913b1e..455936d163f3a 100644 --- a/make/test/BuildTestLibNative.gmk +++ b/make/test/BuildTestLibNative.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2024, 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 @@ -45,6 +45,10 @@ BUILD_LIBTEST_OUTPUT_DIR := $(OUTPUTDIR)/support/test/lib/native BUILD_LIBTEST_IMAGE_DIR := $(TEST_IMAGE_DIR)/lib +ifeq ($(call isTargetOs, windows), false) + BUILD_LIBTEST_LIBRARIES_EXCLUDE += libFileUtils.c +endif + # This evaluation is expensive and should only be done if this target was # explicitly called. ifneq ($(filter build-test-lib-native, $(MAKECMDGOALS)), ) diff --git a/make/test/JtregNativeHotspot.gmk b/make/test/JtregNativeHotspot.gmk index 98101ee1e86bf..d8edb8743d7b5 100644 --- a/make/test/JtregNativeHotspot.gmk +++ b/make/test/JtregNativeHotspot.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2024, 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 @@ -857,6 +857,11 @@ else exeinvoke.c exestack-gap.c exestack-tls.c libAsyncGetCallTraceTest.cpp endif +ifeq ($(call And, $(call isTargetOs, linux) $(call isTargetCpu, aarch64)), false) + BUILD_HOTSPOT_JTREG_EXCLUDE += libTestSVEWithJNI.c +endif + + BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exesigtest := -ljvm ifeq ($(call isTargetOs, windows), true) From ca9635df3357bf70b41645f619237b6d2068afb7 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 8 Jan 2024 21:26:18 +0000 Subject: [PATCH 058/112] 8322759: Eliminate -Wparentheses warnings in compiler code Reviewed-by: kvn, shade --- src/hotspot/share/c1/c1_GraphBuilder.cpp | 10 +++++----- src/hotspot/share/c1/c1_LinearScan.cpp | 6 +++--- src/hotspot/share/c1/c1_ValueStack.hpp | 4 ++-- src/hotspot/share/code/relocInfo.cpp | 6 +++--- .../share/compiler/compilerDefinitions.inline.hpp | 6 +++--- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index fe9a8a478365d..6e5fb99242c8c 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -1315,8 +1315,8 @@ void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* sta Instruction *i = append(new If(x, cond, false, y, tsux, fsux, (is_bb || compilation()->is_optimistic()) ? state_before : nullptr, is_bb)); assert(i->as_Goto() == nullptr || - (i->as_Goto()->sux_at(0) == tsux && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) || - (i->as_Goto()->sux_at(0) == fsux && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()), + (i->as_Goto()->sux_at(0) == tsux && i->as_Goto()->is_safepoint() == (tsux->bci() < stream()->cur_bci())) || + (i->as_Goto()->sux_at(0) == fsux && i->as_Goto()->is_safepoint() == (fsux->bci() < stream()->cur_bci())), "safepoint state of Goto returned by canonicalizer incorrect"); if (is_profiling()) { @@ -1451,7 +1451,7 @@ void GraphBuilder::table_switch() { if (res->as_Goto()) { for (i = 0; i < l; i++) { if (sux->at(i) == res->as_Goto()->sux_at(0)) { - assert(res->as_Goto()->is_safepoint() == sw.dest_offset_at(i) < 0, "safepoint state of Goto returned by canonicalizer incorrect"); + assert(res->as_Goto()->is_safepoint() == (sw.dest_offset_at(i) < 0), "safepoint state of Goto returned by canonicalizer incorrect"); } } } @@ -1500,7 +1500,7 @@ void GraphBuilder::lookup_switch() { if (res->as_Goto()) { for (i = 0; i < l; i++) { if (sux->at(i) == res->as_Goto()->sux_at(0)) { - assert(res->as_Goto()->is_safepoint() == sw.pair_at(i).offset() < 0, "safepoint state of Goto returned by canonicalizer incorrect"); + assert(res->as_Goto()->is_safepoint() == (sw.pair_at(i).offset() < 0), "safepoint state of Goto returned by canonicalizer incorrect"); } } } diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp index 7e46f9d56034b..9e9195a0d60d0 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -4857,8 +4857,8 @@ void IntervalWalker::next_interval() { // intervals may start at same position -> prefer fixed interval kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind; - assert (kind == fixedKind && fixed->from() <= any->from() || - kind == anyKind && any->from() <= fixed->from(), "wrong interval!!!"); + assert((kind == fixedKind && fixed->from() <= any->from()) || + (kind == anyKind && any->from() <= fixed->from()), "wrong interval!!!"); assert(any == Interval::end() || fixed == Interval::end() || any->from() != fixed->from() || kind == fixedKind, "if fixed and any-Interval start at same position, fixed must be processed first"); } else if (fixed != Interval::end()) { diff --git a/src/hotspot/share/c1/c1_ValueStack.hpp b/src/hotspot/share/c1/c1_ValueStack.hpp index 74d5c2e3f3c65..0a75fa39bf607 100644 --- a/src/hotspot/share/c1/c1_ValueStack.hpp +++ b/src/hotspot/share/c1/c1_ValueStack.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -60,7 +60,7 @@ class ValueStack: public CompilationResourceObj { Values* _locks; // the monitor stack (holding the locked values) Value check(ValueTag tag, Value t) { - assert(tag == t->type()->tag() || tag == objectTag && t->type()->tag() == addressTag, "types must correspond"); + assert(tag == t->type()->tag() || (tag == objectTag && t->type()->tag() == addressTag), "types must correspond"); return t; } diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index d2e70fbd6db02..bfb3db72d7265 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -150,8 +150,8 @@ void RelocIterator::initialize(CompiledMethod* nm, address begin, address limit) RelocIterator::RelocIterator(CodeSection* cs, address begin, address limit) { initialize_misc(); - assert((cs->locs_start() != nullptr) && (cs->locs_end() != nullptr) || - (cs->locs_start() == nullptr) && (cs->locs_end() == nullptr), "valid start and end pointer"); + assert(((cs->locs_start() != nullptr) && (cs->locs_end() != nullptr)) || + ((cs->locs_start() == nullptr) && (cs->locs_end() == nullptr)), "valid start and end pointer"); _current = cs->locs_start()-1; _end = cs->locs_end(); _addr = cs->start(); diff --git a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp index ed456a4215720..d490387672dad 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -57,7 +57,7 @@ inline bool CompilerConfig::is_c1_only() { } inline bool CompilerConfig::is_c1_or_interpreter_only_no_jvmci() { - assert(is_jvmci_compiler() && is_jvmci() || !is_jvmci_compiler(), "JVMCI compiler implies enabled JVMCI"); + assert(!is_jvmci_compiler() || is_jvmci(), "JVMCI compiler implies enabled JVMCI"); return !is_jvmci() && (is_interpreter_only() || is_c1_only()); } @@ -114,7 +114,7 @@ inline bool CompilerConfig::is_c2_or_jvmci_compiler_only() { // Tiered is basically C1 & (C2 | JVMCI) minus all the odd cases with restrictions. inline bool CompilerConfig::is_tiered() { - assert(is_c1_simple_only() && is_c1_only() || !is_c1_simple_only(), "c1 simple mode must imply c1-only mode"); + assert(!is_c1_simple_only() || is_c1_only(), "c1 simple mode must imply c1-only mode"); return has_tiered() && !is_interpreter_only() && !is_c1_only() && !is_c2_or_jvmci_compiler_only(); } From 61ebe3b0c4afb6bfdadbf54d0e8a20347bea1975 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Mon, 8 Jan 2024 22:41:07 +0000 Subject: [PATCH 059/112] 8323032: OptimizedModuleHandlingTest failed in dynamic CDS archive mode Reviewed-by: dholmes, matsaave --- test/hotspot/jtreg/ProblemList.txt | 1 - .../OptimizeModuleHandlingTest.java | 34 +++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index f6913a0734ddc..d82f4a919fa81 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -113,7 +113,6 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 -runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java 8323032 generic-all applications/jcstress/copy.java 8229852 linux-all diff --git a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java index 53de474d9cd41..aeb5696830df4 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java @@ -345,20 +345,26 @@ public static void runWithJarPath(String... extraRuntimeArgs) throws Exception { .shouldNotContain(OPTIMIZE_ENABLED) .shouldContain(MAP_FAILED); }); - // Dump an archive with only -Xbootclasspath/a - output = TestCommon.createArchive( - null, - appClasses, - "-Xbootclasspath/a:" + mainJar.toString()); - TestCommon.checkDump(output); - tty("13. run with CDS on, with the same -Xbootclasspath/a as dump time and adding a -cp with test.jar: should pass"); - TestCommon.run("-Xlog:cds,class+load", - "-cp", testJar.toString(), - "-Xbootclasspath/a:" + mainJar.toString(), - MAIN_CLASS) - .assertNormalExit(out -> { - out.shouldMatch(MAIN_FROM_CDS) - .shouldContain(OPTIMIZE_ENABLED); + + // Skip the following test for dynamic CDS archive because the current + // dynamic dump test utililty does not support empty -cp with a classlist. + // (see createArchive(CDSOptions opts) in TestCommon.java) + if (!CDSTestUtils.isDynamicArchive()) { + // Dump an archive with only -Xbootclasspath/a + output = TestCommon.createArchive( + null, + appClasses, + "-Xbootclasspath/a:" + mainJar.toString()); + TestCommon.checkDump(output); + tty("13. run with CDS on, with the same -Xbootclasspath/a as dump time and adding a -cp with test.jar: should pass"); + TestCommon.run("-Xlog:cds,class+load", + "-cp", testJar.toString(), + "-Xbootclasspath/a:" + mainJar.toString(), + MAIN_CLASS) + .assertNormalExit(out -> { + out.shouldMatch(MAIN_FROM_CDS) + .shouldContain(OPTIMIZE_ENABLED); }); + } } } From 841ab487f83d7e3639d352e796dc7131310c2390 Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Mon, 8 Jan 2024 23:53:06 +0000 Subject: [PATCH 060/112] 8322657: CDS filemap fastdebug assert while loading Graal CE Polyglot in isolated classloader Reviewed-by: matsaave, dholmes --- src/hotspot/share/cds/filemap.cpp | 16 +-- src/hotspot/share/cds/filemap.hpp | 3 +- .../jtreg/runtime/cds/appcds/JarBuilder.java | 19 +++- .../ModularJarWithNonExistentJar.java | 105 ++++++++++++++++++ .../test-classes/DefineModuleApp.java | 51 +++++++++ .../manifest-with-non-existent-jar.txt | 3 + 6 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModularJarWithNonExistentJar.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/DefineModuleApp.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/manifest-with-non-existent-jar.txt diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 3b50e01479718..c2bfec3dfeb18 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -576,12 +576,14 @@ int FileMapInfo::get_module_shared_path_index(Symbol* location) { const char* file = ClassLoader::skip_uri_protocol(location->as_C_string()); for (int i = ClassLoaderExt::app_module_paths_start_index(); i < get_number_of_shared_paths(); i++) { SharedClassPathEntry* ent = shared_path(i); - assert(ent->in_named_module(), "must be"); - bool cond = strcmp(file, ent->name()) == 0; - log_debug(class, path)("get_module_shared_path_index (%d) %s : %s = %s", i, - location->as_C_string(), ent->name(), cond ? "same" : "different"); - if (cond) { - return i; + if (!ent->is_non_existent()) { + assert(ent->in_named_module(), "must be"); + bool cond = strcmp(file, ent->name()) == 0; + log_debug(class, path)("get_module_shared_path_index (%d) %s : %s = %s", i, + location->as_C_string(), ent->name(), cond ? "same" : "different"); + if (cond) { + return i; + } } } diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index 3d2062093c6b7..fd84563008ccf 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -89,6 +89,7 @@ class SharedClassPathEntry : public MetaspaceObj { bool is_dir() const { return _type == dir_entry; } bool is_modules_image() const { return _type == modules_image_entry; } bool is_jar() const { return _type == jar_entry; } + bool is_non_existent() const { return _type == non_existent_entry; } bool from_class_path_attr() { return _from_class_path_attr; } time_t timestamp() const { return _timestamp; } const char* name() const; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/JarBuilder.java b/test/hotspot/jtreg/runtime/cds/appcds/JarBuilder.java index b9c2063f3e7e1..ef13a0a94141b 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/JarBuilder.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/JarBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -199,6 +199,23 @@ public static void createModularJar(String jarPath, createJar(argList); } + public static void createModularJarWithManifest(String jarPath, + String classesDir, + String mainClass, + String manifest) throws Exception { + ArrayList argList = new ArrayList(); + argList.add("--create"); + argList.add("--file=" + jarPath); + if (mainClass != null) { + argList.add("--main-class=" + mainClass); + } + argList.add("--manifest=" + manifest); + argList.add("-C"); + argList.add(classesDir); + argList.add("."); + createJar(argList); + } + private static void createJar(ArrayList args) { if (DEBUG) printIterable("createJar args: ", args); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModularJarWithNonExistentJar.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModularJarWithNonExistentJar.java new file mode 100644 index 0000000000000..9e7579a34fd3e --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ModularJarWithNonExistentJar.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024, 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 8322657 + * @summary This test defines an application module using the DefineModuleApp. + * When performing dynamic dump, the modular jar containing the module + * is in the -cp. The jar listed in the "Class-Path" attribute of the modular + * jar doesn't exist. VM should not crash during dynamic dump under this scenario. + * @requires vm.cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes + * @build jdk.test.whitebox.WhiteBox DefineModuleApp + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar define_module_app.jar DefineModuleApp + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. ModularJarWithNonExistentJar + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import jdk.test.lib.cds.CDSTestUtils; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class ModularJarWithNonExistentJar extends DynamicArchiveTestBase { + private static final Path USER_DIR = Paths.get(CDSTestUtils.getOutputDir()); + + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Paths.get(TEST_SRC, "../jigsaw/modulepath/src"); + private static final Path MODS_DIR = Paths.get("mods"); + private static final Path MANIFEST_PATH = Paths.get(TEST_SRC, "test-classes/manifest-with-non-existent-jar.txt"); + + // the module name of the test module + private static final String TEST_MODULE = "com.simple"; + + // the module main class + private static final String MAIN_CLASS = "com.simple.Main"; + + private static Path moduleDir = null; + private static Path modularJar = null; + + public static void buildTestModule() throws Exception { + + // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/** + JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE), + MODS_DIR.resolve(TEST_MODULE), + MODS_DIR.toString()); + + + moduleDir = Files.createTempDirectory(USER_DIR, "mlib"); + + modularJar = moduleDir.resolve(TEST_MODULE + ".jar"); + String classes = MODS_DIR.resolve(TEST_MODULE).toString(); + JarBuilder.createModularJarWithManifest(modularJar.toString(), classes, + MAIN_CLASS, MANIFEST_PATH.toString()); + } + + public static void main(String... args) throws Exception { + runTest(ModularJarWithNonExistentJar::testDefaultBase); + } + + static void testDefaultBase() throws Exception { + String topArchiveName = getNewArchiveName("top"); + doTest(topArchiveName); + } + + private static void doTest(String topArchiveName) throws Exception { + // compile the module and create the modular jar file + buildTestModule(); + String appJar = ClassFileInstaller.getJarPath("define_module_app.jar"); + dump(topArchiveName, + "-Xlog:cds,class+path=info", + "-Xlog:cds+dynamic=debug", + "-cp", appJar + File.pathSeparator + modularJar.toString(), + "DefineModuleApp", moduleDir.toString(), TEST_MODULE) + .assertNormalExit(output -> { + output.shouldContain("Written dynamic archive 0x"); + }); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/DefineModuleApp.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/DefineModuleApp.java new file mode 100644 index 0000000000000..fad62598cc73b --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/DefineModuleApp.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024, 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. + * + */ + +/** + * This app defines a module using the ModuleLayer.defineModulesWithOneLoader API + * which calls the JVM_DefineModule. + **/ + +import java.nio.file.Path; +import java.lang.ModuleLayer.Controller; +import java.lang.module.*; +import java.util.List; +import java.util.Set; + +public class DefineModuleApp { + public static void main(String[] args) throws Throwable { + if (args.length != 2) { + throw new RuntimeException("DefineModuleApp expects 2 args but saw " + args.length); + } + final Path MODS = Path.of(args[0]); + final String MODULE_NAME = args[1]; + Configuration cf = ModuleLayer.boot() + .configuration() + .resolve(ModuleFinder.of(), ModuleFinder.of(MODS), Set.of(MODULE_NAME)); + ResolvedModule m = cf.findModule(MODULE_NAME).orElseThrow(); + ModuleLayer bootLayer = ModuleLayer.boot(); + ClassLoader scl = ClassLoader.getSystemClassLoader(); + Controller controller = ModuleLayer.defineModulesWithOneLoader(cf, List.of(bootLayer), scl); + } +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/manifest-with-non-existent-jar.txt b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/manifest-with-non-existent-jar.txt new file mode 100644 index 0000000000000..7558b8b2c82a5 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/manifest-with-non-existent-jar.txt @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: NonExistent.jar +Created-By: 23-internal (Oracle Corporation) From 8ae309ebacd6947bbad2ef168ca13702e1cba099 Mon Sep 17 00:00:00 2001 From: Weibing Xiao Date: Tue, 9 Jan 2024 04:04:12 +0000 Subject: [PATCH 061/112] 8318971: Better Error Handling for Jar Tool When Processing Non-existent Files Reviewed-by: alanb, jpai --- .../share/classes/sun/tools/jar/Main.java | 6 ++ test/jdk/tools/jar/InputFilesTest.java | 82 ++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index fce80372b1e27..6163ef8264772 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -292,6 +292,9 @@ public synchronized boolean run(String args[]) { } } expand(); + if (!ok) { + return false; + } if (!moduleInfos.isEmpty()) { // All actual file entries (excl manifest and module-info.class) Set jentries = new HashSet<>(); @@ -338,6 +341,9 @@ public synchronized boolean run(String args[]) { tmpFile = createTemporaryFile("tmpjar", ".jar"); } expand(); + if (!ok) { + return false; + } try (FileInputStream in = (fname != null) ? new FileInputStream(inputFile) : new FileInputStream(FileDescriptor.in); FileOutputStream out = new FileOutputStream(tmpFile); diff --git a/test/jdk/tools/jar/InputFilesTest.java b/test/jdk/tools/jar/InputFilesTest.java index 3dc08293a7677..6a0a7e2902188 100644 --- a/test/jdk/tools/jar/InputFilesTest.java +++ b/test/jdk/tools/jar/InputFilesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8165944 + * @bug 8165944 8318971 * @summary test several jar tool input file scenarios with variations on -C * options with/without a --release option. Some input files are * duplicates that sometimes cause exceptions and other times do not, @@ -153,6 +153,84 @@ public void test6() throws IOException { jar("cf test.jar --release 9 -C test1 a -C test2 a"); } + /** + * Containing non-existent file in the file list + * The final jar should not be created and correct error message should be caught. + * IOException is triggered as expected. + */ + @Test + public void testNonExistentFileInput() throws IOException { + touch("existingTestFile.txt"); + onCompletion = () -> rm("existingTestFile.txt"); + try { + jar("cf test.jar existingTestFile.txt nonExistentTestFile.txt"); + Assert.fail("jar tool unexpectedly completed successfully"); + } catch (IOException e) { + Assert.assertEquals(e.getMessage().trim(), "nonExistentTestFile.txt : no such file or directory"); + Assert.assertTrue(Files.notExists(Path.of("test.jar")), "Jar file should not be created."); + } + } + + /** + * With @File as a part of jar command line, where the File is containing one or more + * non-existent files or directories + * The final jar should not be created and correct error message should be caught. + * IOException is triggered as expected. + */ + @Test + public void testNonExistentFileInputClassList() throws IOException { + touch("existingTestFile.txt"); + touch("classes.list"); + Files.writeString(Path.of("classes.list"), """ + existingTestFile.txt + nonExistentTestFile.txt + nonExistentDirectory + """); + onCompletion = () -> rm("existingTestFile.txt classes.list"); + try { + jar("cf test.jar @classes.list"); + Assert.fail("jar tool unexpectedly completed successfully"); + } catch (IOException e) { + String msg = e.getMessage().trim(); + Assert.assertTrue(msg.contains("nonExistentTestFile.txt : no such file or directory")); + Assert.assertTrue(msg.trim().contains("nonExistentDirectory : no such file or directory")); + Assert.assertTrue(Files.notExists(Path.of("test.jar")), "Jar file should not be created."); + } + + } + + /** + * Create a jar file; then with @File as a part of jar command line, where the File is containing one or more + * non-existent files or directories + * The final jar should not be created and correct error message should be caught. + * IOException is triggered as expected. + */ + @Test + public void testUpdateNonExistentFileInputClassList() throws IOException { + touch("existingTestFileUpdate.txt"); + touch("existingTestFileUpdate2.txt"); + touch("classesUpdate.list"); + Files.writeString(Path.of("classesUpdate.list"), """ + existingTestFileUpdate2.txt + nonExistentTestFileUpdate.txt + nonExistentDirectoryUpdate + """); + onCompletion = () -> rm("existingTestFileUpdate.txt existingTestFileUpdate2.txt " + + "classesUpdate.list testUpdate.jar"); + try { + jar("cf testUpdate.jar existingTestFileUpdate.txt"); + Assert.assertTrue(Files.exists(Path.of("testUpdate.jar"))); + jar("uf testUpdate.jar @classesUpdate.list"); + Assert.fail("jar tool unexpectedly completed successfully"); + } catch (IOException e) { + String msg = e.getMessage().trim(); + Assert.assertFalse(msg.contains("existingTestFileUpdate.txt : no such file or directory")); + Assert.assertTrue(msg.contains("nonExistentTestFileUpdate.txt : no such file or directory")); + Assert.assertTrue(msg.trim().contains("nonExistentDirectoryUpdate : no such file or directory")); + } + + } + private Stream mkpath(String... args) { return Arrays.stream(args).map(d -> Paths.get(".", d.split("/"))); } From 176606d0cb9117ca9080261f898cd57339fa5a85 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Tue, 9 Jan 2024 04:36:30 +0000 Subject: [PATCH 062/112] 8310995: missing @since tags in 36 jdk.dynalink classes Reviewed-by: jlaskey, iris, attila --- .../share/classes/jdk/dynalink/CallSiteDescriptor.java | 1 + src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java | 1 + .../share/classes/jdk/dynalink/DynamicLinkerFactory.java | 1 + src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java | 1 + src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java | 1 + .../share/classes/jdk/dynalink/NamespaceOperation.java | 1 + .../classes/jdk/dynalink/NoSuchDynamicMethodException.java | 1 + src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java | 1 + .../share/classes/jdk/dynalink/RelinkableCallSite.java | 1 + .../share/classes/jdk/dynalink/SecureLookupSupplier.java | 1 + .../share/classes/jdk/dynalink/StandardNamespace.java | 1 + .../share/classes/jdk/dynalink/StandardOperation.java | 1 + .../share/classes/jdk/dynalink/beans/BeansLinker.java | 1 + .../classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java | 1 + .../share/classes/jdk/dynalink/beans/StaticClass.java | 1 + .../share/classes/jdk/dynalink/linker/ConversionComparator.java | 2 ++ .../share/classes/jdk/dynalink/linker/GuardedInvocation.java | 1 + .../jdk/dynalink/linker/GuardedInvocationTransformer.java | 1 + .../classes/jdk/dynalink/linker/GuardingDynamicLinker.java | 1 + .../jdk/dynalink/linker/GuardingDynamicLinkerExporter.java | 1 + .../jdk/dynalink/linker/GuardingTypeConverterFactory.java | 1 + .../share/classes/jdk/dynalink/linker/LinkRequest.java | 1 + .../share/classes/jdk/dynalink/linker/LinkerServices.java | 1 + .../classes/jdk/dynalink/linker/MethodHandleTransformer.java | 1 + .../jdk/dynalink/linker/MethodTypeConversionStrategy.java | 1 + .../jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java | 1 + .../dynalink/linker/support/CompositeGuardingDynamicLinker.java | 1 + .../linker/support/CompositeTypeBasedGuardingDynamicLinker.java | 1 + .../dynalink/linker/support/DefaultInternalObjectFilter.java | 1 + .../share/classes/jdk/dynalink/linker/support/Guards.java | 1 + .../share/classes/jdk/dynalink/linker/support/Lookup.java | 1 + .../classes/jdk/dynalink/linker/support/SimpleLinkRequest.java | 1 + .../classes/jdk/dynalink/linker/support/TypeUtilities.java | 1 + src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java | 1 + .../jdk/dynalink/support/AbstractRelinkableCallSite.java | 1 + .../share/classes/jdk/dynalink/support/ChainedCallSite.java | 1 + .../classes/jdk/dynalink/support/SimpleRelinkableCallSite.java | 1 + 37 files changed, 38 insertions(+) diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java b/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java index e1e49f22b4c45..e47625fb497d5 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java @@ -88,6 +88,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * the {@code MethodHandles.Lookup} object it carries. This lookup should be used * to find method handles to set as targets of the call site described by this * descriptor. + * @since 9 */ public class CallSiteDescriptor extends SecureLookupSupplier { private final Operation operation; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java index eb7de0aba75a1..23f4f7a81227c 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java @@ -141,6 +141,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * in the above example the {@code parseOperation} method is left unimplemented. * * + * @since 9 */ public final class DynamicLinker { private static final String CLASS_NAME = DynamicLinker.class.getName(); diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java index a34cff5ba12fe..ed2110085669f 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java @@ -105,6 +105,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * {@link #setClassLoader(ClassLoader) automatically discovered} ones, and * finally the ones configured with {@link #setFallbackLinkers(List)}; this last * category usually includes {@link BeansLinker}. + * @since 9 */ public final class DynamicLinkerFactory { @SuppressWarnings("removal") diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java index 7563e3946ad96..5fe3e96f43ec4 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java @@ -106,6 +106,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * usually containing the textual representation of the source expression that retrieved the * callee, e.g. {@code StandardOperation.CALL.named("window.open")}. *

+ * @since 9 */ public final class NamedOperation implements Operation { private final Operation baseOperation; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java b/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java index 69b68d25ffc3a..8f5e7ede7f639 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java @@ -66,6 +66,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * set of standard namespaces with the {@link StandardNamespace} enum. Operations * that need to specify a namespace they operate on can be expressed using * {@link NamespaceOperation}. + * @since 9 */ public interface Namespace { } diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java index 322767de36463..0e047849c2c52 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java @@ -134,6 +134,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * StandardNamespace.PROPERTY) * .named("empty"); * + * @since 9 */ public final class NamespaceOperation implements Operation { private final Operation baseOperation; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java b/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java index bf20c23b7380d..8842c32c1befc 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java @@ -64,6 +64,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR /** * Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}. + * @since 9 */ public class NoSuchDynamicMethodException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java index ba22e32c54f3a..ef0acbc3b5741 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java @@ -74,6 +74,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * {@code GET:PROPERTY|ELEMENT}), and finally we will refer to named operations * by separating the base operation and the name with the colon character (e.g. * {@code GET:PROPERTY|ELEMENT:color}). + * @since 9 */ public interface Operation { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java index 5f74edd700c48..e14cfdfebd3ed 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java @@ -76,6 +76,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * method handles. A relinkable call site will be managed by a * {@link DynamicLinker} object after being associated with it using its * {@link DynamicLinker#link(RelinkableCallSite)} method. + * @since 9 */ public interface RelinkableCallSite { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java b/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java index 73ee39b9002c5..5ec1f2737fbdb 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/SecureLookupSupplier.java @@ -32,6 +32,7 @@ /** * Provides security-checked access to a {@code MethodHandles.Lookup} object. * See {@link #getLookup()} for details. + * @since 9 */ public class SecureLookupSupplier { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java index 55b9acee7032e..b4c33250d38dd 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java @@ -62,6 +62,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR /** * An enumeration of standard namespaces defined by Dynalink. + * @since 9 */ public enum StandardNamespace implements Namespace { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java index e58bf4e78bf0a..176a87acd3621 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java @@ -67,6 +67,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * disappears from their type signature. * {@link NamedOperation} can also be used to decorate {@link #CALL} and {@link #NEW} operations with a * diagnostic name, and as such it does not affect their type signature. + * @since 9 */ public enum StandardOperation implements Operation { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java index 386f386216ca8..ca09923292a77 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java @@ -135,6 +135,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * property and method names on classes and class instances, as well as access * to per-class linkers using the {@link #getLinkerForClass(Class)} * method.

+ * @since 9 */ public class BeansLinker implements GuardingDynamicLinker { private static final ClassValue linkers = new ClassValue<>() { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java index 1fe50b916d9a1..c1e2f7eb71d15 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MissingMemberHandlerFactory.java @@ -67,6 +67,7 @@ * exception itself, as the linkage for the missing member is often conditional. * * @see BeansLinker#BeansLinker(MissingMemberHandlerFactory) + * @since 9 */ @FunctionalInterface public interface MissingMemberHandlerFactory { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java index 62bb74cb29ea7..ebd6c7e55e2fb 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java @@ -102,6 +102,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * constructor. You might want to expose a mechanism in your language for * selecting a constructor with an explicit signature through * {@link BeansLinker#getConstructorMethod(Class, String)}. + * @since 9 */ public final class StaticClass implements Serializable { private static final ClassValue staticClasses = new ClassValue<>() { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java index 6c0dd438bbb2a..267752b0a238d 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java @@ -70,10 +70,12 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * specific method with unrelated signatures. In these cases, language runtimes * can be asked to resolve the ambiguity by expressing preferences for one * conversion over the other. + * @since 9 */ public interface ConversionComparator { /** * Enumeration of possible outcomes of comparing one conversion to another. + * @since 9 */ enum Comparison { /** The conversions cannot be compared. **/ diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java index 1a1e23981c54a..174e63bff26ca 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java @@ -86,6 +86,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * throw an exception of the designated type. The guard, the switch points, and * the exception type are all optional (a guarded invocation having none of them * is unconditionally valid). + * @since 9 */ public class GuardedInvocation { private final MethodHandle invocation; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java index 6c7750223620f..fa4f0cd454593 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java @@ -67,6 +67,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * another one. Typical usage is for implementing * {@link DynamicLinkerFactory#setPrelinkTransformer(GuardedInvocationTransformer) * pre-link transformers}. + * @since 9 */ @FunctionalInterface public interface GuardedInvocationTransformer { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java index c604712ae43cf..e94cb7b912833 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java @@ -87,6 +87,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * Languages can export linkers to other language runtimes for * {@link DynamicLinkerFactory#setClassLoader(ClassLoader) automatic discovery} * using a {@link GuardingDynamicLinkerExporter}. + * @since 9 */ public interface GuardingDynamicLinker { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java index 03be07cf45914..cd670a8fdbead 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java @@ -45,6 +45,7 @@ * security manager is present, to ensure that only trusted runtimes can * automatically export their linkers into other runtimes. * @see DynamicLinkerFactory#setClassLoader(ClassLoader) + * @since 9 */ public abstract class GuardingDynamicLinkerExporter implements Supplier> { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java index 981a39059af5c..bbd327d5bbefd 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java @@ -75,6 +75,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * these conversions, will cause more ambiguity for {@link BeansLinker} in * selecting the correct overload when trying to link to an overloaded Java * method. + * @since 9 */ public interface GuardingTypeConverterFactory { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java index 209c1920a3f8b..1feeed03d1560 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java @@ -69,6 +69,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * site. Instances of these requests will be constructed and passed to all * {@link GuardingDynamicLinker} objects managed by the {@link DynamicLinker} * that is trying to link the call site. + * @since 9 */ public interface LinkRequest { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java index e66babebf33f5..5a028205676d1 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java @@ -73,6 +73,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR /** * Interface for services provided to {@link GuardingDynamicLinker} instances by * the {@link DynamicLinker} that owns them. + * @since 9 */ public interface LinkerServices { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java index 2af6294c51740..e9ccd30ffed8d 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java @@ -68,6 +68,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * Typical usage is for implementing * {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer) * internal objects filters}. + * @since 9 */ @FunctionalInterface public interface MethodHandleTransformer { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java index b830e375c12c2..394f81858ff35 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java @@ -70,6 +70,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * of * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy) * method invocation conversions}. + * @since 9 */ @FunctionalInterface public interface MethodTypeConversionStrategy { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java index 53c1a66e86294..1565cfee552bd 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java @@ -68,6 +68,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * linkers will fall into this category, as they recognize their native objects as Java objects of classes implementing * a specific language-native interface or superclass. The linker mechanism can optimize the dispatch for these linkers, * see {@link CompositeTypeBasedGuardingDynamicLinker}. + * @since 9 */ public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker { /** diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java index 8ae1f4754cf4e..c226a9c0b178c 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java @@ -72,6 +72,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * A {@link GuardingDynamicLinker} that delegates sequentially to a list of * other guarding dynamic linkers in its * {@link #getGuardedInvocation(LinkRequest, LinkerServices)}. + * @since 9 */ public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java index 184cc8e0ab801..a0805ff57d651 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java @@ -77,6 +77,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * returning true are then bound to the class, and next time a receiver of same * type is encountered, the linking is delegated to those linkers only, speeding * up dispatch. + * @since 9 */ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker { // Using a separate static class instance so there's no strong reference from the class value back to the composite diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java index 9929eeb7e5009..7a43f7ebbc0d7 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java @@ -80,6 +80,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * the parameter filter as being a wrapping method for exposing internal runtime * objects wrapped into an adapter with some public interface, and the return * value filter as being its inverse unwrapping method. + * @since 9 */ public class DefaultInternalObjectFilter implements MethodHandleTransformer { private static final MethodHandle FILTER_VARARGS = new Lookup(MethodHandles.lookup()).findStatic( diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java index 9a456df5ebeab..7b0fd0e156b7c 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java @@ -72,6 +72,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * Utility methods for creating typical guards for * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)} * and for adjusting their method types. + * @since 9 */ public final class Guards { private static final Logger LOG = Logger diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java index ecf66e7d458a6..25792f0108b32 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java @@ -72,6 +72,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * checked exceptions. It is useful in those cases when you're looking up * methods within your own codebase (therefore it is an error if they are not * present). + * @since 9 */ public final class Lookup { private final MethodHandles.Lookup lookup; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java index d8cfd8a9d9c2c..7a00b9fe3ea6d 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java @@ -66,6 +66,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR /** * Default simple implementation of {@link LinkRequest}. + * @since 9 */ public class SimpleLinkRequest implements LinkRequest { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java index f5ee9e0909360..2a3d667d49a86 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java @@ -70,6 +70,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR /** * Various static utility methods for working with Java types. + * @since 9 */ public final class TypeUtilities { private TypeUtilities() { diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java b/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java index 03c7b9603f6b4..1218885ae9afd 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java @@ -60,5 +60,6 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR /** * Contains interfaces and classes that are used to link an {@code invokedynamic} call site. + * @since 9 */ package jdk.dynalink; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java index dbcf3ffd02153..84ecfa1db3887 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java @@ -75,6 +75,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * {@link #relink(GuardedInvocation, MethodHandle)} and * {@link #resetAndRelink(GuardedInvocation, MethodHandle)} * methods. + * @since 9 */ public abstract class AbstractRelinkableCallSite extends MutableCallSite implements RelinkableCallSite { private final CallSiteDescriptor descriptor; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java index a026512242ab9..2f75b53fc3d93 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java @@ -84,6 +84,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * Race conditions in linking are resolved by throwing away the * {@link GuardedInvocation} produced on the losing thread without incorporating * it into the chain, so it can lead to repeated linking for the same arguments. + * @since 9 */ public class ChainedCallSite extends AbstractRelinkableCallSite { private static final MethodHandle PRUNE_CATCHES; diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java b/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java index 06f50b4ff8079..022d6088d01f8 100644 --- a/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java @@ -71,6 +71,7 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * If the guard of that single invocation fails, or it has an invalidated * switch point, or its invalidating exception triggered, then the call site * will throw it away and ask its associated {@link DynamicLinker} to relink it. + * @since 9 */ public class SimpleRelinkableCallSite extends AbstractRelinkableCallSite { /** From 07fce8eff207eedcbab29b52660f19333df7c574 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 9 Jan 2024 06:11:44 +0000 Subject: [PATCH 063/112] 8320864: Serial: Extract out Full GC related fields from ContiguousSpace Reviewed-by: kbarrett, sjohanss --- src/hotspot/share/gc/serial/genMarkSweep.cpp | 452 ++++++++++++++---- src/hotspot/share/gc/serial/genMarkSweep.hpp | 9 +- src/hotspot/share/gc/serial/generation.cpp | 31 -- src/hotspot/share/gc/serial/generation.hpp | 9 +- .../share/gc/serial/tenuredGeneration.hpp | 4 +- .../share/gc/shared/genCollectedHeap.cpp | 13 - .../share/gc/shared/genCollectedHeap.hpp | 12 - src/hotspot/share/gc/shared/space.cpp | 239 +-------- src/hotspot/share/gc/shared/space.hpp | 87 +--- src/hotspot/share/gc/shared/space.inline.hpp | 91 +--- src/hotspot/share/gc/shared/vmStructs_gc.hpp | 4 - 11 files changed, 363 insertions(+), 588 deletions(-) diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp index fb55116ab816b..28ba4615f73a2 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp @@ -36,6 +36,7 @@ #include "gc/serial/defNewGeneration.hpp" #include "gc/serial/generation.hpp" #include "gc/serial/genMarkSweep.hpp" +#include "gc/serial/markSweep.inline.hpp" #include "gc/serial/serialGcRefProcProxyTask.hpp" #include "gc/serial/serialHeap.hpp" #include "gc/shared/classUnloadingContext.hpp" @@ -48,7 +49,7 @@ #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" -#include "gc/shared/space.hpp" +#include "gc/shared/space.inline.hpp" #include "gc/shared/strongRootsScope.hpp" #include "gc/shared/weakProcessor.hpp" #include "memory/universe.hpp" @@ -57,6 +58,7 @@ #include "prims/jvmtiExport.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaThread.hpp" +#include "runtime/prefetch.inline.hpp" #include "runtime/synchronizer.hpp" #include "runtime/vmThread.hpp" #include "utilities/copy.hpp" @@ -66,98 +68,281 @@ #include "jvmci/jvmci.hpp" #endif -void GenMarkSweep::invoke_at_safepoint(bool clear_all_softrefs) { - assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); +class DeadSpacer : StackObj { + size_t _allowed_deadspace_words; + bool _active; + ContiguousSpace* _space; - SerialHeap* gch = SerialHeap::heap(); -#ifdef ASSERT - if (gch->soft_ref_policy()->should_clear_all_soft_refs()) { - assert(clear_all_softrefs, "Policy should have been checked earlier"); +public: + DeadSpacer(ContiguousSpace* space) : _allowed_deadspace_words(0), _space(space) { + size_t ratio = _space->allowed_dead_ratio(); + _active = ratio > 0; + + if (_active) { + // We allow some amount of garbage towards the bottom of the space, so + // we don't start compacting before there is a significant gain to be made. + // Occasionally, we want to ensure a full compaction, which is determined + // by the MarkSweepAlwaysCompactCount parameter. + if ((MarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0) { + _allowed_deadspace_words = (space->capacity() * ratio / 100) / HeapWordSize; + } else { + _active = false; + } + } } -#endif - gch->trace_heap_before_gc(_gc_tracer); - - // Increment the invocation count - _total_invocations++; + bool insert_deadspace(HeapWord* dead_start, HeapWord* dead_end) { + if (!_active) { + return false; + } - // Capture used regions for each generation that will be - // subject to collection, so that card table adjustments can - // be made intelligently (see clear / invalidate further below). - gch->save_used_regions(); + size_t dead_length = pointer_delta(dead_end, dead_start); + if (_allowed_deadspace_words >= dead_length) { + _allowed_deadspace_words -= dead_length; + CollectedHeap::fill_with_object(dead_start, dead_length); + oop obj = cast_to_oop(dead_start); + // obj->set_mark(obj->mark().set_marked()); + + assert(dead_length == obj->size(), "bad filler object size"); + log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b", + p2i(dead_start), p2i(dead_end), dead_length * HeapWordSize); + + return true; + } else { + _active = false; + return false; + } + } +}; - allocate_stacks(); +// Implement the "compaction" part of the mark-compact GC algorithm. +class Compacter { + // There are four spaces in total, but only the first three can be used after + // compact. IOW, old and eden/from must be enough for all live objs + static constexpr uint max_num_spaces = 4; + + struct CompactionSpace { + ContiguousSpace* _space; + // Will be the new top after compaction is complete. + HeapWord* _compaction_top; + // The first dead word in this contiguous space. It's an optimization to + // skip large chunk of live objects at the beginning. + HeapWord* _first_dead; + + void init(ContiguousSpace* space) { + _space = space; + _compaction_top = space->bottom(); + _first_dead = nullptr; + } + }; - mark_sweep_phase1(clear_all_softrefs); + CompactionSpace _spaces[max_num_spaces]; + // The num of spaces to be compacted, i.e. containing live objs. + uint _num_spaces; - mark_sweep_phase2(); + uint _index; - // Don't add any more derived pointers during phase3 -#if COMPILER2_OR_JVMCI - assert(DerivedPointerTable::is_active(), "Sanity"); - DerivedPointerTable::set_active(false); -#endif + HeapWord* get_compaction_top(uint index) const { + return _spaces[index]._compaction_top; + } - mark_sweep_phase3(); + HeapWord* get_first_dead(uint index) const { + return _spaces[index]._first_dead; + } - mark_sweep_phase4(); + ContiguousSpace* get_space(uint index) const { + return _spaces[index]._space; + } - restore_marks(); + void record_first_dead(uint index, HeapWord* first_dead) { + assert(_spaces[index]._first_dead == nullptr, "should write only once"); + _spaces[index]._first_dead = first_dead; + } - // Set saved marks for allocation profiler (and other things? -- dld) - // (Should this be in general part?) - gch->save_marks(); + HeapWord* alloc(size_t words) { + while (true) { + if (words <= pointer_delta(_spaces[_index]._space->end(), + _spaces[_index]._compaction_top)) { + HeapWord* result = _spaces[_index]._compaction_top; + _spaces[_index]._compaction_top += words; + if (_index == 0) { + // old-gen requires BOT update + static_cast(_spaces[0]._space)->update_for_block(result, result + words); + } + return result; + } + + // out-of-memory in this space + _index++; + assert(_index < max_num_spaces - 1, "the last space should not be used"); + } + } - deallocate_stacks(); + static void prefetch_read_scan(void* p) { + if (PrefetchScanIntervalInBytes >= 0) { + Prefetch::read(p, PrefetchScanIntervalInBytes); + } + } - MarkSweep::_string_dedup_requests->flush(); + static void prefetch_write_scan(void* p) { + if (PrefetchScanIntervalInBytes >= 0) { + Prefetch::write(p, PrefetchScanIntervalInBytes); + } + } - bool is_young_gen_empty = (gch->young_gen()->used() == 0); - gch->rem_set()->maintain_old_to_young_invariant(gch->old_gen(), is_young_gen_empty); + static void prefetch_write_copy(void* p) { + if (PrefetchCopyIntervalInBytes >= 0) { + Prefetch::write(p, PrefetchCopyIntervalInBytes); + } + } - gch->prune_scavengable_nmethods(); + static void forward_obj(oop obj, HeapWord* new_addr) { + prefetch_write_scan(obj); + if (cast_from_oop(obj) != new_addr) { + obj->forward_to(cast_to_oop(new_addr)); + } else { + assert(obj->is_gc_marked(), "inv"); + // This obj will stay in-place. Fix the markword. + obj->init_mark(); + } + } - // Update heap occupancy information which is used as - // input to soft ref clearing policy at the next gc. - Universe::heap()->update_capacity_and_used_at_gc(); + static HeapWord* find_next_live_addr(HeapWord* start, HeapWord* end) { + for (HeapWord* i_addr = start; i_addr < end; /* empty */) { + prefetch_read_scan(i_addr); + oop obj = cast_to_oop(i_addr); + if (obj->is_gc_marked()) { + return i_addr; + } + i_addr += obj->size(); + } + return end; + }; - // Signal that we have completed a visit to all live objects. - Universe::heap()->record_whole_heap_examined_timestamp(); + static size_t relocate(HeapWord* addr) { + // Prefetch source and destination + prefetch_read_scan(addr); - gch->trace_heap_after_gc(_gc_tracer); -} + oop obj = cast_to_oop(addr); + oop new_obj = obj->forwardee(); + HeapWord* new_addr = cast_from_oop(new_obj); + assert(addr != new_addr, "inv"); + prefetch_write_copy(new_addr); -void GenMarkSweep::allocate_stacks() { - void* scratch = nullptr; - size_t num_words; - DefNewGeneration* young_gen = (DefNewGeneration*)SerialHeap::heap()->young_gen(); - young_gen->contribute_scratch(scratch, num_words); + size_t obj_size = obj->size(); + Copy::aligned_conjoint_words(addr, new_addr, obj_size); + new_obj->init_mark(); - if (scratch != nullptr) { - _preserved_count_max = num_words * HeapWordSize / sizeof(PreservedMark); - } else { - _preserved_count_max = 0; + return obj_size; } - _preserved_marks = (PreservedMark*)scratch; - _preserved_count = 0; - - _preserved_overflow_stack_set.init(1); -} +public: + explicit Compacter(SerialHeap* heap) { + // In this order so that heap is compacted towards old-gen. + _spaces[0].init(heap->old_gen()->space()); + _spaces[1].init(heap->young_gen()->eden()); + _spaces[2].init(heap->young_gen()->from()); + + bool is_promotion_failed = (heap->young_gen()->from()->next_compaction_space() != nullptr); + if (is_promotion_failed) { + _spaces[3].init(heap->young_gen()->to()); + _num_spaces = 4; + } else { + _num_spaces = 3; + } + _index = 0; + } + void phase2_calculate_new_addr() { + for (uint i = 0; i < _num_spaces; ++i) { + ContiguousSpace* space = get_space(i); + HeapWord* cur_addr = space->bottom(); + HeapWord* top = space->top(); + + bool record_first_dead_done = false; + + DeadSpacer dead_spacer(space); + + while (cur_addr < top) { + oop obj = cast_to_oop(cur_addr); + size_t obj_size = obj->size(); + if (obj->is_gc_marked()) { + HeapWord* new_addr = alloc(obj_size); + forward_obj(obj, new_addr); + cur_addr += obj_size; + } else { + // Skipping the current known-unmarked obj + HeapWord* next_live_addr = find_next_live_addr(cur_addr + obj_size, top); + if (dead_spacer.insert_deadspace(cur_addr, next_live_addr)) { + // Register space for the filler obj + alloc(pointer_delta(next_live_addr, cur_addr)); + } else { + if (!record_first_dead_done) { + record_first_dead(i, cur_addr); + record_first_dead_done = true; + } + *(HeapWord**)cur_addr = next_live_addr; + } + cur_addr = next_live_addr; + } + } + + if (!record_first_dead_done) { + record_first_dead(i, top); + } + } + } -void GenMarkSweep::deallocate_stacks() { - if (_preserved_count_max != 0) { - DefNewGeneration* young_gen = (DefNewGeneration*)SerialHeap::heap()->young_gen(); - young_gen->reset_scratch(); + void phase3_adjust_pointers() { + for (uint i = 0; i < _num_spaces; ++i) { + ContiguousSpace* space = get_space(i); + HeapWord* cur_addr = space->bottom(); + HeapWord* const top = space->top(); + HeapWord* const first_dead = get_first_dead(i); + + while (cur_addr < top) { + prefetch_write_scan(cur_addr); + if (cur_addr < first_dead || cast_to_oop(cur_addr)->is_gc_marked()) { + size_t size = MarkSweep::adjust_pointers(cast_to_oop(cur_addr)); + cur_addr += size; + } else { + assert(*(HeapWord**)cur_addr > cur_addr, "forward progress"); + cur_addr = *(HeapWord**)cur_addr; + } + } + } } - _preserved_overflow_stack_set.reclaim(); - _marking_stack.clear(); - _objarray_stack.clear(true); -} + void phase4_compact() { + for (uint i = 0; i < _num_spaces; ++i) { + ContiguousSpace* space = get_space(i); + HeapWord* cur_addr = space->bottom(); + HeapWord* top = space->top(); + + // Check if the first obj inside this space is forwarded. + if (!cast_to_oop(cur_addr)->is_forwarded()) { + // Jump over consecutive (in-place) live-objs-chunk + cur_addr = get_first_dead(i); + } + + while (cur_addr < top) { + if (!cast_to_oop(cur_addr)->is_forwarded()) { + cur_addr = *(HeapWord**) cur_addr; + continue; + } + cur_addr += relocate(cur_addr); + } + + // Reset top and unused memory + space->set_top(get_compaction_top(i)); + if (ZapUnusedHeapArea) { + space->mangle_unused_area(); + } + } + } +}; -void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { +void GenMarkSweep::phase1_mark(bool clear_all_softrefs) { // Recursively traverse all live objects and mark them GCTraceTime(Info, gc, phases) tm("Phase 1: Mark live objects", _gc_timer); @@ -241,54 +426,121 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { } } +void GenMarkSweep::invoke_at_safepoint(bool clear_all_softrefs) { + assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); -void GenMarkSweep::mark_sweep_phase2() { - // Now all live objects are marked, compute the new object addresses. - GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", _gc_timer); + SerialHeap* gch = SerialHeap::heap(); +#ifdef ASSERT + if (gch->soft_ref_policy()->should_clear_all_soft_refs()) { + assert(clear_all_softrefs, "Policy should have been checked earlier"); + } +#endif - SerialHeap::heap()->prepare_for_compaction(); -} + gch->trace_heap_before_gc(_gc_tracer); -class GenAdjustPointersClosure: public SerialHeap::GenClosure { -public: - void do_generation(Generation* gen) { - gen->adjust_pointers(); + // Increment the invocation count + _total_invocations++; + + // Capture used regions for each generation that will be + // subject to collection, so that card table adjustments can + // be made intelligently (see clear / invalidate further below). + gch->save_used_regions(); + + allocate_stacks(); + + phase1_mark(clear_all_softrefs); + + Compacter compacter{gch}; + + { + // Now all live objects are marked, compute the new object addresses. + GCTraceTime(Info, gc, phases) tm("Phase 2: Compute new object addresses", _gc_timer); + + compacter.phase2_calculate_new_addr(); } -}; -void GenMarkSweep::mark_sweep_phase3() { - SerialHeap* gch = SerialHeap::heap(); + // Don't add any more derived pointers during phase3 +#if COMPILER2_OR_JVMCI + assert(DerivedPointerTable::is_active(), "Sanity"); + DerivedPointerTable::set_active(false); +#endif + + { + // Adjust the pointers to reflect the new locations + GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", gc_timer()); + + ClassLoaderDataGraph::verify_claimed_marks_cleared(ClassLoaderData::_claim_stw_fullgc_adjust); + + CodeBlobToOopClosure code_closure(&adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations); + gch->process_roots(SerialHeap::SO_AllCodeCache, + &adjust_pointer_closure, + &adjust_cld_closure, + &adjust_cld_closure, + &code_closure); - // Adjust the pointers to reflect the new locations - GCTraceTime(Info, gc, phases) tm("Phase 3: Adjust pointers", gc_timer()); + WeakProcessor::oops_do(&adjust_pointer_closure); - ClassLoaderDataGraph::verify_claimed_marks_cleared(ClassLoaderData::_claim_stw_fullgc_adjust); + adjust_marks(); + compacter.phase3_adjust_pointers(); + } - CodeBlobToOopClosure code_closure(&adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations); - gch->process_roots(SerialHeap::SO_AllCodeCache, - &adjust_pointer_closure, - &adjust_cld_closure, - &adjust_cld_closure, - &code_closure); + { + // All pointers are now adjusted, move objects accordingly + GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer); - gch->gen_process_weak_roots(&adjust_pointer_closure); + compacter.phase4_compact(); + } - adjust_marks(); - GenAdjustPointersClosure blk; - gch->generation_iterate(&blk, true); + restore_marks(); + + // Set saved marks for allocation profiler (and other things? -- dld) + // (Should this be in general part?) + gch->save_marks(); + + deallocate_stacks(); + + MarkSweep::_string_dedup_requests->flush(); + + bool is_young_gen_empty = (gch->young_gen()->used() == 0); + gch->rem_set()->maintain_old_to_young_invariant(gch->old_gen(), is_young_gen_empty); + + gch->prune_scavengable_nmethods(); + + // Update heap occupancy information which is used as + // input to soft ref clearing policy at the next gc. + Universe::heap()->update_capacity_and_used_at_gc(); + + // Signal that we have completed a visit to all live objects. + Universe::heap()->record_whole_heap_examined_timestamp(); + + gch->trace_heap_after_gc(_gc_tracer); } -class GenCompactClosure: public SerialHeap::GenClosure { -public: - void do_generation(Generation* gen) { - gen->compact(); +void GenMarkSweep::allocate_stacks() { + void* scratch = nullptr; + size_t num_words; + DefNewGeneration* young_gen = (DefNewGeneration*)SerialHeap::heap()->young_gen(); + young_gen->contribute_scratch(scratch, num_words); + + if (scratch != nullptr) { + _preserved_count_max = num_words * HeapWordSize / sizeof(PreservedMark); + } else { + _preserved_count_max = 0; } -}; -void GenMarkSweep::mark_sweep_phase4() { - // All pointers are now adjusted, move objects accordingly - GCTraceTime(Info, gc, phases) tm("Phase 4: Move objects", _gc_timer); + _preserved_marks = (PreservedMark*)scratch; + _preserved_count = 0; + + _preserved_overflow_stack_set.init(1); +} - GenCompactClosure blk; - SerialHeap::heap()->generation_iterate(&blk, true); +void GenMarkSweep::deallocate_stacks() { + if (_preserved_count_max != 0) { + DefNewGeneration* young_gen = (DefNewGeneration*)SerialHeap::heap()->young_gen(); + young_gen->reset_scratch(); + } + + _preserved_overflow_stack_set.reclaim(); + _marking_stack.clear(); + _objarray_stack.clear(true); } diff --git a/src/hotspot/share/gc/serial/genMarkSweep.hpp b/src/hotspot/share/gc/serial/genMarkSweep.hpp index be830318bd0d9..520e801057389 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.hpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.hpp @@ -32,15 +32,8 @@ class GenMarkSweep : public MarkSweep { static void invoke_at_safepoint(bool clear_all_softrefs); private: - // Mark live objects - static void mark_sweep_phase1(bool clear_all_softrefs); - // Calculate new addresses - static void mark_sweep_phase2(); - // Update pointers - static void mark_sweep_phase3(); - // Move objects to new positions - static void mark_sweep_phase4(); + static void phase1_mark(bool clear_all_softrefs); // Temporary data structures for traversal and storing/restoring marks static void allocate_stacks(); diff --git a/src/hotspot/share/gc/serial/generation.cpp b/src/hotspot/share/gc/serial/generation.cpp index aa3c804ba3c20..30f1429fd40f2 100644 --- a/src/hotspot/share/gc/serial/generation.cpp +++ b/src/hotspot/share/gc/serial/generation.cpp @@ -218,34 +218,3 @@ void Generation::object_iterate(ObjectClosure* cl) { GenerationObjIterateClosure blk(cl); space_iterate(&blk); } - -void Generation::prepare_for_compaction(CompactPoint* cp) { - // Generic implementation, can be specialized - ContiguousSpace* space = first_compaction_space(); - while (space != nullptr) { - space->prepare_for_compaction(cp); - space = space->next_compaction_space(); - } -} - -class AdjustPointersClosure: public SpaceClosure { - public: - void do_space(Space* sp) { - sp->adjust_pointers(); - } -}; - -void Generation::adjust_pointers() { - // Note that this is done over all spaces, not just the compactible - // ones. - AdjustPointersClosure blk; - space_iterate(&blk, true); -} - -void Generation::compact() { - ContiguousSpace* sp = first_compaction_space(); - while (sp != nullptr) { - sp->compact(); - sp = sp->next_compaction_space(); - } -} diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp index 63eefae720bbb..d93c2b66df717 100644 --- a/src/hotspot/share/gc/serial/generation.hpp +++ b/src/hotspot/share/gc/serial/generation.hpp @@ -51,7 +51,7 @@ class DefNewGeneration; class GCMemoryManager; class ContiguousSpace; -class CompactPoint; + class OopClosure; class GCStats; @@ -286,13 +286,6 @@ class Generation: public CHeapObj { GCStats* gc_stats() const { return _gc_stats; } virtual void update_gc_stats(Generation* current_generation, bool full) {} - // Mark sweep support phase2 - virtual void prepare_for_compaction(CompactPoint* cp); - // Mark sweep support phase3 - virtual void adjust_pointers(); - // Mark sweep support phase4 - virtual void compact(); - // Accessing "marks". // This function gives a generation a chance to note a point between diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.hpp b/src/hotspot/share/gc/serial/tenuredGeneration.hpp index 75e8bf8486051..6b2a5891c64cd 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.hpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.hpp @@ -70,8 +70,6 @@ class TenuredGeneration: public Generation { GenerationCounters* _gen_counters; CSpaceCounters* _space_counters; - // Accessing spaces - TenuredSpace* space() const { return _the_space; } // Attempt to expand the generation by "bytes". Expand by at a // minimum "expand_bytes". Return true if some amount (not @@ -85,6 +83,8 @@ class TenuredGeneration: public Generation { public: virtual void compute_new_size(); + TenuredSpace* space() const { return _the_space; } + // Grow generation with specified size (returns false if unable to grow) bool grow_by(size_t bytes); // Grow generation to reserved size. diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index f4c21cce6dcda..cf101caae38b3 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -713,10 +713,6 @@ void GenCollectedHeap::process_roots(ScanningOption so, DEBUG_ONLY(ScavengableNMethods::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); } -void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) { - WeakProcessor::oops_do(root_closure); -} - bool GenCollectedHeap::no_allocs_since_save_marks() { return _young_gen->no_allocs_since_save_marks() && _old_gen->no_allocs_since_save_marks(); @@ -911,15 +907,6 @@ GenCollectedHeap* GenCollectedHeap::heap() { return named_heap(CollectedHeap::Serial); } -#if INCLUDE_SERIALGC -void GenCollectedHeap::prepare_for_compaction() { - // Start by compacting into same gen. - CompactPoint cp(_old_gen); - _old_gen->prepare_for_compaction(&cp); - _young_gen->prepare_for_compaction(&cp); -} -#endif // INCLUDE_SERIALGC - void GenCollectedHeap::verify(VerifyOption option /* ignored */) { log_debug(gc, verify)("%s", _old_gen->name()); _old_gen->verify(); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 72548f6e2f54a..1c1759f1422be 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -292,11 +292,6 @@ class GenCollectedHeap : public CollectedHeap { CLDClosure* weak_cld_closure, CodeBlobToOopClosure* code_roots); - // Apply "root_closure" to all the weak roots of the system. - // These include JNI weak roots, string table, - // and referents of reachable weak refs. - void gen_process_weak_roots(OopClosure* root_closure); - // Set the saved marks of generations, if that makes sense. // In particular, if any generation might iterate over the oops // in other generations, it should call this method. @@ -340,13 +335,6 @@ class GenCollectedHeap : public CollectedHeap { HeapWord* mem_allocate_work(size_t size, bool is_tlab); -#if INCLUDE_SERIALGC - // For use by mark-sweep. As implemented, mark-sweep-compact is global - // in an essential way: compaction is performed across generations, by - // iterating over spaces. - void prepare_for_compaction(); -#endif - // Save the tops of the spaces in all generations void record_gen_tops_before_GC() PRODUCT_RETURN; diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 1c2afaa8b70ea..b6dc4e1e7d8f2 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -35,19 +35,13 @@ #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/java.hpp" -#include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#if INCLUDE_SERIALGC -#include "gc/serial/serialBlockOffsetTable.inline.hpp" -#include "gc/serial/defNewGeneration.hpp" -#endif ContiguousSpace::ContiguousSpace(): Space(), - _compaction_top(nullptr), _next_compaction_space(nullptr), _top(nullptr) { _mangler = new GenSpaceMangler(this); @@ -59,8 +53,7 @@ ContiguousSpace::~ContiguousSpace() { void ContiguousSpace::initialize(MemRegion mr, bool clear_space, - bool mangle_space) -{ + bool mangle_space) { HeapWord* bottom = mr.start(); HeapWord* end = mr.end(); assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end), @@ -70,7 +63,6 @@ void ContiguousSpace::initialize(MemRegion mr, if (clear_space) { clear(mangle_space); } - set_compaction_top(bottom); _next_compaction_space = nullptr; } @@ -80,7 +72,6 @@ void ContiguousSpace::clear(bool mangle_space) { if (ZapUnusedHeapArea && mangle_space) { mangle_unused_area(); } - _compaction_top = bottom(); } bool ContiguousSpace::is_free_block(const HeapWord* p) const { @@ -115,230 +106,6 @@ void ContiguousSpace::mangle_unused_area_complete() { #endif // NOT_PRODUCT -HeapWord* ContiguousSpace::forward(oop q, size_t size, - CompactPoint* cp, HeapWord* compact_top) { - // q is alive - // First check if we should switch compaction space - assert(this == cp->space, "'this' should be current compaction space."); - size_t compaction_max_size = pointer_delta(end(), compact_top); - while (size > compaction_max_size) { - // switch to next compaction space - cp->space->set_compaction_top(compact_top); - cp->space = cp->space->next_compaction_space(); - if (cp->space == nullptr) { - cp->gen = GenCollectedHeap::heap()->young_gen(); - assert(cp->gen != nullptr, "compaction must succeed"); - cp->space = cp->gen->first_compaction_space(); - assert(cp->space != nullptr, "generation must have a first compaction space"); - } - compact_top = cp->space->bottom(); - cp->space->set_compaction_top(compact_top); - compaction_max_size = pointer_delta(cp->space->end(), compact_top); - } - - // store the forwarding pointer into the mark word - if (cast_from_oop(q) != compact_top) { - q->forward_to(cast_to_oop(compact_top)); - assert(q->is_gc_marked(), "encoding the pointer should preserve the mark"); - } else { - // if the object isn't moving we can just set the mark to the default - // mark and handle it specially later on. - q->init_mark(); - assert(!q->is_forwarded(), "should not be forwarded"); - } - - compact_top += size; - - // We need to update the offset table so that the beginnings of objects can be - // found during scavenge. Note that we are updating the offset table based on - // where the object will be once the compaction phase finishes. - cp->space->update_for_block(compact_top - size, compact_top); - return compact_top; -} - -#if INCLUDE_SERIALGC - -void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { - // Compute the new addresses for the live objects and store it in the mark - // Used by universe::mark_sweep_phase2() - - // We're sure to be here before any objects are compacted into this - // space, so this is a good time to initialize this: - set_compaction_top(bottom()); - - if (cp->space == nullptr) { - assert(cp->gen != nullptr, "need a generation"); - assert(cp->gen->first_compaction_space() == this, "just checking"); - cp->space = cp->gen->first_compaction_space(); - cp->space->set_compaction_top(cp->space->bottom()); - } - - HeapWord* compact_top = cp->space->compaction_top(); // This is where we are currently compacting to. - - DeadSpacer dead_spacer(this); - - HeapWord* end_of_live = bottom(); // One byte beyond the last byte of the last live object. - HeapWord* first_dead = nullptr; // The first dead object. - - const intx interval = PrefetchScanIntervalInBytes; - - HeapWord* cur_obj = bottom(); - HeapWord* scan_limit = top(); - - while (cur_obj < scan_limit) { - if (cast_to_oop(cur_obj)->is_gc_marked()) { - // prefetch beyond cur_obj - Prefetch::write(cur_obj, interval); - size_t size = cast_to_oop(cur_obj)->size(); - compact_top = cp->space->forward(cast_to_oop(cur_obj), size, cp, compact_top); - cur_obj += size; - end_of_live = cur_obj; - } else { - // run over all the contiguous dead objects - HeapWord* end = cur_obj; - do { - // prefetch beyond end - Prefetch::write(end, interval); - end += cast_to_oop(end)->size(); - } while (end < scan_limit && !cast_to_oop(end)->is_gc_marked()); - - // see if we might want to pretend this object is alive so that - // we don't have to compact quite as often. - if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { - oop obj = cast_to_oop(cur_obj); - compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); - end_of_live = end; - } else { - // otherwise, it really is a free region. - - // cur_obj is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. - *(HeapWord**)cur_obj = end; - - // see if this is the first dead region. - if (first_dead == nullptr) { - first_dead = cur_obj; - } - } - - // move on to the next object - cur_obj = end; - } - } - - assert(cur_obj == scan_limit, "just checking"); - _end_of_live = end_of_live; - if (first_dead != nullptr) { - _first_dead = first_dead; - } else { - _first_dead = end_of_live; - } - - // save the compaction_top of the compaction space. - cp->space->set_compaction_top(compact_top); -} - -void ContiguousSpace::adjust_pointers() { - // Check first is there is any work to do. - if (used() == 0) { - return; // Nothing to do. - } - - // adjust all the interior pointers to point at the new locations of objects - // Used by MarkSweep::mark_sweep_phase3() - - HeapWord* cur_obj = bottom(); - HeapWord* const end_of_live = _end_of_live; // Established by prepare_for_compaction(). - HeapWord* const first_dead = _first_dead; // Established by prepare_for_compaction(). - - assert(first_dead <= end_of_live, "Stands to reason, no?"); - - const intx interval = PrefetchScanIntervalInBytes; - - debug_only(HeapWord* prev_obj = nullptr); - while (cur_obj < end_of_live) { - Prefetch::write(cur_obj, interval); - if (cur_obj < first_dead || cast_to_oop(cur_obj)->is_gc_marked()) { - // cur_obj is alive - // point all the oops to the new location - size_t size = MarkSweep::adjust_pointers(cast_to_oop(cur_obj)); - debug_only(prev_obj = cur_obj); - cur_obj += size; - } else { - debug_only(prev_obj = cur_obj); - // cur_obj is not a live object, instead it points at the next live object - cur_obj = *(HeapWord**)cur_obj; - assert(cur_obj > prev_obj, "we should be moving forward through memory, cur_obj: " PTR_FORMAT ", prev_obj: " PTR_FORMAT, p2i(cur_obj), p2i(prev_obj)); - } - } - - assert(cur_obj == end_of_live, "just checking"); -} - -void ContiguousSpace::compact() { - // Copy all live objects to their new location - // Used by MarkSweep::mark_sweep_phase4() - - verify_up_to_first_dead(this); - - HeapWord* const start = bottom(); - HeapWord* const end_of_live = _end_of_live; - - assert(_first_dead <= end_of_live, "Invariant. _first_dead: " PTR_FORMAT " <= end_of_live: " PTR_FORMAT, p2i(_first_dead), p2i(end_of_live)); - if (_first_dead == end_of_live && (start == end_of_live || !cast_to_oop(start)->is_gc_marked())) { - // Nothing to compact. The space is either empty or all live object should be left in place. - clear_empty_region(this); - return; - } - - const intx scan_interval = PrefetchScanIntervalInBytes; - const intx copy_interval = PrefetchCopyIntervalInBytes; - - assert(start < end_of_live, "bottom: " PTR_FORMAT " should be < end_of_live: " PTR_FORMAT, p2i(start), p2i(end_of_live)); - HeapWord* cur_obj = start; - if (_first_dead > cur_obj && !cast_to_oop(cur_obj)->is_gc_marked()) { - // All object before _first_dead can be skipped. They should not be moved. - // A pointer to the first live object is stored at the memory location for _first_dead. - cur_obj = *(HeapWord**)(_first_dead); - } - - debug_only(HeapWord* prev_obj = nullptr); - while (cur_obj < end_of_live) { - if (!cast_to_oop(cur_obj)->is_forwarded()) { - debug_only(prev_obj = cur_obj); - // The first word of the dead object contains a pointer to the next live object or end of space. - cur_obj = *(HeapWord**)cur_obj; - assert(cur_obj > prev_obj, "we should be moving forward through memory"); - } else { - // prefetch beyond q - Prefetch::read(cur_obj, scan_interval); - - // size and destination - size_t size = cast_to_oop(cur_obj)->size(); - HeapWord* compaction_top = cast_from_oop(cast_to_oop(cur_obj)->forwardee()); - - // prefetch beyond compaction_top - Prefetch::write(compaction_top, copy_interval); - - // copy object and reinit its mark - assert(cur_obj != compaction_top, "everything in this pass should be moving"); - Copy::aligned_conjoint_words(cur_obj, compaction_top, size); - oop new_obj = cast_to_oop(compaction_top); - - ContinuationGCSupport::transform_stack_chunk(new_obj); - - new_obj->init_mark(); - assert(new_obj->klass() != nullptr, "should have a class"); - - debug_only(prev_obj = cur_obj); - cur_obj += size; - } - } - - clear_empty_region(this); -} - -#endif // INCLUDE_SERIALGC - void Space::print_short() const { print_short_on(tty); } void Space::print_short_on(outputStream* st) const { @@ -481,10 +248,6 @@ HeapWord* ContiguousSpace::par_allocate(size_t size) { } #if INCLUDE_SERIALGC -void TenuredSpace::update_for_block(HeapWord* start, HeapWord* end) { - _offsets.update_for_block(start, end); -} - HeapWord* TenuredSpace::block_start_const(const void* addr) const { HeapWord* cur_block = _offsets.block_start_reaching_into_card(addr); diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 5d559f74f5eef..6b8279ec8bd05 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -184,29 +184,12 @@ class Space: public CHeapObj { // Allocation (return null if full). Enforces mutual exclusion internally. virtual HeapWord* par_allocate(size_t word_size) = 0; -#if INCLUDE_SERIALGC - // Mark-sweep-compact support: all spaces can update pointers to objects - // moving as a part of compaction. - virtual void adjust_pointers() = 0; -#endif - void print() const; virtual void print_on(outputStream* st) const; void print_short() const; void print_short_on(outputStream* st) const; }; -// A structure to represent a point at which objects are being copied -// during compaction. -class CompactPoint : public StackObj { -public: - Generation* gen; - ContiguousSpace* space; - - CompactPoint(Generation* g = nullptr) : - gen(g), space(nullptr) {} -}; - class GenSpaceMangler; // A space in which the free area is contiguous. It therefore supports @@ -215,26 +198,13 @@ class ContiguousSpace: public Space { friend class VMStructs; private: - HeapWord* _compaction_top; ContiguousSpace* _next_compaction_space; - static inline void verify_up_to_first_dead(ContiguousSpace* space) NOT_DEBUG_RETURN; - - static inline void clear_empty_region(ContiguousSpace* space); - - protected: +protected: HeapWord* _top; // A helper for mangling the unused area of the space in debug builds. GenSpaceMangler* _mangler; - // Used during compaction. - HeapWord* _first_dead; - HeapWord* _end_of_live; - - // This the function to invoke when an allocation of an object covering - // "start" to "end" occurs to update other internal data structures. - virtual void update_for_block(HeapWord* start, HeapWord* the_end) { } - GenSpaceMangler* mangler() { return _mangler; } // Allocation helpers (return null if full). @@ -254,23 +224,13 @@ class ContiguousSpace: public Space { // The "clear" method must be called on a region that may have // had allocation performed in it, but is now to be considered empty. - virtual void clear(bool mangle_space); - - // Used temporarily during a compaction phase to hold the value - // top should have when compaction is complete. - HeapWord* compaction_top() const { return _compaction_top; } - - void set_compaction_top(HeapWord* value) { - assert(value == nullptr || (value >= bottom() && value <= end()), - "should point inside space"); - _compaction_top = value; - } + void clear(bool mangle_space); // Returns the next space (in the current generation) to be compacted in // the global compaction order. Also is used to select the next // space into which to compact. - virtual ContiguousSpace* next_compaction_space() const { + ContiguousSpace* next_compaction_space() const { return _next_compaction_space; } @@ -278,42 +238,10 @@ class ContiguousSpace: public Space { _next_compaction_space = csp; } -#if INCLUDE_SERIALGC - // MarkSweep support phase2 - - // Start the process of compaction of the current space: compute - // post-compaction addresses, and insert forwarding pointers. The fields - // "cp->gen" and "cp->compaction_space" are the generation and space into - // which we are currently compacting. This call updates "cp" as necessary, - // and leaves the "compaction_top" of the final value of - // "cp->compaction_space" up-to-date. Offset tables may be updated in - // this phase as if the final copy had occurred; if so, "cp->threshold" - // indicates when the next such action should be taken. - void prepare_for_compaction(CompactPoint* cp); - // MarkSweep support phase3 - void adjust_pointers() override; - // MarkSweep support phase4 - virtual void compact(); -#endif // INCLUDE_SERIALGC - // The maximum percentage of objects that can be dead in the compacted // live part of a compacted space ("deadwood" support.) virtual size_t allowed_dead_ratio() const { return 0; }; - // "q" is an object of the given "size" that should be forwarded; - // "cp" names the generation ("gen") and containing "this" (which must - // also equal "cp->space"). "compact_top" is where in "this" the - // next object should be forwarded to. If there is room in "this" for - // the object, insert an appropriate forwarding pointer in "q". - // If not, go to the next compaction space (there must - // be one, since compaction must succeed -- we go to the first space of - // the previous generation if necessary, updating "cp"), reset compact_top - // and then forward. In either case, returns the new value of "compact_top". - // Invokes the "update_for_block" function of the then-current compaction - // space. - virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, - HeapWord* compact_top); - // Accessors HeapWord* top() const { return _top; } void set_top(HeapWord* value) { _top = value; } @@ -359,12 +287,6 @@ class ContiguousSpace: public Space { // Iteration void object_iterate(ObjectClosure* blk) override; - // Compaction support - void reset_after_compaction() { - assert(compaction_top() >= bottom() && compaction_top() <= end(), "should point inside space"); - set_top(compaction_top()); - } - // Apply "blk->do_oop" to the addresses of all reference fields in objects // starting with the _saved_mark_word, which was noted during a generation's // save_marks and is required to denote the head of an object. @@ -419,8 +341,7 @@ class TenuredSpace: public ContiguousSpace { inline HeapWord* allocate(size_t word_size) override; inline HeapWord* par_allocate(size_t word_size) override; - // MarkSweep support phase3 - void update_for_block(HeapWord* start, HeapWord* end) override; + inline void update_for_block(HeapWord* start, HeapWord* end); void print_on(outputStream* st) const override; }; diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp index 9c4c2864cedb6..bfaf84e8fac01 100644 --- a/src/hotspot/share/gc/shared/space.inline.hpp +++ b/src/hotspot/share/gc/shared/space.inline.hpp @@ -27,17 +27,12 @@ #include "gc/shared/space.hpp" -#include "gc/serial/generation.hpp" #include "gc/shared/collectedHeap.hpp" #include "gc/shared/spaceDecorator.hpp" #include "oops/oop.inline.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" -#if INCLUDE_SERIALGC -#include "gc/serial/serialBlockOffsetTable.inline.hpp" -#include "gc/serial/markSweep.inline.hpp" -#endif inline HeapWord* Space::block_start(const void* p) { return block_start_const(p); @@ -60,90 +55,8 @@ inline HeapWord* TenuredSpace::par_allocate(size_t size) { return res; } -class DeadSpacer : StackObj { - size_t _allowed_deadspace_words; - bool _active; - ContiguousSpace* _space; - -public: - DeadSpacer(ContiguousSpace* space) : _allowed_deadspace_words(0), _space(space) { - size_t ratio = _space->allowed_dead_ratio(); - _active = ratio > 0; - - if (_active) { - assert(!UseG1GC, "G1 should not be using dead space"); - - // We allow some amount of garbage towards the bottom of the space, so - // we don't start compacting before there is a significant gain to be made. - // Occasionally, we want to ensure a full compaction, which is determined - // by the MarkSweepAlwaysCompactCount parameter. - if ((MarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0) { - _allowed_deadspace_words = (space->capacity() * ratio / 100) / HeapWordSize; - } else { - _active = false; - } - } - } - - bool insert_deadspace(HeapWord* dead_start, HeapWord* dead_end) { - if (!_active) { - return false; - } - - size_t dead_length = pointer_delta(dead_end, dead_start); - if (_allowed_deadspace_words >= dead_length) { - _allowed_deadspace_words -= dead_length; - CollectedHeap::fill_with_object(dead_start, dead_length); - oop obj = cast_to_oop(dead_start); - obj->set_mark(obj->mark().set_marked()); - - assert(dead_length == obj->size(), "bad filler object size"); - log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b", - p2i(dead_start), p2i(dead_end), dead_length * HeapWordSize); - - return true; - } else { - _active = false; - return false; - } - } -}; - -#ifdef ASSERT -inline void ContiguousSpace::verify_up_to_first_dead(ContiguousSpace* space) { - HeapWord* cur_obj = space->bottom(); - - if (cur_obj < space->_end_of_live && space->_first_dead > cur_obj && !cast_to_oop(cur_obj)->is_gc_marked()) { - // we have a chunk of the space which hasn't moved and we've reinitialized - // the mark word during the previous pass, so we can't use is_gc_marked for - // the traversal. - HeapWord* prev_obj = nullptr; - - while (cur_obj < space->_first_dead) { - size_t size = cast_to_oop(cur_obj)->size(); - assert(!cast_to_oop(cur_obj)->is_gc_marked(), "should be unmarked (special dense prefix handling)"); - prev_obj = cur_obj; - cur_obj += size; - } - } -} -#endif - -inline void ContiguousSpace::clear_empty_region(ContiguousSpace* space) { - // Let's remember if we were empty before we did the compaction. - bool was_empty = space->used_region().is_empty(); - // Reset space after compaction is complete - space->reset_after_compaction(); - // We do this clear, below, since it has overloaded meanings for some - // space subtypes. For example, TenuredSpace's that were - // compacted into will have had their offset table thresholds updated - // continuously, but those that weren't need to have their thresholds - // re-initialized. Also mangles unused area for debugging. - if (space->used_region().is_empty()) { - if (!was_empty) space->clear(SpaceDecorator::Mangle); - } else { - if (ZapUnusedHeapArea) space->mangle_unused_area(); - } +inline void TenuredSpace::update_for_block(HeapWord* start, HeapWord* end) { + _offsets.update_for_block(start, end); } #endif // INCLUDE_SERIALGC diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index 696cdc00dc520..a5d671a3b9295 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -99,10 +99,6 @@ nonstatic_field(CollectedHeap, _is_gc_active, bool) \ nonstatic_field(CollectedHeap, _total_collections, unsigned int) \ \ - nonstatic_field(ContiguousSpace, _compaction_top, HeapWord*) \ - nonstatic_field(ContiguousSpace, _first_dead, HeapWord*) \ - nonstatic_field(ContiguousSpace, _end_of_live, HeapWord*) \ - \ nonstatic_field(ContiguousSpace, _top, HeapWord*) \ nonstatic_field(ContiguousSpace, _saved_mark_word, HeapWord*) \ \ From 7286f5291d6aad290fda778668eeb3a7cbfd8a55 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 9 Jan 2024 07:05:27 +0000 Subject: [PATCH 064/112] 8322829: Refactor nioBlocker to avoid blocking while holding Thread's interrupt lock Reviewed-by: jpai --- .../share/classes/java/lang/System.java | 4 +- .../share/classes/java/lang/Thread.java | 29 ++++++--- .../classes/java/lang/VirtualThread.java | 27 ++++++-- .../spi/AbstractInterruptibleChannel.java | 63 ++++++++++++------- .../nio/channels/spi/AbstractSelector.java | 28 +++++---- .../classes/sun/nio/ch/Interruptible.java | 21 ++++++- 6 files changed, 118 insertions(+), 54 deletions(-) diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 0c10079316722..227982af9eaf6 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -2374,7 +2374,7 @@ E[] getEnumConstantsShared(Class klass) { return klass.getEnumConstantsShared(); } public void blockedOn(Interruptible b) { - Thread.blockedOn(b); + Thread.currentThread().blockedOn(b); } public void registerShutdownHook(int slot, boolean registerShutdownInProgress, Runnable hook) { Shutdown.add(slot, registerShutdownInProgress, hook); diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 4236368d28743..c3a6a3de5bc0f 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -345,15 +345,20 @@ void inheritScopedValueBindings(ThreadContainer container) { * operation, if any. The blocker's interrupt method should be invoked * after setting this thread's interrupt status. */ - volatile Interruptible nioBlocker; + private Interruptible nioBlocker; + + Interruptible nioBlocker() { + //assert Thread.holdsLock(interruptLock); + return nioBlocker; + } /* Set the blocker field; invoked via jdk.internal.access.SharedSecrets * from java.nio code */ - static void blockedOn(Interruptible b) { - Thread me = Thread.currentThread(); - synchronized (me.interruptLock) { - me.nioBlocker = b; + void blockedOn(Interruptible b) { + //assert Thread.currentThread() == this; + synchronized (interruptLock) { + nioBlocker = b; } } @@ -1699,15 +1704,19 @@ public void interrupt() { checkAccess(); // thread may be blocked in an I/O operation + Interruptible blocker; synchronized (interruptLock) { - Interruptible b = nioBlocker; - if (b != null) { + blocker = nioBlocker; + if (blocker != null) { interrupted = true; interrupt0(); // inform VM of interrupt - b.interrupt(this); - return; + blocker.interrupt(this); } } + if (blocker != null) { + blocker.postInterrupt(); + return; + } } interrupted = true; interrupt0(); // inform VM of interrupt diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 6f82516d86452..72ae1070242e8 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -852,18 +852,32 @@ boolean joinNanos(long nanos) throws InterruptedException { return true; } + @Override + void blockedOn(Interruptible b) { + notifyJvmtiDisableSuspend(true); + try { + super.blockedOn(b); + } finally { + notifyJvmtiDisableSuspend(false); + } + } + @Override @SuppressWarnings("removal") public void interrupt() { if (Thread.currentThread() != this) { checkAccess(); + + // if current thread is a virtual thread then prevent it from being + // suspended when entering or holding interruptLock + Interruptible blocker; notifyJvmtiDisableSuspend(true); try { synchronized (interruptLock) { interrupted = true; - Interruptible b = nioBlocker; - if (b != null) { - b.interrupt(this); + blocker = nioBlocker(); + if (blocker != null) { + blocker.interrupt(this); } // interrupt carrier thread if mounted @@ -873,6 +887,11 @@ public void interrupt() { } finally { notifyJvmtiDisableSuspend(false); } + + // notify blocker after releasing interruptLock + if (blocker != null) { + blocker.postInterrupt(); + } } else { interrupted = true; carrierThread.setInterrupt(); diff --git a/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java b/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java index 26dfc5ebca5e1..6adf2eb227634 100644 --- a/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java +++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -32,9 +32,9 @@ import java.nio.channels.InterruptibleChannel; import jdk.internal.access.SharedSecrets; +import jdk.internal.misc.Unsafe; import sun.nio.ch.Interruptible; - /** * Base implementation class for interruptible channels. * @@ -89,10 +89,26 @@ public abstract class AbstractInterruptibleChannel private final Object closeLock = new Object(); private volatile boolean closed; + // invoked if a Thread is interrupted when blocked in an I/O op + private final Interruptible interruptor; + /** * Initializes a new instance of this class. */ - protected AbstractInterruptibleChannel() { } + protected AbstractInterruptibleChannel() { + this.interruptor = new Interruptible() { + @Override + public void interrupt(Thread target) { + AbstractInterruptibleChannel.this.trySetTarget(target); + } + @Override + public void postInterrupt() { + try { + AbstractInterruptibleChannel.this.close(); + } catch (IOException x) { } + } + }; + } /** * Closes this channel. @@ -139,8 +155,15 @@ public final boolean isOpen() { // -- Interruption machinery -- - private Interruptible interruptor; - private volatile Thread interrupted; + private static final Unsafe U = Unsafe.getUnsafe(); + private static final long INTERRUPTED_TARGET = + U.objectFieldOffset(AbstractInterruptibleChannel.class, "interruptedTarget"); + private volatile Object interruptedTarget; // Thread or placeholder object + + private void trySetTarget(Thread target) { + // can't use VarHandle here as CAS may park on first usage + U.compareAndSetReference(this, INTERRUPTED_TARGET, null, target); + } /** * Marks the beginning of an I/O operation that might block indefinitely. @@ -151,24 +174,12 @@ public final boolean isOpen() { * closing and interruption for this channel.

*/ protected final void begin() { - if (interruptor == null) { - interruptor = new Interruptible() { - public void interrupt(Thread target) { - synchronized (closeLock) { - if (closed) - return; - closed = true; - interrupted = target; - try { - AbstractInterruptibleChannel.this.implCloseChannel(); - } catch (IOException x) { } - } - }}; - } blockedOn(interruptor); Thread me = Thread.currentThread(); - if (me.isInterrupted()) + if (me.isInterrupted()) { interruptor.interrupt(me); + interruptor.postInterrupt(); + } } /** @@ -194,10 +205,14 @@ protected final void end(boolean completed) throws AsynchronousCloseException { blockedOn(null); - Thread interrupted = this.interrupted; - if (interrupted != null && interrupted == Thread.currentThread()) { - this.interrupted = null; - throw new ClosedByInterruptException(); + Object interruptedTarget = this.interruptedTarget; + if (interruptedTarget != null) { + interruptor.postInterrupt(); + if (interruptedTarget == Thread.currentThread()) { + // replace with dummy object to avoid retaining reference to this thread + this.interruptedTarget = new Object(); + throw new ClosedByInterruptException(); + } } if (!completed && closed) throw new AsynchronousCloseException(); diff --git a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java index d04485471cc68..7ea5f89221834 100644 --- a/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java +++ b/src/java.base/share/classes/java/nio/channels/spi/AbstractSelector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -89,6 +89,9 @@ public abstract class AbstractSelector // cancelled-key, not used by the JDK Selector implementations private final Set cancelledKeys; + // invoked if a Thread is interrupted when blocked on a selection op + private final Interruptible interruptor; + /** * Initializes a new instance of this class. * @@ -103,6 +106,15 @@ protected AbstractSelector(SelectorProvider provider) { } else { this.cancelledKeys = new HashSet<>(); } + this.interruptor = new Interruptible() { + @Override + public void interrupt(Thread ignore) { + } + @Override + public void postInterrupt() { + AbstractSelector.this.wakeup(); + } + }; } void cancel(SelectionKey k) { // package-private @@ -209,8 +221,6 @@ protected final void deregister(AbstractSelectionKey key) { // -- Interruption machinery -- - private Interruptible interruptor = null; - /** * Marks the beginning of an I/O operation that might block indefinitely. * @@ -225,16 +235,11 @@ protected final void deregister(AbstractSelectionKey key) { * blocked in an I/O operation upon the selector.

*/ protected final void begin() { - if (interruptor == null) { - interruptor = new Interruptible() { - public void interrupt(Thread ignore) { - AbstractSelector.this.wakeup(); - }}; - } AbstractInterruptibleChannel.blockedOn(interruptor); Thread me = Thread.currentThread(); - if (me.isInterrupted()) - interruptor.interrupt(me); + if (me.isInterrupted()) { + interruptor.postInterrupt(); + } } /** @@ -248,5 +253,4 @@ public void interrupt(Thread ignore) { protected final void end() { AbstractInterruptibleChannel.blockedOn(null); } - } diff --git a/src/java.base/share/classes/sun/nio/ch/Interruptible.java b/src/java.base/share/classes/sun/nio/ch/Interruptible.java index 8445e35f05095..5785ba52e24d6 100644 --- a/src/java.base/share/classes/sun/nio/ch/Interruptible.java +++ b/src/java.base/share/classes/sun/nio/ch/Interruptible.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -31,6 +31,23 @@ public interface Interruptible { - public void interrupt(Thread t); + /** + * Invoked by Thread.interrupt when the given Thread is interrupted. Thread.interrupt + * invokes this method while holding the given Thread's interrupt lock. This method + * is also invoked by AbstractInterruptibleChannel when beginning an I/O operation + * with the current thread's interrupt status set. This method must not block. + */ + void interrupt(Thread target); + + /** + * Invoked by Thread.interrupt after releasing the Thread's interrupt lock. + * It may also be invoked by AbstractInterruptibleChannel or AbstractSelector when + * beginning an I/O operation with the current thread's interrupt status set, or at + * the end of an I/O operation when any thread doing I/O on the channel (or selector) + * has been interrupted. This method closes the channel (or wakes up the Selector) to + * ensure that AsynchronousCloseException or ClosedByInterruptException is thrown. + * This method is required to be idempotent. + */ + void postInterrupt(); } From 4cf131a101d13699b1bf017895798c9bda87f551 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 9 Jan 2024 07:26:35 +0000 Subject: [PATCH 065/112] 8319716: RISC-V: Add SHA-2 Co-authored-by: Robbin Ehn Reviewed-by: fyang, mli, luhenry --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 77 +++- src/hotspot/cpu/riscv/globals_riscv.hpp | 2 + .../cpu/riscv/macroAssembler_riscv.hpp | 14 + src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 398 ++++++++++++++++++ src/hotspot/cpu/riscv/vm_version_riscv.cpp | 44 +- 5 files changed, 516 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 22554972583e3..ffe6dcf07ecd7 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1334,6 +1334,7 @@ enum VectorMask { INSN(vsll_vi, 0b1010111, 0b011, 0b100101); // Vector Slide Instructions + INSN(vslideup_vi, 0b1010111, 0b011, 0b001110); INSN(vslidedown_vi, 0b1010111, 0b011, 0b001111); #undef INSN @@ -1689,7 +1690,6 @@ enum VectorMask { INSN(vmv_v_x, 0b1010111, 0b100, v0, 0b1, 0b010111); #undef INSN -#undef patch_VArith #define INSN(NAME, op, funct13, funct6) \ void NAME(VectorRegister Vd, VectorMask vm = unmasked) { \ @@ -1731,14 +1731,29 @@ enum Nf { patch_reg((address)&insn, 15, Rs1); \ emit(insn) -#define INSN(NAME, op, lumop, vm, mop, nf) \ - void NAME(VectorRegister Vd, Register Rs1, uint32_t width = 0, bool mew = false) { \ +#define INSN(NAME, op, width, lumop, vm, mop, mew, nf) \ + void NAME(VectorRegister Vd, Register Rs1) { \ guarantee(is_uimm3(width), "width is invalid"); \ patch_VLdSt(op, Vd, width, Rs1, lumop, vm, mop, mew, nf); \ } // Vector Load/Store Instructions - INSN(vl1re8_v, 0b0000111, 0b01000, 0b1, 0b00, g1); + INSN(vl1re8_v, 0b0000111, 0b000, 0b01000, 0b1, 0b00, 0b0, g1); + INSN(vl1re16_v, 0b0000111, 0b101, 0b01000, 0b1, 0b00, 0b0, g1); + INSN(vl1re32_v, 0b0000111, 0b110, 0b01000, 0b1, 0b00, 0b0, g1); + INSN(vl1re64_v, 0b0000111, 0b111, 0b01000, 0b1, 0b00, 0b0, g1); + INSN(vl2re8_v, 0b0000111, 0b000, 0b01000, 0b1, 0b00, 0b0, g2); + INSN(vl2re16_v, 0b0000111, 0b101, 0b01000, 0b1, 0b00, 0b0, g2); + INSN(vl2re32_v, 0b0000111, 0b110, 0b01000, 0b1, 0b00, 0b0, g2); + INSN(vl2re64_v, 0b0000111, 0b111, 0b01000, 0b1, 0b00, 0b0, g2); + INSN(vl4re8_v, 0b0000111, 0b000, 0b01000, 0b1, 0b00, 0b0, g4); + INSN(vl4re16_v, 0b0000111, 0b101, 0b01000, 0b1, 0b00, 0b0, g4); + INSN(vl4re32_v, 0b0000111, 0b110, 0b01000, 0b1, 0b00, 0b0, g4); + INSN(vl4re64_v, 0b0000111, 0b111, 0b01000, 0b1, 0b00, 0b0, g4); + INSN(vl8re8_v, 0b0000111, 0b000, 0b01000, 0b1, 0b00, 0b0, g8); + INSN(vl8re16_v, 0b0000111, 0b101, 0b01000, 0b1, 0b00, 0b0, g8); + INSN(vl8re32_v, 0b0000111, 0b110, 0b01000, 0b1, 0b00, 0b0, g8); + INSN(vl8re64_v, 0b0000111, 0b111, 0b01000, 0b1, 0b00, 0b0, g8); #undef INSN @@ -1749,6 +1764,9 @@ enum Nf { // Vector Load/Store Instructions INSN(vs1r_v, 0b0100111, 0b000, 0b01000, 0b1, 0b00, 0b0, g1); + INSN(vs2r_v, 0b0100111, 0b000, 0b01000, 0b1, 0b00, 0b0, g2); + INSN(vs4r_v, 0b0100111, 0b000, 0b01000, 0b1, 0b00, 0b0, g4); + INSN(vs8r_v, 0b0100111, 0b000, 0b01000, 0b1, 0b00, 0b0, g8); #undef INSN @@ -1794,9 +1812,11 @@ enum Nf { } // Vector unordered indexed load instructions + INSN( vluxei8_v, 0b0000111, 0b000, 0b01, 0b0); INSN(vluxei32_v, 0b0000111, 0b110, 0b01, 0b0); // Vector unordered indexed store instructions + INSN( vsuxei8_v, 0b0100111, 0b000, 0b01, 0b0); INSN(vsuxei32_v, 0b0100111, 0b110, 0b01, 0b0); #undef INSN @@ -1820,6 +1840,55 @@ enum Nf { #undef INSN #undef patch_VLdSt +// ==================================== +// RISC-V Vector Crypto Extension +// ==================================== + +#define INSN(NAME, op, funct3, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorRegister Vs1, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1->raw_encoding(), Vs2, vm, funct6); \ + } + + // Vector Bit-manipulation used in Cryptography (Zvkb) Extension + INSN(vandn_vv, 0b1010111, 0b000, 0b000001); + INSN(vandn_vx, 0b1010111, 0b100, 0b000001); + INSN(vandn_vi, 0b1010111, 0b011, 0b000001); + INSN(vclmul_vv, 0b1010111, 0b010, 0b001100); + INSN(vclmul_vx, 0b1010111, 0b110, 0b001100); + INSN(vclmulh_vv, 0b1010111, 0b010, 0b001101); + INSN(vclmulh_vx, 0b1010111, 0b110, 0b001101); + INSN(vror_vv, 0b1010111, 0b000, 0b010100); + INSN(vror_vx, 0b1010111, 0b100, 0b010100); + INSN(vrol_vv, 0b1010111, 0b000, 0b010101); + INSN(vrol_vx, 0b1010111, 0b100, 0b010101); + +#undef INSN + +#define INSN(NAME, op, funct3, Vs1, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorMask vm = unmasked) { \ + patch_VArith(op, Vd, funct3, Vs1, Vs2, vm, funct6); \ + } + + // Vector Bit-manipulation used in Cryptography (Zvkb) Extension + INSN(vbrev8_v, 0b1010111, 0b010, 0b01000, 0b010010); + INSN(vrev8_v, 0b1010111, 0b010, 0b01001, 0b010010); + +#undef INSN + +#define INSN(NAME, op, funct3, vm, funct6) \ + void NAME(VectorRegister Vd, VectorRegister Vs2, VectorRegister Vs1) { \ + patch_VArith(op, Vd, funct3, Vs1->raw_encoding(), Vs2, vm, funct6); \ + } + + // Vector SHA-2 Secure Hash (Zvknh[ab]) Extension + INSN(vsha2ms_vv, 0b1110111, 0b010, 0b1, 0b101101); + INSN(vsha2ch_vv, 0b1110111, 0b010, 0b1, 0b101110); + INSN(vsha2cl_vv, 0b1110111, 0b010, 0b1, 0b101111); + +#undef INSN + +#undef patch_VArith + // ==================================== // RISC-V Bit-Manipulation Extension // Currently only support Zba, Zbb and Zbs bitmanip extensions. diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index 60456c37ffe75..aa95cebec14cd 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -113,6 +113,8 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZtso, false, EXPERIMENTAL, "Assume Ztso memory model") \ product(bool, UseZihintpause, false, EXPERIMENTAL, \ "Use Zihintpause instructions") \ + product(bool, UseZvkn, false, EXPERIMENTAL, \ + "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \ "Use RVV instructions for left/right shift of BigInteger") diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 3e0206746242c..4724dd85e7801 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -1361,6 +1361,16 @@ class MacroAssembler: public Assembler { vmfle_vv(vd, vs1, vs2, vm); } + inline void vmsltu_vi(VectorRegister Vd, VectorRegister Vs2, uint32_t imm, VectorMask vm = unmasked) { + guarantee(imm >= 1 && imm <= 16, "imm is invalid"); + vmsleu_vi(Vd, Vs2, imm-1, vm); + } + + inline void vmsgeu_vi(VectorRegister Vd, VectorRegister Vs2, uint32_t imm, VectorMask vm = unmasked) { + guarantee(imm >= 1 && imm <= 16, "imm is invalid"); + vmsgtu_vi(Vd, Vs2, imm-1, vm); + } + // Copy mask register inline void vmmv_m(VectorRegister vd, VectorRegister vs) { vmand_mm(vd, vs, vs); @@ -1376,6 +1386,10 @@ class MacroAssembler: public Assembler { vmxnor_mm(vd, vd, vd); } + inline void vnot_v(VectorRegister Vd, VectorRegister Vs, VectorMask vm = unmasked) { + vxor_vi(Vd, Vs, -1, vm); + } + static const int zero_words_block_size; void cast_primitive_type(BasicType type, Register Rt) { diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index be5fd98335329..4bd33d08f8928 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -3659,8 +3659,394 @@ class StubGenerator: public StubCodeGenerator { return entry; } }; + #endif // COMPILER2 +#undef __ +#define __ this-> + class Sha2Generator : public MacroAssembler { + StubCodeGenerator* _cgen; + public: + Sha2Generator(MacroAssembler* masm, StubCodeGenerator* cgen) : MacroAssembler(masm->code()), _cgen(cgen) {} + address generate_sha256_implCompress(bool multi_block) { + return generate_sha2_implCompress(Assembler::e32, multi_block); + } + address generate_sha512_implCompress(bool multi_block) { + return generate_sha2_implCompress(Assembler::e64, multi_block); + } + private: + + void vleXX_v(Assembler::SEW vset_sew, VectorRegister vr, Register sr) { + if (vset_sew == Assembler::e32) __ vle32_v(vr, sr); + else __ vle64_v(vr, sr); + } + + void vseXX_v(Assembler::SEW vset_sew, VectorRegister vr, Register sr) { + if (vset_sew == Assembler::e32) __ vse32_v(vr, sr); + else __ vse64_v(vr, sr); + } + + // Overview of the logic in each "quad round". + // + // The code below repeats 16/20 times the logic implementing four rounds + // of the SHA-256/512 core loop as documented by NIST. 16/20 "quad rounds" + // to implementing the 64/80 single rounds. + // + // // Load four word (u32/64) constants (K[t+3], K[t+2], K[t+1], K[t+0]) + // // Output: + // // vTmp1 = {K[t+3], K[t+2], K[t+1], K[t+0]} + // vl1reXX.v vTmp1, ofs + // + // // Increment word constant address by stride (16/32 bytes, 4*4B/8B, 128b/256b) + // addi ofs, ofs, 16/32 + // + // // Add constants to message schedule words: + // // Input + // // vTmp1 = {K[t+3], K[t+2], K[t+1], K[t+0]} + // // vW0 = {W[t+3], W[t+2], W[t+1], W[t+0]}; // Vt0 = W[3:0]; + // // Output + // // vTmp0 = {W[t+3]+K[t+3], W[t+2]+K[t+2], W[t+1]+K[t+1], W[t+0]+K[t+0]} + // vadd.vv vTmp0, vTmp1, vW0 + // + // // 2 rounds of working variables updates. + // // vState1[t+4] <- vState1[t], vState0[t], vTmp0[t] + // // Input: + // // vState1 = {c[t],d[t],g[t],h[t]} " = vState1[t] " + // // vState0 = {a[t],b[t],e[t],f[t]} + // // vTmp0 = {W[t+3]+K[t+3], W[t+2]+K[t+2], W[t+1]+K[t+1], W[t+0]+K[t+0]} + // // Output: + // // vState1 = {f[t+2],e[t+2],b[t+2],a[t+2]} " = vState0[t+2] " + // // = {h[t+4],g[t+4],d[t+4],c[t+4]} " = vState1[t+4] " + // vsha2cl.vv vState1, vState0, vTmp0 + // + // // 2 rounds of working variables updates. + // // vState0[t+4] <- vState0[t], vState0[t+2], vTmp0[t] + // // Input + // // vState0 = {a[t],b[t],e[t],f[t]} " = vState0[t] " + // // = {h[t+2],g[t+2],d[t+2],c[t+2]} " = vState1[t+2] " + // // vState1 = {f[t+2],e[t+2],b[t+2],a[t+2]} " = vState0[t+2] " + // // vTmp0 = {W[t+3]+K[t+3], W[t+2]+K[t+2], W[t+1]+K[t+1], W[t+0]+K[t+0]} + // // Output: + // // vState0 = {f[t+4],e[t+4],b[t+4],a[t+4]} " = vState0[t+4] " + // vsha2ch.vv vState0, vState1, vTmp0 + // + // // Combine 2QW into 1QW + // // + // // To generate the next 4 words, "new_vW0"/"vTmp0" from vW0-vW3, vsha2ms needs + // // vW0[0..3], vW1[0], vW2[1..3], vW3[0, 2..3] + // // and it can only take 3 vectors as inputs. Hence we need to combine + // // vW1[0] and vW2[1..3] in a single vector. + // // + // // vmerge Vt4, Vt1, Vt2, V0 + // // Input + // // V0 = mask // first word from vW2, 1..3 words from vW1 + // // vW2 = {Wt-8, Wt-7, Wt-6, Wt-5} + // // vW1 = {Wt-12, Wt-11, Wt-10, Wt-9} + // // Output + // // Vt4 = {Wt-12, Wt-7, Wt-6, Wt-5} + // vmerge.vvm vTmp0, vW2, vW1, v0 + // + // // Generate next Four Message Schedule Words (hence allowing for 4 more rounds) + // // Input + // // vW0 = {W[t+ 3], W[t+ 2], W[t+ 1], W[t+ 0]} W[ 3: 0] + // // vW3 = {W[t+15], W[t+14], W[t+13], W[t+12]} W[15:12] + // // vTmp0 = {W[t+11], W[t+10], W[t+ 9], W[t+ 4]} W[11: 9,4] + // // Output (next four message schedule words) + // // vW0 = {W[t+19], W[t+18], W[t+17], W[t+16]} W[19:16] + // vsha2ms.vv vW0, vTmp0, vW3 + // + // BEFORE + // vW0 - vW3 hold the message schedule words (initially the block words) + // vW0 = W[ 3: 0] "oldest" + // vW1 = W[ 7: 4] + // vW2 = W[11: 8] + // vW3 = W[15:12] "newest" + // + // vt6 - vt7 hold the working state variables + // vState0 = {a[t],b[t],e[t],f[t]} // initially {H5,H4,H1,H0} + // vState1 = {c[t],d[t],g[t],h[t]} // initially {H7,H6,H3,H2} + // + // AFTER + // vW0 - vW3 hold the message schedule words (initially the block words) + // vW1 = W[ 7: 4] "oldest" + // vW2 = W[11: 8] + // vW3 = W[15:12] + // vW0 = W[19:16] "newest" + // + // vState0 and vState1 hold the working state variables + // vState0 = {a[t+4],b[t+4],e[t+4],f[t+4]} + // vState1 = {c[t+4],d[t+4],g[t+4],h[t+4]} + // + // The group of vectors vW0,vW1,vW2,vW3 is "rotated" by one in each quad-round, + // hence the uses of those vectors rotate in each round, and we get back to the + // initial configuration every 4 quad-rounds. We could avoid those changes at + // the cost of moving those vectors at the end of each quad-rounds. + void sha2_quad_round(Assembler::SEW vset_sew, VectorRegister rot1, VectorRegister rot2, VectorRegister rot3, VectorRegister rot4, + Register scalarconst, VectorRegister vtemp, VectorRegister vtemp2, VectorRegister v_abef, VectorRegister v_cdgh, + bool gen_words = true, bool step_const = true) { + __ vleXX_v(vset_sew, vtemp, scalarconst); + if (step_const) { + __ addi(scalarconst, scalarconst, vset_sew == Assembler::e32 ? 16 : 32); + } + __ vadd_vv(vtemp2, vtemp, rot1); + __ vsha2cl_vv(v_cdgh, v_abef, vtemp2); + __ vsha2ch_vv(v_abef, v_cdgh, vtemp2); + if (gen_words) { + __ vmerge_vvm(vtemp2, rot3, rot2); + __ vsha2ms_vv(rot1, vtemp2, rot4); + } + } + + const char* stub_name(Assembler::SEW vset_sew, bool multi_block) { + if (vset_sew == Assembler::e32 && !multi_block) return "sha256_implCompress"; + if (vset_sew == Assembler::e32 && multi_block) return "sha256_implCompressMB"; + if (vset_sew == Assembler::e64 && !multi_block) return "sha512_implCompress"; + if (vset_sew == Assembler::e64 && multi_block) return "sha512_implCompressMB"; + ShouldNotReachHere(); + return "bad name lookup"; + } + + // Arguments: + // + // Inputs: + // c_rarg0 - byte[] source+offset + // c_rarg1 - int[] SHA.state + // c_rarg2 - int offset + // c_rarg3 - int limit + // + address generate_sha2_implCompress(Assembler::SEW vset_sew, bool multi_block) { + alignas(64) static const uint32_t round_consts_256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, + }; + alignas(64) static const uint64_t round_consts_512[80] = { + 0x428a2f98d728ae22l, 0x7137449123ef65cdl, 0xb5c0fbcfec4d3b2fl, + 0xe9b5dba58189dbbcl, 0x3956c25bf348b538l, 0x59f111f1b605d019l, + 0x923f82a4af194f9bl, 0xab1c5ed5da6d8118l, 0xd807aa98a3030242l, + 0x12835b0145706fbel, 0x243185be4ee4b28cl, 0x550c7dc3d5ffb4e2l, + 0x72be5d74f27b896fl, 0x80deb1fe3b1696b1l, 0x9bdc06a725c71235l, + 0xc19bf174cf692694l, 0xe49b69c19ef14ad2l, 0xefbe4786384f25e3l, + 0x0fc19dc68b8cd5b5l, 0x240ca1cc77ac9c65l, 0x2de92c6f592b0275l, + 0x4a7484aa6ea6e483l, 0x5cb0a9dcbd41fbd4l, 0x76f988da831153b5l, + 0x983e5152ee66dfabl, 0xa831c66d2db43210l, 0xb00327c898fb213fl, + 0xbf597fc7beef0ee4l, 0xc6e00bf33da88fc2l, 0xd5a79147930aa725l, + 0x06ca6351e003826fl, 0x142929670a0e6e70l, 0x27b70a8546d22ffcl, + 0x2e1b21385c26c926l, 0x4d2c6dfc5ac42aedl, 0x53380d139d95b3dfl, + 0x650a73548baf63del, 0x766a0abb3c77b2a8l, 0x81c2c92e47edaee6l, + 0x92722c851482353bl, 0xa2bfe8a14cf10364l, 0xa81a664bbc423001l, + 0xc24b8b70d0f89791l, 0xc76c51a30654be30l, 0xd192e819d6ef5218l, + 0xd69906245565a910l, 0xf40e35855771202al, 0x106aa07032bbd1b8l, + 0x19a4c116b8d2d0c8l, 0x1e376c085141ab53l, 0x2748774cdf8eeb99l, + 0x34b0bcb5e19b48a8l, 0x391c0cb3c5c95a63l, 0x4ed8aa4ae3418acbl, + 0x5b9cca4f7763e373l, 0x682e6ff3d6b2b8a3l, 0x748f82ee5defb2fcl, + 0x78a5636f43172f60l, 0x84c87814a1f0ab72l, 0x8cc702081a6439ecl, + 0x90befffa23631e28l, 0xa4506cebde82bde9l, 0xbef9a3f7b2c67915l, + 0xc67178f2e372532bl, 0xca273eceea26619cl, 0xd186b8c721c0c207l, + 0xeada7dd6cde0eb1el, 0xf57d4f7fee6ed178l, 0x06f067aa72176fbal, + 0x0a637dc5a2c898a6l, 0x113f9804bef90dael, 0x1b710b35131c471bl, + 0x28db77f523047d84l, 0x32caab7b40c72493l, 0x3c9ebe0a15c9bebcl, + 0x431d67c49c100d4cl, 0x4cc5d4becb3e42b6l, 0x597f299cfc657e2al, + 0x5fcb6fab3ad6faecl, 0x6c44198c4a475817l + }; + const int const_add = vset_sew == Assembler::e32 ? 16 : 32; + + __ align(CodeEntryAlignment); + StubCodeMark mark(_cgen, "StubRoutines", stub_name(vset_sew, multi_block)); + address start = __ pc(); + + Register buf = c_rarg0; + Register state = c_rarg1; + Register ofs = c_rarg2; + Register limit = c_rarg3; + Register consts = t2; // caller saved + Register state_c = x28; // caller saved + VectorRegister vindex = v2; + VectorRegister vW0 = v4; + VectorRegister vW1 = v6; + VectorRegister vW2 = v8; + VectorRegister vW3 = v10; + VectorRegister vState0 = v12; + VectorRegister vState1 = v14; + VectorRegister vHash0 = v16; + VectorRegister vHash1 = v18; + VectorRegister vTmp0 = v20; + VectorRegister vTmp1 = v22; + + Label multi_block_loop; + + __ enter(); + + address constant_table = vset_sew == Assembler::e32 ? (address)round_consts_256 : (address)round_consts_512; + la(consts, ExternalAddress(constant_table)); + + // Register use in this function: + // + // VECTORS + // vW0 - vW3 (512/1024-bits / 4*128/256 bits / 4*4*32/65 bits), hold the message + // schedule words (Wt). They start with the message block + // content (W0 to W15), then further words in the message + // schedule generated via vsha2ms from previous Wt. + // Initially: + // vW0 = W[ 3:0] = { W3, W2, W1, W0} + // vW1 = W[ 7:4] = { W7, W6, W5, W4} + // vW2 = W[ 11:8] = {W11, W10, W9, W8} + // vW3 = W[15:12] = {W15, W14, W13, W12} + // + // vState0 - vState1 hold the working state variables (a, b, ..., h) + // vState0 = {f[t],e[t],b[t],a[t]} + // vState1 = {h[t],g[t],d[t],c[t]} + // Initially: + // vState0 = {H5i-1, H4i-1, H1i-1 , H0i-1} + // vState1 = {H7i-i, H6i-1, H3i-1 , H2i-1} + // + // v0 = masks for vrgather/vmerge. Single value during the 16 rounds. + // + // vTmp0 = temporary, Wt+Kt + // vTmp1 = temporary, Kt + // + // vHash0/vHash1 = hold the initial values of the hash, byte-swapped. + // + // During most of the function the vector state is configured so that each + // vector is interpreted as containing four 32/64 bits (e32/e64) elements (128/256 bits). + + // vsha2ch/vsha2cl uses EGW of 4*SEW. + // SHA256 SEW = e32, EGW = 128-bits + // SHA512 SEW = e64, EGW = 256-bits + // + // VLEN is required to be at least 128. + // For the case of VLEN=128 and SHA512 we need LMUL=2 to work with 4*e64 (EGW = 256) + // + // m1: LMUL=1/2 + // ta: tail agnostic (don't care about those lanes) + // ma: mask agnostic (don't care about those lanes) + // x0 is not written, we known the number of vector elements. + + if (vset_sew == Assembler::e64 && MaxVectorSize == 16) { // SHA512 and VLEN = 128 + __ vsetivli(x0, 4, vset_sew, Assembler::m2, Assembler::ma, Assembler::ta); + } else { + __ vsetivli(x0, 4, vset_sew, Assembler::m1, Assembler::ma, Assembler::ta); + } + + int64_t indexes = vset_sew == Assembler::e32 ? 0x00041014ul : 0x00082028ul; + __ li(t0, indexes); + __ vmv_v_x(vindex, t0); + + // Step-over a,b, so we are pointing to c. + // const_add is equal to 4x state variable, div by 2 is thus 2, a,b + __ addi(state_c, state, const_add/2); + + // Use index-load to get {f,e,b,a},{h,g,d,c} + __ vluxei8_v(vState0, state, vindex); + __ vluxei8_v(vState1, state_c, vindex); + + __ bind(multi_block_loop); + + // Capture the initial H values in vHash0 and vHash1 to allow for computing + // the resulting H', since H' = H+{a',b',c',...,h'}. + __ vmv_v_v(vHash0, vState0); + __ vmv_v_v(vHash1, vState1); + + // Load the 512/1024-bits of the message block in vW0-vW3 and perform + // an endian swap on each 4/8 bytes element. + // + // If Zvkb is not implemented one can use vrgather + // with an index sequence to byte-swap. + // sequence = [3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12] + // gives us "N ^ 3" as a nice formula to generate + // this sequence. 'vid' gives us the N. + __ vleXX_v(vset_sew, vW0, buf); + __ vrev8_v(vW0, vW0); + __ addi(buf, buf, const_add); + __ vleXX_v(vset_sew, vW1, buf); + __ vrev8_v(vW1, vW1); + __ addi(buf, buf, const_add); + __ vleXX_v(vset_sew, vW2, buf); + __ vrev8_v(vW2, vW2); + __ addi(buf, buf, const_add); + __ vleXX_v(vset_sew, vW3, buf); + __ vrev8_v(vW3, vW3); + __ addi(buf, buf, const_add); + + // Set v0 up for the vmerge that replaces the first word (idx==0) + __ vid_v(v0); + __ vmseq_vi(v0, v0, 0x0); // v0.mask[i] = (i == 0 ? 1 : 0) + + VectorRegister rotation_regs[] = {vW0, vW1, vW2, vW3}; + int rot_pos = 0; + // Quad-round #0 (+0, vW0->vW1->vW2->vW3) ... #11 (+3, vW3->vW0->vW1->vW2) + const int qr_end = vset_sew == Assembler::e32 ? 12 : 16; + for (int i = 0; i < qr_end; i++) { + sha2_quad_round(vset_sew, + rotation_regs[(rot_pos + 0) & 0x3], + rotation_regs[(rot_pos + 1) & 0x3], + rotation_regs[(rot_pos + 2) & 0x3], + rotation_regs[(rot_pos + 3) & 0x3], + consts, + vTmp1, vTmp0, vState0, vState1); + ++rot_pos; + } + // Quad-round #12 (+0, vW0->vW1->vW2->vW3) ... #15 (+3, vW3->vW0->vW1->vW2) + // Note that we stop generating new message schedule words (Wt, vW0-13) + // as we already generated all the words we end up consuming (i.e., W[63:60]). + const int qr_c_end = qr_end + 4; + for (int i = qr_end; i < qr_c_end; i++) { + sha2_quad_round(vset_sew, + rotation_regs[(rot_pos + 0) & 0x3], + rotation_regs[(rot_pos + 1) & 0x3], + rotation_regs[(rot_pos + 2) & 0x3], + rotation_regs[(rot_pos + 3) & 0x3], + consts, + vTmp1, vTmp0, vState0, vState1, false, i < (qr_c_end-1)); + ++rot_pos; + } + + //-------------------------------------------------------------------------------- + // Compute the updated hash value H' + // H' = H + {h',g',...,b',a'} + // = {h,g,...,b,a} + {h',g',...,b',a'} + // = {h+h',g+g',...,b+b',a+a'} + + // H' = H+{a',b',c',...,h'} + __ vadd_vv(vState0, vHash0, vState0); + __ vadd_vv(vState1, vHash1, vState1); + + if (multi_block) { + int total_adds = vset_sew == Assembler::e32 ? 240 : 608; + __ addi(consts, consts, -total_adds); + __ add(ofs, ofs, vset_sew == Assembler::e32 ? 64 : 128); + __ ble(ofs, limit, multi_block_loop); + __ mv(c_rarg0, ofs); // return ofs + } + + // Store H[0..8] = {a,b,c,d,e,f,g,h} from + // vState0 = {f,e,b,a} + // vState1 = {h,g,d,c} + __ vsuxei8_v(vState0, state, vindex); + __ vsuxei8_v(vState1, state_c, vindex); + + __ leave(); + __ ret(); + + return start; + } + }; +#undef __ +#define __ masm-> + // Continuation point for throwing of implicit exceptions that are // not handled in the current activation. Fabricates an exception // oop and initiates normal exception dispatching in this @@ -4862,6 +5248,18 @@ static const int64_t right_3_bits = right_n_bits(3); } #endif // COMPILER2 + if (UseSHA256Intrinsics) { + Sha2Generator sha2(_masm, this); + StubRoutines::_sha256_implCompress = sha2.generate_sha256_implCompress(false); + StubRoutines::_sha256_implCompressMB = sha2.generate_sha256_implCompress(true); + } + + if (UseSHA512Intrinsics) { + Sha2Generator sha2(_masm, this); + StubRoutines::_sha512_implCompress = sha2.generate_sha512_implCompress(false); + StubRoutines::_sha512_implCompressMB = sha2.generate_sha512_implCompress(true); + } + generate_compare_long_strings(); generate_string_indexof_stubs(); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 41ec15a8634b2..9a72b8d75a136 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -146,26 +146,11 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); } - if (UseSHA) { - warning("SHA instructions are not available on this CPU"); - FLAG_SET_DEFAULT(UseSHA, false); - } - if (UseSHA1Intrinsics) { warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); } - if (UseSHA256Intrinsics) { - warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); - } - - if (UseSHA512Intrinsics) { - warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU."); - FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); - } - if (UseSHA3Intrinsics) { warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); @@ -272,6 +257,10 @@ void VM_Version::initialize() { // NOTE: Make sure codes dependent on UseRVV are put after c2_initialize(), // as there are extra checks inside it which could disable UseRVV // in some situations. + if (UseZvkn && !UseRVV) { + FLAG_SET_DEFAULT(UseZvkn, false); + warning("Cannot enable Zvkn on cpu without RVV support."); + } if (UseRVV) { if (FLAG_IS_DEFAULT(UseChaCha20Intrinsics)) { @@ -283,6 +272,31 @@ void VM_Version::initialize() { } FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + + if (!UseZvkn && UseSHA) { + warning("SHA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseSHA, false); + } else if (UseZvkn && FLAG_IS_DEFAULT(UseSHA)) { + FLAG_SET_DEFAULT(UseSHA, true); + } + + if (!UseSHA) { + if (UseSHA256Intrinsics) { + warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU, UseZvkn needed."); + FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); + } + if (UseSHA512Intrinsics) { + warning("Intrinsics for SHA-384 and SHA-512 crypto hash functions not available on this CPU, UseZvkn needed."); + FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + } + } else { + if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); + } + if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA512Intrinsics, true); + } + } } #ifdef COMPILER2 From 30f93a29c2f677d0279176b89edf2ecdc06b42ca Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Tue, 9 Jan 2024 07:34:50 +0000 Subject: [PATCH 066/112] 8320069: RISC-V: Add Zcb instructions Reviewed-by: fyang, vkempik --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 259 +++++++++++++++++- .../cpu/riscv/macroAssembler_riscv.cpp | 71 +++-- .../cpu/riscv/macroAssembler_riscv.hpp | 19 +- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 6 + .../linux_riscv/vm_version_linux_riscv.cpp | 2 + 5 files changed, 316 insertions(+), 41 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index ffe6dcf07ecd7..55c3e755c48eb 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -506,7 +506,7 @@ class Assembler : public AbstractAssembler { INSN(sllw, 0b0111011, 0b001, 0b0000000); INSN(sraw, 0b0111011, 0b101, 0b0100000); INSN(srlw, 0b0111011, 0b101, 0b0000000); - INSN(mul, 0b0110011, 0b000, 0b0000001); + INSN(_mul, 0b0110011, 0b000, 0b0000001); INSN(mulh, 0b0110011, 0b001, 0b0000001); INSN(mulhsu,0b0110011, 0b010, 0b0000001); INSN(mulhu, 0b0110011, 0b011, 0b0000001); @@ -537,9 +537,9 @@ class Assembler : public AbstractAssembler { } INSN(lb, 0b0000011, 0b000); - INSN(lbu, 0b0000011, 0b100); - INSN(lh, 0b0000011, 0b001); - INSN(lhu, 0b0000011, 0b101); + INSN(_lbu, 0b0000011, 0b100); + INSN(_lh, 0b0000011, 0b001); + INSN(_lhu, 0b0000011, 0b101); INSN(_lw, 0b0000011, 0b010); INSN(lwu, 0b0000011, 0b110); INSN(_ld, 0b0000011, 0b011); @@ -609,8 +609,8 @@ class Assembler : public AbstractAssembler { emit(insn); \ } \ - INSN(sb, Register, 0b0100011, 0b000); - INSN(sh, Register, 0b0100011, 0b001); + INSN(_sb, Register, 0b0100011, 0b000); + INSN(_sh, Register, 0b0100011, 0b001); INSN(_sw, Register, 0b0100011, 0b010); INSN(_sd, Register, 0b0100011, 0b011); INSN(fsw, FloatRegister, 0b0100111, 0b010); @@ -1938,9 +1938,9 @@ enum Nf { } INSN(rev8, 0b0010011, 0b101, 0b011010111000); - INSN(sext_b, 0b0010011, 0b001, 0b011000000100); - INSN(sext_h, 0b0010011, 0b001, 0b011000000101); - INSN(zext_h, 0b0111011, 0b100, 0b000010000000); + INSN(_sext_b, 0b0010011, 0b001, 0b011000000100); + INSN(_sext_h, 0b0010011, 0b001, 0b011000000101); + INSN(_zext_h, 0b0111011, 0b100, 0b000010000000); INSN(clz, 0b0010011, 0b001, 0b011000000000); INSN(clzw, 0b0011011, 0b001, 0b011000000000); INSN(ctz, 0b0010011, 0b001, 0b011000000001); @@ -2652,6 +2652,15 @@ enum Nf { return UseRVC && in_compressible_region(); } + bool do_compress_zcb(Register reg1 = noreg, Register reg2 = noreg) const { + return do_compress() && VM_Version::ext_Zcb.enabled() && + (reg1 == noreg || reg1->is_compressed_valid()) && (reg2 == noreg || reg2->is_compressed_valid()); + } + + bool do_compress_zcb_zbb(Register reg1 = noreg, Register reg2 = noreg) const { + return do_compress_zcb(reg1, reg2) && UseZbb; + } + // -------------------------- // Load/store register // -------------------------- @@ -2986,6 +2995,238 @@ enum Nf { #undef INSN +// -------------- ZCB Instruction Definitions -------------- +// Zcb additional C instructions + private: + // Format CLH, c.lh/c.lhu + template + void c_lh_if(Register Rd_Rs2, Register Rs1, uint32_t uimm) { + assert_cond(uimm == 0 || uimm == 2); + assert_cond(do_compress_zcb(Rd_Rs2, Rs1)); + uint16_t insn = 0; + c_patch((address)&insn, 1, 0, 0b00); + c_patch_compressed_reg((address)&insn, 2, Rd_Rs2); + c_patch((address)&insn, 5, 5, (uimm & nth_bit(1)) >> 1); + c_patch((address)&insn, 6, 6, Unsigned ? 0 : 1); + c_patch_compressed_reg((address)&insn, 7, Rs1); + c_patch((address)&insn, 12, 10, 0b001); + c_patch((address)&insn, 15, 13, 0b100); + emit_int16(insn); + } + + template + void lh_c_mux(Register Rd_Rs2, Register Rs1, const int32_t uimm) { + if (do_compress_zcb(Rd_Rs2, Rs1) && + (uimm == 0 || uimm == 2)) { + c_lh_if(Rd_Rs2, Rs1, uimm); + } else { + if (Unsigned) { + _lhu(Rd_Rs2, Rs1, uimm); + } else { + _lh(Rd_Rs2, Rs1, uimm); + } + } + } + + // Format CU, c.[sz]ext.*, c.not + template + void c_u_if(Register Rs1) { + assert_cond(do_compress_zcb(Rs1)); + uint16_t insn = 0; + c_patch((address)&insn, 1, 0, 0b01); + c_patch((address)&insn, 4, 2, InstructionType); + c_patch((address)&insn, 6, 5, 0b11); + c_patch_compressed_reg((address)&insn, 7, Rs1); + c_patch((address)&insn, 12, 10, 0b111); + c_patch((address)&insn, 15, 13, 0b100); + emit_int16(insn); + } + + public: + + // Prerequisites: Zcb + void c_lh(Register Rd_Rs2, Register Rs1, const int32_t uimm) { c_lh_if(Rd_Rs2, Rs1, uimm); } + void lh(Register Rd_Rs2, Register Rs1, const int32_t uimm) { lh_c_mux(Rd_Rs2, Rs1, uimm); } + + // Prerequisites: Zcb + void c_lhu(Register Rd_Rs2, Register Rs1, const int32_t uimm) { c_lh_if(Rd_Rs2, Rs1, uimm); } + void lhu(Register Rd_Rs2, Register Rs1, const int32_t uimm) { lh_c_mux(Rd_Rs2, Rs1, uimm); } + + // Prerequisites: Zcb + // Format CLB, single instruction + void c_lbu(Register Rd_Rs2, Register Rs1, uint32_t uimm) { + assert_cond(uimm <= 3); + assert_cond(do_compress_zcb(Rd_Rs2, Rs1)); + uint16_t insn = 0; + c_patch((address)&insn, 1, 0, 0b00); + c_patch_compressed_reg((address)&insn, 2, Rd_Rs2); + c_patch((address)&insn, 5, 5, (uimm & nth_bit(1)) >> 1); + c_patch((address)&insn, 6, 6, (uimm & nth_bit(0)) >> 0); + c_patch_compressed_reg((address)&insn, 7, Rs1); + c_patch((address)&insn, 12, 10, 0b000); + c_patch((address)&insn, 15, 13, 0b100); + emit_int16(insn); + } + + void lbu(Register Rd_Rs2, Register Rs1, const int32_t uimm) { + if (do_compress_zcb(Rd_Rs2, Rs1) && + uimm >= 0 && uimm <= 3) { + c_lbu(Rd_Rs2, Rs1, uimm); + } else { + _lbu(Rd_Rs2, Rs1, uimm); + } + } + + // Prerequisites: Zcb + // Format CSB, single instruction + void c_sb(Register Rd_Rs2, Register Rs1, uint32_t uimm) { + assert_cond(uimm <= 3); + assert_cond(do_compress_zcb(Rd_Rs2, Rs1)); + uint16_t insn = 0; + c_patch((address)&insn, 1, 0, 0b00); + c_patch_compressed_reg((address)&insn, 2, Rd_Rs2); + c_patch((address)&insn, 5, 5, (uimm & nth_bit(1)) >> 1); + c_patch((address)&insn, 6, 6, (uimm & nth_bit(0)) >> 0); + c_patch_compressed_reg((address)&insn, 7, Rs1); + c_patch((address)&insn, 12, 10, 0b010); + c_patch((address)&insn, 15, 13, 0b100); + emit_int16(insn); + } + + void sb(Register Rd_Rs2, Register Rs1, const int32_t uimm) { + if (do_compress_zcb(Rd_Rs2, Rs1) && + uimm >= 0 && uimm <= 3) { + c_sb(Rd_Rs2, Rs1, uimm); + } else { + _sb(Rd_Rs2, Rs1, uimm); + } + } + + // Prerequisites: Zcb + // Format CSH, single instruction + void c_sh(Register Rd_Rs2, Register Rs1, uint32_t uimm) { + assert_cond(uimm == 0 || uimm == 2); + assert_cond(do_compress_zcb(Rd_Rs2, Rs1)); + uint16_t insn = 0; + c_patch((address)&insn, 1, 0, 0b00); + c_patch_compressed_reg((address)&insn, 2, Rd_Rs2); + c_patch((address)&insn, 5, 5, (uimm & nth_bit(1)) >> 1); + c_patch((address)&insn, 6, 6, 0); + c_patch_compressed_reg((address)&insn, 7, Rs1); + c_patch((address)&insn, 12, 10, 0b011); + c_patch((address)&insn, 15, 13, 0b100); + emit_int16(insn); + } + + void sh(Register Rd_Rs2, Register Rs1, const int32_t uimm) { + if (do_compress_zcb(Rd_Rs2, Rs1) && + (uimm == 0 || uimm == 2)) { + c_sh(Rd_Rs2, Rs1, uimm); + } else { + _sh(Rd_Rs2, Rs1, uimm); + } + } + + // Prerequisites: Zcb + // Format CS + void c_zext_b(Register Rs1) { + assert_cond(do_compress_zcb(Rs1)); + c_u_if<0b000>(Rs1); + } + + // Prerequisites: Zbb + void sext_b(Register Rd_Rs2, Register Rs1) { + assert_cond(UseZbb); + if (do_compress_zcb_zbb(Rd_Rs2, Rs1) && (Rd_Rs2 == Rs1)) { + c_sext_b(Rd_Rs2); + } else { + _sext_b(Rd_Rs2, Rs1); + } + } + + // Prerequisites: Zcb, Zbb + // Format CS + void c_sext_b(Register Rs1) { + c_u_if<0b001>(Rs1); + } + + // Prerequisites: Zbb + void zext_h(Register Rd_Rs2, Register Rs1) { + assert_cond(UseZbb); + if (do_compress_zcb_zbb(Rd_Rs2, Rs1) && (Rd_Rs2 == Rs1)) { + c_zext_h(Rd_Rs2); + } else { + _zext_h(Rd_Rs2, Rs1); + } + } + + // Prerequisites: Zcb, Zbb + // Format CS + void c_zext_h(Register Rs1) { + c_u_if<0b010>(Rs1); + } + + // Prerequisites: Zbb + void sext_h(Register Rd_Rs2, Register Rs1) { + assert_cond(UseZbb); + if (do_compress_zcb_zbb(Rd_Rs2, Rs1) && (Rd_Rs2 == Rs1)) { + c_sext_h(Rd_Rs2); + } else { + _sext_h(Rd_Rs2, Rs1); + } + } + + // Prerequisites: Zcb, Zbb + // Format CS + void c_sext_h(Register Rs1) { + c_u_if<0b011>(Rs1); + } + + // Prerequisites: Zcb, Zba + // Format CS + void c_zext_w(Register Rs1) { + c_u_if<0b100>(Rs1); + } + + // Prerequisites: Zcb + // Format CS + void c_not(Register Rs1) { + c_u_if<0b101>(Rs1); + } + + // Prerequisites: Zcb (M or Zmmul) + // Format CA, c.mul + void c_mul(Register Rd_Rs1, Register Rs2) { + uint16_t insn = 0; + c_patch((address)&insn, 1, 0, 0b01); + c_patch_compressed_reg((address)&insn, 2, Rs2); + c_patch((address)&insn, 6, 5, 0b10); + c_patch_compressed_reg((address)&insn, 7, Rd_Rs1); + c_patch((address)&insn, 12, 10, 0b111); + c_patch((address)&insn, 15, 13, 0b100); + emit_int16(insn); + } + + void mul(Register Rd, Register Rs1, Register Rs2) { + if (Rd != Rs1 && Rd != Rs2) { + // Three registers needed without a mv, emit uncompressed + _mul(Rd, Rs1, Rs2); + return; + } + + // Rd is either Rs1 or Rs2 + if (!do_compress_zcb(Rs2, Rs1)) { + _mul(Rd, Rs1, Rs2); + } else { + if (Rd == Rs2) { + Rs2 = Rs1; + } else { + assert(Rd == Rs1, "must be"); + } + c_mul(Rd, Rs2); + } + } + // Stack overflow checking virtual void bang_stack_with_offset(int offset) { Unimplemented(); } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 50ad3efbdb450..5008a0c08c219 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -4678,41 +4678,54 @@ void MacroAssembler::shadd(Register Rd, Register Rs1, Register Rs2, Register tmp } void MacroAssembler::zero_extend(Register dst, Register src, int bits) { - if (UseZba && bits == 32) { - zext_w(dst, src); - return; - } - - if (UseZbb && bits == 16) { - zext_h(dst, src); - return; - } - - if (bits == 8) { - zext_b(dst, src); - } else { - slli(dst, src, XLEN - bits); - srli(dst, dst, XLEN - bits); + switch (bits) { + case 32: + if (UseZba) { + zext_w(dst, src); + return; + } + break; + case 16: + if (UseZbb) { + zext_h(dst, src); + return; + } + break; + case 8: + if (UseZbb) { + zext_b(dst, src); + return; + } + break; + default: + break; } + slli(dst, src, XLEN - bits); + srli(dst, dst, XLEN - bits); } void MacroAssembler::sign_extend(Register dst, Register src, int bits) { - if (UseZbb) { - if (bits == 8) { - sext_b(dst, src); + switch (bits) { + case 32: + sext_w(dst, src); return; - } else if (bits == 16) { - sext_h(dst, src); - return; - } - } - - if (bits == 32) { - sext_w(dst, src); - } else { - slli(dst, src, XLEN - bits); - srai(dst, dst, XLEN - bits); + case 16: + if (UseZbb) { + sext_h(dst, src); + return; + } + break; + case 8: + if (UseZbb) { + sext_b(dst, src); + return; + } + break; + default: + break; } + slli(dst, src, XLEN - bits); + srai(dst, dst, XLEN - bits); } void MacroAssembler::cmp_x2i(Register dst, Register src1, Register src2, diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 4724dd85e7801..d283654e6e179 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -473,7 +473,11 @@ class MacroAssembler: public Assembler { } inline void notr(Register Rd, Register Rs) { - xori(Rd, Rs, -1); + if (do_compress_zcb(Rd, Rs) && (Rd == Rs)) { + c_not(Rd); + } else { + xori(Rd, Rs, -1); + } } inline void neg(Register Rd, Register Rs) { @@ -489,7 +493,11 @@ class MacroAssembler: public Assembler { } inline void zext_b(Register Rd, Register Rs) { - andi(Rd, Rs, 0xFF); + if (do_compress_zcb(Rd, Rs) && (Rd == Rs)) { + c_zext_b(Rd); + } else { + andi(Rd, Rs, 0xFF); + } } inline void seqz(Register Rd, Register Rs) { @@ -511,7 +519,12 @@ class MacroAssembler: public Assembler { // Bit-manipulation extension pseudo instructions // zero extend word inline void zext_w(Register Rd, Register Rs) { - add_uw(Rd, Rs, zr); + assert(UseZba, "must be"); + if (do_compress_zcb(Rd, Rs) && (Rd == Rs)) { + c_zext_w(Rd); + } else { + add_uw(Rd, Rs, zr); + } } // Floating-point data-processing pseudo instructions diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 290b44eb0efe9..1ea853284ff15 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -110,6 +110,9 @@ class VM_Version : public Abstract_VM_Version { // Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space. // Zihintpause Pause instruction HINT // + // Zc Code Size Reduction - Additional compressed instructions. + // Zcb Simple code-size saving instructions + // // Other features and settings // mvendorid Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. // marchid Id for microarch. Mvendorid plus marchid uniquely identify the microarch. @@ -117,6 +120,8 @@ class VM_Version : public Abstract_VM_Version { // unaligned_access Unaligned memory accesses (unknown, unspported, emulated, slow, firmware, fast) // satp mode SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 + public: + #define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord // declaration name , extension name, bit pos ,in str, mapped flag) @@ -137,6 +142,7 @@ class VM_Version : public Abstract_VM_Version { decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \ decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \ + decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \ decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \ diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp index 6e93406b1a353..354dbd70bb4e1 100644 --- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp @@ -240,6 +240,8 @@ void VM_Version::rivos_features() { ext_Zbb.enable_feature(); ext_Zbs.enable_feature(); + ext_Zcb.enable_feature(); + ext_Zicsr.enable_feature(); ext_Zifencei.enable_feature(); ext_Zic64b.enable_feature(); From 075fed91bd144d94328e198b41ea2946961940e9 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 9 Jan 2024 08:19:57 +0000 Subject: [PATCH 067/112] 8323241: jcmd manpage should use lists for argument lists Reviewed-by: alanb --- src/jdk.jcmd/share/man/jcmd.1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index f0e14a9dbd2e5..0da1ee6912777 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -172,11 +172,11 @@ Impact: Low: Depends on code heap size and content. Holds CodeCache_lock during analysis step, usually sub-second duration. .PP \f[I]arguments\f[R]: -.PP +.IP \[bu] 2 \f[I]function\f[R]: (Optional) Function to be performed (aggregate, UsedSpace, FreeSpace, MethodCount, MethodSpace, MethodAge, MethodNames, discard (STRING, all) -.PP +.IP \[bu] 2 \f[I]granularity\f[R]: (Optional) Detail level - smaller value -> more detail (INT, 4096) .RE @@ -202,7 +202,7 @@ Adds compiler directives from a file. Impact: Low .PP \f[I]arguments\f[R]: -.PP +.IP \[bu] 2 \f[I]filename\f[R]: The name of the directives file (STRING, no default value) .RE @@ -253,7 +253,7 @@ Write map file for Linux perf tool. Impact: Low .PP \f[I]arguments\f[R]: -.PP +.IP \[bu] 2 \f[I]filename\f[R]: (Optional) The name of the map file (STRING, no default value) .RE From 52a6c37558fa970f595067bc1bb5bc2b710c3876 Mon Sep 17 00:00:00 2001 From: Boris Ulasevich Date: Tue, 9 Jan 2024 10:33:52 +0000 Subject: [PATCH 068/112] 8322858: compiler/c2/aarch64/TestFarJump.java fails on AArch64 due to unexpected PrintAssembly output Reviewed-by: aph, thartmann --- test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java index d461d56d8a390..3fe213122bda6 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestFarJump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2024, BELLSOFT. 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 @@ -89,10 +89,9 @@ static void runVM(boolean bigCodeHeap) throws Exception { "-Xbatch", "-XX:+TieredCompilation", "-XX:+SegmentedCodeCache", - "-XX:CompileOnly=" + className + "::main", "-XX:ReservedCodeCacheSize=" + (bigCodeHeap ? "256M" : "200M"), "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintAssembly", + "-XX:CompileCommand=option," + className + "::main,bool,PrintAssembly,true", className}; ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(procArgs); From 6e9671a8a87a369c6986854a2c3c32cc9d7027ba Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 9 Jan 2024 10:37:02 +0000 Subject: [PATCH 069/112] 8323264: Serial: Remove unused GenerationBlockSizeClosure Reviewed-by: stefank --- src/hotspot/share/gc/serial/generation.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/hotspot/share/gc/serial/generation.cpp b/src/hotspot/share/gc/serial/generation.cpp index 30f1429fd40f2..302f8f231e7be 100644 --- a/src/hotspot/share/gc/serial/generation.cpp +++ b/src/hotspot/share/gc/serial/generation.cpp @@ -173,18 +173,6 @@ HeapWord* Generation::block_start(const void* p) const { return blk._start; } -class GenerationBlockSizeClosure : public SpaceClosure { - public: - const HeapWord* _p; - size_t size; - virtual void do_space(Space* s) { - if (size == 0 && s->is_in_reserved(_p)) { - size = s->block_size(_p); - } - } - GenerationBlockSizeClosure(const HeapWord* p) { _p = p; size = 0; } -}; - class GenerationBlockIsObjClosure : public SpaceClosure { public: const HeapWord* _p; From 7d42aa15137814761ff314112a055e835a659cf1 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 9 Jan 2024 11:31:50 +0000 Subject: [PATCH 070/112] 8310277: jdk/javadoc/doclet/testMethodCommentAlgorithm/TestMethodCommentsAlgorithm.java fails with IllegalStateException Reviewed-by: jjg --- .../TestMethodCommentsAlgorithm.java | 155 +++++++++--------- 1 file changed, 77 insertions(+), 78 deletions(-) diff --git a/test/langtools/jdk/javadoc/doclet/testMethodCommentAlgorithm/TestMethodCommentsAlgorithm.java b/test/langtools/jdk/javadoc/doclet/testMethodCommentAlgorithm/TestMethodCommentsAlgorithm.java index 2931ae40f9d7e..3e5d978cc8f7d 100644 --- a/test/langtools/jdk/javadoc/doclet/testMethodCommentAlgorithm/TestMethodCommentsAlgorithm.java +++ b/test/langtools/jdk/javadoc/doclet/testMethodCommentAlgorithm/TestMethodCommentsAlgorithm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -31,13 +31,15 @@ * @run main TestMethodCommentsAlgorithm */ +import java.io.IOError; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; import javax.lang.model.element.Modifier; import javax.lang.model.type.TypeKind; @@ -109,6 +111,12 @@ * 3. While documentation for java.lang.Object is currently inaccessible outside * of the JDK, these test mimic what happens when the JDK documentation is * built. + * + * Note + * ==== + * + * If any of these tests cannot find a valid Object.java file in the test + * environment, they will throw jtreg.SkippedException. */ public class TestMethodCommentsAlgorithm extends JavadocTester { @@ -136,20 +144,7 @@ public static void main(String... args) throws Exception { */ @Test public void testMixedHierarchyEquals(Path base) throws Exception { - Path p = Path.of(System.getProperty("test.src", ".")).toAbsolutePath(); - while (!Files.exists(p.resolve("TEST.ROOT"))) { - p = p.getParent(); - if (p == null) { - throw new SkippedException("can't find TEST.ROOT"); - } - } - out.println("Test suite root: " + p); - Path javaBase = p.resolve("../../src/java.base").normalize(); - if (!Files.exists(javaBase)) { - throw new SkippedException("can't find java.base"); - } - out.println("java.base: " + javaBase); - + var javaBase = findJavaBase(); for (int i = 1; i < 7; i++) { mixedHierarchyI(base, javaBase, i); new OutputChecker("mymodule/x/T1.html").check(""" @@ -265,20 +260,7 @@ private static String generateDocComment(int index, int run, boolean includeComm */ @Test public void testInterfaceHierarchy(Path base) throws Exception { - Path p = Path.of(System.getProperty("test.src", ".")).toAbsolutePath(); - while (!Files.exists(p.resolve("TEST.ROOT"))) { - p = p.getParent(); - if (p == null) { - throw new SkippedException("can't find TEST.ROOT"); - } - } - System.err.println("Test suite root: " + p); - Path javaBase = p.resolve("../../src/java.base").normalize(); - if (!Files.exists(javaBase)) { - throw new SkippedException("can't find java.base"); - } - System.err.println("java.base: " + javaBase); - + var javaBase = findJavaBase(); for (int i = 1; i < 6; i++) { interfaceHierarchyI(base, javaBase, i); new OutputChecker("mymodule/x/T1.html").check(""" @@ -306,20 +288,7 @@ public void testInterfaceHierarchy(Path base) throws Exception { */ @Test public void testRecursiveInheritDocTagsAreProcessedFirst(Path base) throws Exception { - Path p = Path.of(System.getProperty("test.src", ".")).toAbsolutePath(); - while (!Files.exists(p.resolve("TEST.ROOT"))) { - p = p.getParent(); - if (p == null) { - throw new SkippedException("can't find TEST.ROOT"); - } - } - System.err.println("Test suite root: " + p); - Path javaBase = p.resolve("../../src/java.base").normalize(); - if (!Files.exists(javaBase)) { - throw new SkippedException("can't find java.base"); - } - System.err.println("java.base: " + javaBase); - + var javaBase = findJavaBase(); Path src = base.resolve("src"); tb.writeJavaFiles(src.resolve("mymodule"), """ package x; @@ -418,41 +387,67 @@ public interface T5 { } /* - * Takes a path to the java.base module, finds the Object.java file in - * there, creates a copy of that file _with the modified doc comment_ - * for Object.equals in the provided destination directory and returns - * the path to that created copy. + * Locates source of the java.base module. */ - private Path createPatchedJavaLangObject(Path src, Path dst, String newComment) - throws IOException { - if (!Files.isDirectory(src) || !Files.isDirectory(dst)) { - throw new IllegalArgumentException(); + private Path findJavaBase() { + String testSrc = System.getProperty("test.src"); + if (testSrc == null) { + // shouldn't happen + throw new SkippedException("test.src is not set"); } - var obj = Path.of("java/lang/Object.java"); - List files; - // ensure Object.java is found and unique - try (var s = Files.find(src, Integer.MAX_VALUE, - (p, attr) -> attr.isRegularFile() && p.endsWith(obj))) { - files = s.limit(2).toList(); // 2 is enough to deduce non-uniqueness + Path start; + try { + start = Path.of(testSrc).toAbsolutePath(); + } catch (InvalidPathException | IOError e) { + throw new SkippedException("Couldn't make sense of '" + testSrc + "'", e); } - if (files.size() != 1) { - throw new IllegalStateException(Arrays.toString(files.toArray())); + Path p = start; + while (!Files.exists(p.resolve("TEST.ROOT"))) { + p = p.getParent(); + if (p == null) { + // shouldn't happen as jtreg won't even run a test without TEST.ROOT + throw new SkippedException("Couldn't find TEST.ROOT above '" + start + "'"); + } } - var original = files.get(0); - out.println("found " + original.toAbsolutePath()); - var source = Files.readString(original); - var region = findDocCommentRegion(original); - var newSource = source.substring(0, region.start) - + newComment - + source.substring(region.end); - // create intermediate directories in the destination first, otherwise - // writeString will throw java.nio.file.NoSuchFileException - var copy = dst.resolve(src.relativize(original)); - out.println("to be copied to " + copy); - if (Files.notExists(copy.getParent())) { - Files.createDirectories(copy.getParent()); + Path javaBase = p.resolve("../../src/java.base").normalize(); + out.println("Source for java.base is found at: " + javaBase); + return javaBase; + } + + /* + * Finds java/lang/Object.java rooted at src, creates a copy of that file + * _with the modified doc comment_ for Object.equals in dst, and returns + * the path to that copy. + */ + private Path createPatchedJavaLangObject(Path src, Path dst, String newComment) { + var obj = Path.of("java/lang/Object.java"); + try { + Optional files; + try (var s = Files.find(src, Integer.MAX_VALUE, + (p, attr) -> attr.isRegularFile() && p.endsWith(obj))) { + files = s.findAny(); + } + if (files.isEmpty()) { + throw new SkippedException("Couldn't find '" + obj + "' at '" + src + "'"); + } + var original = files.get(); + out.println("Found '" + obj + "' at " + original.toAbsolutePath()); + var source = Files.readString(original); + var region = findDocCommentRegion(original); + var newSource = source.substring(0, region.start) + + newComment + + source.substring(region.end); + // create intermediate directories in the destination first, otherwise + // writeString will throw java.nio.file.NoSuchFileException + var copy = dst.resolve(src.relativize(original)); + out.println("To be copied to '" + copy + "'"); + if (Files.notExists(copy.getParent())) { + Files.createDirectories(copy.getParent()); + } + return Files.writeString(copy, newSource, StandardOpenOption.CREATE); + } catch (IOException e) { + throw new SkippedException("Couldn't create patched '" + obj + "'", e); } - return Files.writeString(copy, newSource, StandardOpenOption.CREATE); } private static SourceRegion findDocCommentRegion(Path src) throws IOException { @@ -464,14 +459,18 @@ private static SourceRegion findDocCommentRegion(Path src) throws IOException { var task = (JavacTask) compiler.getTask(null, null, null, null, null, List.of(fileObject)); Iterator iterator = task.parse().iterator(); if (!iterator.hasNext()) { - throw new AssertionError(); + throw new SkippedException("Couldn't parse '" + src + "'"); } var tree = iterator.next(); var pathToEqualsMethod = findMethod(tree); + if (pathToEqualsMethod == null) { + throw new SkippedException("Couldn't find the equals method in '" + src + "'"); + } var trees = DocTrees.instance(task); DocCommentTree docCommentTree = trees.getDocCommentTree(pathToEqualsMethod); - if (docCommentTree == null) - throw new AssertionError("cannot find the doc comment for java.lang.Object#equals"); + if (docCommentTree == null) { + throw new SkippedException("Couldn't find documentation for the equals method at '" + src + "'"); + } var positions = trees.getSourcePositions(); long start = positions.getStartPosition(null, docCommentTree, docCommentTree); long end = positions.getEndPosition(null, docCommentTree, docCommentTree); @@ -510,7 +509,7 @@ public Void visitMethod(MethodTree m, Void unused) { List params = m.getParameters(); if (params.size() != 1) return null; - var parameterType = params.get(0).getType(); + var parameterType = params.getFirst().getType(); if (parameterType.getKind() == Tree.Kind.IDENTIFIER && ((IdentifierTree) parameterType).getName().toString().equals("Object")) { throw new Result(getCurrentPath()); From 37a61720b60a503a958b35c422ca4f2eb06d62fb Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Tue, 9 Jan 2024 11:36:36 +0000 Subject: [PATCH 071/112] 8322936: Update blessed-modifier-order.sh for default, sealed, and non-sealed Reviewed-by: erikj, rriggs, martin --- bin/blessed-modifier-order.sh | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/blessed-modifier-order.sh b/bin/blessed-modifier-order.sh index 4e999e02506ca..548a89dbe14b8 100644 --- a/bin/blessed-modifier-order.sh +++ b/bin/blessed-modifier-order.sh @@ -1,5 +1,6 @@ #!/bin/bash # +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. # Copyright 2015 Google, Inc. All Rights Reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -26,12 +27,17 @@ usage() { echo "$0 DIR ..." echo "Modifies in place all the java source files found" echo "in the given directories so that all java language modifiers" - echo "are in the canonical order given by Modifier#toString()." + echo "are in the canonical order." echo "Tries to get it right even within javadoc comments," echo "and even if the list of modifiers spans 2 lines." echo echo "See:" - echo "https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Modifier.html#toString-int-" + echo "https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.1.1" + echo "https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.3.1" + echo "https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.4.3" + echo "https://docs.oracle.com/javase/specs/jls/se21/html/jls-8.html#jls-8.8.3" + echo "https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.1.1" + echo "https://docs.oracle.com/javase/specs/jls/se21/html/jls-9.html#jls-9.4" echo echo "Example:" echo "$0 jdk/src/java.base jdk/test/java/{util,io,lang}" @@ -46,7 +52,7 @@ for dir in "${dirs[@]}"; do [[ -d "$dir" ]] || usage; done declare -ar modifiers=( public protected private - abstract static final transient + abstract default static final sealed non-sealed transient volatile synchronized native strictfp ) declare -r SAVE_IFS="$IFS" From ff499ef79f6bffe95afa17a9aa312ac9f67fba18 Mon Sep 17 00:00:00 2001 From: Lei Zaakjyu Date: Tue, 9 Jan 2024 13:26:38 +0000 Subject: [PATCH 072/112] 8233443: G1 DetailedUsage class names overly generic for global namespace Reviewed-by: ayang, gli, tschatzl --- src/hotspot/share/gc/g1/g1HeapTransition.cpp | 4 ++-- src/hotspot/share/gc/g1/g1HeapTransition.hpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1HeapTransition.cpp b/src/hotspot/share/gc/g1/g1HeapTransition.cpp index a2097041b2093..4f759b4a6069e 100644 --- a/src/hotspot/share/gc/g1/g1HeapTransition.cpp +++ b/src/hotspot/share/gc/g1/g1HeapTransition.cpp @@ -62,7 +62,7 @@ G1HeapTransition::Data::~Data() { G1HeapTransition::G1HeapTransition(G1CollectedHeap* g1_heap) : _g1_heap(g1_heap), _before(g1_heap) { } -struct DetailedUsage : public StackObj { +struct G1HeapTransition::DetailedUsage : public StackObj { size_t _eden_used; size_t _survivor_used; size_t _old_used; @@ -79,7 +79,7 @@ struct DetailedUsage : public StackObj { _humongous_region_count(0) {} }; -class DetailedUsageClosure: public HeapRegionClosure { +class G1HeapTransition::DetailedUsageClosure: public HeapRegionClosure { public: DetailedUsage _usage; bool do_heap_region(HeapRegion* r) { diff --git a/src/hotspot/share/gc/g1/g1HeapTransition.hpp b/src/hotspot/share/gc/g1/g1HeapTransition.hpp index 09d901f283c70..54f87fd3b71dd 100644 --- a/src/hotspot/share/gc/g1/g1HeapTransition.hpp +++ b/src/hotspot/share/gc/g1/g1HeapTransition.hpp @@ -31,6 +31,9 @@ class G1CollectedHeap; class G1HeapTransition { + struct DetailedUsage; + class DetailedUsageClosure; + struct Data { size_t _eden_length; size_t _survivor_length; From 52c7ff1d81940d6d0d1e3dd7ad0447c80708161c Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 9 Jan 2024 13:47:32 +0000 Subject: [PATCH 073/112] 8322330: JavadocHelperTest.java OOMEs with Parallel GC and ZGC Reviewed-by: ayang, aboldtch --- .../jdk/internal/shellsupport/doc/JavadocHelperTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java index 48106face35aa..d8539b8c656c7 100644 --- a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java +++ b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java @@ -30,7 +30,7 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/jdk.internal.shellsupport.doc * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask - * @run testng/timeout=900/othervm JavadocHelperTest + * @run testng/timeout=900/othervm -Xmx1024m JavadocHelperTest */ import java.io.IOException; From 438ab7c115249d7501edfbb2d3c62e96ae824181 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 9 Jan 2024 14:23:42 +0000 Subject: [PATCH 074/112] 8323284: Remove unused FilteringClosure declaration Reviewed-by: stefank, tschatzl --- src/hotspot/share/gc/shared/space.hpp | 1 - src/hotspot/share/oops/oop.hpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 6b8279ec8bd05..541747e38f838 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -51,7 +51,6 @@ class Generation; class ContiguousSpace; class CardTableRS; class DirtyCardToOopClosure; -class FilteringClosure; // A Space describes a heap area. Class Space is an abstract // base class. diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index 50d8b6041b674..75bc3d9af7216 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -45,8 +45,6 @@ // Forward declarations. class OopClosure; -class FilteringClosure; - class PSPromotionManager; class ParCompactionManager; From 886386c0396d4cd4f1be24906a77c9dbfc8626e6 Mon Sep 17 00:00:00 2001 From: Lei Zaakjyu Date: Tue, 9 Jan 2024 15:52:39 +0000 Subject: [PATCH 075/112] 8322890: Directly return in OldPLABSizeConstraintFunc Reviewed-by: ayang, tschatzl --- src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp index 8ac9a3fc783d7..6c6f83177d204 100644 --- a/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp +++ b/src/hotspot/share/gc/shared/jvmFlagConstraintsGC.cpp @@ -93,13 +93,7 @@ JVMFlag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose) { } JVMFlag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose) { - JVMFlag::Error status = JVMFlag::SUCCESS; - - { - status = MinMaxPLABSizeBounds("OldPLABSize", value, verbose); - } - - return status; + return MinMaxPLABSizeBounds("OldPLABSize", value, verbose); } JVMFlag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose) { From ee98d262181f5822609674c71c85ad4576ac1632 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 9 Jan 2024 17:03:28 +0000 Subject: [PATCH 076/112] 8323066: gc/g1/TestSkipRebuildRemsetPhase.java fails with 'Skipping Remembered Set Rebuild.' missing Reviewed-by: ayang, iwalulya --- test/hotspot/jtreg/ProblemList.txt | 1 - .../gc/g1/TestSkipRebuildRemsetPhase.java | 24 ++++++++----------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index d82f4a919fa81..754cf68ba591f 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -93,7 +93,6 @@ gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithSerial.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithShenandoah.java 8180622 generic-all gc/stress/TestStressG1Humongous.java 8286554 windows-x64 -gc/g1/TestSkipRebuildRemsetPhase.java 8323066 linux-aarch64 ############################################################################# diff --git a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java index f7f768c9d7dfd..1dc64bf625510 100644 --- a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java +++ b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java @@ -45,7 +45,7 @@ public static void main(String[] args) throws Exception { "-XX:+UnlockExperimentalVMOptions", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", - "-XX:G1MixedGCLiveThresholdPercent=20", + "-XX:G1MixedGCLiveThresholdPercent=0", "-Xlog:gc+marking=debug,gc+phases=debug,gc+remset+tracking=trace", "-Xms10M", "-Xmx10M", @@ -58,24 +58,20 @@ public static void main(String[] args) throws Exception { public static class GCTest { public static void main(String args[]) throws Exception { WhiteBox wb = WhiteBox.getWhiteBox(); - // Allocate some memory less than region size. - Object used = alloc(); + // Allocate some memory less than region size. Any object is just fine as we set + // G1MixedGCLiveThresholdPercent to zero (and no region should be selected). + Object used = new byte[2000]; - // Trigger the full GC using the WhiteBox API. - wb.fullGC(); // full + // Trigger the full GC using the WhiteBox API to make sure that at least "used" + // has been promoted to old gen. + wb.fullGC(); // Memory objects have been promoted to old by full GC. - // Concurrent cycle should not select any regions for rebuilding + // Concurrent cycle should not select any regions for rebuilding and print the + // appropriate message. wb.g1RunConcurrentGC(); System.out.println(used); } - - private static Object alloc() { - // Since G1MixedGCLiveThresholdPercent is 20%, make sure to allocate object larger than that - // so that it will not be collected and the expected message printed. - final int objectSize = WhiteBox.getWhiteBox().g1RegionSize() / 3; - Object ret = new byte[objectSize]; - return ret; - } } } + From dd8ae616437398f957f9b4f09cf2c7f1d0bd0938 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Tue, 9 Jan 2024 19:31:03 +0000 Subject: [PATCH 077/112] 8322237: Heap dump contains duplicate thread records for mounted virtual threads Reviewed-by: dholmes, sspitsyn --- src/hotspot/share/services/heapDumper.cpp | 18 +++++++++++++++++- .../vthread/HeapDump/VThreadInHeapDump.java | 19 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/services/heapDumper.cpp b/src/hotspot/share/services/heapDumper.cpp index a46101f6d8d1d..add86b338deef 100644 --- a/src/hotspot/share/services/heapDumper.cpp +++ b/src/hotspot/share/services/heapDumper.cpp @@ -1641,6 +1641,19 @@ class ThreadDumper : public CHeapObj { && java_lang_VirtualThread::state(vt) != java_lang_VirtualThread::TERMINATED; } + static bool is_vthread_mounted(oop vt) { + // The code should be consistent with the "mounted virtual thread" case + // (VM_HeapDumper::dump_stack_traces(), ThreadDumper::get_top_frame()). + // I.e. virtual thread is mounted if its carrierThread is not null + // and is_vthread_mounted() for the carrier thread returns true. + oop carrier_thread = java_lang_VirtualThread::carrier_thread(vt); + if (carrier_thread == nullptr) { + return false; + } + JavaThread* java_thread = java_lang_Thread::thread(carrier_thread); + return java_thread->is_vthread_mounted(); + } + ThreadDumper(ThreadType thread_type, JavaThread* java_thread, oop thread_oop); // affects frame_count @@ -1918,7 +1931,10 @@ void HeapObjectDumper::do_object(oop o) { if (o->is_instance()) { // create a HPROF_GC_INSTANCE record for each object DumperSupport::dump_instance(writer(), o, &_class_cache); - if (java_lang_VirtualThread::is_instance(o) && ThreadDumper::should_dump_vthread(o)) { + // If we encounter an unmounted virtual thread it needs to be dumped explicitly + // (mounted virtual threads are dumped with their carriers). + if (java_lang_VirtualThread::is_instance(o) + && ThreadDumper::should_dump_vthread(o) && !ThreadDumper::is_vthread_mounted(o)) { _vthread_dumper->dump_vthread(o, writer()); } } else if (o->is_objArray()) { diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java index 7fe5abb800fd2..2243a1d37b6ba 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/HeapDump/VThreadInHeapDump.java @@ -26,7 +26,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -223,11 +225,22 @@ private static void verifyDump(File dumpFile) throws Exception { // Log all threads with stack traces and stack references. List threads = snapshot.getThreads(); List roots = Collections.list(snapshot.getRoots()); + // And detect thread object duplicates. + Set uniqueThreads = new HashSet<>(); + log("Threads:"); for (ThreadObject thread: threads) { + JavaHeapObject threadObj = snapshot.findThing(thread.getId()); + JavaClass threadClass = threadObj.getClazz(); StackTrace st = thread.getStackTrace(); StackFrame[] frames = st.getFrames(); - log("thread " + thread.getIdString() + ", " + frames.length + " frames"); + log("thread " + thread.getIdString() + " (" + threadClass.getName() + "), " + frames.length + " frames"); + + if (uniqueThreads.contains(thread.getId())) { + log(" - ERROR: duplicate"); + } else { + uniqueThreads.add(thread.getId()); + } List stackRoots = findStackRoot(roots, thread); for (int i = 0; i < frames.length; i++) { @@ -250,6 +263,10 @@ private static void verifyDump(File dumpFile) throws Exception { } } + if (threads.size() != uniqueThreads.size()) { + throw new RuntimeException("Thread duplicates detected (" + (threads.size() - uniqueThreads.size()) + ")"); + } + // Verify objects from thread stacks are dumped. test(snapshot, VThreadInHeapDumpTarg.VThreadMountedReferenced.class); test(snapshot, VThreadInHeapDumpTarg.PThreadReferenced.class); From bc05893f820ff8158897f84b9d2fdaed2cd1661b Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 9 Jan 2024 19:37:28 +0000 Subject: [PATCH 078/112] 8323318: Remove unused Space::is_free_block Reviewed-by: tschatzl --- src/hotspot/share/gc/shared/space.cpp | 4 ---- src/hotspot/share/gc/shared/space.hpp | 5 ----- 2 files changed, 9 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index b6dc4e1e7d8f2..67d3ad5338388 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -74,10 +74,6 @@ void ContiguousSpace::clear(bool mangle_space) { } } -bool ContiguousSpace::is_free_block(const HeapWord* p) const { - return p >= _top; -} - #ifndef PRODUCT void ContiguousSpace::set_top_for_allocations(HeapWord* v) { diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 541747e38f838..8299a7e628913 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -133,9 +133,6 @@ class Space: public CHeapObj { // given address. bool is_in_reserved(const void* p) const { return _bottom <= p && p < _end; } - // Returns true iff the given block is not allocated. - virtual bool is_free_block(const HeapWord* p) const = 0; - // Test whether p is double-aligned static bool is_aligned(void* p) { return ::is_aligned(p, sizeof(double)); @@ -273,8 +270,6 @@ class ContiguousSpace: public Space { size_t used() const override { return byte_size(bottom(), top()); } size_t free() const override { return byte_size(top(), end()); } - bool is_free_block(const HeapWord* p) const override; - // In a contiguous space we have a more obvious bound on what parts // contain objects. MemRegion used_region() const override { return MemRegion(bottom(), top()); } From f3be138eb80c9e7f6cc21afb75cda9e49b667c8a Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 9 Jan 2024 22:04:02 +0000 Subject: [PATCH 079/112] 8322809: SystemModulesMap::classNames and moduleNames arrays do not match the order Reviewed-by: alanb --- .../internal/plugins/SystemModulesPlugin.java | 13 +- .../ModuleMainClassTest.java | 145 ++++++++++++++++++ .../src/com.foo/com/foo/Main.java | 53 +++++++ .../src/com.foo/module-info.java | 27 ++++ .../src/net.foo/module-info.java | 26 ++++ .../src/net.foo/net/foo/Main.java | 54 +++++++ 6 files changed, 313 insertions(+), 5 deletions(-) create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java create mode 100644 test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java index 735c969a88603..40693b33d6db2 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -1827,6 +1827,9 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules, // write the class file to the pool as a resource String rn = "/java.base/" + SYSTEM_MODULES_MAP_CLASSNAME + ".class"; + // sort the map of module name to the class name of the generated SystemModules class + List> systemModulesMap = map.entrySet() + .stream().sorted(Map.Entry.comparingByKey()).toList(); ResourcePoolEntry e = ResourcePoolEntry.create(rn, ClassFile.of().build( CD_SYSTEM_MODULES_MAP, clb -> clb.withFlags(ACC_FINAL + ACC_SUPER) @@ -1877,10 +1880,10 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules, cob.anewarray(CD_String); int index = 0; - for (String moduleName : sorted(map.keySet())) { + for (Map.Entry entry : systemModulesMap) { cob.dup() // arrayref .constantInstruction(index) - .constantInstruction(moduleName) + .constantInstruction(entry.getKey()) .aastore(); index++; } @@ -1898,10 +1901,10 @@ private String genSystemModulesMapClass(ClassDesc allSystemModules, .anewarray(CD_String); int index = 0; - for (String className : sorted(map.values())) { + for (Map.Entry entry : systemModulesMap) { cob.dup() // arrayref .constantInstruction(index) - .constantInstruction(className.replace('/', '.')) + .constantInstruction(entry.getValue().replace('/', '.')) .aastore(); index++; } diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java new file mode 100644 index 0000000000000..ca7e2bc5f3009 --- /dev/null +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/ModuleMainClassTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024, 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. + */ + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.spi.ToolProvider; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.util.FileUtils; + +import static jdk.test.lib.process.ProcessTools.*; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import static org.junit.jupiter.api.Assertions.*; + +/** + * @test + * @bug 8322809 + * @library /test/lib + * @modules jdk.compiler jdk.jlink + * @build jdk.test.lib.compiler.CompilerUtils + * jdk.test.lib.process.ProcessTools + * jdk.test.lib.util.FileUtils + * ModuleMainClassTest + * @run junit ModuleMainClassTest + */ + +public class ModuleMainClassTest { + private static final String JAVA_HOME = System.getProperty("java.home"); + private static final String TEST_SRC = System.getProperty("test.src"); + + private static final Path SRC_DIR = Path.of(TEST_SRC, "src"); + private static final Path MODS_DIR = Path.of("mods"); + private static final Path JMODS_DIR = Path.of("jmods"); + + private static final Path IMAGE = Path.of("image"); + + // the module names are sorted by the plugin and so these names cover + // the cases that are before and after the elements of `jdk.*` modules + // with main classes + private static String[] modules = new String[] {"com.foo", "net.foo"}; + + private static boolean hasJmods() { + if (!Files.exists(Paths.get(JAVA_HOME, "jmods"))) { + System.err.println("Test skipped. NO jmods directory"); + return false; + } + return true; + } + + @BeforeAll + public static void compileAll() throws Throwable { + if (!hasJmods()) return; + + for (String mn : modules) { + Path msrc = SRC_DIR.resolve(mn); + assertTrue(CompilerUtils.compile(msrc, MODS_DIR, + "--module-source-path", SRC_DIR.toString(), + "--add-exports", "java.base/jdk.internal.module=" + mn)); + } + + if (Files.exists(IMAGE)) { + FileUtils.deleteFileTreeUnchecked(IMAGE); + } + + // create JMOD files + Files.createDirectories(JMODS_DIR); + Stream.of(modules).forEach(mn -> + assertTrue(jmod("create", + "--class-path", MODS_DIR.resolve(mn).toString(), + "--main-class", mn + ".Main", + JMODS_DIR.resolve(mn + ".jmod").toString()) == 0) + ); + + // the run-time image created will have 4 modules with main classes + createImage(IMAGE, "com.foo"); + } + + @Test + public void testComFoo() throws Exception { + if (!hasJmods()) return; + + Path java = IMAGE.resolve("bin").resolve("java"); + assertTrue(executeProcess(java.toString(), + "-m", "com.foo") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue() == 0); + } + + @Test + public void testNetFoo() throws Exception { + if (!hasJmods()) return; + + Path java = IMAGE.resolve("bin").resolve("java"); + assertTrue(executeProcess(java.toString(), + "-m", "net.foo") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue() == 0); + } + + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> new RuntimeException("jlink tool not found")); + + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> new RuntimeException("jmod tool not found")); + + private static void createImage(Path outputDir, String... modules) throws Throwable { + assertTrue(JLINK_TOOL.run(System.out, System.out, + "--output", outputDir.toString(), + "--add-modules", Arrays.stream(modules).collect(Collectors.joining(",")), + "--module-path", JMODS_DIR.toString()) == 0); + } + + private static int jmod(String... options) { + System.out.println("jmod " + Arrays.asList(options)); + return JMOD_TOOL.run(System.out, System.out, options); + } +} diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java new file mode 100644 index 0000000000000..f8b230647fabe --- /dev/null +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/com/foo/Main.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024, 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 com.foo; + +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.util.stream.Stream; + +/** + * Sanity test if SystemModules pre-resolved at link-time for com.foo + * with main class is loaded properly. + */ +public class Main { + public static void main(String... args) throws Exception { + ModuleDescriptor md = Main.class.getModule().getDescriptor(); + System.out.println(md); + + checkMainClass("com.foo", "com.foo.Main"); + checkMainClass("net.foo", "net.foo.Main"); + Stream.of("jdk.httpserver", "jdk.jfr").forEach(mn -> + ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass() + .orElseThrow(() -> new RuntimeException(mn + " no main class")) + ); + } + + static void checkMainClass(String mn, String mainClass) { + String cn = ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass().get(); + if (!cn.equals(mainClass)) { + throw new RuntimeException("Mismatched main class of module " + mn + ": " + cn + " expected: " + mainClass); + } + } +} diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java new file mode 100644 index 0000000000000..99107602506c7 --- /dev/null +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/com.foo/module-info.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024, 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. + */ + +module com.foo { + requires jdk.httpserver; + requires net.foo; +} diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java new file mode 100644 index 0000000000000..360a989d9b339 --- /dev/null +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/module-info.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024, 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. + */ + +module net.foo { + requires jdk.jfr; +} diff --git a/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java new file mode 100644 index 0000000000000..c147923e75a0d --- /dev/null +++ b/test/jdk/tools/jlink/plugins/SystemModuleDescriptors/src/net.foo/net/foo/Main.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, 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 net.foo; + +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.util.stream.Stream; + +/** + * Sanity test if SystemModules pre-resolved at link-time for net.foo + * with main class is loaded properly. + */ +public class Main { + public static void main(String... args) throws Exception { + ModuleDescriptor md = Main.class.getModule().getDescriptor(); + System.out.println(md); + + checkMainClass("com.foo", "com.foo.Main"); + checkMainClass("net.foo", "net.foo.Main"); + Stream.of("jdk.httpserver", "jdk.jfr").forEach(mn -> + ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass() + .orElseThrow(() -> new RuntimeException(mn + " no main class")) + ); + } + + static void checkMainClass(String mn, String mainClass) { + String cn = ModuleFinder.ofSystem().find(mn).get().descriptor().mainClass().get(); + if (!cn.equals(mainClass)) { + throw new RuntimeException("Mismatched main class of module " + mn + ": " + cn + " expected: " + mainClass); + } + } + +} From aba19334eaeb46d37169cddeef929b13e050a60e Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 9 Jan 2024 22:05:37 +0000 Subject: [PATCH 080/112] 8323210: Update the usage of cmsFLAGS_COPY_ALPHA Reviewed-by: prr --- src/java.desktop/share/native/liblcms/LCMS.c | 9 +++++++-- .../cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/share/native/liblcms/LCMS.c b/src/java.desktop/share/native/liblcms/LCMS.c index 1295d6df356d4..5cf7ee6c43629 100644 --- a/src/java.desktop/share/native/liblcms/LCMS.c +++ b/src/java.desktop/share/native/liblcms/LCMS.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -177,8 +177,13 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform } } + cmsUInt32Number dwFlags = 0; + if (T_EXTRA(inFormatter) > 0 && T_EXTRA(outFormatter) > 0) { + dwFlags |= cmsFLAGS_COPY_ALPHA; + } + sTrans = cmsCreateMultiprofileTransform(iccArray, j, - inFormatter, outFormatter, renderingIntent, cmsFLAGS_COPY_ALPHA); + inFormatter, outFormatter, renderingIntent, dwFlags); (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0); diff --git a/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java b/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java index 31db9d1a38083..22868ffaf3c11 100644 --- a/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java +++ b/test/jdk/sun/java2d/cmm/ColorConvertOp/ColCvtAlphaDifferentSrcDst.java @@ -52,7 +52,7 @@ /* * @test - * @bug 8012229 8300725 8279216 + * @bug 8012229 8300725 8279216 8323210 * @summary one more test to check the alpha channel */ public final class ColCvtAlphaDifferentSrcDst { From e9f7db304559cbc8e2b46ea30496d3c570569f4c Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 9 Jan 2024 22:26:17 +0000 Subject: [PATCH 081/112] 8322880: Eliminate -Wparentheses warnings in arm32 code Reviewed-by: shade, dholmes --- src/hotspot/cpu/arm/arm.ad | 4 ++-- src/hotspot/cpu/arm/assembler_arm.hpp | 4 ++-- src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp | 6 +++--- src/hotspot/cpu/arm/frame_arm.inline.hpp | 4 ++-- src/hotspot/cpu/arm/nativeInst_arm_32.cpp | 4 ++-- src/hotspot/cpu/arm/nativeInst_arm_32.hpp | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index c4197235987d5..e31ad91613a1a 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2008, 2024, 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 @@ -9193,7 +9193,7 @@ instruct clear_array(iRegX cnt, iRegP base, iRegI temp, iRegX zero, Universe dum ins_encode %{ __ mov($zero$$Register, 0); __ mov($temp$$Register, $cnt$$Register); - Label(loop); + Label loop; __ bind(loop); __ subs($temp$$Register, $temp$$Register, 4); __ str($zero$$Register, Address($base$$Register, $temp$$Register), ge); diff --git a/src/hotspot/cpu/arm/assembler_arm.hpp b/src/hotspot/cpu/arm/assembler_arm.hpp index b1b4199e88de0..6a3092f7b3b91 100644 --- a/src/hotspot/cpu/arm/assembler_arm.hpp +++ b/src/hotspot/cpu/arm/assembler_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -175,7 +175,7 @@ class Address { if (_index == noreg) { assert(-256 < _disp && _disp < 256, "encoding constraint"); return _mode | up(_disp) << 23 | 1 << 22 | _base->encoding() << 16 | - (abs(_disp) & 0xf0) << 4 | abs(_disp) & 0x0f; + (abs(_disp) & 0xf0) << 4 | (abs(_disp) & 0x0f); } else { assert(_index != PC && (_mode == basic_offset || _index != _base), "unpredictable instruction"); assert(_disp == 0 && _shift == lsl && _shift_imm == 0, "encoding constraint"); diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp index 72993b3211f9d..999309c02258d 100644 --- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -2640,8 +2640,8 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* arg void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { - assert(src->is_double_cpu() && dest->is_address() || - src->is_address() && dest->is_double_cpu(), + assert((src->is_double_cpu() && dest->is_address()) || + (src->is_address() && dest->is_double_cpu()), "Simple move_op is called for all other cases"); int null_check_offset; diff --git a/src/hotspot/cpu/arm/frame_arm.inline.hpp b/src/hotspot/cpu/arm/frame_arm.inline.hpp index 9191d03baf0ec..43cc523658b5a 100644 --- a/src/hotspot/cpu/arm/frame_arm.inline.hpp +++ b/src/hotspot/cpu/arm/frame_arm.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -93,7 +93,7 @@ inline bool frame::equal(frame other) const { && unextended_sp() == other.unextended_sp() && fp() == other.fp() && pc() == other.pc(); - assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction"); + assert(!ret || (cb() == other.cb() && _deopt_state == other._deopt_state), "inconsistent construction"); return ret; } diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp index e5e5e89c2002b..429a0c000f637 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -162,7 +162,7 @@ void NativeMovConstReg::set_data(intptr_t x, address pc) { unsigned int hi = (unsigned int)(x >> 16); this->set_encoding((this->encoding() & 0xfff0f000) | (lo & 0xf000) << 4 | (lo & 0xfff)); next->set_encoding((next->encoding() & 0xfff0f000) | (hi & 0xf000) << 4 | (hi & 0xfff)); - } else if (oop_addr == nullptr & metadata_addr == nullptr) { + } else if (oop_addr == nullptr && metadata_addr == nullptr) { // A static ldr_literal (without oop or metadata relocation) assert(is_ldr_literal(), "must be"); int offset = ldr_offset(); diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index 804292c24b086..a7a51f017d22d 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -396,7 +396,7 @@ class NativeMovConstReg: public NativeInstruction { inline NativeMovConstReg* nativeMovConstReg_at(address address) { NativeInstruction* ni = nativeInstruction_at(address); assert(ni->is_ldr_literal() || ni->is_pc_rel() || - ni->is_movw() && VM_Version::supports_movw(), "must be"); + (ni->is_movw() && VM_Version::supports_movw()), "must be"); return (NativeMovConstReg*)address; } From 28d8149c693a9470bbde4b1a27c4b9be6c5f365c Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 9 Jan 2024 22:33:13 +0000 Subject: [PATCH 082/112] 8323115: x86-32: Incorrect predicates for cmov instruct transforms with UseSSE Reviewed-by: shade, thartmann --- src/hotspot/cpu/x86/x86_32.ad | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 45cc785a5394d..f2e9c042b244f 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 2024, 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 @@ -13161,7 +13161,7 @@ instruct cmovPP_reg_LTGE_U(cmpOpU cmp, flagsReg_ulong_LTGE flags, eRegP dst, eRe // Compare 2 longs and CMOVE doubles instruct cmovDDPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regDPR dst, regDPR src) %{ - predicate( UseSSE<=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate( UseSSE<=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); match(Set dst (CMoveD (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13171,7 +13171,7 @@ instruct cmovDDPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regDPR dst, regD // Compare 2 longs and CMOVE doubles instruct cmovDD_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regD dst, regD src) %{ - predicate( UseSSE>=2 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate( UseSSE>=2 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); match(Set dst (CMoveD (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13180,7 +13180,7 @@ instruct cmovDD_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regD dst, regD src %} instruct cmovFFPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regFPR dst, regFPR src) %{ - predicate( UseSSE==0 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate( UseSSE==0 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); match(Set dst (CMoveF (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13189,7 +13189,7 @@ instruct cmovFFPR_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regFPR dst, regF %} instruct cmovFF_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, regF dst, regF src) %{ - predicate( UseSSE>=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge ); + predicate( UseSSE>=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge )); match(Set dst (CMoveF (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13352,7 +13352,7 @@ instruct cmovPP_reg_EQNE_U(cmpOpU cmp, flagsReg_ulong_EQNE flags, eRegP dst, eRe // Compare 2 longs and CMOVE doubles instruct cmovDDPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regDPR dst, regDPR src) %{ - predicate( UseSSE<=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate( UseSSE<=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne )); match(Set dst (CMoveD (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13362,7 +13362,7 @@ instruct cmovDDPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regDPR dst, regD // Compare 2 longs and CMOVE doubles instruct cmovDD_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regD dst, regD src) %{ - predicate( UseSSE>=2 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate( UseSSE>=2 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne )); match(Set dst (CMoveD (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13371,7 +13371,7 @@ instruct cmovDD_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regD dst, regD src %} instruct cmovFFPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regFPR dst, regFPR src) %{ - predicate( UseSSE==0 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate( UseSSE==0 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne )); match(Set dst (CMoveF (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13380,7 +13380,7 @@ instruct cmovFFPR_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regFPR dst, regF %} instruct cmovFF_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, regF dst, regF src) %{ - predicate( UseSSE>=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne ); + predicate( UseSSE>=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne )); match(Set dst (CMoveF (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13571,7 +13571,7 @@ instruct cmovPP_reg_LEGT_U(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, eRegP // Compare 2 longs and CMOVE doubles instruct cmovDDPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regDPR dst, regDPR src) %{ - predicate( UseSSE<=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate( UseSSE<=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); match(Set dst (CMoveD (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13581,7 +13581,7 @@ instruct cmovDDPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regDPR d // Compare 2 longs and CMOVE doubles instruct cmovDD_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regD dst, regD src) %{ - predicate( UseSSE>=2 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate( UseSSE>=2 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); match(Set dst (CMoveD (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13590,7 +13590,7 @@ instruct cmovDD_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regD dst, %} instruct cmovFFPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regFPR dst, regFPR src) %{ - predicate( UseSSE==0 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate( UseSSE==0 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); match(Set dst (CMoveF (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ @@ -13600,7 +13600,7 @@ instruct cmovFFPR_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regFPR d instruct cmovFF_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, regF dst, regF src) %{ - predicate( UseSSE>=1 && _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt ); + predicate( UseSSE>=1 && ( _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le || _kids[0]->_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt )); match(Set dst (CMoveF (Binary cmp flags) (Binary dst src))); ins_cost(200); expand %{ From a5071e010be8c79f1a3cd96f7325d04bac8f7ae0 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 9 Jan 2024 22:47:36 +0000 Subject: [PATCH 083/112] 8322817: RISC-V: Eliminate -Wparentheses warnings in riscv code Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/frame_riscv.inline.hpp | 4 ++-- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp index dfec388019216..37f273be6c19b 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -186,7 +186,7 @@ inline bool frame::equal(frame other) const { unextended_sp() == other.unextended_sp() && fp() == other.fp() && pc() == other.pc(); - assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction"); + assert(!ret || (cb() == other.cb() && _deopt_state == other._deopt_state), "inconsistent construction"); return ret; } diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 5008a0c08c219..ce336c16aa718 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4904,9 +4904,9 @@ void MacroAssembler::object_move(OopMap* map, // A float arg may have to do float reg int reg conversion void MacroAssembler::float_move(VMRegPair src, VMRegPair dst, Register tmp) { - assert(src.first()->is_stack() && dst.first()->is_stack() || - src.first()->is_reg() && dst.first()->is_reg() || - src.first()->is_stack() && dst.first()->is_reg(), "Unexpected error"); + assert((src.first()->is_stack() && dst.first()->is_stack()) || + (src.first()->is_reg() && dst.first()->is_reg()) || + (src.first()->is_stack() && dst.first()->is_reg()), "Unexpected error"); if (src.first()->is_stack()) { if (dst.first()->is_stack()) { lwu(tmp, Address(fp, reg2offset_in(src.first()))); @@ -4948,9 +4948,9 @@ void MacroAssembler::long_move(VMRegPair src, VMRegPair dst, Register tmp) { // A double move void MacroAssembler::double_move(VMRegPair src, VMRegPair dst, Register tmp) { - assert(src.first()->is_stack() && dst.first()->is_stack() || - src.first()->is_reg() && dst.first()->is_reg() || - src.first()->is_stack() && dst.first()->is_reg(), "Unexpected error"); + assert((src.first()->is_stack() && dst.first()->is_stack()) || + (src.first()->is_reg() && dst.first()->is_reg()) || + (src.first()->is_stack() && dst.first()->is_reg()), "Unexpected error"); if (src.first()->is_stack()) { if (dst.first()->is_stack()) { ld(tmp, Address(fp, reg2offset_in(src.first()))); From 376051a9be95e0e4acf3c59d0eba3e9ef8727d79 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 9 Jan 2024 23:11:21 +0000 Subject: [PATCH 084/112] 8320919: Clarify Locale related system properties Reviewed-by: smarks, rriggs --- .../share/classes/java/util/Locale.java | 91 +++++++++++++++++-- 1 file changed, 81 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 02f556489e641..88a49a94f9be5 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -45,6 +45,7 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamField; import java.io.Serializable; +import java.text.DateFormat; import java.text.MessageFormat; import java.util.concurrent.ConcurrentHashMap; import java.util.spi.LocaleNameProvider; @@ -258,6 +259,74 @@ * locales. For example, {@code Locale.US} is the {@code Locale} object * for the United States. * + *

Default Locale

+ * + *

The default Locale is provided for any locale-sensitive methods if no + * {@code Locale} is explicitly specified as an argument, such as + * {@link DateFormat#getInstance()}. The default Locale is determined at startup + * of the Java runtime and established in the following three phases: + *

    + *
  1. The locale-related system properties listed below are established from the + * host environment. Some system properties (except for {@code user.language}) may + * not have values from the host environment. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Shows property keys and associated values
    Locale-related System Properties KeyDescription
    {@systemProperty user.language}{@link ##def_language language} for the default Locale, + * such as "en" (English)
    {@systemProperty user.script}{@link ##def_script script} for the default Locale, + * such as "Latn" (Latin)
    {@systemProperty user.country}{@link ##def_region country} for the default Locale, + * such as "US" (United States)
    {@systemProperty user.variant}{@link ##def_variant variant} for the default Locale, + * such as "POSIX"
    {@systemProperty user.extensions}{@link ##def_extensions extensions} for the default Locale, + * such as "u-ca-japanese" (Japanese Calendar)
    + *
  2. + *
  3. The values of these system properties can be overridden by values designated + * at startup time. If the overriding value of the {@code user.extensions} property + * is unparsable, it is ignored. The overriding values of other properties are not + * checked for syntax or validity and are used directly in the default Locale. + * (Typically, system property values can be provided using the {@code -D} command-line + * option of a launcher. For example, specifying {@code -Duser.extensions=foobarbaz} + * results in a default Locale with no extensions, while specifying + * {@code -Duser.language=foobarbaz} results in a default Locale whose language is + * "foobarbaz".) + *
  4. + *
  5. The default {@code Locale} instance is constructed from the values of these + * system properties. + *
  6. + *
+ *

Altering the system property values with {@link System#setProperties(Properties)}/ + * {@link System#setProperty(String, String)} has no effect on the default Locale. + *

Once the default Locale is established, applications can query the default + * Locale with {@link #getDefault()} and change it with {@link #setDefault(Locale)}. + * If the default Locale is changed with {@link #setDefault(Locale)}, the corresponding + * system properties are not altered. It is not recommended that applications read + * these system properties and parse or interpret them as their values may be out of date. + * + *

There are finer-grained default Locales specific for each {@link Locale.Category}. + * These category specific default Locales can be queried by {@link #getDefault(Category)}, + * and set by {@link #setDefault(Category, Locale)}. Construction of these category + * specific default Locales are determined by the corresponding system properties, + * which consist of the base system properties as listed above, suffixed by either + * {@code ".display"} or {@code ".format"} depending on the category. For example, + * the value of the {@code user.language.display} system property will be used in the + * {@code language} part of the default Locale for the {@link Locale.Category#DISPLAY} + * category. In the absence of category specific system properties, the "category-less" + * system properties are used, such as {@code user.language} in the previous example. + * *

Locale Matching

* *

If an application or a system is internationalized and provides localized @@ -984,14 +1053,14 @@ public int hashCode() { } /** - * Gets the current value of the default locale for this instance - * of the Java Virtual Machine. + * Gets the current value of the {@link ##default_locale default locale} for + * this instance of the Java Virtual Machine. *

* The Java Virtual Machine sets the default locale during startup * based on the host environment. It is used by many locale-sensitive * methods if no locale is explicitly specified. * It can be changed using the - * {@link #setDefault(java.util.Locale) setDefault} method. + * {@link #setDefault(Locale)} method. * * @return the default locale for this instance of the Java Virtual Machine */ @@ -1001,13 +1070,13 @@ public static Locale getDefault() { } /** - * Gets the current value of the default locale for the specified Category - * for this instance of the Java Virtual Machine. + * Gets the current value of the {@link ##default_locale default locale} for + * the specified Category for this instance of the Java Virtual Machine. *

* The Java Virtual Machine sets the default locale during startup based * on the host environment. It is used by many locale-sensitive methods * if no locale is explicitly specified. It can be changed using the - * setDefault(Locale.Category, Locale) method. + * {@link #setDefault(Locale.Category, Locale)} method. * * @param category the specified category to get the default locale * @throws NullPointerException if category is null @@ -1108,8 +1177,9 @@ private static Optional getDefaultExtensions(String extensions } /** - * Sets the default locale for this instance of the Java Virtual Machine. - * This does not affect the host locale. + * Sets the {@link ##default_locale default locale} for + * this instance of the Java Virtual Machine. This does not affect the + * host locale. *

* If there is a security manager, its {@code checkPermission} * method is called with a {@code PropertyPermission("user.language", "write")} @@ -1142,8 +1212,9 @@ public static synchronized void setDefault(Locale newLocale) { } /** - * Sets the default locale for the specified Category for this instance - * of the Java Virtual Machine. This does not affect the host locale. + * Sets the {@link ##default_locale default locale} for the specified + * Category for this instance of the Java Virtual Machine. This does + * not affect the host locale. *

* If there is a security manager, its checkPermission method is called * with a PropertyPermission("user.language", "write") permission before From f4ca41ad75fa78a08ff069ba0b6ac3596e35c23d Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 10 Jan 2024 00:19:05 +0000 Subject: [PATCH 085/112] 8322816: RISC-V: Incorrect guarantee in patch_vtype Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 55c3e755c48eb..f44840d9f8cc7 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -1156,10 +1156,8 @@ static Assembler::SEW elemtype_to_sew(BasicType etype) { } #define patch_vtype(hsb, lsb, vlmul, vsew, vta, vma, vill) \ - if (vill == 1) { \ - guarantee((vlmul | vsew | vta | vma == 0), \ - "the other bits in vtype shall be zero"); \ - } \ + /* If vill then other bits of vtype must be zero. */ \ + guarantee(!vill, "vill not supported"); \ patch((address)&insn, lsb + 2, lsb, vlmul); \ patch((address)&insn, lsb + 5, lsb + 3, vsew); \ patch((address)&insn, lsb + 6, vta); \ From 856922747358291ed2e112c328fb776a7be2567d Mon Sep 17 00:00:00 2001 From: Zhiqiang Zang Date: Wed, 10 Jan 2024 07:31:56 +0000 Subject: [PATCH 086/112] 8322589: Add Ideal transformation: (~a) & (~b) => ~(a | b) Reviewed-by: thartmann, epeter --- src/hotspot/share/opto/addnode.cpp | 18 ++++- src/hotspot/share/opto/addnode.hpp | 9 ++- src/hotspot/share/opto/mulnode.cpp | 16 ++++- .../c2/irTests/AndINodeIdealizationTests.java | 25 +++++-- .../c2/irTests/AndLNodeIdealizationTests.java | 68 +++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 7 +- 6 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/AndLNodeIdealizationTests.java diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 305501bfb1467..49d17d84fc91c 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -253,6 +253,22 @@ AddNode* AddNode::make(Node* in1, Node* in2, BasicType bt) { return nullptr; } +bool AddNode::is_not(PhaseGVN* phase, Node* n, BasicType bt) { + return n->Opcode() == Op_Xor(bt) && phase->type(n->in(2)) == TypeInteger::minus_1(bt); +} + +AddNode* AddNode::make_not(PhaseGVN* phase, Node* n, BasicType bt) { + switch (bt) { + case T_INT: + return new XorINode(n, phase->intcon(-1)); + case T_LONG: + return new XorLNode(n, phase->longcon(-1L)); + default: + fatal("Not implemented for %s", type2name(bt)); + } + return nullptr; +} + //============================================================================= //------------------------------Idealize--------------------------------------- Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 709958b6abf25..577dd6ba29588 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -78,6 +78,13 @@ class AddNode : public Node { virtual int min_opcode() const = 0; static AddNode* make(Node* in1, Node* in2, BasicType bt); + + // Utility function to check if the given node is a NOT operation, + // i.e., n == m ^ (-1). + static bool is_not(PhaseGVN* phase, Node* n, BasicType bt); + + // Utility function to make a NOT operation, i.e., returning n ^ (-1). + static AddNode* make_not(PhaseGVN* phase, Node* n, BasicType bt); }; //------------------------------AddINode--------------------------------------- diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 3b493b5efa277..8b7fa22af55a7 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -610,6 +610,13 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { return progress; } + // Convert "(~a) & (~b)" into "~(a | b)" + if (AddNode::is_not(phase, in(1), T_INT) && AddNode::is_not(phase, in(2), T_INT)) { + Node* or_a_b = new OrINode(in(1)->in(1), in(2)->in(1)); + Node* tn = phase->transform(or_a_b); + return AddNode::make_not(phase, tn, T_INT); + } + // Special case constant AND mask const TypeInt *t2 = phase->type( in(2) )->isa_int(); if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); @@ -750,6 +757,13 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) { return progress; } + // Convert "(~a) & (~b)" into "~(a | b)" + if (AddNode::is_not(phase, in(1), T_LONG) && AddNode::is_not(phase, in(2), T_LONG)) { + Node* or_a_b = new OrLNode(in(1)->in(1), in(2)->in(1)); + Node* tn = phase->transform(or_a_b); + return AddNode::make_not(phase, tn, T_LONG); + } + // Special case constant AND mask const TypeLong *t2 = phase->type( in(2) )->isa_long(); if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/AndINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/AndINodeIdealizationTests.java index ad2b52392b6c3..f20c28e321db1 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/AndINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/AndINodeIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -38,22 +38,24 @@ public static void main(String[] args) { TestFramework.run(); } - @Run(test = { "test1" }) + @Run(test = { "test1", "test2" }) public void runMethod() { int a = RunInfo.getRandom().nextInt(); + int b = RunInfo.getRandom().nextInt(); int min = Integer.MIN_VALUE; int max = Integer.MAX_VALUE; - assertResult(0); - assertResult(a); - assertResult(min); - assertResult(max); + assertResult(0, 0); + assertResult(a, b); + assertResult(min, min); + assertResult(max, max); } @DontCompile - public void assertResult(int a) { + public void assertResult(int a, int b) { Asserts.assertEQ((0 - a) & 1, test1(a)); + Asserts.assertEQ((~a) & (~b), test2(a, b)); } @Test @@ -63,4 +65,13 @@ public void assertResult(int a) { public int test1(int x) { return (0 - x) & 1; } + + @Test + @IR(failOn = { IRNode.AND }) + @IR(counts = { IRNode.OR, "1", + IRNode.XOR, "1" }) + // Checks (~a) & (~b) => ~(a | b) + public int test2(int a, int b) { + return (~a) & (~b); + } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/AndLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/AndLNodeIdealizationTests.java new file mode 100644 index 0000000000000..9aa1b62be9743 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/AndLNodeIdealizationTests.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024, 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.c2.irTests; + +import jdk.test.lib.Asserts; +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8322589 + * @summary Test that Ideal transformations of AndLNode* are being performed as expected. + * @library /test/lib / + * @run driver compiler.c2.irTests.AndLNodeIdealizationTests + */ +public class AndLNodeIdealizationTests { + + public static void main(String[] args) { + TestFramework.run(); + } + + @Run(test = { "test1" }) + public void runMethod() { + long a = RunInfo.getRandom().nextLong(); + long b = RunInfo.getRandom().nextLong(); + + long min = Long.MIN_VALUE; + long max = Long.MAX_VALUE; + + assertResult(0, 0); + assertResult(a, b); + assertResult(min, min); + assertResult(max, max); + } + + @DontCompile + public void assertResult(long a, long b) { + Asserts.assertEQ((~a) & (~b), test1(a, b)); + } + + @Test + @IR(failOn = { IRNode.AND }) + @IR(counts = { IRNode.OR, "1", + IRNode.XOR, "1" }) + // Checks (~a) & (~b) => ~(a | b) + public long test1(long a, long b) { + return (~a) & (~b); + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 9e91268edffc3..040fe5d0222c7 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, 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 @@ -298,6 +298,11 @@ public class IRNode { optoOnly(ALLOC_ARRAY_OF, regex); } + public static final String OR = PREFIX + "OR" + POSTFIX; + static { + beforeMatchingNameRegex(OR, "Or(I|L)"); + } + public static final String AND = PREFIX + "AND" + POSTFIX; static { beforeMatchingNameRegex(AND, "And(I|L)"); From 88378ed0584c7eb0849b6fc1e361fd8ea0698caf Mon Sep 17 00:00:00 2001 From: Tobias Holenstein Date: Wed, 10 Jan 2024 08:30:47 +0000 Subject: [PATCH 087/112] 8277869: Maven POMs are using HTTP links where HTTPS is available Reviewed-by: kvn, thartmann --- src/utils/IdealGraphVisualizer/Bytecodes/pom.xml | 2 +- .../igv/bytecodes/BytecodeViewTopComponentSettings.xml | 2 +- .../igv/bytecodes/BytecodeViewTopComponentWstcref.xml | 2 +- .../main/resources/com/sun/hotspot/igv/bytecodes/layer.xml | 2 +- src/utils/IdealGraphVisualizer/ControlFlow/pom.xml | 2 +- .../igv/controlflow/ControlFlowTopComponentSettings.xml | 2 +- .../igv/controlflow/ControlFlowTopComponentWstcref.xml | 2 +- .../resources/com/sun/hotspot/igv/controlflow/layer.xml | 2 +- src/utils/IdealGraphVisualizer/Coordinator/pom.xml | 2 +- .../hotspot/igv/coordinator/OutlineTopComponentSettings.xml | 2 +- .../hotspot/igv/coordinator/OutlineTopComponentWstcref.xml | 2 +- .../sun/hotspot/igv/coordinator/StandardConfiguration.xml | 2 +- .../resources/com/sun/hotspot/igv/coordinator/layer.xml | 2 +- src/utils/IdealGraphVisualizer/Data/pom.xml | 2 +- .../sun/hotspot/igv/data/serialization/graphdocument.xsd | 2 +- src/utils/IdealGraphVisualizer/Difference/pom.xml | 2 +- src/utils/IdealGraphVisualizer/Filter/pom.xml | 2 +- .../src/main/resources/com/sun/hotspot/igv/filter/layer.xml | 2 +- src/utils/IdealGraphVisualizer/FilterWindow/pom.xml | 2 +- .../hotspot/igv/filterwindow/FilterTopComponentSettings.xml | 2 +- .../hotspot/igv/filterwindow/FilterTopComponentWstcref.xml | 2 +- .../resources/com/sun/hotspot/igv/filterwindow/layer.xml | 2 +- src/utils/IdealGraphVisualizer/Graph/pom.xml | 2 +- src/utils/IdealGraphVisualizer/HierarchicalLayout/pom.xml | 2 +- src/utils/IdealGraphVisualizer/Layout/pom.xml | 2 +- src/utils/IdealGraphVisualizer/NetworkConnection/pom.xml | 2 +- src/utils/IdealGraphVisualizer/SelectionCoordinator/pom.xml | 2 +- src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml | 2 +- .../resources/com/sun/hotspot/igv/servercompiler/layer.xml | 2 +- src/utils/IdealGraphVisualizer/Settings/pom.xml | 2 +- .../main/resources/com/sun/hotspot/igv/settings/layer.xml | 2 +- src/utils/IdealGraphVisualizer/Util/pom.xml | 2 +- src/utils/IdealGraphVisualizer/View/pom.xml | 2 +- .../src/main/resources/com/sun/hotspot/igv/view/layer.xml | 2 +- .../resources/com/sun/hotspot/igv/view/propertiesWsmode.xml | 2 +- .../com/sun/hotspot/igv/view/propertiesWstcref.xml | 2 +- src/utils/IdealGraphVisualizer/application/pom.xml | 2 +- src/utils/IdealGraphVisualizer/branding/pom.xml | 2 +- src/utils/IdealGraphVisualizer/pom.xml | 2 +- src/utils/LogCompilation/pom.xml | 6 +++--- 40 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml b/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml index e87ad7fb50998..0a4f81d4d4ad9 100644 --- a/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml +++ b/src/utils/IdealGraphVisualizer/Bytecodes/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml b/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml index d9469aba6b11c..50a58be99cd6c 100644 --- a/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml +++ b/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml b/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml index a680c8f02fe72..3e0a7c7db2e30 100644 --- a/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml +++ b/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/layer.xml b/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/layer.xml index c864c8d9269dd..ae88bac2414ae 100644 --- a/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/layer.xml +++ b/src/utils/IdealGraphVisualizer/Bytecodes/src/main/resources/com/sun/hotspot/igv/bytecodes/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/ControlFlow/pom.xml b/src/utils/IdealGraphVisualizer/ControlFlow/pom.xml index 9b77a418dd205..a75a439c011d1 100644 --- a/src/utils/IdealGraphVisualizer/ControlFlow/pom.xml +++ b/src/utils/IdealGraphVisualizer/ControlFlow/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentSettings.xml b/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentSettings.xml index e226cd5ece9ec..5ffb8213fbc5c 100644 --- a/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentSettings.xml +++ b/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentSettings.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentWstcref.xml b/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentWstcref.xml index 07bbb1f52fb3b..66bc3093c7ea6 100644 --- a/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentWstcref.xml +++ b/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/ControlFlowTopComponentWstcref.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/layer.xml b/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/layer.xml index 176712f1595e2..5e79cc22ee712 100644 --- a/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/layer.xml +++ b/src/utils/IdealGraphVisualizer/ControlFlow/src/main/resources/com/sun/hotspot/igv/controlflow/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Coordinator/pom.xml b/src/utils/IdealGraphVisualizer/Coordinator/pom.xml index e93c6d20a40e1..718ef67044e5c 100644 --- a/src/utils/IdealGraphVisualizer/Coordinator/pom.xml +++ b/src/utils/IdealGraphVisualizer/Coordinator/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentSettings.xml b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentSettings.xml index 1acdbcbe986e7..7f2a5a45a0f42 100644 --- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentSettings.xml +++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentSettings.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentWstcref.xml b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentWstcref.xml index 329140ea6bd6f..e0d1d62766cda 100644 --- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentWstcref.xml +++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/OutlineTopComponentWstcref.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml index ada940d0094ac..2412c5fed215a 100644 --- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml +++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/StandardConfiguration.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml index c4759676284c7..60e73788c952a 100644 --- a/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml +++ b/src/utils/IdealGraphVisualizer/Coordinator/src/main/resources/com/sun/hotspot/igv/coordinator/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Data/pom.xml b/src/utils/IdealGraphVisualizer/Data/pom.xml index 832be674e9885..90010dd700112 100644 --- a/src/utils/IdealGraphVisualizer/Data/pom.xml +++ b/src/utils/IdealGraphVisualizer/Data/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/resources/com/sun/hotspot/igv/data/serialization/graphdocument.xsd b/src/utils/IdealGraphVisualizer/Data/src/main/resources/com/sun/hotspot/igv/data/serialization/graphdocument.xsd index be576142ed45c..4e02fb64bb911 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/resources/com/sun/hotspot/igv/data/serialization/graphdocument.xsd +++ b/src/utils/IdealGraphVisualizer/Data/src/main/resources/com/sun/hotspot/igv/data/serialization/graphdocument.xsd @@ -1,6 +1,6 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Difference/pom.xml b/src/utils/IdealGraphVisualizer/Difference/pom.xml index d4605c6072722..d51896a5d969d 100644 --- a/src/utils/IdealGraphVisualizer/Difference/pom.xml +++ b/src/utils/IdealGraphVisualizer/Difference/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Filter/pom.xml b/src/utils/IdealGraphVisualizer/Filter/pom.xml index fa5089c8e65f8..e000c824f4f40 100644 --- a/src/utils/IdealGraphVisualizer/Filter/pom.xml +++ b/src/utils/IdealGraphVisualizer/Filter/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/layer.xml b/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/layer.xml index 32fe79fc1a8e2..0cd6bc645b6bd 100644 --- a/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/layer.xml +++ b/src/utils/IdealGraphVisualizer/Filter/src/main/resources/com/sun/hotspot/igv/filter/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/FilterWindow/pom.xml b/src/utils/IdealGraphVisualizer/FilterWindow/pom.xml index 1617e1a5fa7db..4a4034c864f0a 100644 --- a/src/utils/IdealGraphVisualizer/FilterWindow/pom.xml +++ b/src/utils/IdealGraphVisualizer/FilterWindow/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml b/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml index 6ae22f0fcd8e5..516361b0e88ce 100644 --- a/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml +++ b/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml b/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml index cc493bc5d6df7..29efbd5705d04 100644 --- a/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml +++ b/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/layer.xml b/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/layer.xml index aabc0e3829cac..72802a59b8a16 100644 --- a/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/layer.xml +++ b/src/utils/IdealGraphVisualizer/FilterWindow/src/main/resources/com/sun/hotspot/igv/filterwindow/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Graph/pom.xml b/src/utils/IdealGraphVisualizer/Graph/pom.xml index 3dba21fa7a048..d828c9140abe0 100644 --- a/src/utils/IdealGraphVisualizer/Graph/pom.xml +++ b/src/utils/IdealGraphVisualizer/Graph/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/HierarchicalLayout/pom.xml b/src/utils/IdealGraphVisualizer/HierarchicalLayout/pom.xml index 4a99ff829d5ad..64d1f8f58dc72 100644 --- a/src/utils/IdealGraphVisualizer/HierarchicalLayout/pom.xml +++ b/src/utils/IdealGraphVisualizer/HierarchicalLayout/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Layout/pom.xml b/src/utils/IdealGraphVisualizer/Layout/pom.xml index 6a046b5e6b871..42975afd54d65 100644 --- a/src/utils/IdealGraphVisualizer/Layout/pom.xml +++ b/src/utils/IdealGraphVisualizer/Layout/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/NetworkConnection/pom.xml b/src/utils/IdealGraphVisualizer/NetworkConnection/pom.xml index 93ffbcee64be6..b755fec8fc6c6 100644 --- a/src/utils/IdealGraphVisualizer/NetworkConnection/pom.xml +++ b/src/utils/IdealGraphVisualizer/NetworkConnection/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/SelectionCoordinator/pom.xml b/src/utils/IdealGraphVisualizer/SelectionCoordinator/pom.xml index cf813426bdea3..8dd8dda05af6b 100644 --- a/src/utils/IdealGraphVisualizer/SelectionCoordinator/pom.xml +++ b/src/utils/IdealGraphVisualizer/SelectionCoordinator/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml b/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml index 86980e79c50fc..59d4cce7a465a 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml index 24533b75af02f..808a281fee4e1 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/resources/com/sun/hotspot/igv/servercompiler/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Settings/pom.xml b/src/utils/IdealGraphVisualizer/Settings/pom.xml index 4003013bfa6eb..21f92b3001d9a 100644 --- a/src/utils/IdealGraphVisualizer/Settings/pom.xml +++ b/src/utils/IdealGraphVisualizer/Settings/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/Settings/src/main/resources/com/sun/hotspot/igv/settings/layer.xml b/src/utils/IdealGraphVisualizer/Settings/src/main/resources/com/sun/hotspot/igv/settings/layer.xml index 789b0ee8fd8a1..3573869405708 100644 --- a/src/utils/IdealGraphVisualizer/Settings/src/main/resources/com/sun/hotspot/igv/settings/layer.xml +++ b/src/utils/IdealGraphVisualizer/Settings/src/main/resources/com/sun/hotspot/igv/settings/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/Util/pom.xml b/src/utils/IdealGraphVisualizer/Util/pom.xml index bc27c79d17532..664ad35ef770b 100644 --- a/src/utils/IdealGraphVisualizer/Util/pom.xml +++ b/src/utils/IdealGraphVisualizer/Util/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/View/pom.xml b/src/utils/IdealGraphVisualizer/View/pom.xml index c66cb8c9a2430..2ffb98774cf8c 100644 --- a/src/utils/IdealGraphVisualizer/View/pom.xml +++ b/src/utils/IdealGraphVisualizer/View/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 IdealGraphVisualizer-parent diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/layer.xml b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/layer.xml index 4e0417884a2b5..d50f7c914ccfe 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/layer.xml +++ b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/layer.xml @@ -1,5 +1,5 @@ - + diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWsmode.xml b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWsmode.xml index 22540d0628be0..d5ba5b18fc143 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWsmode.xml +++ b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWsmode.xml @@ -2,7 +2,7 @@ + "https://www.netbeans.org/dtds/mode-properties2_0.dtd"> diff --git a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWstcref.xml b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWstcref.xml index a706bb6e26591..cfba9aebfce4c 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWstcref.xml +++ b/src/utils/IdealGraphVisualizer/View/src/main/resources/com/sun/hotspot/igv/view/propertiesWstcref.xml @@ -2,7 +2,7 @@ + "https://www.netbeans.org/dtds/tc-ref2_0.dtd"> diff --git a/src/utils/IdealGraphVisualizer/application/pom.xml b/src/utils/IdealGraphVisualizer/application/pom.xml index d202691a4ab1a..8266f2cf9e1b2 100644 --- a/src/utils/IdealGraphVisualizer/application/pom.xml +++ b/src/utils/IdealGraphVisualizer/application/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 com.sun.hotspot.igv diff --git a/src/utils/IdealGraphVisualizer/branding/pom.xml b/src/utils/IdealGraphVisualizer/branding/pom.xml index ed33298d3e4c5..522445d897823 100644 --- a/src/utils/IdealGraphVisualizer/branding/pom.xml +++ b/src/utils/IdealGraphVisualizer/branding/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 com.sun.hotspot.igv diff --git a/src/utils/IdealGraphVisualizer/pom.xml b/src/utils/IdealGraphVisualizer/pom.xml index 9363b05ae1f7f..772916540ff72 100644 --- a/src/utils/IdealGraphVisualizer/pom.xml +++ b/src/utils/IdealGraphVisualizer/pom.xml @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 com.sun.hotspot.igv IdealGraphVisualizer-parent diff --git a/src/utils/LogCompilation/pom.xml b/src/utils/LogCompilation/pom.xml index 1d8e0ffa1bda8..e033a3fbc073f 100644 --- a/src/utils/LogCompilation/pom.xml +++ b/src/utils/LogCompilation/pom.xml @@ -29,15 +29,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> - + 4.0.0 com.sun.hotspot.tools.compiler LogCompilation jar 1.0-SNAPSHOT LogCompilation - http://maven.apache.org + https://maven.apache.org junit From 40861761c2b0bb5ae548afc4752dc7cee3bf506a Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 10 Jan 2024 09:57:16 +0000 Subject: [PATCH 088/112] 8322987: Remove gc/stress/gclocker/TestGCLocker* since they always fail with OOME Reviewed-by: ayang, lmesnik --- test/hotspot/jtreg/ProblemList.txt | 3 - .../gc/stress/gclocker/TestGCLocker.java | 228 ------------------ .../stress/gclocker/TestGCLockerWithG1.java | 39 --- .../gclocker/TestGCLockerWithParallel.java | 39 --- .../gclocker/TestGCLockerWithSerial.java | 40 --- .../gclocker/TestGCLockerWithShenandoah.java | 64 ----- .../gc/stress/gclocker/libTestGCLocker.c | 35 --- 7 files changed, 448 deletions(-) delete mode 100644 test/hotspot/jtreg/gc/stress/gclocker/TestGCLocker.java delete mode 100644 test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithG1.java delete mode 100644 test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithParallel.java delete mode 100644 test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java delete mode 100644 test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java delete mode 100644 test/hotspot/jtreg/gc/stress/gclocker/libTestGCLocker.c diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 754cf68ba591f..4cb1ec5489880 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -89,9 +89,6 @@ gc/TestAllocHumongousFragment.java#iu-aggressive 8298781 generic-all gc/TestAllocHumongousFragment.java#g1 8298781 generic-all gc/TestAllocHumongousFragment.java#static 8298781 generic-all gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all -gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all -gc/stress/gclocker/TestGCLockerWithSerial.java 8180622 generic-all -gc/stress/gclocker/TestGCLockerWithShenandoah.java 8180622 generic-all gc/stress/TestStressG1Humongous.java 8286554 windows-x64 ############################################################################# diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLocker.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLocker.java deleted file mode 100644 index 36b9a59fde66a..0000000000000 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLocker.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2017, 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. - * - */ - -package gc.stress.gclocker; - -// Stress the GC locker by calling GetPrimitiveArrayCritical while -// concurrently filling up old gen. - -import java.lang.management.MemoryPoolMXBean; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryUsage; -import java.util.ArrayDeque; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Queue; - -final class ThreadUtils { - public static void sleep(long durationMS) { - try { - Thread.sleep(durationMS); - } catch (Exception e) { - } - } -} - -class Filler { - private static final int SIZE = 250000; - - private int[] i1 = new int[SIZE]; - private int[] i2 = new int[SIZE]; - private short[] s1 = new short[SIZE]; - private short[] s2 = new short[SIZE]; - - private Map map = new HashMap<>(); - - public Filler() { - for (int i = 0; i < 10000; i++) { - map.put(new Object(), new Object()); - } - } -} - -class Exitable { - private volatile boolean shouldExit = false; - - protected boolean shouldExit() { - return shouldExit; - } - - public void exit() { - shouldExit = true; - } -} - -class MemoryWatcher { - private MemoryPoolMXBean bean; - private final int thresholdPromille = 750; - private final int criticalThresholdPromille = 800; - private final long minGCWaitNanos = 1_000_000_000L; - private final long minFreeWaitElapsedNanos = 30L * 1_000_000_000L; - private final long minFreeCriticalWaitNanos; - - private int lastUsage = 0; - private long lastGCDetectedNanos = System.nanoTime(); - private long lastFreeNanos = System.nanoTime(); - - public MemoryWatcher(String mxBeanName, long minFreeCriticalWaitNanos) { - this.minFreeCriticalWaitNanos = minFreeCriticalWaitNanos; - List memoryBeans = ManagementFactory.getMemoryPoolMXBeans(); - for (MemoryPoolMXBean bean : memoryBeans) { - if (bean.getName().equals(mxBeanName)) { - this.bean = bean; - break; - } - } - } - - private int getMemoryUsage() { - if (bean == null) { - Runtime r = Runtime.getRuntime(); - float free = (float) r.freeMemory() / r.maxMemory(); - return Math.round((1 - free) * 1000); - } else { - MemoryUsage usage = bean.getUsage(); - float used = (float) usage.getUsed() / usage.getCommitted(); - return Math.round(used * 1000); - } - } - - public synchronized boolean shouldFreeUpSpace() { - int usage = getMemoryUsage(); - long nowNanos = System.nanoTime(); - - boolean detectedGC = false; - if (usage < lastUsage) { - lastGCDetectedNanos = nowNanos; - detectedGC = true; - } - - lastUsage = usage; - - long elapsedNanos = nowNanos - lastFreeNanos; - long timeSinceLastGCNanos = nowNanos - lastGCDetectedNanos; - - if (usage > criticalThresholdPromille && elapsedNanos > minFreeCriticalWaitNanos) { - lastFreeNanos = nowNanos; - return true; - } else if (usage > thresholdPromille && !detectedGC) { - if (elapsedNanos > minFreeWaitElapsedNanos || timeSinceLastGCNanos > minGCWaitNanos) { - lastFreeNanos = nowNanos; - return true; - } - } - - return false; - } -} - -class MemoryUser extends Exitable implements Runnable { - private final Queue cache = new ArrayDeque(); - private final MemoryWatcher watcher; - - private void load() { - if (watcher.shouldFreeUpSpace()) { - int toRemove = cache.size() / 5; - for (int i = 0; i < toRemove; i++) { - cache.remove(); - } - } - cache.add(new Filler()); - } - - public MemoryUser(String mxBeanName, long minFreeCriticalWaitNanos) { - watcher = new MemoryWatcher(mxBeanName, minFreeCriticalWaitNanos); - } - - @Override - public void run() { - for (int i = 0; i < 200; i++) { - load(); - } - - while (!shouldExit()) { - load(); - } - } -} - -class GCLockerStresser extends Exitable implements Runnable { - static native void fillWithRandomValues(byte[] array); - - @Override - public void run() { - byte[] array = new byte[1024 * 1024]; - while (!shouldExit()) { - fillWithRandomValues(array); - } - } -} - -public class TestGCLocker { - private static Exitable startGCLockerStresser(String name) { - GCLockerStresser task = new GCLockerStresser(); - - Thread thread = new Thread(task); - thread.setName(name); - thread.setPriority(Thread.MIN_PRIORITY); - thread.start(); - - return task; - } - - private static Exitable startMemoryUser(String mxBeanName, long minFreeCriticalWaitNanos) { - MemoryUser task = new MemoryUser(mxBeanName, minFreeCriticalWaitNanos); - - Thread thread = new Thread(task); - thread.setName("Memory User"); - thread.start(); - - return task; - } - - public static void main(String[] args) { - System.loadLibrary("TestGCLocker"); - - long durationMinutes = args.length > 0 ? Long.parseLong(args[0]) : 5; - String mxBeanName = args.length > 1 ? args[1] : null; - long minFreeCriticalWaitNanos = args.length > 2 - ? Integer.parseInt(args[2]) * 1_000_000L - : 500_000_000L; - - Exitable stresser1 = startGCLockerStresser("GCLockerStresser1"); - Exitable stresser2 = startGCLockerStresser("GCLockerStresser2"); - Exitable memoryUser = startMemoryUser(mxBeanName, minFreeCriticalWaitNanos); - - try { - Thread.sleep(durationMinutes * 60_000L); - } catch (InterruptedException e) { - throw new RuntimeException("Test Failure, did not except an InterruptedException", e); - } - - stresser1.exit(); - stresser2.exit(); - memoryUser.exit(); - } -} diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithG1.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithG1.java deleted file mode 100644 index a70a35daa63ea..0000000000000 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithG1.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017, 2020, 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 gc.stress.gclocker; - -/* - * @test TestGCLockerWithG1 - * @library / - * @requires vm.gc.G1 - * @summary Stress G1's GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen. - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UseG1GC gc.stress.gclocker.TestGCLockerWithG1 - */ -public class TestGCLockerWithG1 { - public static void main(String[] args) { - String[] testArgs = {"2", "G1 Old Gen"}; - TestGCLocker.main(testArgs); - } -} diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithParallel.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithParallel.java deleted file mode 100644 index eeee969a2521a..0000000000000 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithParallel.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2017, 2020, 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 gc.stress.gclocker; - -/* - * @test TestGCLockerWithParallel - * @library / - * @requires vm.gc.Parallel - * @summary Stress Parallel's GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen. - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UseParallelGC gc.stress.gclocker.TestGCLockerWithParallel - */ -public class TestGCLockerWithParallel { - public static void main(String[] args) { - String[] testArgs = {"2", "PS Old Gen"}; - TestGCLocker.main(testArgs); - } -} diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java deleted file mode 100644 index 9de8fa88ca708..0000000000000 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithSerial.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2017, 2020, 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 gc.stress.gclocker; - -/* - * @test TestGCLockerWithSerial - * @library / - * @requires vm.gc.Serial - * @requires vm.flavor != "minimal" - * @summary Stress Serial's GC locker by calling GetPrimitiveArrayCritical while concurrently filling up old gen. - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UseSerialGC gc.stress.gclocker.TestGCLockerWithSerial - */ -public class TestGCLockerWithSerial { - public static void main(String[] args) { - String[] testArgs = {"2", "Tenured Gen"}; - TestGCLocker.main(testArgs); - } -} diff --git a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java b/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java deleted file mode 100644 index 586fdc798817f..0000000000000 --- a/test/hotspot/jtreg/gc/stress/gclocker/TestGCLockerWithShenandoah.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2017, 2018, 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. - * - */ - -package gc.stress.gclocker; - -/* - * @test id=default - * @library / - * @requires vm.gc.Shenandoah - * @summary Stress Shenandoah's JNI handling by calling GetPrimitiveArrayCritical while concurrently filling up old gen. - * - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:+UseShenandoahGC - * -XX:+ShenandoahVerify - * gc.stress.gclocker.TestGCLockerWithShenandoah - * - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:+UseShenandoahGC - * gc.stress.gclocker.TestGCLockerWithShenandoah - */ - -/* - * @test id=aggressive - * @library / - * @requires vm.gc.Shenandoah - * @summary Stress Shenandoah's JNI handling by calling GetPrimitiveArrayCritical while concurrently filling up old gen. - * - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive - * -XX:+ShenandoahOOMDuringEvacALot - * gc.stress.gclocker.TestGCLockerWithShenandoah - * - * @run main/native/othervm/timeout=200 -Xlog:gc*=info -Xms1500m -Xmx1500m -XX:+UnlockExperimentalVMOptions -XX:+UnlockDiagnosticVMOptions - * -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=aggressive - * -XX:+ShenandoahAllocFailureALot - * gc.stress.gclocker.TestGCLockerWithShenandoah - */ -public class TestGCLockerWithShenandoah { - public static void main(String[] args) { - String[] testArgs = {"2", "Shenandoah", "0"}; - TestGCLocker.main(testArgs); - } -} diff --git a/test/hotspot/jtreg/gc/stress/gclocker/libTestGCLocker.c b/test/hotspot/jtreg/gc/stress/gclocker/libTestGCLocker.c deleted file mode 100644 index 2ac2064775c26..0000000000000 --- a/test/hotspot/jtreg/gc/stress/gclocker/libTestGCLocker.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017, 2019, 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. - */ - -#include - -JNIEXPORT void JNICALL -Java_gc_stress_gclocker_GCLockerStresser_fillWithRandomValues(JNIEnv* env, jclass clz, jbyteArray arr) { - jsize size = (*env)->GetArrayLength(env, arr); - jbyte* p = (*env)->GetPrimitiveArrayCritical(env, arr, NULL); - jsize i; - for (i = 0; i < size; i++) { - p[i] = i % 128; - } - (*env)->ReleasePrimitiveArrayCritical(env, arr, p, 0); -} From 9847086466359e330fdb7dceb29c7d31cf0242ce Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 10 Jan 2024 10:56:24 +0000 Subject: [PATCH 089/112] 8323499: Remove unused methods in space.hpp Reviewed-by: tschatzl --- src/hotspot/share/gc/shared/space.hpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 8299a7e628913..85f870ba1e2af 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -84,12 +84,6 @@ class Space: public CHeapObj { void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; } - // Returns true if this object has been allocated since a - // generation's "save_marks" call. - bool obj_allocated_since_save_marks(const oop obj) const { - return cast_from_oop(obj) >= saved_mark_word(); - } - // Returns a subregion of the space containing only the allocated objects in // the space. virtual MemRegion used_region() const = 0; @@ -304,7 +298,6 @@ class ContiguousSpace: public Space { // Addresses for inlined allocation HeapWord** top_addr() { return &_top; } - HeapWord** end_addr() { return &_end; } void print_on(outputStream* st) const override; From 8d9479910f587a2524a2d4068174f14e224ff2cf Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 10 Jan 2024 11:28:51 +0000 Subject: [PATCH 090/112] 8322828: Parallel: Rename ParallelCompactData::_region_start Reviewed-by: tschatzl, ehelin --- .../share/gc/parallel/psParallelCompact.cpp | 25 +++++----- .../share/gc/parallel/psParallelCompact.hpp | 49 +++++++++---------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 8946362026a29..e45b60851124f 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -415,8 +415,8 @@ print_initial_summary_data(ParallelCompactData& summary_data, #endif // #ifndef PRODUCT ParallelCompactData::ParallelCompactData() : - _region_start(nullptr), - DEBUG_ONLY(_region_end(nullptr) COMMA) + _heap_start(nullptr), + DEBUG_ONLY(_heap_end(nullptr) COMMA) _region_vspace(nullptr), _reserved_byte_size(0), _region_data(nullptr), @@ -425,16 +425,16 @@ ParallelCompactData::ParallelCompactData() : _block_data(nullptr), _block_count(0) {} -bool ParallelCompactData::initialize(MemRegion covered_region) +bool ParallelCompactData::initialize(MemRegion reserved_heap) { - _region_start = covered_region.start(); - const size_t region_size = covered_region.word_size(); - DEBUG_ONLY(_region_end = _region_start + region_size;) + _heap_start = reserved_heap.start(); + const size_t heap_size = reserved_heap.word_size(); + DEBUG_ONLY(_heap_end = _heap_start + heap_size;) - assert(region_align_down(_region_start) == _region_start, + assert(region_align_down(_heap_start) == _heap_start, "region start not aligned"); - bool result = initialize_region_data(region_size) && initialize_block_data(); + bool result = initialize_region_data(heap_size) && initialize_block_data(); return result; } @@ -467,12 +467,11 @@ ParallelCompactData::create_vspace(size_t count, size_t element_size) return 0; } -bool ParallelCompactData::initialize_region_data(size_t region_size) +bool ParallelCompactData::initialize_region_data(size_t heap_size) { - assert((region_size & RegionSizeOffsetMask) == 0, - "region size not a multiple of RegionSize"); + assert(is_aligned(heap_size, RegionSize), "precondition"); - const size_t count = region_size >> Log2RegionSize; + const size_t count = heap_size >> Log2RegionSize; _region_vspace = create_vspace(count, sizeof(RegionData)); if (_region_vspace != 0) { _region_data = (RegionData*)_region_vspace->reserved_low_addr(); @@ -530,7 +529,7 @@ HeapWord* ParallelCompactData::partial_obj_end(size_t region_idx) const void ParallelCompactData::add_obj(HeapWord* addr, size_t len) { - const size_t obj_ofs = pointer_delta(addr, _region_start); + const size_t obj_ofs = pointer_delta(addr, _heap_start); const size_t beg_region = obj_ofs >> Log2RegionSize; // end_region is inclusive const size_t end_region = (obj_ofs + len - 1) >> Log2RegionSize; diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 4cee322a589e4..173c883c498d4 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -399,7 +399,7 @@ class ParallelCompactData public: ParallelCompactData(); - bool initialize(MemRegion covered_region); + bool initialize(MemRegion reserved_heap); size_t region_count() const { return _region_count; } size_t reserved_byte_size() const { return _reserved_byte_size; } @@ -481,13 +481,12 @@ class ParallelCompactData private: bool initialize_block_data(); - bool initialize_region_data(size_t region_size); + bool initialize_region_data(size_t heap_size); PSVirtualSpace* create_vspace(size_t count, size_t element_size); -private: - HeapWord* _region_start; + HeapWord* _heap_start; #ifdef ASSERT - HeapWord* _region_end; + HeapWord* _heap_end; #endif // #ifdef ASSERT PSVirtualSpace* _region_vspace; @@ -662,18 +661,18 @@ ParallelCompactData::block(size_t n) const { inline size_t ParallelCompactData::region_offset(const HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); + assert(addr >= _heap_start, "bad addr"); // would mistakenly return 0 for _region_end - assert(addr < _region_end, "bad addr"); + assert(addr < _heap_end, "bad addr"); return (size_t(addr) & RegionAddrOffsetMask) >> LogHeapWordSize; } inline size_t ParallelCompactData::addr_to_region_idx(const HeapWord* addr) const { - assert(addr >= _region_start, "bad addr " PTR_FORMAT " _region_start " PTR_FORMAT, p2i(addr), p2i(_region_start)); - assert(addr <= _region_end, "bad addr " PTR_FORMAT " _region_end " PTR_FORMAT, p2i(addr), p2i(_region_end)); - return pointer_delta(addr, _region_start) >> Log2RegionSize; + assert(addr >= _heap_start, "bad addr " PTR_FORMAT " _region_start " PTR_FORMAT, p2i(addr), p2i(_heap_start)); + assert(addr <= _heap_end, "bad addr " PTR_FORMAT " _region_end " PTR_FORMAT, p2i(addr), p2i(_heap_end)); + return pointer_delta(addr, _heap_start) >> Log2RegionSize; } inline ParallelCompactData::RegionData* @@ -686,7 +685,7 @@ inline HeapWord* ParallelCompactData::region_to_addr(size_t region) const { assert(region <= _region_count, "region out of range"); - return _region_start + (region << Log2RegionSize); + return _heap_start + (region << Log2RegionSize); } inline HeapWord* @@ -707,16 +706,16 @@ ParallelCompactData::region_to_addr(size_t region, size_t offset) const inline HeapWord* ParallelCompactData::region_align_down(HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); - assert(addr < _region_end + RegionSize, "bad addr"); + assert(addr >= _heap_start, "bad addr"); + assert(addr < _heap_end + RegionSize, "bad addr"); return (HeapWord*)(size_t(addr) & RegionAddrMask); } inline HeapWord* ParallelCompactData::region_align_up(HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); - assert(addr <= _region_end, "bad addr"); + assert(addr >= _heap_start, "bad addr"); + assert(addr <= _heap_end, "bad addr"); return region_align_down(addr + RegionSizeOffsetMask); } @@ -729,17 +728,17 @@ ParallelCompactData::is_region_aligned(HeapWord* addr) const inline size_t ParallelCompactData::block_offset(const HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); - assert(addr <= _region_end, "bad addr"); + assert(addr >= _heap_start, "bad addr"); + assert(addr <= _heap_end, "bad addr"); return (size_t(addr) & BlockAddrOffsetMask) >> LogHeapWordSize; } inline size_t ParallelCompactData::addr_to_block_idx(const HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); - assert(addr <= _region_end, "bad addr"); - return pointer_delta(addr, _region_start) >> Log2BlockSize; + assert(addr >= _heap_start, "bad addr"); + assert(addr <= _heap_end, "bad addr"); + return pointer_delta(addr, _heap_start) >> Log2BlockSize; } inline ParallelCompactData::BlockData* @@ -752,7 +751,7 @@ inline HeapWord* ParallelCompactData::block_to_addr(size_t block) const { assert(block < _block_count, "block out of range"); - return _region_start + (block << Log2BlockSize); + return _heap_start + (block << Log2BlockSize); } inline size_t @@ -764,16 +763,16 @@ ParallelCompactData::region_to_block_idx(size_t region) const inline HeapWord* ParallelCompactData::block_align_down(HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); - assert(addr < _region_end + RegionSize, "bad addr"); + assert(addr >= _heap_start, "bad addr"); + assert(addr < _heap_end + RegionSize, "bad addr"); return (HeapWord*)(size_t(addr) & BlockAddrMask); } inline HeapWord* ParallelCompactData::block_align_up(HeapWord* addr) const { - assert(addr >= _region_start, "bad addr"); - assert(addr <= _region_end, "bad addr"); + assert(addr >= _heap_start, "bad addr"); + assert(addr <= _heap_end, "bad addr"); return block_align_down(addr + BlockSizeOffsetMask); } From 88dafe564f163ed738a8cb6adc449b94e606999f Mon Sep 17 00:00:00 2001 From: Guoxiong Li Date: Wed, 10 Jan 2024 12:15:38 +0000 Subject: [PATCH 091/112] 8314629: Generational ZGC: Clearing All SoftReferences log line lacks GCId Reviewed-by: eosterlund, tschatzl --- src/hotspot/share/gc/z/zReferenceProcessor.cpp | 8 +++++++- src/hotspot/share/gc/z/zReferenceProcessor.hpp | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.cpp b/src/hotspot/share/gc/z/zReferenceProcessor.cpp index 1037093523dd6..df8cb2b0e959f 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp @@ -113,6 +113,7 @@ static void list_append(zaddress& head, zaddress& tail, zaddress reference) { ZReferenceProcessor::ZReferenceProcessor(ZWorkers* workers) : _workers(workers), _soft_reference_policy(nullptr), + _clear_all_soft_refs(false), _encountered_count(), _discovered_count(), _enqueued_count(), @@ -124,8 +125,9 @@ void ZReferenceProcessor::set_soft_reference_policy(bool clear) { static AlwaysClearPolicy always_clear_policy; static LRUMaxHeapPolicy lru_max_heap_policy; + _clear_all_soft_refs = clear; + if (clear) { - log_info(gc, ref)("Clearing All SoftReferences"); _soft_reference_policy = &always_clear_policy; } else { _soft_reference_policy = &lru_max_heap_policy; @@ -438,6 +440,10 @@ class ZReferenceProcessorTask : public ZTask { void ZReferenceProcessor::process_references() { ZStatTimerOld timer(ZSubPhaseConcurrentReferencesProcess); + if (_clear_all_soft_refs) { + log_info(gc, ref)("Clearing All SoftReferences"); + } + // Process discovered lists ZReferenceProcessorTask task(this); _workers->run(&task); diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.hpp b/src/hotspot/share/gc/z/zReferenceProcessor.hpp index d39cc8634cd22..7a8900827da83 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.hpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.hpp @@ -41,6 +41,7 @@ class ZReferenceProcessor : public ReferenceDiscoverer { ZWorkers* const _workers; ReferencePolicy* _soft_reference_policy; + bool _clear_all_soft_refs; ZPerWorker _encountered_count; ZPerWorker _discovered_count; ZPerWorker _enqueued_count; From 2e472fe7ea98ca1f07a90d1ad6704e8b2bb3afcf Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Wed, 10 Jan 2024 12:18:01 +0000 Subject: [PATCH 092/112] 8322294: Cleanup NativePostCallNop Reviewed-by: mdoerr, aph --- src/hotspot/cpu/aarch64/frame_aarch64.hpp | 2 -- .../cpu/aarch64/frame_aarch64.inline.hpp | 14 ------------- .../cpu/aarch64/nativeInst_aarch64.cpp | 13 ++++++++---- .../cpu/aarch64/nativeInst_aarch64.hpp | 14 ++++++++----- src/hotspot/cpu/arm/frame_arm.hpp | 2 -- src/hotspot/cpu/arm/frame_arm.inline.hpp | 14 ------------- src/hotspot/cpu/arm/nativeInst_arm_32.cpp | 4 ---- src/hotspot/cpu/arm/nativeInst_arm_32.hpp | 4 ++-- src/hotspot/cpu/ppc/frame_ppc.hpp | 2 -- src/hotspot/cpu/ppc/frame_ppc.inline.hpp | 14 ------------- src/hotspot/cpu/ppc/nativeInst_ppc.cpp | 4 ---- src/hotspot/cpu/ppc/nativeInst_ppc.hpp | 4 ++-- src/hotspot/cpu/riscv/frame_riscv.hpp | 2 -- src/hotspot/cpu/riscv/frame_riscv.inline.hpp | 14 ------------- src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 21 ++++++++++++++----- src/hotspot/cpu/riscv/nativeInst_riscv.hpp | 4 ++-- src/hotspot/cpu/s390/frame_s390.hpp | 1 - src/hotspot/cpu/s390/frame_s390.inline.hpp | 14 ------------- src/hotspot/cpu/s390/nativeInst_s390.hpp | 4 ++-- src/hotspot/cpu/x86/frame_x86.hpp | 2 -- src/hotspot/cpu/x86/frame_x86.inline.hpp | 14 ------------- src/hotspot/cpu/x86/nativeInst_x86.cpp | 11 +++++++--- src/hotspot/cpu/x86/nativeInst_x86.hpp | 12 +++++++++-- src/hotspot/cpu/zero/frame_zero.hpp | 2 -- src/hotspot/cpu/zero/frame_zero.inline.hpp | 5 ----- src/hotspot/cpu/zero/nativeInst_zero.hpp | 4 ++-- src/hotspot/share/code/codeCache.inline.hpp | 14 +++++++------ src/hotspot/share/code/nmethod.cpp | 5 +---- src/hotspot/share/runtime/frame.hpp | 2 ++ src/hotspot/share/runtime/frame.inline.hpp | 13 ++++++++++++ 30 files changed, 86 insertions(+), 149 deletions(-) diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.hpp index 558bd80a0e0c2..099dcdb4f2b16 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.hpp @@ -156,8 +156,6 @@ static void verify_deopt_original_pc( CompiledMethod* nm, intptr_t* unextended_sp); #endif - const ImmutableOopMap* get_oop_map() const; - public: // Constructors diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index 5c850c6bcbd65..d3ae7871f61f2 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -359,20 +359,6 @@ inline int frame::sender_sp_ret_address_offset() { return frame::sender_sp_offset - frame::return_addr_offset; } -inline const ImmutableOopMap* frame::get_oop_map() const { - if (_cb == nullptr) return nullptr; - if (_cb->oop_maps() != nullptr) { - NativePostCallNop* nop = nativePostCallNop_at(_pc); - if (nop != nullptr && nop->displacement() != 0) { - int slot = ((nop->displacement() >> 24) & 0xff); - return _cb->oop_map_for_slot(slot, _pc); - } - const ImmutableOopMap* oop_map = OopMapSet::find_map(this); - return oop_map; - } - return nullptr; -} - //------------------------------------------------------------------------------ // frame::sender inline frame frame::sender(RegisterMap* map) const { diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 27bf35e12c87a..a12caa3daeefb 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -560,18 +560,23 @@ static bool is_movk_to_zr(uint32_t insn) { } #endif -void NativePostCallNop::patch(jint diff) { +bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { + if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) { + return false; // cannot encode + } + uint32_t data = ((uint32_t)oopmap_slot << 24) | cb_offset; #ifdef ASSERT - assert(diff != 0, "must be"); + assert(data != 0, "must be"); uint32_t insn1 = uint_at(4); uint32_t insn2 = uint_at(8); assert (is_movk_to_zr(insn1) && is_movk_to_zr(insn2), "must be"); #endif - uint32_t lo = diff & 0xffff; - uint32_t hi = (uint32_t)diff >> 16; + uint32_t lo = data & 0xffff; + uint32_t hi = data >> 16; Instruction_aarch64::patch(addr_at(4), 20, 5, lo); Instruction_aarch64::patch(addr_at(8), 20, 5, hi); + return true; // successfully encoded } void NativeDeoptInstruction::verify() { diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp index 1740fde772f0f..c0be84d3f5ce6 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp @@ -691,16 +691,20 @@ class NativePostCallNop: public NativeInstruction { return (insns & 0xffe0001fffffffff) == 0xf280001fd503201f; } - jint displacement() const { + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { uint64_t movk_insns = *(uint64_t*)addr_at(4); uint32_t lo = (movk_insns >> 5) & 0xffff; uint32_t hi = (movk_insns >> (5 + 32)) & 0xffff; - uint32_t result = (hi << 16) | lo; - - return (jint)result; + uint32_t data = (hi << 16) | lo; + if (data == 0) { + return false; // no information encoded + } + cb_offset = (data & 0xffffff); + oopmap_slot = (data >> 24) & 0xff; + return true; // decoding succeeded } - void patch(jint diff); + bool patch(int32_t oopmap_slot, int32_t cb_offset); void make_deopt(); }; diff --git a/src/hotspot/cpu/arm/frame_arm.hpp b/src/hotspot/cpu/arm/frame_arm.hpp index 7ef941ad0ff78..56f8fc9932e84 100644 --- a/src/hotspot/cpu/arm/frame_arm.hpp +++ b/src/hotspot/cpu/arm/frame_arm.hpp @@ -99,8 +99,6 @@ } #endif - const ImmutableOopMap* get_oop_map() const; - public: // Constructors diff --git a/src/hotspot/cpu/arm/frame_arm.inline.hpp b/src/hotspot/cpu/arm/frame_arm.inline.hpp index 43cc523658b5a..8a08c0d0e9c43 100644 --- a/src/hotspot/cpu/arm/frame_arm.inline.hpp +++ b/src/hotspot/cpu/arm/frame_arm.inline.hpp @@ -218,20 +218,6 @@ inline int frame::frame_size() const { return sender_sp() - sp(); } -inline const ImmutableOopMap* frame::get_oop_map() const { - if (_cb == nullptr) return nullptr; - if (_cb->oop_maps() != nullptr) { - NativePostCallNop* nop = nativePostCallNop_at(_pc); - if (nop != nullptr && nop->displacement() != 0) { - int slot = ((nop->displacement() >> 24) & 0xff); - return _cb->oop_map_for_slot(slot, _pc); - } - const ImmutableOopMap* oop_map = OopMapSet::find_map(this); - return oop_map; - } - return nullptr; -} - inline int frame::compiled_frame_stack_argsize() const { Unimplemented(); return 0; diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp index 429a0c000f637..23ee01d335264 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp @@ -341,10 +341,6 @@ void NativePostCallNop::make_deopt() { NativeDeoptInstruction::insert(addr_at(0)); } -void NativePostCallNop::patch(jint diff) { - // unsupported for now -} - void NativeDeoptInstruction::verify() { } diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index a7a51f017d22d..7006d7709813a 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -438,8 +438,8 @@ inline NativeCall* nativeCall_before(address return_address) { class NativePostCallNop: public NativeInstruction { public: bool check() const { return is_nop(); } - int displacement() const { return 0; } - void patch(jint diff); + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { return false; } + bool patch(int32_t oopmap_slot, int32_t cb_offset) { return false; } void make_deopt(); }; diff --git a/src/hotspot/cpu/ppc/frame_ppc.hpp b/src/hotspot/cpu/ppc/frame_ppc.hpp index e2e2b9d015dde..d2c9927f119ee 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.hpp +++ b/src/hotspot/cpu/ppc/frame_ppc.hpp @@ -400,8 +400,6 @@ public: - const ImmutableOopMap* get_oop_map() const; - // Constructors inline frame(intptr_t* sp, intptr_t* fp, address pc); inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp = nullptr, intptr_t* fp = nullptr, CodeBlob* cb = nullptr); diff --git a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp index 861c6adc491e4..220b9c3241e01 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/frame_ppc.inline.hpp @@ -361,20 +361,6 @@ inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) { *result_adr = obj; } -inline const ImmutableOopMap* frame::get_oop_map() const { - if (_cb == nullptr) return nullptr; - if (_cb->oop_maps() != nullptr) { - NativePostCallNop* nop = nativePostCallNop_at(_pc); - if (nop != nullptr && nop->displacement() != 0) { - int slot = ((nop->displacement() >> 24) & 0xff); - return _cb->oop_map_for_slot(slot, _pc); - } - const ImmutableOopMap* oop_map = OopMapSet::find_map(this); - return oop_map; - } - return nullptr; -} - inline int frame::compiled_frame_stack_argsize() const { assert(cb()->is_compiled(), ""); return (cb()->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord; diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp index f60f3f147ae09..06754ccfdd7d2 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp @@ -429,10 +429,6 @@ void NativePostCallNop::make_deopt() { NativeDeoptInstruction::insert(addr_at(0)); } -void NativePostCallNop::patch(jint diff) { - // unsupported for now -} - void NativeDeoptInstruction::verify() { } diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp index 378f4ea928a57..ec6f5a90a7211 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp @@ -508,8 +508,8 @@ class NativeMovRegMem: public NativeInstruction { class NativePostCallNop: public NativeInstruction { public: bool check() const { return is_nop(); } - int displacement() const { return 0; } - void patch(jint diff); + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { return false; } + bool patch(int32_t oopmap_slot, int32_t cb_offset) { return false; } void make_deopt(); }; diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp index ae6242a75bdd8..0c0659d1eee13 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.hpp +++ b/src/hotspot/cpu/riscv/frame_riscv.hpp @@ -189,8 +189,6 @@ static void verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp); #endif - const ImmutableOopMap* get_oop_map() const; - public: // Constructors diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp index 37f273be6c19b..33727a8c6d0a7 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp @@ -345,20 +345,6 @@ inline int frame::sender_sp_ret_address_offset() { return frame::sender_sp_offset - frame::return_addr_offset; } -inline const ImmutableOopMap* frame::get_oop_map() const { - if (_cb == nullptr) return nullptr; - if (_cb->oop_maps() != nullptr) { - NativePostCallNop* nop = nativePostCallNop_at(_pc); - if (nop != nullptr && nop->displacement() != 0) { - int slot = ((nop->displacement() >> 24) & 0xff); - return _cb->oop_map_for_slot(slot, _pc); - } - const ImmutableOopMap* oop_map = OopMapSet::find_map(this); - return oop_map; - } - return nullptr; -} - //------------------------------------------------------------------------------ // frame::sender frame frame::sender(RegisterMap* map) const { diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 2b2e5606c81ea..c29ac1a04fae1 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -451,16 +451,27 @@ void NativePostCallNop::make_deopt() { NativeDeoptInstruction::insert(addr_at(0)); } -int NativePostCallNop::displacement() const { +bool NativePostCallNop::decode(int32_t& oopmap_slot, int32_t& cb_offset) const { // Discard the high 32 bits - return (int)(intptr_t)MacroAssembler::get_target_of_li32(addr_at(4)); + int32_t data = (int32_t)(intptr_t)MacroAssembler::get_target_of_li32(addr_at(4)); + if (data == 0) { + return false; // no information encoded + } + cb_offset = (data & 0xffffff); + oopmap_slot = (data >> 24) & 0xff; + return true; // decoding succeeded } -void NativePostCallNop::patch(jint diff) { - assert(diff != 0, "must be"); +bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { + if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) { + return false; // cannot encode + } + int32_t data = (oopmap_slot << 24) | cb_offset; + assert(data != 0, "must be"); assert(is_lui_to_zr_at(addr_at(4)) && is_addiw_to_zr_at(addr_at(8)), "must be"); - MacroAssembler::patch_imm_in_li32(addr_at(4), diff); + MacroAssembler::patch_imm_in_li32(addr_at(4), data); + return true; // successfully encoded } void NativeDeoptInstruction::verify() { diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index 3c6ec1cf588b3..48bbb2b3b181d 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -591,8 +591,8 @@ class NativePostCallNop: public NativeInstruction { // an addiw as well. return is_nop() && is_lui_to_zr_at(addr_at(4)); } - int displacement() const; - void patch(jint diff); + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const; + bool patch(int32_t oopmap_slot, int32_t cb_offset); void make_deopt(); }; diff --git a/src/hotspot/cpu/s390/frame_s390.hpp b/src/hotspot/cpu/s390/frame_s390.hpp index 3f81cd254d080..06433d9136fdc 100644 --- a/src/hotspot/cpu/s390/frame_s390.hpp +++ b/src/hotspot/cpu/s390/frame_s390.hpp @@ -465,7 +465,6 @@ // Initialize frame members (_pc and _sp must be given) inline void setup(); - const ImmutableOopMap* get_oop_map() const; // Constructors diff --git a/src/hotspot/cpu/s390/frame_s390.inline.hpp b/src/hotspot/cpu/s390/frame_s390.inline.hpp index 91a6917c3191e..178f7f908491c 100644 --- a/src/hotspot/cpu/s390/frame_s390.inline.hpp +++ b/src/hotspot/cpu/s390/frame_s390.inline.hpp @@ -292,20 +292,6 @@ inline intptr_t* frame::real_fp() const { return fp(); } -inline const ImmutableOopMap* frame::get_oop_map() const { - if (_cb == nullptr) return nullptr; - if (_cb->oop_maps() != nullptr) { - NativePostCallNop* nop = nativePostCallNop_at(_pc); - if (nop != nullptr && nop->displacement() != 0) { - int slot = ((nop->displacement() >> 24) & 0xff); - return _cb->oop_map_for_slot(slot, _pc); - } - const ImmutableOopMap* oop_map = OopMapSet::find_map(this); - return oop_map; - } - return nullptr; -} - inline int frame::compiled_frame_stack_argsize() const { Unimplemented(); return 0; diff --git a/src/hotspot/cpu/s390/nativeInst_s390.hpp b/src/hotspot/cpu/s390/nativeInst_s390.hpp index 65bfe4993705e..abad50da8b421 100644 --- a/src/hotspot/cpu/s390/nativeInst_s390.hpp +++ b/src/hotspot/cpu/s390/nativeInst_s390.hpp @@ -657,8 +657,8 @@ class NativeGeneralJump: public NativeInstruction { class NativePostCallNop: public NativeInstruction { public: bool check() const { Unimplemented(); return false; } - int displacement() const { return 0; } - void patch(jint diff) { Unimplemented(); } + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { return false; } + bool patch(int32_t oopmap_slot, int32_t cb_offset) { Unimplemented(); return false; } void make_deopt() { Unimplemented(); } }; diff --git a/src/hotspot/cpu/x86/frame_x86.hpp b/src/hotspot/cpu/x86/frame_x86.hpp index 122f640a92a35..44c8574c54002 100644 --- a/src/hotspot/cpu/x86/frame_x86.hpp +++ b/src/hotspot/cpu/x86/frame_x86.hpp @@ -149,8 +149,6 @@ static void verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp); #endif - const ImmutableOopMap* get_oop_map() const; - public: // Constructors diff --git a/src/hotspot/cpu/x86/frame_x86.inline.hpp b/src/hotspot/cpu/x86/frame_x86.inline.hpp index 70008e1011779..f69803d579d43 100644 --- a/src/hotspot/cpu/x86/frame_x86.inline.hpp +++ b/src/hotspot/cpu/x86/frame_x86.inline.hpp @@ -343,20 +343,6 @@ inline int frame::sender_sp_ret_address_offset() { return frame::sender_sp_offset - frame::return_addr_offset; } -inline const ImmutableOopMap* frame::get_oop_map() const { - if (_cb == nullptr) return nullptr; - if (_cb->oop_maps() != nullptr) { - NativePostCallNop* nop = nativePostCallNop_at(_pc); - if (nop != nullptr && nop->displacement() != 0) { - int slot = ((nop->displacement() >> 24) & 0xff); - return _cb->oop_map_for_slot(slot, _pc); - } - const ImmutableOopMap* oop_map = OopMapSet::find_map(this); - return oop_map; - } - return nullptr; -} - //------------------------------------------------------------------------------ // frame::sender diff --git a/src/hotspot/cpu/x86/nativeInst_x86.cpp b/src/hotspot/cpu/x86/nativeInst_x86.cpp index 1df8c78c99d57..b59f424625636 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.cpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.cpp @@ -684,10 +684,15 @@ void NativePostCallNop::make_deopt() { ICache::invalidate_range(instr_addr, instruction_size); } -void NativePostCallNop::patch(jint diff) { - assert(diff != 0, "must be"); +bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { + if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) { + return false; // cannot encode + } + int32_t data = (oopmap_slot << 24) | cb_offset; + assert(data != 0, "must be"); int32_t *code_pos = (int32_t *) addr_at(displacement_offset); - *((int32_t *)(code_pos)) = (int32_t) diff; + *((int32_t *)(code_pos)) = (int32_t) data; + return true; // successfully encoded } void NativeDeoptInstruction::verify() { diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp index 938a10cb63d75..f8cbf70f18961 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.hpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp @@ -735,8 +735,16 @@ class NativePostCallNop: public NativeInstruction { }; bool check() const { return int_at(0) == 0x841f0f; } - int displacement() const { return (jint) int_at(displacement_offset); } - void patch(jint diff); + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { + int32_t data = int_at(displacement_offset); + if (data == 0) { + return false; // no information encoded + } + cb_offset = (data & 0xffffff); + oopmap_slot = (data >> 24) & 0xff; + return true; // decoding succeeded + } + bool patch(int32_t oopmap_slot, int32_t cb_offset); void make_deopt(); }; diff --git a/src/hotspot/cpu/zero/frame_zero.hpp b/src/hotspot/cpu/zero/frame_zero.hpp index 87511ab212e1f..a4815d2c10ba9 100644 --- a/src/hotspot/cpu/zero/frame_zero.hpp +++ b/src/hotspot/cpu/zero/frame_zero.hpp @@ -44,8 +44,6 @@ align_wiggle = 1 }; - const ImmutableOopMap* get_oop_map() const; - // Constructor public: frame(ZeroFrame* zeroframe, intptr_t* sp); diff --git a/src/hotspot/cpu/zero/frame_zero.inline.hpp b/src/hotspot/cpu/zero/frame_zero.inline.hpp index 1b504cfa6663e..944084f70af40 100644 --- a/src/hotspot/cpu/zero/frame_zero.inline.hpp +++ b/src/hotspot/cpu/zero/frame_zero.inline.hpp @@ -176,11 +176,6 @@ inline intptr_t* frame::unextended_sp() const { return (intptr_t *) -1; } -inline const ImmutableOopMap* frame::get_oop_map() const { - Unimplemented(); - return nullptr; -} - inline int frame::compiled_frame_stack_argsize() const { Unimplemented(); return 0; diff --git a/src/hotspot/cpu/zero/nativeInst_zero.hpp b/src/hotspot/cpu/zero/nativeInst_zero.hpp index 5b2c9743cf904..77a7d511ac5e8 100644 --- a/src/hotspot/cpu/zero/nativeInst_zero.hpp +++ b/src/hotspot/cpu/zero/nativeInst_zero.hpp @@ -214,8 +214,8 @@ inline NativeGeneralJump* nativeGeneralJump_at(address address) { class NativePostCallNop: public NativeInstruction { public: bool check() const { Unimplemented(); return false; } - int displacement() const { Unimplemented(); return 0; } - void patch(jint diff) { Unimplemented(); } + bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { Unimplemented(); return false; } + bool patch(int32_t oopmap_slot, int32_t cb_offset) { Unimplemented(); return false; } void make_deopt() { Unimplemented(); } }; diff --git a/src/hotspot/share/code/codeCache.inline.hpp b/src/hotspot/share/code/codeCache.inline.hpp index bea66cf00106a..5ab7187cd2685 100644 --- a/src/hotspot/share/code/codeCache.inline.hpp +++ b/src/hotspot/share/code/codeCache.inline.hpp @@ -37,10 +37,9 @@ inline CodeBlob* CodeCache::find_blob_fast(void* pc) { inline CodeBlob* CodeCache::find_blob_and_oopmap(void* pc, int& slot) { NativePostCallNop* nop = nativePostCallNop_at((address) pc); CodeBlob* cb; - if (nop != nullptr && nop->displacement() != 0) { - int offset = (nop->displacement() & 0xffffff); + int offset; + if (nop != nullptr && nop->decode(slot, offset)) { cb = (CodeBlob*) ((address) pc - offset); - slot = ((nop->displacement() >> 24) & 0xff); assert(cb == CodeCache::find_blob(pc), "must be"); } else { cb = CodeCache::find_blob(pc); @@ -52,9 +51,12 @@ inline CodeBlob* CodeCache::find_blob_and_oopmap(void* pc, int& slot) { inline int CodeCache::find_oopmap_slot_fast(void* pc) { NativePostCallNop* nop = nativePostCallNop_at((address) pc); - return (nop != nullptr && nop->displacement() != 0) - ? ((nop->displacement() >> 24) & 0xff) - : -1; + int oopmap_slot; + int cb_offset; + if (nop != nullptr && nop->decode(oopmap_slot, cb_offset)) { + return oopmap_slot; + } + return -1; } #endif // SHARE_VM_COMPILER_CODECACHE_INLINE_HPP diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index cb185446cccb2..b18077fddfdef 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1137,10 +1137,7 @@ static void install_post_call_nop_displacement(nmethod* nm, address pc) { int oopmap_slot = nm->oop_maps()->find_slot_for_offset(int((intptr_t) pc - (intptr_t) nm->code_begin())); if (oopmap_slot < 0) { // this can happen at asynchronous (non-safepoint) stackwalks log_debug(codecache)("failed to find oopmap for cb: " INTPTR_FORMAT " offset: %d", cbaddr, (int) offset); - } else if (((oopmap_slot & 0xff) == oopmap_slot) && ((offset & 0xffffff) == offset)) { - jint value = (oopmap_slot << 24) | (jint) offset; - nop->patch(value); - } else { + } else if (!nop->patch(oopmap_slot, offset)) { log_debug(codecache)("failed to encode %d %d", oopmap_slot, (int) offset); } } diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp index dc5177942c450..4d5777059e008 100644 --- a/src/hotspot/share/runtime/frame.hpp +++ b/src/hotspot/share/runtime/frame.hpp @@ -90,6 +90,8 @@ class frame { void assert_offset() const { assert(_frame_index >= 0, "Using offset with a non-chunk frame"); assert_on_heap(); } void assert_absolute() const { assert(_frame_index == -1, "Using absolute addresses with a chunk frame"); } + const ImmutableOopMap* get_oop_map() const; + public: // Constructors frame(); diff --git a/src/hotspot/share/runtime/frame.inline.hpp b/src/hotspot/share/runtime/frame.inline.hpp index 2cfaba170540d..da774fe1620e4 100644 --- a/src/hotspot/share/runtime/frame.inline.hpp +++ b/src/hotspot/share/runtime/frame.inline.hpp @@ -104,6 +104,19 @@ inline CodeBlob* frame::get_cb() const { return _cb; } +inline const ImmutableOopMap* frame::get_oop_map() const { + if (_cb == nullptr || _cb->oop_maps() == nullptr) return nullptr; + + NativePostCallNop* nop = nativePostCallNop_at(_pc); + int oopmap_slot; + int cb_offset; + if (nop != nullptr && nop->decode(oopmap_slot, cb_offset)) { + return _cb->oop_map_for_slot(oopmap_slot, _pc); + } + const ImmutableOopMap* oop_map = OopMapSet::find_map(this); + return oop_map; +} + inline int frame::interpreter_frame_monitor_size_in_bytes() { // Number of bytes for a monitor. return frame::interpreter_frame_monitor_size() * wordSize; From 679f526d89f679b1f42a1a4acdecf93686bde8a4 Mon Sep 17 00:00:00 2001 From: Guoxiong Li Date: Wed, 10 Jan 2024 12:18:12 +0000 Subject: [PATCH 093/112] 8322278: Generational ZGC: Adjust the comment of ZHeuristics::use_per_cpu_shared_small_pages Reviewed-by: eosterlund --- src/hotspot/share/gc/z/zHeuristics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/z/zHeuristics.cpp b/src/hotspot/share/gc/z/zHeuristics.cpp index bcd9dd844052b..df2f5f68489cc 100644 --- a/src/hotspot/share/gc/z/zHeuristics.cpp +++ b/src/hotspot/share/gc/z/zHeuristics.cpp @@ -60,8 +60,8 @@ size_t ZHeuristics::relocation_headroom() { } bool ZHeuristics::use_per_cpu_shared_small_pages() { - // Use per-CPU shared small pages only if these pages occupy at most 3.125% - // of the max heap size. Otherwise fall back to using a single shared small + // Use per-CPU shared small pages only if these pages don't have a significant + // heap overhead. Otherwise fall back to using a single shared small // page. This is useful when using small heaps on large machines. const size_t per_cpu_share = significant_heap_overhead() / ZCPU::count(); return per_cpu_share >= ZPageSizeSmall; From b2a39c576706622b624314c89fa6d10d0b422f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 10 Jan 2024 13:03:36 +0000 Subject: [PATCH 094/112] 8316241: Test jdk/jdk/jfr/jvm/TestChunkIntegrity.java failed Reviewed-by: egahlin --- .../recorder/checkpoint/types/jfrTypeSet.cpp | 1037 +++++++++-------- .../checkpoint/types/jfrTypeSetUtils.cpp | 30 +- .../checkpoint/types/jfrTypeSetUtils.hpp | 47 +- .../traceid/jfrTraceIdLoadBarrier.inline.hpp | 41 +- .../storage/jfrMemorySpace.inline.hpp | 2 +- 5 files changed, 626 insertions(+), 531 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 94ac07729697e..2d49c5aa405fb 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -66,20 +66,38 @@ static bool _class_unload = false; static bool _flushpoint = false; static bool _initial_type_set = true; -static bool current_epoch() { - return _class_unload || _flushpoint; +static inline bool flushpoint() { + return _flushpoint; } -static bool previous_epoch() { +static inline bool unloading() { + return _class_unload; +} + +static inline bool current_epoch() { + return flushpoint() || unloading(); +} + +static inline bool previous_epoch() { return !current_epoch(); } -static bool is_initial_typeset_for_chunk() { - return _initial_type_set && !_class_unload; +template +static inline bool used(const T* ptr) { + assert(ptr != nullptr, "invariant"); + return current_epoch() ? USED_THIS_EPOCH(ptr) : USED_PREVIOUS_EPOCH(ptr); +} + +template +static inline bool not_used(const T* ptr) { + return !used(ptr); } -static bool is_complete() { - return !_artifacts->has_klass_entries() && current_epoch(); +template +static void do_artifact(const T* ptr) { + if (used(ptr)) { + _subsystem_callback->do_artifact(ptr); + } } static traceid mark_symbol(KlassPtr klass, bool leakp) { @@ -94,66 +112,107 @@ static traceid get_bootstrap_name(bool leakp) { return _artifacts->bootstrap_name(leakp); } -static const char* primitive_name(KlassPtr type_array_klass) { - switch (type_array_klass->name()->base()[1]) { - case JVM_SIGNATURE_BOOLEAN: return "boolean"; - case JVM_SIGNATURE_BYTE: return "byte"; - case JVM_SIGNATURE_CHAR: return "char"; - case JVM_SIGNATURE_SHORT: return "short"; - case JVM_SIGNATURE_INT: return "int"; - case JVM_SIGNATURE_LONG: return "long"; - case JVM_SIGNATURE_FLOAT: return "float"; - case JVM_SIGNATURE_DOUBLE: return "double"; +template +static traceid artifact_id(const T* ptr) { + assert(ptr != nullptr, "invariant"); + return JfrTraceId::load_raw(ptr); +} + +template +static traceid artifact_tag(const T* ptr, bool leakp) { + assert(ptr != nullptr, "invariant"); + if (leakp) { + if (IS_NOT_LEAKP(ptr)) { + SET_LEAKP(ptr); + } + assert(IS_LEAKP(ptr), "invariant"); + return artifact_id(ptr); } - assert(false, "invalid type array klass"); - return nullptr; + if (not_used(ptr)) { + SET_TRANSIENT(ptr); + } + assert(used(ptr), "invariant"); + return artifact_id(ptr); } -static Symbol* primitive_symbol(KlassPtr type_array_klass) { - if (type_array_klass == nullptr) { - // void.class - static Symbol* const void_class_name = SymbolTable::probe("void", 4); - assert(void_class_name != nullptr, "invariant"); - return void_class_name; +static inline bool should_do_cld_klass(const Klass* klass, bool leakp) { + return klass != nullptr && _artifacts->should_do_cld_klass(klass, leakp); +} + +static inline KlassPtr get_cld_klass(CldPtr cld, bool leakp) { + if (cld == nullptr) { + return nullptr; } - const char* const primitive_type_str = primitive_name(type_array_klass); - assert(primitive_type_str != nullptr, "invariant"); - Symbol* const primitive_type_sym = SymbolTable::probe(primitive_type_str, (int)strlen(primitive_type_str)); - assert(primitive_type_sym != nullptr, "invariant"); - return primitive_type_sym; + assert(leakp ? IS_LEAKP(cld) : used(cld), "invariant"); + KlassPtr cld_klass = cld->class_loader_klass(); + if (cld_klass == nullptr) { + return nullptr; + } + if (should_do_cld_klass(cld_klass, leakp)) { + if (current_epoch()) { + // This will enqueue the klass, which is important for + // reachability when doing clear and reset at rotation. + JfrTraceId::load(cld_klass); + } else { + artifact_tag(cld_klass, leakp); + } + return cld_klass; + } + return nullptr; } -template -static traceid artifact_id(const T* ptr) { - assert(ptr != nullptr, "invariant"); - return JfrTraceId::load_raw(ptr); +static inline CldPtr get_cld(ModPtr mod) { + return mod != nullptr ? mod->loader_data() : nullptr; } -static traceid package_id(KlassPtr klass, bool leakp) { +static ClassLoaderData* get_cld(const Klass* klass) { assert(klass != nullptr, "invariant"); - PkgPtr pkg_entry = klass->package(); - if (pkg_entry == nullptr) { - return 0; - } - if (leakp) { - SET_LEAKP(pkg_entry); + if (klass->is_objArray_klass()) { + klass = ObjArrayKlass::cast(klass)->bottom_klass(); } - // package implicitly tagged already - return artifact_id(pkg_entry); + return klass->is_non_strong_hidden() ? nullptr : klass->class_loader_data(); +} + +static inline ModPtr get_module(PkgPtr pkg) { + return pkg != nullptr ? pkg->module() : nullptr; +} + +static inline PkgPtr get_package(KlassPtr klass) { + return klass != nullptr ? klass->package() : nullptr; +} + +static inline KlassPtr get_module_cld_klass(KlassPtr klass, bool leakp) { + assert(klass != nullptr, "invariant"); + return get_cld_klass(get_cld(get_module(get_package(klass))), leakp); +} + +static traceid cld_id(CldPtr cld, bool leakp) { + assert(cld != nullptr, "invariant"); + return artifact_tag(cld, leakp); } static traceid module_id(PkgPtr pkg, bool leakp) { assert(pkg != nullptr, "invariant"); - ModPtr module_entry = pkg->module(); - if (module_entry == nullptr) { + ModPtr mod = get_module(pkg); + if (mod == nullptr) { return 0; } - if (leakp) { - SET_LEAKP(module_entry); - } else { - SET_TRANSIENT(module_entry); + CldPtr cld = get_cld(mod); + if (cld != nullptr) { + cld_id(cld, leakp); } - return artifact_id(module_entry); + return artifact_tag(mod, leakp); +} + +static traceid package_id(KlassPtr klass, bool leakp) { + assert(klass != nullptr, "invariant"); + PkgPtr pkg = get_package(klass); + if (pkg == nullptr) { + return 0; + } + // Ensure module and its CLD gets tagged. + module_id(pkg, leakp); + return artifact_tag(pkg, leakp); } static traceid method_id(KlassPtr klass, MethodPtr method) { @@ -162,16 +221,6 @@ static traceid method_id(KlassPtr klass, MethodPtr method) { return METHOD_ID(klass, method); } -static traceid cld_id(CldPtr cld, bool leakp) { - assert(cld != nullptr, "invariant"); - if (leakp) { - SET_LEAKP(cld); - } else { - SET_TRANSIENT(cld); - } - return artifact_id(cld); -} - template static s4 get_flags(const T* ptr) { assert(ptr != nullptr, "invariant"); @@ -183,73 +232,203 @@ static u4 get_primitive_flags() { return JVM_ACC_ABSTRACT | JVM_ACC_FINAL | JVM_ACC_PUBLIC; } -static ClassLoaderData* get_cld(const Klass* klass) { - assert(klass != nullptr, "invariant"); - if (klass->is_objArray_klass()) { - klass = ObjArrayKlass::cast(klass)->bottom_klass(); +class PackageFieldSelector { + public: + typedef PkgPtr TypePtr; + static TypePtr select(KlassPtr klass) { + assert(klass != nullptr, "invariant"); + return klass->package(); } - if (klass->is_non_strong_hidden()) return nullptr; - return klass->class_loader_data(); -} +}; + +class ModuleFieldSelector { + public: + typedef ModPtr TypePtr; + static TypePtr select(KlassPtr klass) { + assert(klass != nullptr, "invariant"); + PkgPtr pkg = klass->package(); + return pkg != nullptr ? pkg->module() : nullptr; + } +}; + +class KlassCldFieldSelector { + public: + typedef CldPtr TypePtr; + static TypePtr select(KlassPtr klass) { + assert(klass != nullptr, "invariant"); + return get_cld(klass); + } +}; + +class ModuleCldFieldSelector { + public: + typedef CldPtr TypePtr; + static TypePtr select(KlassPtr klass) { + assert(klass != nullptr, "invariant"); + ModPtr mod = ModuleFieldSelector::select(klass); + return mod != nullptr ? mod->loader_data() : nullptr; + } +}; + +template +class SerializePredicate { + bool _class_unload; + public: + SerializePredicate(bool class_unload) : _class_unload(class_unload) {} + bool operator()(T const& value) { + assert(value != nullptr, "invariant"); + return _class_unload ? _artifacts->should_do_unloading_artifact(value) : IS_NOT_SERIALIZED(value); + } +}; + +template <> +class SerializePredicate { + bool _class_unload; +public: + SerializePredicate(bool class_unload) : _class_unload(class_unload) {} + bool operator()(const Klass* klass) { + assert(klass != nullptr, "invariant"); + return _class_unload ? true : IS_NOT_SERIALIZED(klass); + } +}; + +template <> +class SerializePredicate { + bool _class_unload; +public: + SerializePredicate(bool class_unload) : _class_unload(class_unload) {} + bool operator()(const Method* method) { + assert(method != nullptr, "invariant"); + return _class_unload ? true : METHOD_IS_NOT_SERIALIZED(method); + } +}; template static void set_serialized(const T* ptr) { assert(ptr != nullptr, "invariant"); - SET_SERIALIZED(ptr); - assert(IS_SERIALIZED(ptr), "invariant"); if (current_epoch()) { CLEAR_THIS_EPOCH_CLEARED_BIT(ptr); } + SET_SERIALIZED(ptr); + assert(IS_SERIALIZED(ptr), "invariant"); } /* - * In C++03, functions used as template parameters must have external linkage; - * this restriction was removed in C++11. Change back to "static" and - * rename functions when C++11 becomes available. + *********************** Klasses ************************* + * + * When we process a Klass, we need to process its transitive closure. + * + * This includes two branches: + * + * [1] Klass -> CLD -> class_loader_Klass + * [2] Klass -> PackageEntry -> ModuleEntry -> CLD -> class_loader_Klass + * + * A Klass viewed as this closure becomes a node in a binary tree: + * + * Klass + * O + * / \ + * / \ + * [1] O O [2] + * + * We write the Klass and tag the artifacts in its closure (subtree) + * using preorder traversal by recursing the class_loader_Klass(es). * - * The weird naming is an effort to decrease the risk of name clashes. */ -static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp) { +static void do_write_klass(JfrCheckpointWriter* writer, CldPtr cld, KlassPtr klass, bool leakp) { assert(writer != nullptr, "invariant"); assert(_artifacts != nullptr, "invariant"); assert(klass != nullptr, "invariant"); writer->write(artifact_id(klass)); - ClassLoaderData* cld = get_cld(klass); writer->write(cld != nullptr ? cld_id(cld, leakp) : 0); writer->write(mark_symbol(klass, leakp)); writer->write(package_id(klass, leakp)); writer->write(klass->modifier_flags()); writer->write(klass->is_hidden()); - return 1; + if (!leakp) { + set_serialized(klass); + } +} + +static inline bool should_write_cld_klass(KlassPtr klass, bool leakp) { + return klass != nullptr && (leakp || IS_NOT_SERIALIZED(klass)); +} + +static void write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp, int& elements) { + assert(elements >= 0, "invariant"); + ClassLoaderData* cld = get_cld(klass); + do_write_klass(writer, cld, klass, leakp); + ++elements; + if (cld != nullptr) { + // Write the klass for the direct cld. + KlassPtr cld_klass = get_cld_klass(cld, leakp); + if (should_write_cld_klass(cld_klass, leakp)) { + write_klass(writer, cld_klass, leakp, elements); + } + } + KlassPtr mod_klass = get_module_cld_klass(klass, leakp); + if (should_write_cld_klass(mod_klass, leakp)) { + // Write the klass for the module cld. + write_klass(writer, mod_klass, leakp, elements); + } } +/* + * In C++03, functions used as template parameters must have external linkage; + * this restriction was removed in C++11. Change back to "static" and + * rename functions when C++11 becomes available. + * + * The weird naming is an effort to decrease the risk of name clashes. + */ int write__klass(JfrCheckpointWriter* writer, const void* k) { assert(k != nullptr, "invariant"); - KlassPtr klass = (KlassPtr)k; - set_serialized(klass); - return write_klass(writer, klass, false); + KlassPtr klass = static_cast(k); + int elements = 0; + write_klass(writer, klass, false, elements); + return elements; } int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) { assert(k != nullptr, "invariant"); - KlassPtr klass = (KlassPtr)k; + KlassPtr klass = static_cast(k); CLEAR_LEAKP(klass); - return write_klass(writer, klass, true); + int elements = 0; + write_klass(writer, klass, true, elements); + return elements; } -static bool is_implied(const Klass* klass) { - assert(klass != nullptr, "invariant"); - return klass->is_subclass_of(vmClasses::ClassLoader_klass()) || klass == vmClasses::Object_klass(); -} +static int primitives_count = 9; -static void do_klass(Klass* klass) { - assert(klass != nullptr, "invariant"); - assert(_flushpoint ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass), "invariant"); - assert(_subsystem_callback != nullptr, "invariant"); - _subsystem_callback->do_artifact(klass); +static const char* primitive_name(KlassPtr type_array_klass) { + switch (type_array_klass->name()->base()[1]) { + case JVM_SIGNATURE_BOOLEAN: return "boolean"; + case JVM_SIGNATURE_BYTE: return "byte"; + case JVM_SIGNATURE_CHAR: return "char"; + case JVM_SIGNATURE_SHORT: return "short"; + case JVM_SIGNATURE_INT: return "int"; + case JVM_SIGNATURE_LONG: return "long"; + case JVM_SIGNATURE_FLOAT: return "float"; + case JVM_SIGNATURE_DOUBLE: return "double"; + } + assert(false, "invalid type array klass"); + return nullptr; } +static Symbol* primitive_symbol(KlassPtr type_array_klass) { + if (type_array_klass == nullptr) { + // void.class + static Symbol* const void_class_name = SymbolTable::probe("void", 4); + assert(void_class_name != nullptr, "invariant"); + return void_class_name; + } + const char* const primitive_type_str = primitive_name(type_array_klass); + assert(primitive_type_str != nullptr, "invariant"); + Symbol* const primitive_type_sym = SymbolTable::probe(primitive_type_str, + (int)strlen(primitive_type_str)); + assert(primitive_type_sym != nullptr, "invariant"); + return primitive_type_sym; +} static traceid primitive_id(KlassPtr array_klass) { if (array_klass == nullptr) { @@ -271,148 +450,69 @@ static void write_primitive(JfrCheckpointWriter* writer, KlassPtr type_array_kla writer->write(false); } -static void do_loader_klass(const Klass* klass) { - if (klass != nullptr && _artifacts->should_do_loader_klass(klass)) { - if (_leakp_writer != nullptr) { - SET_LEAKP(klass); - } - SET_TRANSIENT(klass); - _subsystem_callback->do_artifact(klass); - } -} - -static bool register_klass_unload(Klass* klass) { - assert(klass != nullptr, "invariant"); - return JfrKlassUnloading::on_unload(klass); -} - -static void do_unloading_klass(Klass* klass) { - assert(klass != nullptr, "invariant"); - assert(_subsystem_callback != nullptr, "invariant"); - if (register_klass_unload(klass)) { - _subsystem_callback->do_artifact(klass); - do_loader_klass(klass->class_loader_data()->class_loader_klass()); - } -} - -/* - * Abstract klasses are filtered out unconditionally. - * If a klass is not yet initialized, i.e yet to run its - * it is also filtered out so we don't accidentally - * trigger initialization. - */ -static bool is_classloader_klass_allowed(const Klass* k) { - assert(k != nullptr, "invariant"); - return !(k->is_abstract() || k->should_be_initialized()); -} - -static void do_classloaders() { - for (ClassHierarchyIterator iter(vmClasses::ClassLoader_klass()); !iter.done(); iter.next()) { - Klass* subk = iter.klass(); - if (is_classloader_klass_allowed(subk)) { - do_loader_klass(subk); - } - } +static bool is_initial_typeset_for_chunk() { + return _initial_type_set && !unloading(); } -static int primitives_count = 9; - // A mirror representing a primitive class (e.g. int.class) has no reified Klass*, // instead it has an associated TypeArrayKlass* (e.g. int[].class). // We can use the TypeArrayKlass* as a proxy for deriving the id of the primitive class. // The exception is the void.class, which has neither a Klass* nor a TypeArrayKlass*. // It will use a reserved constant. static void do_primitives() { - // Only write the primitive classes once per chunk. - if (is_initial_typeset_for_chunk()) { - write_primitive(_writer, Universe::boolArrayKlassObj()); - write_primitive(_writer, Universe::byteArrayKlassObj()); - write_primitive(_writer, Universe::charArrayKlassObj()); - write_primitive(_writer, Universe::shortArrayKlassObj()); - write_primitive(_writer, Universe::intArrayKlassObj()); - write_primitive(_writer, Universe::longArrayKlassObj()); - write_primitive(_writer, Universe::floatArrayKlassObj()); - write_primitive(_writer, Universe::doubleArrayKlassObj()); - write_primitive(_writer, nullptr); // void.class - } + assert(is_initial_typeset_for_chunk(), "invariant"); + write_primitive(_writer, Universe::boolArrayKlassObj()); + write_primitive(_writer, Universe::byteArrayKlassObj()); + write_primitive(_writer, Universe::charArrayKlassObj()); + write_primitive(_writer, Universe::shortArrayKlassObj()); + write_primitive(_writer, Universe::intArrayKlassObj()); + write_primitive(_writer, Universe::longArrayKlassObj()); + write_primitive(_writer, Universe::floatArrayKlassObj()); + write_primitive(_writer, Universe::doubleArrayKlassObj()); + write_primitive(_writer, nullptr); // void.class } -static void do_object() { - SET_TRANSIENT(vmClasses::Object_klass()); - do_klass(vmClasses::Object_klass()); -} - -static void do_klasses() { - if (_class_unload) { - ClassLoaderDataGraph::classes_unloading_do(&do_unloading_klass); - return; - } - JfrTraceIdLoadBarrier::do_klasses(&do_klass, previous_epoch()); - do_classloaders(); - do_primitives(); - do_object(); -} - -template -static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) { - assert(callback != nullptr, "invariant"); - assert(value != nullptr, "invariant"); - if (USED_PREVIOUS_EPOCH(value)) { - callback->do_artifact(value); - } - if (IS_SERIALIZED(value)) { - CLEAR_SERIALIZED(value); - } - assert(IS_NOT_SERIALIZED(value), "invariant"); -} - -static void do_previous_epoch_klass(JfrArtifactClosure* callback, const Klass* value) { - assert(callback != nullptr, "invariant"); - assert(value != nullptr, "invariant"); - if (USED_PREVIOUS_EPOCH(value)) { - callback->do_artifact(value); +static void do_unloading_klass(Klass* klass) { + assert(klass != nullptr, "invariant"); + assert(_subsystem_callback != nullptr, "invariant"); + if (JfrKlassUnloading::on_unload(klass)) { + _subsystem_callback->do_artifact(klass); } } -static void do_klass_on_clear(Klass* klass) { +static void do_klass(Klass* klass) { assert(klass != nullptr, "invariant"); + assert(used(klass), "invariant"); assert(_subsystem_callback != nullptr, "invariant"); - do_previous_epoch_klass(_subsystem_callback, klass); + _subsystem_callback->do_artifact(klass); } -static void do_loader_klass_on_clear(const Klass* klass) { - if (klass != nullptr && _artifacts->should_do_loader_klass(klass)) { - if (_leakp_writer != nullptr) { - SET_LEAKP(klass); - } - SET_TRANSIENT(klass); - do_previous_epoch_klass(_subsystem_callback, klass); +static void do_klasses() { + if (unloading()) { + ClassLoaderDataGraph::classes_unloading_do(&do_unloading_klass); + return; } -} - -static void do_classloaders_on_clear() { - for (ClassHierarchyIterator iter(vmClasses::ClassLoader_klass()); !iter.done(); iter.next()) { - Klass* subk = iter.klass(); - if (is_classloader_klass_allowed(subk)) { - do_loader_klass_on_clear(subk); - } + if (is_initial_typeset_for_chunk()) { + // Only write the primitive classes once per chunk. + do_primitives(); } + JfrTraceIdLoadBarrier::do_klasses(&do_klass, previous_epoch()); } -static void do_object_on_clear() { - SET_TRANSIENT(vmClasses::Object_klass()); - do_klass_on_clear(vmClasses::Object_klass()); +static void do_klass_on_clear(Klass* klass) { + do_artifact(klass); } static void do_all_klasses() { ClassLoaderDataGraph::classes_do(&do_klass_on_clear); - do_classloaders_on_clear(); - do_object_on_clear(); } +// KlassWriter. typedef SerializePredicate KlassPredicate; typedef JfrPredicatedTypeWriterImplHost KlassWriterImpl; typedef JfrTypeWriterHost KlassWriter; + +// Klass registration. typedef CompositeFunctor KlassWriterRegistration; typedef JfrArtifactCallbackHost KlassCallback; @@ -422,29 +522,31 @@ class LeakPredicate { LeakPredicate(bool class_unload) {} bool operator()(const Klass* klass) { assert(klass != nullptr, "invariant"); - return IS_LEAKP(klass) || is_implied(klass); + return IS_LEAKP(klass); } }; +// KlassWriter for leakp. Only used during start or rotation, i.e. the previous epoch. typedef LeakPredicate LeakKlassPredicate; typedef JfrPredicatedTypeWriterImplHost LeakKlassWriterImpl; typedef JfrTypeWriterHost LeakKlassWriter; +// Composite KlassWriter with registration. typedef CompositeFunctor CompositeKlassWriter; typedef CompositeFunctor CompositeKlassWriterRegistration; typedef JfrArtifactCallbackHost CompositeKlassCallback; -static bool write_klasses() { +static void write_klasses() { assert(!_artifacts->has_klass_entries(), "invariant"); assert(_writer != nullptr, "invariant"); KlassArtifactRegistrator reg(_artifacts); - KlassWriter kw(_writer, _class_unload); + KlassWriter kw(_writer, unloading()); KlassWriterRegistration kwr(&kw, ®); if (_leakp_writer == nullptr) { KlassCallback callback(&_subsystem_callback, &kwr); do_klasses(); } else { - LeakKlassWriter lkw(_leakp_writer, _class_unload); + LeakKlassWriter lkw(_leakp_writer, unloading()); CompositeKlassWriter ckw(&lkw, &kw); CompositeKlassWriterRegistration ckwr(&ckw, ®); CompositeKlassCallback callback(&_subsystem_callback, &ckwr); @@ -455,32 +557,26 @@ static bool write_klasses() { // their count is not automatically incremented. kw.add(primitives_count); } - if (is_complete()) { - return false; - } _artifacts->tally(kw); - return true; } -static bool write_klasses_on_clear() { +static void write_klasses_on_clear() { assert(!_artifacts->has_klass_entries(), "invariant"); assert(_writer != nullptr, "invariant"); assert(_leakp_writer != nullptr, "invariant"); KlassArtifactRegistrator reg(_artifacts); - KlassWriter kw(_writer, _class_unload); + KlassWriter kw(_writer, unloading()); KlassWriterRegistration kwr(&kw, ®); - LeakKlassWriter lkw(_leakp_writer, _class_unload); + LeakKlassWriter lkw(_leakp_writer, unloading()); CompositeKlassWriter ckw(&lkw, &kw); CompositeKlassWriterRegistration ckwr(&ckw, ®); CompositeKlassCallback callback(&_subsystem_callback, &ckwr); do_all_klasses(); - if (is_complete()) { - return false; - } _artifacts->tally(kw); - return true; } +/***** Packages *****/ + static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) { assert(writer != nullptr, "invariant"); assert(_artifacts != nullptr, "invariant"); @@ -494,98 +590,101 @@ static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) { int write__package(JfrCheckpointWriter* writer, const void* p) { assert(p != nullptr, "invariant"); - PkgPtr pkg = (PkgPtr)p; + PkgPtr pkg = static_cast(p); set_serialized(pkg); return write_package(writer, pkg, false); } int write__package__leakp(JfrCheckpointWriter* writer, const void* p) { assert(p != nullptr, "invariant"); - PkgPtr pkg = (PkgPtr)p; + PkgPtr pkg = static_cast(p); CLEAR_LEAKP(pkg); return write_package(writer, pkg, true); } -static void do_package(PackageEntry* entry) { - do_previous_epoch_artifact(_subsystem_callback, entry); -} - -static void do_packages() { - ClassLoaderDataGraph::packages_do(&do_package); -} - -class PackageFieldSelector { - public: - typedef PkgPtr TypePtr; - static TypePtr select(KlassPtr klass) { - assert(klass != nullptr, "invariant"); - return klass->package(); - } -}; +// PackageWriter. typedef SerializePredicate PackagePredicate; typedef JfrPredicatedTypeWriterImplHost PackageWriterImpl; typedef JfrTypeWriterHost PackageWriter; -typedef CompositeFunctor > PackageWriterWithClear; +typedef JfrArtifactCallbackHost PackageCallback; + +// PackageWriter used during flush or unloading i.e. the current epoch. typedef KlassToFieldEnvelope KlassPackageWriter; -typedef JfrArtifactCallbackHost PackageCallback; +// PackageWriter with clear. Only used during start or rotation, i.e. the previous epoch. +typedef CompositeFunctor > PackageWriterWithClear; +typedef JfrArtifactCallbackHost PackageClearCallback; + +// PackageWriter for leakp. Only used during start or rotation, i.e. the previous epoch. typedef LeakPredicate LeakPackagePredicate; typedef JfrPredicatedTypeWriterImplHost LeakPackageWriterImpl; typedef JfrTypeWriterHost LeakPackageWriter; +// Composite PackageWriter with clear. Only used during start or rotation, i.e. the previous epoch. typedef CompositeFunctor CompositePackageWriter; -typedef KlassToFieldEnvelope KlassCompositePackageWriter; -typedef KlassToFieldEnvelope KlassPackageWriterWithClear; typedef CompositeFunctor > CompositePackageWriterWithClear; -typedef JfrArtifactCallbackHost CompositePackageCallback; +typedef JfrArtifactCallbackHost CompositePackageClearCallback; + +static void do_package(PackageEntry* pkg) { + do_artifact(pkg); +} + +static void do_all_packages() { + ClassLoaderDataGraph::packages_do(&do_package); +} + +static void do_all_packages(PackageWriter& pw) { + do_all_packages(); + _artifacts->tally(pw); +} + +static void do_packages(PackageWriter& pw) { + KlassPackageWriter kpw(&pw); + _artifacts->iterate_klasses(kpw); + _artifacts->tally(pw); +} + +static void write_packages_with_leakp(PackageWriter& pw) { + assert(_writer != nullptr, "invariant"); + assert(_leakp_writer != nullptr, "invariant"); + assert(previous_epoch(), "invariant"); + LeakPackageWriter lpw(_leakp_writer, unloading()); + CompositePackageWriter cpw(&lpw, &pw); + ClearArtifact clear; + CompositePackageWriterWithClear cpwwc(&cpw, &clear); + CompositePackageClearCallback callback(&_subsystem_callback, &cpwwc); + do_all_packages(pw); +} static void write_packages() { assert(_writer != nullptr, "invariant"); - PackageWriter pw(_writer, _class_unload); - KlassPackageWriter kpw(&pw); + PackageWriter pw(_writer, unloading()); if (current_epoch()) { - _artifacts->iterate_klasses(kpw); - _artifacts->tally(pw); + do_packages(pw); return; } assert(previous_epoch(), "invariant"); if (_leakp_writer == nullptr) { - _artifacts->iterate_klasses(kpw); ClearArtifact clear; PackageWriterWithClear pwwc(&pw, &clear); - PackageCallback callback(&_subsystem_callback, &pwwc); - do_packages(); - } else { - LeakPackageWriter lpw(_leakp_writer, _class_unload); - CompositePackageWriter cpw(&lpw, &pw); - KlassCompositePackageWriter kcpw(&cpw); - _artifacts->iterate_klasses(kcpw); - ClearArtifact clear; - CompositePackageWriterWithClear cpwwc(&cpw, &clear); - CompositePackageCallback callback(&_subsystem_callback, &cpwwc); - do_packages(); + PackageClearCallback callback(&_subsystem_callback, &pwwc); + do_all_packages(pw); + return; } - _artifacts->tally(pw); + write_packages_with_leakp(pw); } static void write_packages_on_clear() { assert(_writer != nullptr, "invariant"); assert(_leakp_writer != nullptr, "invariant"); assert(previous_epoch(), "invariant"); - PackageWriter pw(_writer, _class_unload); - KlassPackageWriter kpw(&pw); - LeakPackageWriter lpw(_leakp_writer, _class_unload); - CompositePackageWriter cpw(&lpw, &pw); - KlassCompositePackageWriter kcpw(&cpw); - _artifacts->iterate_klasses(kcpw); - ClearArtifact clear; - CompositePackageWriterWithClear cpwwc(&cpw, &clear); - CompositePackageCallback callback(&_subsystem_callback, &cpwwc); - do_packages(); - _artifacts->tally(pw); + PackageWriter pw(_writer, unloading()); + write_packages_with_leakp(pw); } +/***** Modules *****/ + static int write_module(JfrCheckpointWriter* writer, ModPtr mod, bool leakp) { assert(mod != nullptr, "invariant"); assert(_artifacts != nullptr, "invariant"); @@ -599,99 +698,101 @@ static int write_module(JfrCheckpointWriter* writer, ModPtr mod, bool leakp) { int write__module(JfrCheckpointWriter* writer, const void* m) { assert(m != nullptr, "invariant"); - ModPtr mod = (ModPtr)m; + ModPtr mod = static_cast(m); set_serialized(mod); return write_module(writer, mod, false); } int write__module__leakp(JfrCheckpointWriter* writer, const void* m) { assert(m != nullptr, "invariant"); - ModPtr mod = (ModPtr)m; + ModPtr mod = static_cast(m); CLEAR_LEAKP(mod); return write_module(writer, mod, true); } -static void do_module(ModuleEntry* entry) { - do_previous_epoch_artifact(_subsystem_callback, entry); -} - -static void do_modules() { - ClassLoaderDataGraph::modules_do(&do_module); -} - -class ModuleFieldSelector { - public: - typedef ModPtr TypePtr; - static TypePtr select(KlassPtr klass) { - assert(klass != nullptr, "invariant"); - PkgPtr pkg = klass->package(); - return pkg != nullptr ? pkg->module() : nullptr; - } -}; - +// ModuleWriter. typedef SerializePredicate ModulePredicate; typedef JfrPredicatedTypeWriterImplHost ModuleWriterImpl; typedef JfrTypeWriterHost ModuleWriter; -typedef CompositeFunctor > ModuleWriterWithClear; -typedef JfrArtifactCallbackHost ModuleCallback; +typedef JfrArtifactCallbackHost ModuleCallback; + +// ModuleWriter used during flush or unloading i.e. the current epoch. typedef KlassToFieldEnvelope KlassModuleWriter; +// ModuleWriter with clear. Only used during start or rotation, i.e. the previous epoch. +typedef CompositeFunctor > ModuleWriterWithClear; +typedef JfrArtifactCallbackHost ModuleClearCallback; + +// ModuleWriter for leakp. Only used during start or rotation, i.e. the previous epoch. typedef LeakPredicate LeakModulePredicate; typedef JfrPredicatedTypeWriterImplHost LeakModuleWriterImpl; typedef JfrTypeWriterHost LeakModuleWriter; +// Composite ModuleWriter with clear. Only used during start or rotation, i.e. the previous epoch. typedef CompositeFunctor CompositeModuleWriter; -typedef KlassToFieldEnvelope KlassCompositeModuleWriter; typedef CompositeFunctor > CompositeModuleWriterWithClear; -typedef JfrArtifactCallbackHost CompositeModuleCallback; +typedef JfrArtifactCallbackHost CompositeModuleClearCallback; + +static void do_module(ModuleEntry* mod) { + do_artifact(mod); +} + +static void do_all_modules() { + ClassLoaderDataGraph::modules_do(&do_module); +} + +static void do_all_modules(ModuleWriter& mw) { + do_all_modules(); + _artifacts->tally(mw); +} + +static void do_modules(ModuleWriter& mw) { + KlassModuleWriter kmw(&mw); + _artifacts->iterate_klasses(kmw); + _artifacts->tally(mw); +} + +static void write_modules_with_leakp(ModuleWriter& mw) { + assert(_writer != nullptr, "invariant"); + assert(_leakp_writer != nullptr, "invariant"); + assert(previous_epoch(), "invariant"); + LeakModuleWriter lmw(_leakp_writer, unloading()); + CompositeModuleWriter cmw(&lmw, &mw); + ClearArtifact clear; + CompositeModuleWriterWithClear cmwwc(&cmw, &clear); + CompositeModuleClearCallback callback(&_subsystem_callback, &cmwwc); + do_all_modules(mw); +} static void write_modules() { assert(_writer != nullptr, "invariant"); - ModuleWriter mw(_writer, _class_unload); - KlassModuleWriter kmw(&mw); + ModuleWriter mw(_writer, unloading()); if (current_epoch()) { - _artifacts->iterate_klasses(kmw); - _artifacts->tally(mw); + do_modules(mw); return; } assert(previous_epoch(), "invariant"); if (_leakp_writer == nullptr) { - _artifacts->iterate_klasses(kmw); ClearArtifact clear; ModuleWriterWithClear mwwc(&mw, &clear); - ModuleCallback callback(&_subsystem_callback, &mwwc); - do_modules(); - } else { - LeakModuleWriter lmw(_leakp_writer, _class_unload); - CompositeModuleWriter cmw(&lmw, &mw); - KlassCompositeModuleWriter kcpw(&cmw); - _artifacts->iterate_klasses(kcpw); - ClearArtifact clear; - CompositeModuleWriterWithClear cmwwc(&cmw, &clear); - CompositeModuleCallback callback(&_subsystem_callback, &cmwwc); - do_modules(); + ModuleClearCallback callback(&_subsystem_callback, &mwwc); + do_all_modules(mw); + return; } - _artifacts->tally(mw); + write_modules_with_leakp(mw); } static void write_modules_on_clear() { assert(_writer != nullptr, "invariant"); assert(_leakp_writer != nullptr, "invariant"); assert(previous_epoch(), "invariant"); - ModuleWriter mw(_writer, _class_unload); - KlassModuleWriter kmw(&mw); - LeakModuleWriter lmw(_leakp_writer, _class_unload); - CompositeModuleWriter cmw(&lmw, &mw); - KlassCompositeModuleWriter kcpw(&cmw); - _artifacts->iterate_klasses(kcpw); - ClearArtifact clear; - CompositeModuleWriterWithClear cmwwc(&cmw, &clear); - CompositeModuleCallback callback(&_subsystem_callback, &cmwwc); - do_modules(); - _artifacts->tally(mw); + ModuleWriter mw(_writer, unloading()); + write_modules_with_leakp(mw); } -static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) { +/***** ClassLoaderData - CLD *****/ + +static int write_cld(JfrCheckpointWriter* writer, CldPtr cld, bool leakp) { assert(cld != nullptr, "invariant"); // class loader type const Klass* class_loader_klass = cld->class_loader_klass(); @@ -701,7 +802,7 @@ static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp writer->write((traceid)0); // class loader type id (absence of) writer->write(get_bootstrap_name(leakp)); // maps to synthetic name -> "bootstrap" } else { - assert(_class_unload ? true : IS_SERIALIZED(class_loader_klass), "invariant"); + assert(IS_SERIALIZED(class_loader_klass), "invariant"); writer->write(artifact_id(cld)); // class loader instance id writer->write(artifact_id(class_loader_klass)); // class loader type id writer->write(mark_symbol(cld->name(), leakp)); // class loader instance name @@ -709,146 +810,127 @@ static int write_classloader(JfrCheckpointWriter* writer, CldPtr cld, bool leakp return 1; } -int write__classloader(JfrCheckpointWriter* writer, const void* c) { +int write__cld(JfrCheckpointWriter* writer, const void* c) { assert(c != nullptr, "invariant"); - CldPtr cld = (CldPtr)c; + CldPtr cld = static_cast(c); set_serialized(cld); - return write_classloader(writer, cld, false); + return write_cld(writer, cld, false); } -int write__classloader__leakp(JfrCheckpointWriter* writer, const void* c) { +int write__cld__leakp(JfrCheckpointWriter* writer, const void* c) { assert(c != nullptr, "invariant"); - CldPtr cld = (CldPtr)c; + CldPtr cld = static_cast(c); CLEAR_LEAKP(cld); - return write_classloader(writer, cld, true); + return write_cld(writer, cld, true); } -static void do_class_loader_data(ClassLoaderData* cld) { - do_previous_epoch_artifact(_subsystem_callback, cld); -} +// CldWriter. +typedef SerializePredicate CldPredicate; +typedef JfrPredicatedTypeWriterImplHost CldWriterImpl; +typedef JfrTypeWriterHost CldWriter; +typedef JfrArtifactCallbackHost CldCallback; -class KlassCldFieldSelector { - public: - typedef CldPtr TypePtr; - static TypePtr select(KlassPtr klass) { - assert(klass != nullptr, "invariant"); - return get_cld(klass); - } -}; +// CldWriter used during flush or unloading i.e. the current epoch. +typedef KlassToFieldEnvelope KlassCldWriter; +typedef KlassToFieldEnvelope ModuleCldWriter; +typedef CompositeFunctor KlassAndModuleCldWriter; -class ModuleCldFieldSelector { -public: - typedef CldPtr TypePtr; - static TypePtr select(KlassPtr klass) { - assert(klass != nullptr, "invariant"); - ModPtr mod = ModuleFieldSelector::select(klass); - return mod != nullptr ? mod->loader_data() : nullptr; - } -}; +// CldWriter with clear. Only used during start or rotation, i.e. the previous epoch. +typedef CompositeFunctor > CldWriterWithClear; +typedef JfrArtifactCallbackHost CldClearCallback; + +// CldWriter for leakp. Only used during start or rotation, i.e. the previous epoch. +typedef LeakPredicate LeakCldPredicate; +typedef JfrPredicatedTypeWriterImplHost LeakCldWriterImpl; +typedef JfrTypeWriterHost LeakCldWriter; + +// Composite CldWriter with clear. Only used during start or rotation, i.e. the previous epoch. +typedef CompositeFunctor CompositeCldWriter; +typedef CompositeFunctor > CompositeCldWriterWithClear; +typedef JfrArtifactCallbackHost CompositeCldClearCallback; class CLDCallback : public CLDClosure { public: - CLDCallback() {} void do_cld(ClassLoaderData* cld) { assert(cld != nullptr, "invariant"); - if (cld->has_class_mirror_holder()) { - return; + if (!cld->has_class_mirror_holder()) { + do_artifact(cld); } - do_class_loader_data(cld); } }; -static void do_class_loaders() { +static void do_all_clds() { CLDCallback cld_cb; ClassLoaderDataGraph::loaded_cld_do(&cld_cb); } -typedef SerializePredicate CldPredicate; -typedef JfrPredicatedTypeWriterImplHost CldWriterImpl; -typedef JfrTypeWriterHost CldWriter; -typedef CompositeFunctor > CldWriterWithClear; -typedef JfrArtifactCallbackHost CldCallback; -typedef KlassToFieldEnvelope KlassCldWriter; -typedef KlassToFieldEnvelope ModuleCldWriter; -typedef CompositeFunctor KlassAndModuleCldWriter; - -typedef LeakPredicate LeakCldPredicate; -typedef JfrPredicatedTypeWriterImplHost LeakCldWriterImpl; -typedef JfrTypeWriterHost LeakCldWriter; - -typedef CompositeFunctor CompositeCldWriter; -typedef KlassToFieldEnvelope KlassCompositeCldWriter; -typedef KlassToFieldEnvelope ModuleCompositeCldWriter; -typedef CompositeFunctor KlassAndModuleCompositeCldWriter; -typedef CompositeFunctor > CompositeCldWriterWithClear; -typedef JfrArtifactCallbackHost CompositeCldCallback; +static void do_all_clds(CldWriter& cldw) { + do_all_clds(); + _artifacts->tally(cldw); +} -static void write_classloaders() { - assert(_writer != nullptr, "invariant"); - CldWriter cldw(_writer, _class_unload); +static void do_clds(CldWriter& cldw) { KlassCldWriter kcw(&cldw); ModuleCldWriter mcw(&cldw); KlassAndModuleCldWriter kmcw(&kcw, &mcw); + _artifacts->iterate_klasses(kmcw); + _artifacts->tally(cldw); +} + +static void write_clds_with_leakp(CldWriter& cldw) { + assert(_writer != nullptr, "invariant"); + assert(_leakp_writer != nullptr, "invariant"); + assert(previous_epoch(), "invariant"); + LeakCldWriter lcldw(_leakp_writer, unloading()); + CompositeCldWriter ccldw(&lcldw, &cldw); + ClearArtifact clear; + CompositeCldWriterWithClear ccldwwc(&ccldw, &clear); + CompositeCldClearCallback callback(&_subsystem_callback, &ccldwwc); + do_all_clds(cldw); +} + +static void write_clds() { + assert(_writer != nullptr, "invariant"); + CldWriter cldw(_writer, unloading()); if (current_epoch()) { - _artifacts->iterate_klasses(kmcw); - _artifacts->tally(cldw); + do_clds(cldw); return; } assert(previous_epoch(), "invariant"); if (_leakp_writer == nullptr) { - _artifacts->iterate_klasses(kmcw); ClearArtifact clear; CldWriterWithClear cldwwc(&cldw, &clear); - CldCallback callback(&_subsystem_callback, &cldwwc); - do_class_loaders(); - } else { - LeakCldWriter lcldw(_leakp_writer, _class_unload); - CompositeCldWriter ccldw(&lcldw, &cldw); - KlassCompositeCldWriter kccldw(&ccldw); - ModuleCompositeCldWriter mccldw(&ccldw); - KlassAndModuleCompositeCldWriter kmccldw(&kccldw, &mccldw); - _artifacts->iterate_klasses(kmccldw); - ClearArtifact clear; - CompositeCldWriterWithClear ccldwwc(&ccldw, &clear); - CompositeCldCallback callback(&_subsystem_callback, &ccldwwc); - do_class_loaders(); + CldClearCallback callback(&_subsystem_callback, &cldwwc); + do_all_clds(cldw); + return; } - _artifacts->tally(cldw); + write_clds_with_leakp(cldw); } -static void write_classloaders_on_clear() { +static void write_clds_on_clear() { assert(_writer != nullptr, "invariant"); assert(_leakp_writer != nullptr, "invariant"); - CldWriter cldw(_writer, _class_unload); - KlassCldWriter kcw(&cldw); - ModuleCldWriter mcw(&cldw); - KlassAndModuleCldWriter kmcw(&kcw, &mcw); - LeakCldWriter lcldw(_leakp_writer, _class_unload); - CompositeCldWriter ccldw(&lcldw, &cldw); - KlassCompositeCldWriter kccldw(&ccldw); - ModuleCompositeCldWriter mccldw(&ccldw); - KlassAndModuleCompositeCldWriter kmccldw(&kccldw, &mccldw); - _artifacts->iterate_klasses(kmccldw); - ClearArtifact clear; - CompositeCldWriterWithClear ccldwwc(&ccldw, &clear); - CompositeCldCallback callback(&_subsystem_callback, &ccldwwc); - do_class_loaders(); - _artifacts->tally(cldw); + assert(previous_epoch(), "invariant"); + CldWriter cldw(_writer, unloading()); + write_clds_with_leakp(cldw); } -static u1 get_visibility(MethodPtr method) { - assert(method != nullptr, "invariant"); - return const_cast(method)->is_hidden() ? (u1)1 : (u1)0; -} +/***** Methods *****/ template <> void set_serialized(MethodPtr method) { assert(method != nullptr, "invariant"); - SET_METHOD_SERIALIZED(method); - assert(METHOD_IS_SERIALIZED(method), "invariant"); if (current_epoch()) { CLEAR_THIS_EPOCH_METHOD_CLEARED_BIT(method); } + assert(unloading() ? true : METHOD_IS_NOT_SERIALIZED(method), "invariant"); + SET_METHOD_SERIALIZED(method); + assert(METHOD_IS_SERIALIZED(method), "invariant"); +} + +static inline u1 get_visibility(MethodPtr method) { + assert(method != nullptr, "invariant"); + return const_cast(method)->is_hidden() ? (u1)1 : (u1)0; } static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leakp) { @@ -857,58 +939,37 @@ static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leak assert(_artifacts != nullptr, "invariant"); KlassPtr klass = method->method_holder(); assert(klass != nullptr, "invariant"); + assert(used(klass), "invariant"); + assert(IS_SERIALIZED(klass), "invariant"); writer->write(method_id(klass, method)); writer->write(artifact_id(klass)); writer->write(mark_symbol(method->name(), leakp)); writer->write(mark_symbol(method->signature(), leakp)); - writer->write((u2)get_flags(method)); + writer->write(static_cast(get_flags(method))); writer->write(get_visibility(method)); return 1; } int write__method(JfrCheckpointWriter* writer, const void* m) { assert(m != nullptr, "invariant"); - MethodPtr method = (MethodPtr)m; + MethodPtr method = static_cast(m); + assert(METHOD_IS_NOT_SERIALIZED(method), "invariant"); set_serialized(method); return write_method(writer, method, false); } int write__method__leakp(JfrCheckpointWriter* writer, const void* m) { assert(m != nullptr, "invariant"); - MethodPtr method = (MethodPtr)m; + MethodPtr method = static_cast(m); CLEAR_LEAKP_METHOD(method); return write_method(writer, method, true); } - -class BitMapFilter { - ResourceBitMap _bitmap; - public: - explicit BitMapFilter(int length = 0) : _bitmap((size_t)length) {} - bool operator()(size_t idx) { - if (_bitmap.size() == 0) { - return true; - } - if (_bitmap.at(idx)) { - return false; - } - _bitmap.set_bit(idx); - return true; - } -}; - -class AlwaysTrue { - public: - explicit AlwaysTrue(int length = 0) {} - bool operator()(size_t idx) { - return true; - } -}; - -template +template class MethodIteratorHost { private: MethodCallback _method_cb; KlassCallback _klass_cb; + KlassUsedPredicate _klass_used_predicate; MethodUsedPredicate _method_used_predicate; MethodFlagPredicate _method_flag_predicate; public: @@ -918,6 +979,7 @@ class MethodIteratorHost { bool skip_header = false) : _method_cb(writer, class_unload, skip_header), _klass_cb(writer, class_unload, skip_header), + _klass_used_predicate(current_epoch), _method_used_predicate(current_epoch), _method_flag_predicate(current_epoch) {} @@ -937,7 +999,7 @@ class MethodIteratorHost { ik = ik->previous_versions(); } } - return _klass_cb(klass); + return _klass_used_predicate(klass) ? _klass_cb(klass) : true; } int count() const { return _method_cb.count(); } @@ -964,37 +1026,42 @@ typedef SerializePredicate MethodPredicate; typedef JfrPredicatedTypeWriterImplHost MethodWriterImplTarget; typedef Wrapper KlassCallbackStub; typedef JfrTypeWriterHost MethodWriterImpl; -typedef MethodIteratorHost MethodWriter; +typedef MethodIteratorHost MethodWriter; typedef LeakPredicate LeakMethodPredicate; typedef JfrPredicatedTypeWriterImplHost LeakMethodWriterImplTarget; typedef JfrTypeWriterHost LeakMethodWriterImpl; -typedef MethodIteratorHost LeakMethodWriter; -typedef MethodIteratorHost LeakMethodWriter; +typedef MethodIteratorHost LeakMethodWriter; +typedef MethodIteratorHost LeakMethodWriter; typedef CompositeFunctor CompositeMethodWriter; +static void write_methods_with_leakp(MethodWriter& mw) { + assert(_writer != nullptr, "invariant"); + assert(_leakp_writer != nullptr, "invariant"); + assert(previous_epoch(), "invariant"); + LeakMethodWriter lpmw(_leakp_writer, current_epoch(), unloading()); + CompositeMethodWriter cmw(&lpmw, &mw); + _artifacts->iterate_klasses(cmw); + _artifacts->tally(mw); +} + static void write_methods() { assert(_writer != nullptr, "invariant"); - MethodWriter mw(_writer, current_epoch(), _class_unload); + MethodWriter mw(_writer, current_epoch(), unloading()); if (_leakp_writer == nullptr) { _artifacts->iterate_klasses(mw); - } else { - LeakMethodWriter lpmw(_leakp_writer, current_epoch(), _class_unload); - CompositeMethodWriter cmw(&lpmw, &mw); - _artifacts->iterate_klasses(cmw); + _artifacts->tally(mw); + return; } - _artifacts->tally(mw); + write_methods_with_leakp(mw); } static void write_methods_on_clear() { assert(_writer != nullptr, "invariant"); assert(_leakp_writer != nullptr, "invariant"); assert(previous_epoch(), "invariant"); - MethodWriter mw(_writer, current_epoch(), _class_unload); - LeakMethodWriter lpmw(_leakp_writer, current_epoch(), _class_unload); - CompositeMethodWriter cmw(&lpmw, &mw); - _artifacts->iterate_klasses(cmw); - _artifacts->tally(mw); + MethodWriter mw(_writer, current_epoch(), unloading()); + write_methods_with_leakp(mw); } template <> @@ -1022,14 +1089,14 @@ static int write_symbol(JfrCheckpointWriter* writer, SymbolEntryPtr entry, bool int write__symbol(JfrCheckpointWriter* writer, const void* e) { assert(e != nullptr, "invariant"); - SymbolEntryPtr entry = (SymbolEntryPtr)e; + SymbolEntryPtr entry = static_cast(e); set_serialized(entry); return write_symbol(writer, entry, false); } int write__symbol__leakp(JfrCheckpointWriter* writer, const void* e) { assert(e != nullptr, "invariant"); - SymbolEntryPtr entry = (SymbolEntryPtr)e; + SymbolEntryPtr entry = static_cast(e); return write_symbol(writer, entry, true); } @@ -1043,14 +1110,14 @@ static int write_string(JfrCheckpointWriter* writer, StringEntryPtr entry, bool int write__string(JfrCheckpointWriter* writer, const void* e) { assert(e != nullptr, "invariant"); - StringEntryPtr entry = (StringEntryPtr)e; + StringEntryPtr entry = static_cast(e); set_serialized(entry); return write_string(writer, entry, false); } int write__string__leakp(JfrCheckpointWriter* writer, const void* e) { assert(e != nullptr, "invariant"); - StringEntryPtr entry = (StringEntryPtr)e; + StringEntryPtr entry = static_cast(e); return write_string(writer, entry, true); } @@ -1071,30 +1138,15 @@ typedef JfrTypeWriterHost LeakStringEntr typedef CompositeFunctor CompositeStringWriter; static void write_symbols_with_leakp() { - assert(_leakp_writer != nullptr, "invariant"); - SymbolEntryWriter sw(_writer, _class_unload); - LeakSymbolEntryWriter lsw(_leakp_writer, _class_unload); - CompositeSymbolWriter csw(&lsw, &sw); - _artifacts->iterate_symbols(csw); - StringEntryWriter sew(_writer, _class_unload, true); // skip header - LeakStringEntryWriter lsew(_leakp_writer, _class_unload, true); // skip header - CompositeStringWriter csew(&lsew, &sew); - _artifacts->iterate_strings(csew); - sw.add(sew.count()); - lsw.add(lsew.count()); - _artifacts->tally(sw); -} - -static void write_symbols_on_clear() { assert(_writer != nullptr, "invariant"); assert(_leakp_writer != nullptr, "invariant"); assert(previous_epoch(), "invariant"); - SymbolEntryWriter sw(_writer, _class_unload); - LeakSymbolEntryWriter lsw(_leakp_writer, _class_unload); + SymbolEntryWriter sw(_writer, unloading()); + LeakSymbolEntryWriter lsw(_leakp_writer, unloading()); CompositeSymbolWriter csw(&lsw, &sw); _artifacts->iterate_symbols(csw); - StringEntryWriter sew(_writer, _class_unload, true); // skip header - LeakStringEntryWriter lsew(_leakp_writer, _class_unload, true); // skip header + StringEntryWriter sew(_writer, unloading(), true); // skip header + LeakStringEntryWriter lsew(_leakp_writer, unloading(), true); // skip header CompositeStringWriter csew(&lsew, &sew); _artifacts->iterate_strings(csew); sw.add(sew.count()); @@ -1108,17 +1160,24 @@ static void write_symbols() { write_symbols_with_leakp(); return; } - SymbolEntryWriter sw(_writer, _class_unload); + SymbolEntryWriter sw(_writer, unloading()); _artifacts->iterate_symbols(sw); - StringEntryWriter sew(_writer, _class_unload, true); // skip header + StringEntryWriter sew(_writer, unloading(), true); // skip header _artifacts->iterate_strings(sew); sw.add(sew.count()); _artifacts->tally(sw); } +static void write_symbols_on_clear() { + assert(_writer != nullptr, "invariant"); + assert(_leakp_writer != nullptr, "invariant"); + assert(previous_epoch(), "invariant"); + write_symbols_with_leakp(); +} + typedef Wrapper ClearKlassBits; typedef Wrapper ClearMethodFlag; -typedef MethodIteratorHost ClearKlassAndMethods; +typedef MethodIteratorHost ClearKlassAndMethods; static void clear_klasses_and_methods() { ClearKlassAndMethods clear(_writer); @@ -1165,19 +1224,17 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l setup(writer, leakp_writer, class_unload, flushpoint); // write order is important because an individual write step // might tag an artifact to be written in a subsequent step - if (!write_klasses()) { - return 0; - } + write_klasses(); write_packages(); write_modules(); - write_classloaders(); + write_clds(); write_methods(); write_symbols(); return teardown(); } /** - * Clear all tags from the previous epoch. + * Clear all tags from the previous epoch. Reset support structures. */ void JfrTypeSet::clear(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) { ResourceMark rm; @@ -1185,7 +1242,7 @@ void JfrTypeSet::clear(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_w write_klasses_on_clear(); write_packages_on_clear(); write_modules_on_clear(); - write_classloaders_on_clear(); + write_clds_on_clear(); write_methods_on_clear(); write_symbols_on_clear(); teardown(); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp index 0876281d53f6b..883821f853c0a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp @@ -32,7 +32,8 @@ JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_table(nullptr), _klass_list(nullptr), - _total_count(0) { + _total_count(0), + _class_unload(class_unload) { initialize(class_unload); assert(_klass_list != nullptr, "invariant"); } @@ -41,6 +42,7 @@ static const size_t initial_klass_list_size = 256; const int initial_klass_loader_set_size = 64; void JfrArtifactSet::initialize(bool class_unload) { + _class_unload = class_unload; if (_symbol_table == nullptr) { _symbol_table = JfrSymbolTable::create(); assert(_symbol_table != nullptr, "invariant"); @@ -51,6 +53,11 @@ void JfrArtifactSet::initialize(bool class_unload) { // resource allocation _klass_list = new GrowableArray(initial_klass_list_size); _klass_loader_set = new GrowableArray(initial_klass_loader_set_size); + _klass_loader_leakp_set = new GrowableArray(initial_klass_loader_set_size); + + if (class_unload) { + _unloading_set = new GrowableArray(initial_klass_list_size); + } } void JfrArtifactSet::clear() { @@ -97,10 +104,27 @@ int JfrArtifactSet::entries() const { return _klass_list->length(); } -bool JfrArtifactSet::should_do_loader_klass(const Klass* k) { +static inline bool not_in_set(GrowableArray* set, const Klass* k) { + assert(set != nullptr, "invariant"); + assert(k != nullptr, "invariant"); + return !JfrMutablePredicate::test(set, k); +} + +bool JfrArtifactSet::should_do_cld_klass(const Klass* k, bool leakp) { assert(k != nullptr, "invariant"); assert(_klass_loader_set != nullptr, "invariant"); - return !JfrMutablePredicate::test(_klass_loader_set, k); + assert(_klass_loader_leakp_set != nullptr, "invariant"); + return not_in_set(leakp ? _klass_loader_leakp_set : _klass_loader_set, k); +} + +bool JfrArtifactSet::should_do_unloading_artifact(const void* ptr) { + assert(ptr != nullptr, "invariant"); + assert(_class_unload, "invariant"); + assert(_unloading_set != nullptr, "invariant"); + // The incoming pointers are of all kinds of different types. + // However, we are only interested in set membership. + // Treat them uniformly as const Klass* for simplicity and code reuse. + return not_in_set(_unloading_set, static_cast(ptr)); } void JfrArtifactSet::register_klass(const Klass* k) { diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp index b0c2d989de52e..24424fdef3aa9 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp @@ -114,28 +114,6 @@ class ClearArtifact { } }; -template -class SerializePredicate { - bool _class_unload; - public: - SerializePredicate(bool class_unload) : _class_unload(class_unload) {} - bool operator()(T const& value) { - assert(value != nullptr, "invariant"); - return _class_unload ? true : IS_NOT_SERIALIZED(value); - } -}; - -template <> -class SerializePredicate { - bool _class_unload; - public: - SerializePredicate(bool class_unload) : _class_unload(class_unload) {} - bool operator()(const Method* method) { - assert(method != nullptr, "invariant"); - return _class_unload ? true : METHOD_IS_NOT_SERIALIZED(method); - } -}; - template class SymbolPredicate { bool _class_unload; @@ -150,11 +128,23 @@ class SymbolPredicate { } }; +class KlassUsedPredicate { + bool _current_epoch; +public: + KlassUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {} + bool operator()(const Klass* klass) { + return _current_epoch ? USED_THIS_EPOCH(klass) : USED_PREVIOUS_EPOCH(klass); + } +}; + class MethodUsedPredicate { bool _current_epoch; public: MethodUsedPredicate(bool current_epoch) : _current_epoch(current_epoch) {} bool operator()(const Klass* klass) { + if (!klass->is_instance_klass()) { + return false; + } return _current_epoch ? METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_PREVIOUS_EPOCH(klass); } }; @@ -210,7 +200,10 @@ class JfrArtifactSet : public JfrCHeapObj { JfrSymbolTable* _symbol_table; GrowableArray* _klass_list; GrowableArray* _klass_loader_set; + GrowableArray* _klass_loader_leakp_set; + GrowableArray* _unloading_set; size_t _total_count; + bool _class_unload; public: JfrArtifactSet(bool class_unload); @@ -235,14 +228,20 @@ class JfrArtifactSet : public JfrCHeapObj { int entries() const; size_t total_count() const; void register_klass(const Klass* k); - bool should_do_loader_klass(const Klass* k); + bool should_do_cld_klass(const Klass* k, bool leakp); + bool should_do_unloading_artifact(const void* ptr); void increment_checkpoint_id(); template void iterate_klasses(Functor& functor) const { for (int i = 0; i < _klass_list->length(); ++i) { if (!functor(_klass_list->at(i))) { - break; + return; + } + } + for (int i = 0; i < _klass_loader_set->length(); ++i) { + if (!functor(_klass_loader_set->at(i))) { + return; } } } diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp index e5b9a33ef56a3..13853e14a1334 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/traceid/jfrTraceIdLoadBarrier.inline.hpp @@ -33,6 +33,7 @@ #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdBits.inline.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdMacros.hpp" +#include "jfr/support/jfrKlassExtension.hpp" #include "oops/klass.hpp" #include "oops/method.hpp" #include "runtime/javaThread.hpp" @@ -66,10 +67,14 @@ inline traceid set_used_and_get(const T* type) { return TRACE_ID(type); } +// We set the 'method_and_class' bits to have a consistent +// bit pattern set always. This is because the tag is non-atomic, +// hence, we always need the same bit pattern in an epoch to avoid losing information. inline void JfrTraceIdLoadBarrier::load_barrier(const Klass* klass) { - SET_USED_THIS_EPOCH(klass); - enqueue(klass); - JfrTraceIdEpoch::set_changed_tag_state(); + SET_METHOD_AND_CLASS_USED_THIS_EPOCH(klass); + assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); + enqueue(klass); + JfrTraceIdEpoch::set_changed_tag_state(); } inline traceid JfrTraceIdLoadBarrier::load(const Klass* klass) { @@ -113,26 +118,36 @@ inline traceid JfrTraceIdLoadBarrier::load_no_enqueue(const Klass* klass, const return (METHOD_ID(klass, method)); } -inline traceid JfrTraceIdLoadBarrier::load(const ModuleEntry* module) { - return set_used_and_get(module); -} - -inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) { - return set_used_and_get(package); -} - inline traceid JfrTraceIdLoadBarrier::load(const ClassLoaderData* cld) { assert(cld != nullptr, "invariant"); if (cld->has_class_mirror_holder()) { return 0; } const Klass* const class_loader_klass = cld->class_loader_klass(); - if (class_loader_klass != nullptr && should_tag(class_loader_klass)) { - load_barrier(class_loader_klass); + if (class_loader_klass != nullptr) { + load(class_loader_klass); } return set_used_and_get(cld); } +inline traceid JfrTraceIdLoadBarrier::load(const ModuleEntry* module) { + assert(module != nullptr, "invariant"); + const ClassLoaderData* cld = module->loader_data(); + if (cld != nullptr) { + load(cld); + } + return set_used_and_get(module); +} + +inline traceid JfrTraceIdLoadBarrier::load(const PackageEntry* package) { + assert(package != nullptr, "invariant"); + const ModuleEntry* const module_entry = package->module(); + if (module_entry != nullptr) { + load(module_entry); + } + return set_used_and_get(package); +} + inline traceid JfrTraceIdLoadBarrier::load_leakp(const Klass* klass, const Method* method) { assert(klass != nullptr, "invariant"); assert(METHOD_AND_CLASS_USED_THIS_EPOCH(klass), "invariant"); diff --git a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp index 09a452caaa589..49ced300e5591 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrMemorySpace.inline.hpp @@ -626,8 +626,8 @@ inline bool ReinitializeAllReleaseRetiredOp::process(typename const bool retired = node->retired(); node->reinitialize(); assert(node->empty(), "invariant"); - assert(!node->retired(), "invariant"); if (retired) { + assert(!node->retired(), "invariant"); _prev = _list.excise(_prev, node); node->release(); mspace_release(node, _mspace); From d2d58dd6a8ec366a4bc3eb12a253b252de24557e Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Wed, 10 Jan 2024 13:13:32 +0000 Subject: [PATCH 095/112] 8322324: java/foreign/TestStubAllocFailure.java times out while waiting for forked process 8322637: java/foreign/critical/TestCriticalUpcall.java timed out Reviewed-by: mcimadamore --- test/jdk/java/foreign/UpcallTestHelper.java | 29 ++++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/jdk/java/foreign/UpcallTestHelper.java b/test/jdk/java/foreign/UpcallTestHelper.java index bbc01959ccdaf..8adf5580f514c 100644 --- a/test/jdk/java/foreign/UpcallTestHelper.java +++ b/test/jdk/java/foreign/UpcallTestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -29,8 +29,9 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; -import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; public class UpcallTestHelper extends NativeTestHelper { @@ -50,16 +51,18 @@ public OutputAnalyzer runInNewProcess(Class target, boolean useSpec, List Date: Wed, 10 Jan 2024 13:25:43 +0000 Subject: [PATCH 096/112] 8323508: Remove TestGCLockerWithShenandoah.java line from TEST.groups Reviewed-by: dholmes, shade, tschatzl --- test/hotspot/jtreg/TEST.groups | 1 - 1 file changed, 1 deletion(-) diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 4573c0ebb9b9d..27956797948ed 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -356,7 +356,6 @@ tier2_gc_shenandoah = \ tier3_gc_shenandoah = \ gc/stress/gcold/TestGCOldWithShenandoah.java \ gc/stress/gcbasher/TestGCBasherWithShenandoah.java \ - gc/stress/gclocker/TestGCLockerWithShenandoah.java \ gc/stress/systemgc/TestSystemGCWithShenandoah.java \ gc/shenandoah/TestStringDedupStress.java \ -:tier2_gc_shenandoah From 2806adee2d8cca6bc215f285888631799bd02eac Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 10 Jan 2024 14:07:57 +0000 Subject: [PATCH 097/112] 8321685: Missing ResourceMark in code called from JvmtiEnvBase::get_vthread_jvf Reviewed-by: amenkov, cjplummer --- src/hotspot/share/prims/jvmtiEnvBase.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index 9d6296ee31603..6a3ee71870901 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -2407,6 +2407,7 @@ UpdateForPopTopFrameClosure::doit(Thread *target, bool self) { void SetFramePopClosure::do_thread(Thread *target) { Thread* current = Thread::current(); + ResourceMark rm(current); // vframes are resource allocated JavaThread* java_thread = JavaThread::cast(target); if (java_thread->is_exiting()) { @@ -2433,6 +2434,9 @@ SetFramePopClosure::do_thread(Thread *target) { void SetFramePopClosure::do_vthread(Handle target_h) { + Thread* current = Thread::current(); + ResourceMark rm(current); // vframes are resource allocated + if (!_self && !JvmtiVTSuspender::is_vthread_suspended(target_h())) { _result = JVMTI_ERROR_THREAD_NOT_SUSPENDED; return; From 16170678a72dbd7eecf55c21a426fb6179362fba Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 10 Jan 2024 15:03:21 +0000 Subject: [PATCH 098/112] 8323331: fix typo hpage_pdm_size Reviewed-by: shade, mdoerr --- src/hotspot/os/linux/os_linux.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 5117ccac84bb1..73785461df65e 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2216,7 +2216,7 @@ void os::Linux::print_system_memory_info(outputStream* st) { // https://www.kernel.org/doc/Documentation/vm/transhuge.txt _print_ascii_file_h("/sys/kernel/mm/transparent_hugepage/enabled", "/sys/kernel/mm/transparent_hugepage/enabled", st); - _print_ascii_file_h("/sys/kernel/mm/transparent_hugepage/hpage_pdm_size", + _print_ascii_file_h("/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", st); _print_ascii_file_h("/sys/kernel/mm/transparent_hugepage/shmem_enabled", "/sys/kernel/mm/transparent_hugepage/shmem_enabled", st); From 2174f6646e8897f7e3991141a743c047c6e57026 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 10 Jan 2024 15:18:57 +0000 Subject: [PATCH 099/112] 8323005: Parallel: Refactor PSPromotionManager::claim_or_forward_depth Reviewed-by: tschatzl, rrich --- .../share/gc/parallel/psPromotionManager.cpp | 4 +--- .../gc/parallel/psPromotionManager.inline.hpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.cpp b/src/hotspot/share/gc/parallel/psPromotionManager.cpp index 149acc1a4297f..19f688852385b 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.cpp @@ -272,9 +272,7 @@ template void PSPromotionManager::process_array_chunk_work( T* p = base + start; T* const chunk_end = base + end; while (p < chunk_end) { - if (PSScavenge::should_scavenge(p)) { - claim_or_forward_depth(p); - } + claim_or_forward_depth(p); ++p; } } diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index fd830b831552f..730d31893d54c 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -56,11 +56,14 @@ inline void PSPromotionManager::push_depth(ScannerTask task) { template inline void PSPromotionManager::claim_or_forward_depth(T* p) { - assert(should_scavenge(p, true), "revisiting object?"); assert(ParallelScavengeHeap::heap()->is_in(p), "pointer outside heap"); - oop obj = RawAccess::oop_load(p); - Prefetch::write(obj->mark_addr(), 0); - push_depth(ScannerTask(p)); + T heap_oop = RawAccess<>::oop_load(p); + if (PSScavenge::is_obj_in_young(heap_oop)) { + oop obj = CompressedOops::decode_not_null(heap_oop); + assert(!PSScavenge::is_obj_in_to_space(obj), "revisiting object?"); + Prefetch::write(obj->mark_addr(), 0); + push_depth(ScannerTask(p)); + } } inline void PSPromotionManager::promotion_trace_event(oop new_obj, oop old_obj, @@ -96,9 +99,7 @@ class PSPushContentsClosure: public BasicOopIterateClosure { PSPushContentsClosure(PSPromotionManager* pm) : BasicOopIterateClosure(PSScavenge::reference_processor()), _pm(pm) {} template void do_oop_work(T* p) { - if (PSScavenge::should_scavenge(p)) { - _pm->claim_or_forward_depth(p); - } + _pm->claim_or_forward_depth(p); } virtual void do_oop(oop* p) { do_oop_work(p); } From f0169341846360d202c973ec368fdc3c5bf1ae5d Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 10 Jan 2024 15:19:09 +0000 Subject: [PATCH 100/112] 8323518: Parallel: Remove unused methods in psParallelCompact.hpp Reviewed-by: tschatzl --- .../share/gc/parallel/psParallelCompact.hpp | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 173c883c498d4..94995bd4f195c 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -123,7 +123,6 @@ class SplitInfo // The index of the split region, the size of the partial object on that // region and the destination of the partial object. - size_t src_region_idx() const { return _src_region_idx; } size_t partial_obj_size() const { return _partial_obj_size; } HeapWord* destination() const { return _destination; } @@ -283,9 +282,6 @@ class ParallelCompactData // The location of the java heap data that corresponds to this region. inline HeapWord* data_location() const; - // The highest address referenced by objects in this region. - inline HeapWord* highest_ref() const; - // Whether this region is available to be claimed, has been claimed, or has // been completed. // @@ -314,7 +310,6 @@ class ParallelCompactData // These are atomic. inline void add_live_obj(size_t words); - inline void set_highest_ref(HeapWord* addr); inline void decrement_destination_count(); inline bool claim(); @@ -443,26 +438,16 @@ class ParallelCompactData inline size_t addr_to_region_idx(const HeapWord* addr) const; inline RegionData* addr_to_region_ptr(const HeapWord* addr) const; inline HeapWord* region_to_addr(size_t region) const; - inline HeapWord* region_to_addr(size_t region, size_t offset) const; inline HeapWord* region_to_addr(const RegionData* region) const; inline HeapWord* region_align_down(HeapWord* addr) const; inline HeapWord* region_align_up(HeapWord* addr) const; inline bool is_region_aligned(HeapWord* addr) const; - // Analogous to region_offset() for blocks. - size_t block_offset(const HeapWord* addr) const; size_t addr_to_block_idx(const HeapWord* addr) const; - size_t addr_to_block_idx(const oop obj) const { - return addr_to_block_idx(cast_from_oop(obj)); - } inline BlockData* addr_to_block_ptr(const HeapWord* addr) const; - inline HeapWord* block_to_addr(size_t block) const; - inline size_t region_to_block_idx(size_t region) const; inline HeapWord* block_align_down(HeapWord* addr) const; - inline HeapWord* block_align_up(HeapWord* addr) const; - inline bool is_block_aligned(HeapWord* addr) const; // Return the address one past the end of the partial object. HeapWord* partial_obj_end(size_t region_idx) const; @@ -563,12 +548,6 @@ inline HeapWord* ParallelCompactData::RegionData::data_location() const NOT_DEBUG(return nullptr;) } -inline HeapWord* ParallelCompactData::RegionData::highest_ref() const -{ - DEBUG_ONLY(return _highest_ref;) - NOT_DEBUG(return nullptr;) -} - inline void ParallelCompactData::RegionData::set_data_location(HeapWord* addr) { DEBUG_ONLY(_data_location = addr;) @@ -597,16 +576,6 @@ inline void ParallelCompactData::RegionData::add_live_obj(size_t words) Atomic::add(&_dc_and_los, static_cast(words)); } -inline void ParallelCompactData::RegionData::set_highest_ref(HeapWord* addr) -{ -#ifdef ASSERT - HeapWord* tmp = _highest_ref; - while (addr > tmp) { - tmp = Atomic::cmpxchg(&_highest_ref, tmp, addr); - } -#endif // #ifdef ASSERT -} - inline bool ParallelCompactData::RegionData::claim() { const region_sz_t los = static_cast(live_obj_size()); @@ -695,14 +664,6 @@ ParallelCompactData::region_to_addr(const RegionData* region) const sizeof(RegionData))); } -inline HeapWord* -ParallelCompactData::region_to_addr(size_t region, size_t offset) const -{ - assert(region <= _region_count, "region out of range"); - assert(offset < RegionSize, "offset too big"); // This may be too strict. - return region_to_addr(region) + offset; -} - inline HeapWord* ParallelCompactData::region_align_down(HeapWord* addr) const { @@ -725,14 +686,6 @@ ParallelCompactData::is_region_aligned(HeapWord* addr) const return (size_t(addr) & RegionAddrOffsetMask) == 0; } -inline size_t -ParallelCompactData::block_offset(const HeapWord* addr) const -{ - assert(addr >= _heap_start, "bad addr"); - assert(addr <= _heap_end, "bad addr"); - return (size_t(addr) & BlockAddrOffsetMask) >> LogHeapWordSize; -} - inline size_t ParallelCompactData::addr_to_block_idx(const HeapWord* addr) const { @@ -747,19 +700,6 @@ ParallelCompactData::addr_to_block_ptr(const HeapWord* addr) const return block(addr_to_block_idx(addr)); } -inline HeapWord* -ParallelCompactData::block_to_addr(size_t block) const -{ - assert(block < _block_count, "block out of range"); - return _heap_start + (block << Log2BlockSize); -} - -inline size_t -ParallelCompactData::region_to_block_idx(size_t region) const -{ - return region << Log2BlocksPerRegion; -} - inline HeapWord* ParallelCompactData::block_align_down(HeapWord* addr) const { @@ -768,20 +708,6 @@ ParallelCompactData::block_align_down(HeapWord* addr) const return (HeapWord*)(size_t(addr) & BlockAddrMask); } -inline HeapWord* -ParallelCompactData::block_align_up(HeapWord* addr) const -{ - assert(addr >= _heap_start, "bad addr"); - assert(addr <= _heap_end, "bad addr"); - return block_align_down(addr + BlockSizeOffsetMask); -} - -inline bool -ParallelCompactData::is_block_aligned(HeapWord* addr) const -{ - return block_offset(addr) == 0; -} - // Abstract closure for use with ParMarkBitMap::iterate(), which will invoke the // do_addr() method. // @@ -1170,15 +1096,6 @@ class PSParallelCompact : AllStatic { static inline HeapWord* dense_prefix(SpaceId space_id); static inline ObjectStartArray* start_array(SpaceId space_id); - // Process the end of the given region range in the dense prefix. - // This includes saving any object not updated. - static void dense_prefix_regions_epilogue(ParCompactionManager* cm, - size_t region_start_index, - size_t region_end_index, - idx_t exiting_object_offset, - idx_t region_offset_start, - idx_t region_offset_end); - // Update a region in the dense prefix. For each live object // in the region, update it's interior references. For each // dead object, fill it with deadwood. Dead space at the end From 475306b7576356ca8e5b93fa7fe1be6c4d15065e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 10 Jan 2024 16:34:06 +0000 Subject: [PATCH 101/112] 7057369: (fs spec) FileStore getUsableSpace and getUnallocatedSpace could be clearer Reviewed-by: alanb --- .../share/classes/java/nio/file/FileStore.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/nio/file/FileStore.java b/src/java.base/share/classes/java/nio/file/FileStore.java index fc191d69c1c53..cdd8f66f45a8b 100644 --- a/src/java.base/share/classes/java/nio/file/FileStore.java +++ b/src/java.base/share/classes/java/nio/file/FileStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -103,11 +103,11 @@ protected FileStore() { *

The returned number of available bytes is a hint, but not a * guarantee, that it is possible to use most or any of these bytes. The * number of usable bytes is most likely to be accurate immediately - * after the space attributes are obtained. It is likely to be made inaccurate + * after this method returns. It is likely to be made inaccurate * by any external I/O operations including those made on the system outside * of this Java virtual machine. * - * @return the number of bytes available + * @return the current number of usable bytes * * @throws IOException * if an I/O error occurs @@ -122,11 +122,11 @@ protected FileStore() { *

The returned number of unallocated bytes is a hint, but not a * guarantee, that it is possible to use most or any of these bytes. The * number of unallocated bytes is most likely to be accurate immediately - * after the space attributes are obtained. It is likely to be + * after this method returns. It is likely to be * made inaccurate by any external I/O operations including those made on * the system outside of this virtual machine. * - * @return the number of unallocated bytes + * @return the current number of unallocated bytes * * @throws IOException * if an I/O error occurs From b86c3b7a68335d57699ea3c5ec6d09a62ea9026a Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 10 Jan 2024 16:42:30 +0000 Subject: [PATCH 102/112] 8309218: java/util/concurrent/locks/Lock/OOMEInAQS.java still times out with ZGC, Generational ZGC, and SerialGC Reviewed-by: jpai, dholmes, alanb --- test/jdk/ProblemList-generational-zgc.txt | 3 +-- test/jdk/ProblemList-zgc.txt | 4 +--- test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java | 5 +++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/test/jdk/ProblemList-generational-zgc.txt b/test/jdk/ProblemList-generational-zgc.txt index d6a6f63c6a5e8..9fa9874d20c64 100644 --- a/test/jdk/ProblemList-generational-zgc.txt +++ b/test/jdk/ProblemList-generational-zgc.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2024, 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 @@ -38,4 +38,3 @@ sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java 8307393 generic-all sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java 8307393 generic-all com/sun/jdi/ThreadMemoryLeakTest.java 8307402 generic-all -java/util/concurrent/locks/Lock/OOMEInAQS.java 8309218 generic-all diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index df7edd2cf7d08..9fae070e25d1f 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2024, 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 @@ -27,7 +27,5 @@ # ############################################################################# -java/util/concurrent/locks/Lock/OOMEInAQS.java 8309218 generic-all - sun/tools/jhsdb/JShellHeapDumpTest.java 8276539 generic-all sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java 8276539 generic-all diff --git a/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java b/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java index f8bb222fb98ef..5a78d2791fe6d 100644 --- a/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java +++ b/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -38,7 +38,8 @@ * @test * @bug 8066859 * @summary Check that AQS-based locks, conditions, and CountDownLatches do not fail when encountering OOME - * @run main/othervm -XX:-UseGCOverheadLimit -Xmx48M -XX:-UseTLAB OOMEInAQS + * @requires vm.gc.G1 + * @run main/othervm -XX:+UseG1GC -XX:-UseGCOverheadLimit -Xmx48M -XX:-UseTLAB OOMEInAQS */ public class OOMEInAQS extends Thread { From a7db4fecebe98135d36c6f46e1fa60959adbe78b Mon Sep 17 00:00:00 2001 From: William Kemper Date: Wed, 10 Jan 2024 17:10:39 +0000 Subject: [PATCH 103/112] 8323428: Shenandoah: Unused memory in regions compacted during a full GC should be mangled Reviewed-by: ysr, kdnilsen, shade --- src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index 18fd09ead0ade..4cef5378d30bc 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -910,6 +910,9 @@ class ShenandoahPostCompactClosure : public ShenandoahHeapRegionClosure { // Make empty regions that have been allocated into regular if (r->is_empty() && live > 0) { r->make_regular_bypass(); + if (ZapUnusedHeapArea) { + SpaceMangler::mangle_region(MemRegion(r->top(), r->end())); + } } // Reclaim regular regions that became empty From c96cbe481c86800b76e220374b24b6671984adb7 Mon Sep 17 00:00:00 2001 From: Gerard Ziemski Date: Wed, 10 Jan 2024 17:29:55 +0000 Subject: [PATCH 104/112] 8313083: Print 'rss' and 'cache' as part of the container information Reviewed-by: sgehwolf --- src/hotspot/os/linux/cgroupSubsystem_linux.hpp | 2 ++ src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp | 11 +++++++++++ src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp | 2 ++ src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp | 12 ++++++++++++ src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp | 2 ++ src/hotspot/os/linux/osContainer_linux.cpp | 10 ++++++++++ src/hotspot/os/linux/osContainer_linux.hpp | 2 ++ src/hotspot/os/linux/os_linux.cpp | 2 ++ test/hotspot/jtreg/containers/docker/TestMisc.java | 4 +++- 9 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 6c5470445f18c..3cc2141f176b2 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -266,6 +266,8 @@ class CgroupSubsystem: public CHeapObj { virtual jlong memory_and_swap_limit_in_bytes() = 0; virtual jlong memory_soft_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; + virtual jlong rss_usage_in_bytes() = 0; + virtual jlong cache_usage_in_bytes() = 0; virtual char * cpu_cpuset_cpus() = 0; virtual char * cpu_cpuset_memory_nodes() = 0; diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 146d7237a9070..37a1f476bde8b 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -214,6 +214,17 @@ jlong CgroupV1Subsystem::memory_max_usage_in_bytes() { return memmaxusage; } +jlong CgroupV1Subsystem::rss_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "rss", JULONG_FORMAT, JULONG_FORMAT, rss); + return rss; +} + +jlong CgroupV1Subsystem::cache_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "cache", JULONG_FORMAT, JULONG_FORMAT, cache); + return cache; +} jlong CgroupV1Subsystem::kernel_memory_usage_in_bytes() { GET_CONTAINER_INFO(jlong, _memory->controller(), "/memory.kmem.usage_in_bytes", diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index fae65da2a58fe..c7550136f48bd 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -79,6 +79,8 @@ class CgroupV1Subsystem: public CgroupSubsystem { jlong memory_soft_limit_in_bytes(); jlong memory_usage_in_bytes(); jlong memory_max_usage_in_bytes(); + jlong rss_usage_in_bytes(); + jlong cache_usage_in_bytes(); jlong kernel_memory_usage_in_bytes(); jlong kernel_memory_limit_in_bytes(); diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 1a02bbe95d249..1c433be1c2391 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -139,6 +139,18 @@ jlong CgroupV2Subsystem::memory_max_usage_in_bytes() { return OSCONTAINER_ERROR; // not supported } +jlong CgroupV2Subsystem::rss_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "anon", JULONG_FORMAT, JULONG_FORMAT, rss); + return rss; +} + +jlong CgroupV2Subsystem::cache_usage_in_bytes() { + GET_CONTAINER_INFO_LINE(julong, _memory->controller(), "/memory.stat", + "file", JULONG_FORMAT, JULONG_FORMAT, cache); + return cache; +} + char* CgroupV2Subsystem::mem_soft_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low", "Memory Soft Limit is: %s", "%1023s", mem_soft_limit_str, 1024); diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index bb6b538c216e3..b12b4ce6512cd 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -78,6 +78,8 @@ class CgroupV2Subsystem: public CgroupSubsystem { jlong memory_soft_limit_in_bytes(); jlong memory_usage_in_bytes(); jlong memory_max_usage_in_bytes(); + jlong rss_usage_in_bytes(); + jlong cache_usage_in_bytes(); char * cpu_cpuset_cpus(); char * cpu_cpuset_memory_nodes(); diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index c70c96c678ac6..14bfa5a7678d4 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -92,6 +92,16 @@ jlong OSContainer::memory_max_usage_in_bytes() { return cgroup_subsystem->memory_max_usage_in_bytes(); } +jlong OSContainer::rss_usage_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->rss_usage_in_bytes(); +} + +jlong OSContainer::cache_usage_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->cache_usage_in_bytes(); +} + void OSContainer::print_version_specific_info(outputStream* st) { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); cgroup_subsystem->print_version_specific_info(st); diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index 776167993cba1..bb03ba3b005a2 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -55,6 +55,8 @@ class OSContainer: AllStatic { static jlong memory_soft_limit_in_bytes(); static jlong memory_usage_in_bytes(); static jlong memory_max_usage_in_bytes(); + static jlong rss_usage_in_bytes(); + static jlong cache_usage_in_bytes(); static int active_processor_count(); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 73785461df65e..3a170edd697a0 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2398,6 +2398,8 @@ bool os::Linux::print_container_info(outputStream* st) { OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::cache_usage_in_bytes(), "cache_usage_in_bytes"); OSContainer::print_version_specific_info(st); diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index fbea62f81f8d5..5b7f96112b901 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -117,7 +117,9 @@ private static void checkContainerInfo(OutputAnalyzer out) throws Exception { "Maximum Memory Usage", "memory_max_usage_in_bytes", "maximum number of tasks", - "current number of tasks" + "current number of tasks", + "rss_usage_in_bytes", + "cache_usage_in_bytes" }; for (String s : expectedToContain) { From 5ba69e17340cf44194c080a38219c6e150418fcf Mon Sep 17 00:00:00 2001 From: Vicente Romero Date: Wed, 10 Jan 2024 17:52:50 +0000 Subject: [PATCH 105/112] 8322477: order of subclasses in the permits clause can differ between compilations Reviewed-by: jlahoda --- .../com/sun/tools/javac/code/Symbol.java | 40 ++++++++++++++-- .../com/sun/tools/javac/code/Types.java | 2 +- .../com/sun/tools/javac/comp/Attr.java | 46 +++++++++---------- .../com/sun/tools/javac/comp/Flow.java | 4 +- .../com/sun/tools/javac/comp/TypeEnter.java | 4 +- .../com/sun/tools/javac/jvm/ClassReader.java | 4 +- .../com/sun/tools/javac/jvm/ClassWriter.java | 8 ++-- .../JavacProcessingEnvironment.java | 2 +- .../sealed/SealedDiffConfigurationsTest.java | 35 +++++++++++++- 9 files changed, 106 insertions(+), 39 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 6464afdfff899..2bb36eeded215 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -27,6 +27,7 @@ import java.lang.annotation.Annotation; import java.lang.annotation.Inherited; +import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; @@ -1303,10 +1304,12 @@ public static class ClassSymbol extends TypeSymbol implements TypeElement { // sealed classes related fields /** The classes, or interfaces, permitted to extend this class, or interface */ - public List permitted; + private java.util.List permitted; public boolean isPermittedExplicit = false; + private record PermittedClassWithPos(Symbol permittedClass, int pos) {} + public ClassSymbol(long flags, Name name, Type type, Symbol owner) { super(TYP, flags, name, type, owner); this.members_field = null; @@ -1315,7 +1318,7 @@ public ClassSymbol(long flags, Name name, Type type, Symbol owner) { this.sourcefile = null; this.classfile = null; this.annotationTypeMetadata = AnnotationTypeMetadata.notAnAnnotationType(); - this.permitted = List.nil(); + this.permitted = new ArrayList<>(); } public ClassSymbol(long flags, Name name, Symbol owner) { @@ -1327,6 +1330,37 @@ public ClassSymbol(long flags, Name name, Symbol owner) { this.type.tsym = this; } + public void addPermittedSubclass(ClassSymbol csym, int pos) { + Assert.check(!isPermittedExplicit); + // we need to insert at the right pos + PermittedClassWithPos element = new PermittedClassWithPos(csym, pos); + int index = Collections.binarySearch(permitted, element, java.util.Comparator.comparing(PermittedClassWithPos::pos)); + if (index < 0) { + index = -index - 1; + } + permitted.add(index, element); + } + + public boolean isPermittedSubclass(Symbol csym) { + for (PermittedClassWithPos permittedClassWithPos : permitted) { + if (permittedClassWithPos.permittedClass.equals(csym)) { + return true; + } + } + return false; + } + + public void clearPermittedSubclasses() { + permitted.clear(); + } + + public void setPermittedSubclasses(List permittedSubs) { + permitted.clear(); + for (Symbol csym : permittedSubs) { + permitted.add(new PermittedClassWithPos(csym, 0)); + } + } + /** The Java source which this symbol represents. */ public String toString() { @@ -1643,7 +1677,7 @@ public boolean isRecord() { @DefinedBy(Api.LANGUAGE_MODEL) public List getPermittedSubclasses() { - return permitted.map(s -> s.type); + return permitted.stream().map(s -> s.permittedClass().type).collect(List.collector()); } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java index d6ff37b3e53e2..7af1193c6ce3a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java @@ -1701,7 +1701,7 @@ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) { // permitted subtypes have to be disjoint with the other symbol ClassSymbol sealedOne = ts.isSealed() ? ts : ss; ClassSymbol other = sealedOne == ts ? ss : ts; - return sealedOne.permitted.stream().allMatch(sym -> areDisjoint((ClassSymbol)sym, other)); + return sealedOne.getPermittedSubclasses().stream().allMatch(type -> areDisjoint((ClassSymbol)type.tsym, other)); } return false; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 342ccb267981b..bcc1645293518 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -5383,58 +5383,58 @@ void attribClass(ClassSymbol c) throws CompletionFailure { if (c.isSealed() && !c.isEnum() && !c.isPermittedExplicit && - c.permitted.isEmpty()) { + c.getPermittedSubclasses().isEmpty()) { log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.SealedClassMustHaveSubclasses); } if (c.isSealed()) { Set permittedTypes = new HashSet<>(); boolean sealedInUnnamed = c.packge().modle == syms.unnamedModule || c.packge().modle == syms.noModule; - for (Symbol subTypeSym : c.permitted) { + for (Type subType : c.getPermittedSubclasses()) { boolean isTypeVar = false; - if (subTypeSym.type.getTag() == TYPEVAR) { + if (subType.getTag() == TYPEVAR) { isTypeVar = true; //error recovery - log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), - Errors.InvalidPermitsClause(Fragments.IsATypeVariable(subTypeSym.type))); + log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), + Errors.InvalidPermitsClause(Fragments.IsATypeVariable(subType))); } - if (subTypeSym.isAnonymous() && !c.isEnum()) { - log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.LocalClassesCantExtendSealed(Fragments.Anonymous)); + if (subType.tsym.isAnonymous() && !c.isEnum()) { + log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), Errors.LocalClassesCantExtendSealed(Fragments.Anonymous)); } - if (permittedTypes.contains(subTypeSym)) { + if (permittedTypes.contains(subType.tsym)) { DiagnosticPosition pos = env.enclClass.permitting.stream() - .filter(permittedExpr -> TreeInfo.diagnosticPositionFor(subTypeSym, permittedExpr, true) != null) + .filter(permittedExpr -> TreeInfo.diagnosticPositionFor(subType.tsym, permittedExpr, true) != null) .limit(2).collect(List.collector()).get(1); - log.error(pos, Errors.InvalidPermitsClause(Fragments.IsDuplicated(subTypeSym.type))); + log.error(pos, Errors.InvalidPermitsClause(Fragments.IsDuplicated(subType))); } else { - permittedTypes.add(subTypeSym); + permittedTypes.add(subType.tsym); } if (sealedInUnnamed) { - if (subTypeSym.packge() != c.packge()) { - log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), + if (subType.tsym.packge() != c.packge()) { + log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), Errors.ClassInUnnamedModuleCantExtendSealedInDiffPackage(c) ); } - } else if (subTypeSym.packge().modle != c.packge().modle) { - log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), + } else if (subType.tsym.packge().modle != c.packge().modle) { + log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), Errors.ClassInModuleCantExtendSealedInDiffModule(c, c.packge().modle) ); } - if (subTypeSym == c.type.tsym || types.isSuperType(subTypeSym.type, c.type)) { - log.error(TreeInfo.diagnosticPositionFor(subTypeSym, ((JCClassDecl)env.tree).permitting), + if (subType.tsym == c.type.tsym || types.isSuperType(subType, c.type)) { + log.error(TreeInfo.diagnosticPositionFor(subType.tsym, ((JCClassDecl)env.tree).permitting), Errors.InvalidPermitsClause( - subTypeSym == c.type.tsym ? + subType.tsym == c.type.tsym ? Fragments.MustNotBeSameClass : - Fragments.MustNotBeSupertype(subTypeSym.type) + Fragments.MustNotBeSupertype(subType) ) ); } else if (!isTypeVar) { - boolean thisIsASuper = types.directSupertypes(subTypeSym.type) + boolean thisIsASuper = types.directSupertypes(subType) .stream() .anyMatch(d -> d.tsym == c); if (!thisIsASuper) { - log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), - Errors.InvalidPermitsClause(Fragments.DoesntExtendSealed(subTypeSym.type))); + log.error(TreeInfo.diagnosticPositionFor(subType.tsym, env.tree), + Errors.InvalidPermitsClause(Fragments.DoesntExtendSealed(subType))); } } } @@ -5469,7 +5469,7 @@ void attribClass(ClassSymbol c) throws CompletionFailure { if (!c.type.isCompound()) { for (ClassSymbol supertypeSym : sealedSupers) { - if (!supertypeSym.permitted.contains(c.type.tsym)) { + if (!supertypeSym.isPermittedSubclass(c.type.tsym)) { log.error(TreeInfo.diagnosticPositionFor(c.type.tsym, env.tree), Errors.CantInheritFromSealed(supertypeSym)); } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index dc02b434af02e..e1f5b6f38a0b6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -945,8 +945,8 @@ private Set allPermittedSubTypes(ClassSymbol root, Predicate baseEnv) { !supClass.isPermittedExplicit && supClassEnv != null && supClassEnv.toplevel == baseEnv.toplevel) { - supClass.permitted = supClass.permitted.append(sym); + supClass.addPermittedSubclass(sym, tree.pos); } } } @@ -932,7 +932,7 @@ private void fillPermits(JCClassDecl tree, Env baseEnv) { Type pt = attr.attribBase(permitted, baseEnv, false, false, false); permittedSubtypeSymbols.append(pt.tsym); } - sym.permitted = permittedSubtypeSymbols.toList(); + sym.setPermittedSubclasses(permittedSubtypeSymbols.toList()); } } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index c64877f739229..47c7d9c7d4500 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -1298,7 +1298,7 @@ protected void read(Symbol sym, int attrLen) { for (int i = 0; i < numberOfPermittedSubtypes; i++) { subtypes.add(poolReader.getClass(nextChar())); } - ((ClassSymbol)sym).permitted = subtypes.toList(); + ((ClassSymbol)sym).setPermittedSubclasses(subtypes.toList()); } } }, @@ -2930,7 +2930,7 @@ void readClass(ClassSymbol c) { for (int i = 0; i < methodCount; i++) skipMember(); readClassAttrs(c); - if (c.permitted != null && !c.permitted.isEmpty()) { + if (!c.getPermittedSubclasses().isEmpty()) { c.flags_field |= SEALED; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index aed63c44bb165..625d3fb890b3e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -922,11 +922,11 @@ private void listNested(Symbol sym, ListBuffer seen) { /** Write "PermittedSubclasses" attribute. */ int writePermittedSubclassesIfNeeded(ClassSymbol csym) { - if (csym.permitted.nonEmpty()) { + if (csym.getPermittedSubclasses().nonEmpty()) { int alenIdx = writeAttr(names.PermittedSubclasses); - databuf.appendChar(csym.permitted.size()); - for (Symbol c : csym.permitted) { - databuf.appendChar(poolWriter.putClass((ClassSymbol) c)); + databuf.appendChar(csym.getPermittedSubclasses().size()); + for (Type t : csym.getPermittedSubclasses()) { + databuf.appendChar(poolWriter.putClass((ClassSymbol) t.tsym)); } endAttr(alenIdx); return 1; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 028b8ba8f9f7d..c9fba2389012d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1643,7 +1643,7 @@ public void visitClassDef(JCClassDecl node) { originalAnnos.forEach(a -> visitAnnotation(a)); } // we should empty the list of permitted subclasses for next round - node.sym.permitted = List.nil(); + node.sym.clearPermittedSubclasses(); } node.sym = null; } diff --git a/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java b/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java index 0b20fee0b81a3..16860d65cc232 100644 --- a/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java +++ b/test/langtools/tools/javac/sealed/SealedDiffConfigurationsTest.java @@ -142,7 +142,6 @@ private void checkSealedClassFile(Path out, String cfName, List expected } catch (ConstantPoolException ex) { } }); - subtypeNames.sort((s1, s2) -> s1.compareTo(s2)); for (int i = 0; i < expectedSubTypeNames.size(); i++) { Assert.check(expectedSubTypeNames.get(0).equals(subtypeNames.get(0))); } @@ -695,4 +694,38 @@ public void testSupertypePermitsLoop(Path base) throws Exception { .run() .writeAll(); } + + @Test + public void testClientSwapsPermittedSubclassesOrder(Path base) throws Exception { + Path src = base.resolve("src"); + Path foo = src.resolve("Foo.java"); + Path fooUser = src.resolve("FooUser.java"); + + tb.writeFile(foo, + """ + public sealed interface Foo { + record R1() implements Foo {} + record R2() implements Foo {} + } + """); + + tb.writeFile(fooUser, + """ + public class FooUser { + // see that the order of arguments differ from the order of subclasses of Foo in the source above + // we need to check that the order of permitted subclasses of Foo in the class file corresponds to the + // original order in the source code + public void blah(Foo.R2 a, Foo.R1 b) {} + } + """); + + Path out = base.resolve("out"); + Files.createDirectories(out); + + new JavacTask(tb) + .outdir(out) + .files(fooUser, foo) + .run(); + checkSealedClassFile(out, "Foo.class", List.of("Foo$R1", "Foo$R2")); + } } From c1282b57f50002edd08c93aed784390cca83b9b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 10 Jan 2024 18:37:33 +0000 Subject: [PATCH 106/112] 8323540: assert((!((((method)->is_trace_flag_set(((1 << 4) << 8))))))) failed: invariant Reviewed-by: mikael --- src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 2d49c5aa405fb..8df2f6593efd2 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -953,7 +953,6 @@ static int write_method(JfrCheckpointWriter* writer, MethodPtr method, bool leak int write__method(JfrCheckpointWriter* writer, const void* m) { assert(m != nullptr, "invariant"); MethodPtr method = static_cast(m); - assert(METHOD_IS_NOT_SERIALIZED(method), "invariant"); set_serialized(method); return write_method(writer, method, false); } From 525063be90bc67257e5d9301a4270179c03ada9d Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 10 Jan 2024 18:46:56 +0000 Subject: [PATCH 107/112] 8322878: Including sealing information Class.toGenericString() Co-authored-by: Pavel Rappo Reviewed-by: rriggs --- .../share/classes/java/lang/Class.java | 53 +++++- .../java/lang/Class/GenericStringTest.java | 172 ++++++++++++++++-- 2 files changed, 205 insertions(+), 20 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 851d65d06ad77..4573a6dc69004 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, 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 @@ -261,7 +261,8 @@ public String toString() { /** * Returns a string describing this {@code Class}, including - * information about modifiers and type parameters. + * information about modifiers, {@link #isSealed() sealed}/{@code + * non-sealed} status, and type parameters. * * The string is formatted as a list of type modifiers, if any, * followed by the kind of type (empty string for primitive types @@ -314,6 +315,11 @@ public String toGenericString() { sb.append(' '); } + // A class cannot be strictfp and sealed/non-sealed so + // it is sufficient to check for sealed-ness after all + // modifiers are printed. + addSealingInfo(modifiers, sb); + if (isAnnotation()) { sb.append('@'); } @@ -344,6 +350,49 @@ else if (isRecord()) } } + private void addSealingInfo(int modifiers, StringBuilder sb) { + // A class can be final XOR sealed XOR non-sealed. + if (Modifier.isFinal(modifiers)) { + return; // no-op + } else { + if (isSealed()) { + sb.append("sealed "); + return; + } else { + // Check for sealed ancestor, which implies this class + // is non-sealed. + if (hasSealedAncestor(this)) { + sb.append("non-sealed "); + } + } + } + } + + private boolean hasSealedAncestor(Class clazz) { + // From JLS 8.1.1.2: + // "It is a compile-time error if a class has a sealed direct + // superclass or a sealed direct superinterface, and is not + // declared final, sealed, or non-sealed either explicitly or + // implicitly. + // Thus, an effect of the sealed keyword is to force all + // direct subclasses to explicitly declare whether they are + // final, sealed, or non-sealed. This avoids accidentally + // exposing a sealed class hierarchy to unwanted subclassing." + + // Therefore, will just check direct superclass and + // superinterfaces. + var superclass = clazz.getSuperclass(); + if (superclass != null && superclass.isSealed()) { + return true; + } + for (var superinterface : clazz.getInterfaces()) { + if (superinterface.isSealed()) { + return true; + } + } + return false; + } + static String typeVarBounds(TypeVariable typeVar) { Type[] bounds = typeVar.getBounds(); if (bounds.length == 1 && bounds[0].equals(Object.class)) { diff --git a/test/jdk/java/lang/Class/GenericStringTest.java b/test/jdk/java/lang/Class/GenericStringTest.java index f117a44b4465c..71f39f602283f 100644 --- a/test/jdk/java/lang/Class/GenericStringTest.java +++ b/test/jdk/java/lang/Class/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -23,9 +23,8 @@ /* * @test - * @bug 6298888 6992705 8161500 6304578 + * @bug 6298888 6992705 8161500 6304578 8322878 * @summary Check Class.toGenericString() - * @author Joseph D. Darcy */ import java.lang.reflect.*; @@ -37,25 +36,41 @@ public class GenericStringTest { public Map[] mixed = null; public Map[][] mixed2 = null; + private static record PlatformTestCase(Class clazz, String expected) {} + public static void main(String... args) throws ReflectiveOperationException { int failures = 0; String[][] nested = {{""}}; int[][] intArray = {{1}}; - Map, String> testCases = - Map.of(int.class, "int", - void.class, "void", - args.getClass(), "java.lang.String[]", - nested.getClass(), "java.lang.String[][]", - intArray.getClass(), "int[][]", - java.lang.Enum.class, "public abstract class java.lang.Enum>", - java.util.Map.class, "public abstract interface java.util.Map", - java.util.EnumMap.class, "public class java.util.EnumMap,V>", - java.util.EventListenerProxy.class, "public abstract class java.util.EventListenerProxy"); - - for (Map.Entry, String> testCase : testCases.entrySet()) { - failures += checkToGenericString(testCase.getKey(), testCase.getValue()); + List platformTestCases = + List.of(new PlatformTestCase(int.class, "int"), + new PlatformTestCase(void.class, "void"), + new PlatformTestCase(args.getClass(), "java.lang.String[]"), + new PlatformTestCase(nested.getClass(), "java.lang.String[][]"), + new PlatformTestCase(intArray.getClass(), "int[][]"), + + new PlatformTestCase(java.lang.Enum.class, + "public abstract class java.lang.Enum>"), + new PlatformTestCase(java.util.Map.class, + "public abstract interface java.util.Map"), + new PlatformTestCase(java.util.EnumMap.class, + "public class java.util.EnumMap,V>"), + new PlatformTestCase(java.util.EventListenerProxy.class, + "public abstract class java.util.EventListenerProxy"), + + // Sealed class + new PlatformTestCase(java.lang.ref.Reference.class, + "public abstract sealed class java.lang.ref.Reference"), + // non-sealed class + new PlatformTestCase(java.lang.ref.WeakReference.class, + "public non-sealed class java.lang.ref.WeakReference") + ); + + for (PlatformTestCase platformTestCase : platformTestCases) { + failures += checkToGenericString(platformTestCase.clazz, + platformTestCase.expected); } Field f = GenericStringTest.class.getDeclaredField("mixed"); @@ -70,7 +85,33 @@ public static void main(String... args) throws ReflectiveOperationException { AnInterface.class, LocalMap.class, AnEnum.class, - AnotherEnum.class)) { + AnotherEnum.class, + + SealedRootClass.class, + SealedRootClass.ChildA.class, + SealedRootClass.ChildB.class, + SealedRootClass.ChildB.GrandChildAB.class, + SealedRootClass.ChildC.class, + SealedRootClass.ChildC.GrandChildACA.class, + SealedRootClass.ChildC.GrandChildACB.class, + SealedRootClass.ChildC.GrandChildACC.class, + SealedRootClass.ChildC.GrandChildACC.GreatGrandChildACCA.class, + SealedRootClass.ChildC.GrandChildACC.GreatGrandChildACCB.class, + + SealedRootIntf.class, + SealedRootIntf.ChildA.class, + SealedRootIntf.ChildB.class, + SealedRootIntf.ChildB.GrandChildAB.class, + SealedRootIntf.ChildC.class, + SealedRootIntf.ChildC.GrandChildACA.class, + SealedRootIntf.ChildC.GrandChildACB.class, + SealedRootIntf.ChildC.GrandChildACC.class, + SealedRootIntf.ChildC.GrandChildACC.GreatGrandChildACCA.class, + SealedRootIntf.ChildC.GrandChildACC.GreatGrandChildACCB.class, + SealedRootIntf.IntfA.class, + SealedRootIntf.IntfA.IntfAImpl.class, + SealedRootIntf.IntfB.class, + SealedRootIntf.IntfB.IntfAImpl.class)) { failures += checkToGenericString(clazz, clazz.getAnnotation(ExpectedGenericString.class).value()); } @@ -107,7 +148,102 @@ enum AnEnum { FOO; } -@ExpectedGenericString("enum AnotherEnum") +// If an enum class has a specialized enum constant, that is compiled +// by having the enum class as being sealed rather than final. See JLS +// 8.9 Enum Classes. +@ExpectedGenericString("sealed enum AnotherEnum") enum AnotherEnum { BAR{}; } + +// Test cases for sealed/non-sealed _class_ hierarchy. +@ExpectedGenericString("sealed class SealedRootClass") +sealed class SealedRootClass + permits + SealedRootClass.ChildA, + SealedRootClass.ChildB, + SealedRootClass.ChildC { + + @ExpectedGenericString("final class SealedRootClass$ChildA") + final class ChildA extends SealedRootClass {} + + @ExpectedGenericString("sealed class SealedRootClass$ChildB") + sealed class ChildB extends SealedRootClass permits SealedRootClass.ChildB.GrandChildAB { + @ExpectedGenericString("final class SealedRootClass$ChildB$GrandChildAB") + final class GrandChildAB extends ChildB {} + } + + @ExpectedGenericString("non-sealed class SealedRootClass$ChildC") + non-sealed class ChildC extends SealedRootClass { + // The subclasses of ChildC do not themselves have to be + // sealed, non-sealed, or final. + @ExpectedGenericString("class SealedRootClass$ChildC$GrandChildACA") + class GrandChildACA extends ChildC {} + + @ExpectedGenericString("final class SealedRootClass$ChildC$GrandChildACB") + final class GrandChildACB extends ChildC {} + + @ExpectedGenericString("sealed class SealedRootClass$ChildC$GrandChildACC") + sealed class GrandChildACC extends ChildC { + @ExpectedGenericString("final class SealedRootClass$ChildC$GrandChildACC$GreatGrandChildACCA") + final class GreatGrandChildACCA extends GrandChildACC {} + + @ExpectedGenericString("non-sealed class SealedRootClass$ChildC$GrandChildACC$GreatGrandChildACCB") + non-sealed class GreatGrandChildACCB extends GrandChildACC {} + } + } +} + +// Test cases for sealed/non-sealed _interface_ hierarchy. +@ExpectedGenericString("abstract sealed interface SealedRootIntf") +sealed interface SealedRootIntf + permits + SealedRootIntf.ChildA, + SealedRootIntf.ChildB, + SealedRootIntf.ChildC, + + SealedRootIntf.IntfA, + SealedRootIntf.IntfB { + + @ExpectedGenericString("public static final class SealedRootIntf$ChildA") + final class ChildA implements SealedRootIntf {} + + @ExpectedGenericString("public static sealed class SealedRootIntf$ChildB") + sealed class ChildB implements SealedRootIntf permits SealedRootIntf.ChildB.GrandChildAB { + @ExpectedGenericString("final class SealedRootIntf$ChildB$GrandChildAB") + final class GrandChildAB extends ChildB {} + } + + @ExpectedGenericString("public static non-sealed class SealedRootIntf$ChildC") + non-sealed class ChildC implements SealedRootIntf { + // The subclasses of ChildC do not themselves have to be + // sealed, non-sealed, or final. + @ExpectedGenericString("class SealedRootIntf$ChildC$GrandChildACA") + class GrandChildACA extends ChildC {} + + @ExpectedGenericString("final class SealedRootIntf$ChildC$GrandChildACB") + final class GrandChildACB extends ChildC {} + + @ExpectedGenericString("sealed class SealedRootIntf$ChildC$GrandChildACC") + sealed class GrandChildACC extends ChildC { + @ExpectedGenericString("final class SealedRootIntf$ChildC$GrandChildACC$GreatGrandChildACCA") + final class GreatGrandChildACCA extends GrandChildACC {} + + @ExpectedGenericString("non-sealed class SealedRootIntf$ChildC$GrandChildACC$GreatGrandChildACCB") + non-sealed class GreatGrandChildACCB extends GrandChildACC {} + } + } + + @ExpectedGenericString("public abstract static sealed interface SealedRootIntf$IntfA") + sealed interface IntfA extends SealedRootIntf { + @ExpectedGenericString("public static non-sealed class SealedRootIntf$IntfA$IntfAImpl") + non-sealed class IntfAImpl implements IntfA {} + } + + @ExpectedGenericString("public abstract static non-sealed interface SealedRootIntf$IntfB") + non-sealed interface IntfB extends SealedRootIntf { + // Check that non-sealing can be allowed with a second superinterface being sealed. + @ExpectedGenericString("public static non-sealed class SealedRootIntf$IntfB$IntfAImpl") + non-sealed class IntfAImpl implements IntfB, IntfA {} + } +} From 3bd9042054116365323912ed5867b70936fe85c4 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 10 Jan 2024 18:54:02 +0000 Subject: [PATCH 108/112] 8320788: The system properties page is missing some properties Reviewed-by: iris, rriggs, bpb, joehw --- src/java.base/share/classes/java/lang/System.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 227982af9eaf6..39ecb2a6436ca 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -57,6 +57,7 @@ import java.security.ProtectionDomain; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Properties; @@ -813,6 +814,10 @@ public static native void arraycopy(Object src, int srcPos, * Note that even if the security manager does not permit the * {@code getProperties} operation, it may choose to permit the * {@link #getProperty(String)} operation. + *

+ * Additional locale-related system properties defined by the + * {@link Locale##default_locale Default Locale} section in the {@code Locale} + * class description may also be obtained with this method. * * @apiNote * Changing a standard system property may have unpredictable results From d89602a53f173e4fc1e0aa10bb0ffdf7232456cb Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Wed, 10 Jan 2024 19:42:03 +0000 Subject: [PATCH 109/112] 8322982: CTW fails to build after 8308753 Reviewed-by: shade, phh --- test/hotspot/jtreg/testlibrary/ctw/Makefile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary/ctw/Makefile b/test/hotspot/jtreg/testlibrary/ctw/Makefile index 5ba3bbb659a42..b67500d0c5e0b 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/Makefile +++ b/test/hotspot/jtreg/testlibrary/ctw/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2024, 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 @@ -42,21 +42,18 @@ JAVAC = $(JDK_HOME)/bin/javac JAR = $(JDK_HOME)/bin/jar SRC_FILES = $(shell find $(SRC_DIR) -name '*.java') -LIB_FILES = $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/ \ +# Exclude files that need '--enable-preview' to compile. +LIB_FILES = $(filter-out %ModuleInfoWriter.java, $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/ \ $(TESTLIBRARY_DIR)/jdk/test/lib/process \ $(TESTLIBRARY_DIR)/jdk/test/lib/util \ $(TESTLIBRARY_DIR)/jtreg \ - -maxdepth 1 -name '*.java') + -maxdepth 1 -name '*.java')) WB_SRC_FILES = $(shell find $(TESTLIBRARY_DIR)/jdk/test/lib/compiler $(TESTLIBRARY_DIR)/jdk/test/whitebox -name '*.java') WB_CLASS_FILES := $(subst $(TESTLIBRARY_DIR)/,,$(WB_SRC_FILES)) WB_CLASS_FILES := $(patsubst %.java,%.class,$(WB_CLASS_FILES)) EXPORTS=--add-exports java.base/jdk.internal.jimage=ALL-UNNAMED \ --add-exports java.base/jdk.internal.misc=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.module=ALL-UNNAMED \ --add-exports java.base/jdk.internal.reflect=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.classfile=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.classfile.attribute=ALL-UNNAMED \ - --add-exports java.base/jdk.internal.classfile.constantpool=ALL-UNNAMED \ --add-exports java.base/jdk.internal.access=ALL-UNNAMED CTW_MAIN_CLASS = sun.hotspot.tools.ctw.CompileTheWorld From e70cb4e6c7fe131d585cfa3ff3b4dbeb4f9bbccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?= Date: Wed, 10 Jan 2024 21:42:23 +0000 Subject: [PATCH 110/112] 8322565: (zipfs) Files.setPosixPermissions should preserve 'external file attributes' bits Reviewed-by: clanger, lancea --- .../classes/jdk/nio/zipfs/ZipFileSystem.java | 11 +- test/jdk/jdk/nio/zipfs/TestPosix.java | 161 ++++++++++++++---- 2 files changed, 136 insertions(+), 36 deletions(-) diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java index 1924ccd11f86b..7b478151c43e8 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, 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 @@ -644,7 +644,12 @@ void setPermissions(byte[] path, Set perms) throws IOExcept if (e.type == Entry.CEN) { e.type = Entry.COPY; // copy e } - e.posixPerms = perms == null ? -1 : ZipUtils.permsToFlags(perms); + if (perms == null) { + e.posixPerms = -1; + } else { + e.posixPerms = ZipUtils.permsToFlags(perms) | + (e.posixPerms & 0xFE00); // Preserve unrelated bits + } update(e); } finally { endWrite(); @@ -3008,7 +3013,7 @@ private void readCEN(ZipFileSystem zipfs, IndexNode inode) throws IOException { attrsEx = CENATX(cen, pos); */ if (CENVEM_FA(cen, pos) == FILE_ATTRIBUTES_UNIX) { - posixPerms = CENATX_PERMS(cen, pos) & 0xFFF; // 12 bits for setuid, setgid, sticky + perms + posixPerms = (CENATX_PERMS(cen, pos) & 0xFFFF); // 16 bits for file type, setuid, setgid, sticky + perms } locoff = CENOFF(cen, pos); pos += CENHDR; diff --git a/test/jdk/jdk/nio/zipfs/TestPosix.java b/test/jdk/jdk/nio/zipfs/TestPosix.java index f629dfef2225d..1fa3bdf2d7b26 100644 --- a/test/jdk/jdk/nio/zipfs/TestPosix.java +++ b/test/jdk/jdk/nio/zipfs/TestPosix.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, SAP SE. All rights reserved. + * Copyright (c) 2019, 2024, SAP SE. 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 @@ -25,23 +25,16 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.GroupPrincipal; -import java.nio.file.attribute.PosixFileAttributeView; -import java.nio.file.attribute.PosixFileAttributes; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.nio.file.attribute.UserPrincipal; +import java.nio.file.attribute.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.time.Instant; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.jar.JarEntry; import java.util.jar.JarFile; @@ -49,7 +42,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Test; import static java.nio.file.attribute.PosixFilePermission.GROUP_EXECUTE; import static java.nio.file.attribute.PosixFilePermission.GROUP_READ; @@ -60,11 +53,11 @@ import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /** * @test @@ -72,8 +65,8 @@ * @summary Test POSIX ZIP file operations. * @modules jdk.zipfs * jdk.jartool - * @run testng TestPosix - * @run testng/othervm/java.security.policy=test.policy.posix TestPosix + * @run junit TestPosix + * @run junit/othervm/java.security.policy=test.policy.posix TestPosix */ public class TestPosix { private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") @@ -364,7 +357,7 @@ private void checkEntry(Path file, checkExpects expected) { fail("Caught IOException reading file attributes (basic) " + name + ": " + e.getMessage()); } } - assertEquals(Files.isDirectory(file), ei.isDir, "Unexpected directory attribute for:" + System.lineSeparator() + attrs); + assertEquals(ei.isDir, Files.isDirectory(file), "Unexpected directory attribute for:" + System.lineSeparator() + attrs); if (expected == checkExpects.contentOnly) { return; @@ -402,7 +395,7 @@ private void doCheckEntries(Path path, checkExpects expected) throws IOException }); } System.out.println("Number of entries: " + entries.get() + "."); - assertEquals(entries.get(), entriesCreated, "File contained wrong number of entries."); + assertEquals(entriesCreated, entries.get(), "File contained wrong number of entries."); } private void checkEntries(FileSystem fs, checkExpects expected) throws IOException { @@ -429,7 +422,7 @@ private void comparePermissions(Set expected, Set { + Path path = fs.getPath("hello.txt"); + // Set permissions to their current value + Files.setPosixFilePermissions(path, Files.getPosixFilePermissions(path)); + }); + } + + /** + * Verify that a non-POSIX operation such as Files.setLastModifiedTime + * does not change the 'external file attributes' field. + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void setLastModifiedTimeShouldNotChangeExternalFileAttribute() throws IOException { + assertExternalFileAttributeUnchanged(fs -> { + Path path = fs.getPath("hello.txt"); + Files.setLastModifiedTime(path, FileTime.from(Instant.now())); + }); + } + + // Represents an operation performed on a FileSystem + static interface FileSystemOperation { + void accept(FileSystem fileSystem) throws IOException; + } + + /** + * Assert that running the given operation on a ZipFileSystem does not + * change the 'external file attributes' value of the 'hello.txt' entry + * @param action the action to run on the file system + * + * @throws IOException if an unexpected IOException occurs + */ + private void assertExternalFileAttributeUnchanged(FileSystemOperation action) throws IOException { + /* + * The ZIP test vector used here is created using: + * % touch hello.txt + * % chmod u+s hello.txt # setuid + * % chmod g+s hello.txt # setgid + * % chmod +t hello.txt # sticky + * % zip hello.zip hello.txt + * % cat hello.zip | xxd -ps + */ + byte[] zip = HexFormat.of().parseHex(""" + 504b03040a0000000000d994945700000000000000000000000009001c00 + 68656c6c6f2e7478745554090003aa268365aa26836575780b000104f501 + 00000414000000504b01021e030a0000000000d994945700000000000000 + 0000000000090018000000000000000000a48f0000000068656c6c6f2e74 + 78745554050003aa26836575780b000104f50100000414000000504b0506 + 00000000010001004f000000430000000000 + """.replaceAll("\n","")); + + // Expected bit values of the 'external file attributes' CEN field in the ZIP above + String expectedBits = "1000111110100100"; + // ^^^^ file type: 1000 (regular file) + // ^ setuid: ON + // ^ setgid: ON + // ^ sticky: ON + // ^^^^^^^^^ rwxr--r-- (9 bits) + + // Sanity check that 'external file attributes' has the expected value + verifyExternalFileAttribute(zip, expectedBits); + + + Path zipFile = Path.of("preserve-external-file-attrs.zip"); + Files.write(zipFile, zip); + + // Run the provided action on the ZipFileSystem + try (FileSystem fs = FileSystems.newFileSystem(zipFile, ENV_POSIX)) { + action.accept(fs); + } + // Running the action should not change the 'external file attributes' value + verifyExternalFileAttribute(Files.readAllBytes(zipFile), expectedBits); + } + + /** + * Verify that the first 16 bits of the CEN field 'external file attributes' matches + * a given bit string + * @param zip the ZIP file to parse + * @param expectedBits a string of '0' or '1' representing the expected bits + */ + private void verifyExternalFileAttribute(byte[] zip, String expectedBits) { + // Buffer to help parse the ZIP + ByteBuffer buffer = ByteBuffer.wrap(zip).order(ByteOrder.LITTLE_ENDIAN); + // Look up offset of first CEN header from the END header + int cenOff = buffer.getInt(buffer.capacity() - ZipFile.ENDHDR + ZipFile.ENDOFF); + // We're interested in the first 16 'unix' bits of the 32-bit 'external file attributes' field + int externalFileAttr = (buffer.getInt(cenOff + ZipFile.CENATX) >> 16) & 0xFFFF; + + // Verify that the expected bits are set + assertEquals(expectedBits, Integer.toBinaryString(externalFileAttr), + "The 'external file attributes' field does not match the expected value:"); } } From b530c0281b5082994065b10addeb8366ffa58e2f Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Thu, 11 Jan 2024 00:36:16 +0000 Subject: [PATCH 111/112] 8317804: com/sun/jdi/JdwpAllowTest.java fails on Alpine 3.17 / 3.18 Reviewed-by: cjplummer, mbaesken --- .../share/native/libdt_socket/socketTransport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c b/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c index d494a7ecb2cee..28eb403448f67 100644 --- a/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c +++ b/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -752,7 +752,7 @@ socketTransport_startListening(jdwpTransportEnv* env, const char* address, if (isEqualIPv6Addr(listenAddr, mappedAny)) { for (ai = addrInfo; ai != NULL; ai = ai->ai_next) { - if (isEqualIPv6Addr(listenAddr, in6addr_any)) { + if (isEqualIPv6Addr(ai, in6addr_any)) { listenAddr = ai; break; } From 26de9e247a6ed1c0b8b247d77514ed16905d7c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?= Date: Thu, 11 Jan 2024 06:32:24 +0000 Subject: [PATCH 112/112] 8321616: Retire binary test vectors in test/jdk/java/util/zip/ZipFile 8322830: Add test case for ZipFile opening a ZIP with no entries Reviewed-by: lancea --- test/jdk/java/util/zip/CopyZipFile.java | 291 ++++++----- test/jdk/java/util/zip/ZipFile/Available.java | 37 -- test/jdk/java/util/zip/ZipFile/CopyJar.java | 48 -- .../java/util/zip/ZipFile/EnumAfterClose.java | 49 -- .../util/zip/ZipFile/EnumerateAfterClose.java | 94 ++++ .../util/zip/ZipFile/FinalizeInflater.java | 67 ++- .../java/util/zip/ZipFile/GetDirEntry.java | 43 -- .../java/util/zip/ZipFile/ReadAfterClose.java | 51 -- test/jdk/java/util/zip/ZipFile/ReadZip.java | 476 ++++++++++++------ .../util/zip/ZipFile/ReleaseInflater.java | 79 ++- .../zip/ZipFile/StreamZipEntriesTest.java | 157 ++++-- test/jdk/java/util/zip/ZipFile/crash.jar | Bin 781 -> 0 bytes test/jdk/java/util/zip/ZipFile/input.jar | Bin 832 -> 0 bytes test/jdk/java/util/zip/ZipFile/input.zip | Bin 450 -> 0 bytes 14 files changed, 837 insertions(+), 555 deletions(-) delete mode 100644 test/jdk/java/util/zip/ZipFile/Available.java delete mode 100644 test/jdk/java/util/zip/ZipFile/CopyJar.java delete mode 100644 test/jdk/java/util/zip/ZipFile/EnumAfterClose.java create mode 100644 test/jdk/java/util/zip/ZipFile/EnumerateAfterClose.java delete mode 100644 test/jdk/java/util/zip/ZipFile/GetDirEntry.java delete mode 100644 test/jdk/java/util/zip/ZipFile/ReadAfterClose.java delete mode 100644 test/jdk/java/util/zip/ZipFile/crash.jar delete mode 100644 test/jdk/java/util/zip/ZipFile/input.jar delete mode 100644 test/jdk/java/util/zip/ZipFile/input.zip diff --git a/test/jdk/java/util/zip/CopyZipFile.java b/test/jdk/java/util/zip/CopyZipFile.java index e6fa4bfe057c2..ae90e4b6400db 100644 --- a/test/jdk/java/util/zip/CopyZipFile.java +++ b/test/jdk/java/util/zip/CopyZipFile.java @@ -23,99 +23,120 @@ /** * @test + * @bug 8253952 * @summary Test behaviour when copying ZipEntries between zip files. - * @run main/othervm CopyZipFile + * @run junit CopyZipFile */ -import java.io.File; -import java.io.ByteArrayOutputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.zip.CRC32; -import java.util.zip.Deflater; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; +import java.util.zip.*; + +import static org.junit.jupiter.api.Assertions.*; public class CopyZipFile { - private static final String ZIP_FILE = "first.zip"; - private static final String TEST_STRING = "TestTestTest"; + // ZIP file created in this test + private Path zip = Path.of("first.zip"); + // The content to put in each entry + private static final byte[] TEST_STRING = "TestTestTest".getBytes(StandardCharsets.UTF_8); - private static void createZip(String zipFile) throws Exception { - File f = new File(zipFile); - f.deleteOnExit(); - try (OutputStream os = new FileOutputStream(f); + /** + * Create the sample ZIP file used in this test, including a STORED entry + * and DEFLATE entries with various compression levels. + * @throws IOException if an unexpected IOException occurs + */ + @BeforeEach + public void createZip() throws IOException { + // By default, ZipOutputStream creates zip files with Local File Headers + // without size, compressed size and crc values and an extra Data + // Descriptor (see https://en.wikipedia.org/wiki/Zip_(file_format) + // after the data belonging to that entry with these values if in the + // corresponding ZipEntry one of the size, compressedSize or crc fields is + // equal to '-1' (which is the default for newly created ZipEntries). + try (OutputStream os = Files.newOutputStream(zip) ; ZipOutputStream zos = new ZipOutputStream(os)) { // First file will be compressed with DEFAULT_COMPRESSION (i.e. -1 or 6) - zos.putNextEntry(new ZipEntry("test1.txt")); - zos.write(TEST_STRING.getBytes()); - zos.closeEntry(); + zos.setLevel(Deflater.DEFAULT_COMPRESSION); + zos.putNextEntry(new ZipEntry("DEFAULT_COMPRESSION.txt")); + zos.write(TEST_STRING); + // Second file won't be compressed at all (i.e. STORED) zos.setMethod(ZipOutputStream.STORED); - ZipEntry ze = new ZipEntry("test2.txt"); - int length = TEST_STRING.length(); - ze.setSize(length); - ze.setCompressedSize(length); + ZipEntry ze = new ZipEntry("STORED.txt"); + ze.setSize(TEST_STRING.length); + ze.setCompressedSize(TEST_STRING.length); CRC32 crc = new CRC32(); - crc.update(TEST_STRING.getBytes("utf8"), 0, length); + crc.update(TEST_STRING); ze.setCrc(crc.getValue()); zos.putNextEntry(ze); - zos.write(TEST_STRING.getBytes()); + zos.write(TEST_STRING); + // Third file will be compressed with NO_COMPRESSION (i.e. 0) zos.setMethod(ZipOutputStream.DEFLATED); zos.setLevel(Deflater.NO_COMPRESSION); - zos.putNextEntry(new ZipEntry("test3.txt")); - zos.write(TEST_STRING.getBytes()); + zos.putNextEntry(new ZipEntry("NO_COMPRESSION.txt")); + zos.write(TEST_STRING); + // Fourth file will be compressed with BEST_SPEED (i.e. 1) zos.setLevel(Deflater.BEST_SPEED); - zos.putNextEntry(new ZipEntry("test4.txt")); - zos.write(TEST_STRING.getBytes()); + zos.putNextEntry(new ZipEntry("BEST_SPEED.txt")); + zos.write(TEST_STRING); + // Fifth file will be compressed with BEST_COMPRESSION (i.e. 9) zos.setLevel(Deflater.BEST_COMPRESSION); - zos.putNextEntry(new ZipEntry("test5.txt")); - zos.write(TEST_STRING.getBytes()); + zos.putNextEntry(new ZipEntry("BEST_COMPRESSION.txt")); + zos.write(TEST_STRING); } } - public static void main(String args[]) throws Exception { - // By default, ZipOutputStream creates zip files with Local File Headers - // without size, compressedSize and crc values and an extra Data - // Descriptor (see https://en.wikipedia.org/wiki/Zip_(file_format) - // after the data belonging to that entry with these values if in the - // corresponding ZipEntry one of the size, compressedSize or crc fields is - // equal to '-1' (which is the default for newly created ZipEntries). - createZip(ZIP_FILE); - - // Now read all the entries of the newly generated zip file with a ZipInputStream - // and copy them to a new zip file with the help of a ZipOutputStream. - // This only works reliably because the generated zip file has no values for the - // size, compressedSize and crc values of a zip entry in the local file header and - // therefore the ZipEntry objects created by ZipOutputStream.getNextEntry() will have - // all these fields set to '-1'. - ZipEntry entry; - byte[] buf = new byte[512]; - try (InputStream is = new FileInputStream(ZIP_FILE); - ZipInputStream zis = new ZipInputStream(is); - OutputStream os = new ByteArrayOutputStream(); - ZipOutputStream zos = new ZipOutputStream(os)) { - while((entry = zis.getNextEntry())!=null) { + /** + * Delete the ZIP file produced by this test + * @throws IOException if an unexpected IOException occurs + */ + @AfterEach + public void cleanup() throws IOException { + Files.deleteIfExists(zip); + } + + /** + * Read all entries using ZipInputStream.getNextEntry and copy them + * to a new zip file using ZipOutputStream.putNextEntry. This only works + * reliably because the input zip file has no values for the size, compressedSize + * and crc values of streamed zip entries in the local file header and + * therefore the ZipEntry objects created by ZipOutputStream.getNextEntry + * will have all these fields set to '-1'. + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void copyFromZipInputStreamToZipOutputStream() throws IOException { + + try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(zip)); + ZipOutputStream zos = new ZipOutputStream(OutputStream.nullOutputStream())) { + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { // ZipInputStream.getNextEntry() only reads the Local File Header of a zip entry, // so for the zip file we've just generated the ZipEntry fields 'size', 'compressedSize` // and 'crc' for deflated entries should be uninitialized (i.e. '-1'). System.out.println( - String.format("name=%s, clen=%d, len=%d, crc=%d", - entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc())); - if (entry.getMethod() == ZipEntry.DEFLATED && - (entry.getCompressedSize() != -1 || entry.getSize() != -1 || entry.getCrc() != -1)) { - throw new Exception("'size', 'compressedSize' and 'crc' shouldn't be initialized at this point."); + String.format("name=%s, clen=%d, len=%d, crc=%d", + entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc())); + if (entry.getMethod() == ZipEntry.DEFLATED) { + // Expect size, compressed size and crc to not be initialized at this point + assertEquals(-1, entry.getCompressedSize()); + assertEquals(-1, entry.getSize()); + assertEquals(-1, entry.getCrc()); } zos.putNextEntry(entry); zis.transferTo(zos); @@ -124,29 +145,37 @@ public static void main(String args[]) throws Exception { // Descriptor (if any) after the data and will have updated the 'size', 'compressedSize' and 'crc' // fields of the ZipEntry object. System.out.println( - String.format("name=%s, clen=%d, len=%d, crc=%d\n", - entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc())); - if (entry.getCompressedSize() == -1 || entry.getSize() == -1) { - throw new Exception("'size' and 'compressedSize' must be initialized at this point."); - } + String.format("name=%s, clen=%d, len=%d, crc=%d\n", + entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc())); + // Expect size, compressed size and crc to be initialized at this point + assertNotEquals(-1, entry.getCompressedSize()); + assertNotEquals(-1, entry.getSize()); + assertNotEquals(-1, entry.getCrc()); } } + } - // Now we read all the entries of the initially generated zip file with the help - // of the ZipFile class. The ZipFile class reads all the zip entries from the Central - // Directory which must have accurate information for size, compressedSize and crc. - // This means that all ZipEntry objects returned from ZipFile will have correct - // settings for these fields. - // If the compression level was different in the initial zip file (which we can't find - // out any more now because the zip file format doesn't record this information) the - // size of the re-compressed entry we are writing to the ZipOutputStream might differ - // from the original compressed size recorded in the ZipEntry. This would result in an - // "invalid entry compressed size" ZipException if ZipOutputStream wouldn't ignore - // the implicitely set compressed size attribute of ZipEntries read from a ZipFile - // or ZipInputStream. - try (OutputStream os = new ByteArrayOutputStream(); - ZipOutputStream zos = new ZipOutputStream(os); - ZipFile zf = new ZipFile(ZIP_FILE)) { + /** + * Read all entries using the ZipFile class and copy them to a new zip file + * using ZipOutputStream.putNextEntry. + * The ZipFile class reads all the zip entries from the Central + * Directory, which has accurate information for size, compressedSize and crc. + * This means that all ZipEntry objects returned from ZipFile will have correct + * settings for these fields. + * If the compression level was different in the input zip file (which we can't know + * because the zip file format doesn't record this information), the + * size of the re-compressed entry we are writing to the ZipOutputStream might differ + * from the original compressed size recorded in the ZipEntry. This would result in an + * "invalid entry compressed size" ZipException if ZipOutputStream wouldn't ignore + * the implicitely set compressed size attribute of ZipEntries read from a ZipFile + * or ZipInputStream. + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void copyFromZipFileToZipOutputStream() throws IOException { + try (ZipOutputStream zos = new ZipOutputStream(OutputStream.nullOutputStream()); + ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry entry; Enumeration entries = zf.entries(); while (entries.hasMoreElements()) { entry = entries.nextElement(); @@ -154,48 +183,84 @@ public static void main(String args[]) throws Exception { String.format("name=%s, clen=%d, len=%d, crc=%d\n", entry.getName(), entry.getCompressedSize(), entry.getSize(), entry.getCrc())); - if (entry.getCompressedSize() == -1 || entry.getSize() == -1) { - throw new Exception("'size' and 'compressedSize' must be initialized at this point."); - } - InputStream is = zf.getInputStream(entry); + // Expect size, compressed size and crc to be initialized at this point + assertNotEquals(-1, entry.getCompressedSize()); + assertNotEquals(-1, entry.getSize()); + assertNotEquals(-1, entry.getCrc()); + zos.putNextEntry(entry); - is.transferTo(zos); + try (InputStream is = zf.getInputStream(entry)) { + is.transferTo(zos); + } zos.closeEntry(); } } + } + + /** + * If the compressed size is set explicitly using ZipEntry.setCompressedSize(), + * then the entry will be restreamed with a data descriptor and the compressed size + * recomputed. If the source compression level was different from the target compression + * level, the compressed sizes may differ and a ZipException will be thrown + * when the entry is closed in ZipOutputStream.closeEntry + * + * @throws IOException if an unexpected IOException is thrown + */ + @Test + public void explicitCompressedSizeWithDifferentCompressionLevels() throws IOException { + try (ZipOutputStream zos = new ZipOutputStream(OutputStream.nullOutputStream()); + ZipFile zf = new ZipFile(zip.toFile())) { + // Be explicit about the default compression level + zos.setLevel(Deflater.DEFAULT_COMPRESSION); - // The compressed size attribute of a ZipEntry shouldn't be ignored if it was set - // explicitely by calling ZipEntry.setCpompressedSize() - try (OutputStream os = new ByteArrayOutputStream(); - ZipOutputStream zos = new ZipOutputStream(os); - ZipFile zf = new ZipFile(ZIP_FILE)) { Enumeration entries = zf.entries(); while (entries.hasMoreElements()) { - try { - entry = entries.nextElement(); - entry.setCompressedSize(entry.getCompressedSize()); - InputStream is = zf.getInputStream(entry); + ZipEntry entry = entries.nextElement(); + + // Explicitly setting the compressed size will disable data descriptors + // and enable validation that the compressed size in the ZipEntry matches the + // actual compressed size written by ZipOutputStream + entry.setCompressedSize(entry.getCompressedSize()); + + try (InputStream is = zf.getInputStream(entry)) { zos.putNextEntry(entry); is.transferTo(zos); - zos.closeEntry(); - if ("test3.txt".equals(entry.getName())) { - throw new Exception( - "Should throw a ZipException if ZipEntry.setCpompressedSize() was called."); - } - } catch (ZipException ze) { - if ("test1.txt".equals(entry.getName()) || "test2.txt".equals(entry.getName())) { - throw new Exception( - "Shouldn't throw a ZipExcpetion for STORED files or files compressed with DEFAULT_COMPRESSION"); + // Some compression levels lead to unexpected recompressed sizes when closing the entry + switch (entry.getName()) { + case "DEFAULT_COMPRESSION.txt" -> { + // DEFAULT_COMPRESSION matches expected size + zos.closeEntry(); + } + case "STORED.txt" -> { + // STORED should not throw + zos.closeEntry(); + } + case "NO_COMPRESSION.txt", "BEST_SPEED.txt" -> { + // NO_COMPRESSION and BEST_SPEED should lead to an unexpected recompressed size + ZipException ze = assertThrows(ZipException.class, () -> { + zos.closeEntry(); + }); + + // Hack to fix and close the offending zip entry with the correct recompressed size. + // The exception message is something like: + // "invalid entry compressed size (expected 12 but got 7 bytes)" + // and we need to extract the second integer. + Pattern cSize = Pattern.compile("\\d+"); + Matcher m = cSize.matcher(ze.getMessage()); + m.find(); + m.find(); + entry.setCompressedSize(Integer.parseInt(m.group())); + zos.closeEntry(); + } + case "BEST_COMPRESSION.txt" -> { + // BEST_COMPRESSION produces the same compressed + // size as DEFAULT_COMPRESSION for sample content + zos.closeEntry(); + } + default -> { + throw new IllegalArgumentException("Unexpected entry " + entry.getName()); + } } - // Hack to fix and close the offending zip entry with the correct compressed size. - // The exception message is something like: - // "invalid entry compressed size (expected 12 but got 7 bytes)" - // and we need to extract the second integer. - Pattern cSize = Pattern.compile("\\d+"); - Matcher m = cSize.matcher(ze.getMessage()); - m.find(); - m.find(); - entry.setCompressedSize(Integer.parseInt(m.group())); } } } diff --git a/test/jdk/java/util/zip/ZipFile/Available.java b/test/jdk/java/util/zip/ZipFile/Available.java deleted file mode 100644 index 364a3b0243944..0000000000000 --- a/test/jdk/java/util/zip/ZipFile/Available.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 1999, 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. - */ - -import java.util.zip.*; -import java.io.File; - -public class Available -{ - public static void main (String argv[]) throws Exception { - ZipFile zf = new ZipFile(new File(System.getProperty("test.src"), - "input.jar")); - ZipEntry e = zf.getEntry("ReleaseInflater.java"); - if (e.getSize() != zf.getInputStream(e).available()) { - throw new Exception("wrong return value of available"); - } - } -} diff --git a/test/jdk/java/util/zip/ZipFile/CopyJar.java b/test/jdk/java/util/zip/ZipFile/CopyJar.java deleted file mode 100644 index abeb1f3c46279..0000000000000 --- a/test/jdk/java/util/zip/ZipFile/CopyJar.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1999, 2011, 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 1.1 99/06/01 - @bug 4239446 - @summary Make sure the ZipEntry fields are correct. - */ - -import java.io.*; -import java.util.zip.*; - -public class CopyJar { - public static void main(String args[]) throws Exception { - try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), - "input.jar"))) { - ZipEntry ze = zf.getEntry("ReleaseInflater.java"); - ZipOutputStream zos = new ZipOutputStream(new ByteArrayOutputStream()); - InputStream in = zf.getInputStream(ze); - byte[] b = new byte[128]; - int n; - zos.putNextEntry(ze); - while((n = in.read(b)) != -1) { - zos.write(b, 0, n); - } - zos.close(); - } - } -} diff --git a/test/jdk/java/util/zip/ZipFile/EnumAfterClose.java b/test/jdk/java/util/zip/ZipFile/EnumAfterClose.java deleted file mode 100644 index 38c00466e8f77..0000000000000 --- a/test/jdk/java/util/zip/ZipFile/EnumAfterClose.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2000, 2011, 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 4290060 - @summary Check if the zip file is closed before access any - elements in the Enumeration. - */ - -import java.io.*; -import java.util.zip.*; -import java.util.Enumeration; - -public class EnumAfterClose { - public static void main(String args[]) throws Exception { - Enumeration e; - try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), - "input.zip"))) { - e = zf.entries(); - } - // ensure that the ZipFile is closed before checking the Enumeration - try { - if (e.hasMoreElements()) { - ZipEntry ze = (ZipEntry)e.nextElement(); - } - } catch (IllegalStateException ie) { - } - } -} diff --git a/test/jdk/java/util/zip/ZipFile/EnumerateAfterClose.java b/test/jdk/java/util/zip/ZipFile/EnumerateAfterClose.java new file mode 100644 index 0000000000000..e165e5d2a0a61 --- /dev/null +++ b/test/jdk/java/util/zip/ZipFile/EnumerateAfterClose.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2000, 2024, 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 4290060 + @summary Check if the zip file is closed before access any + elements in the Enumeration. + @run junit EnumerateAfterClose + */ + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Enumeration; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class EnumerateAfterClose { + + // ZIP file used in this test + private Path zip = Path.of("enum-after-close.zip"); + + /** + * Create a sample ZIP file for use by this test + * @throws IOException if an unexpected IOException occurs + */ + @BeforeEach + public void setUp() throws IOException { + try (OutputStream out = Files.newOutputStream(zip); + ZipOutputStream zo = new ZipOutputStream(out)) { + zo.putNextEntry(new ZipEntry("file.txt")); + zo.write("hello".getBytes(StandardCharsets.UTF_8)); + } + } + + /** + * Delete the ZIP file produced by this test + * @throws IOException if an unexpected IOException occurs + */ + @AfterEach + public void cleanup() throws IOException { + Files.deleteIfExists(zip); + } + + /** + * Attempting to using a ZipEntry Enumeration after its backing + * ZipFile is closed should throw IllegalStateException. + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void enumeratingAfterCloseShouldThrowISE() throws IOException { + // Retain a reference to an enumeration backed by a closed ZipFile + Enumeration e; + try (ZipFile zf = new ZipFile(zip.toFile())) { + e = zf.entries(); + } + // Using the enumeration after the ZipFile is closed should throw ISE + assertThrows(IllegalStateException.class, () -> { + if (e.hasMoreElements()) { + ZipEntry ze = (ZipEntry)e.nextElement(); + } + }); + } +} diff --git a/test/jdk/java/util/zip/ZipFile/FinalizeInflater.java b/test/jdk/java/util/zip/ZipFile/FinalizeInflater.java index e80fd7490762b..254f1d445eac7 100644 --- a/test/jdk/java/util/zip/ZipFile/FinalizeInflater.java +++ b/test/jdk/java/util/zip/ZipFile/FinalizeInflater.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, 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 @@ -24,20 +24,64 @@ /* @test @bug 7003462 @summary Make sure cached Inflater does not get finalized. + @run junit FinalizeInflater */ -import java.io.File; -import java.io.InputStream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; public class FinalizeInflater { - public static void main(String[] args) throws Throwable { - try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.zip"))) - { - ZipEntry ze = zf.getEntry("ReadZip.java"); + // ZIP file produced by this test + private Path zip = Path.of("finalize-inflater.zip"); + + /** + * Create the sample ZIP used in this test + * + * @throws IOException if an unexpected IOException occurs + */ + @BeforeEach + public void setUp() throws IOException { + try (OutputStream out = Files.newOutputStream(zip); + ZipOutputStream zo = new ZipOutputStream(out)) { + zo.putNextEntry(new ZipEntry("file.txt")); + byte[] hello = "hello".getBytes(StandardCharsets.UTF_8); + for (int i = 0; i < 100; i++) { + zo.write(hello); + } + } + } + + /** + * Delete the ZIP file produced by this test + * + * @throws IOException if an unexpected IOException occurs + */ + @AfterEach + public void cleanup() throws IOException { + Files.deleteIfExists(zip); + } + + /** + * A cached Inflater should not be made invalid by finalization + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void shouldNotFinalizeInflaterInPool() throws IOException { + try (ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry ze = zf.getEntry("file.txt"); read(zf.getInputStream(ze)); System.gc(); System.runFinalization(); @@ -51,15 +95,10 @@ private static void read(InputStream is) throws IOException { Wrapper wrapper = new Wrapper(is); - byte[] buffer = new byte[32]; - try { - while(is.read(buffer)>0){} - } catch (IOException ioe) { - ioe.printStackTrace(); - } + is.readAllBytes(); } - static class Wrapper{ + static class Wrapper { InputStream is; public Wrapper(InputStream is) { this.is = is; diff --git a/test/jdk/java/util/zip/ZipFile/GetDirEntry.java b/test/jdk/java/util/zip/ZipFile/GetDirEntry.java deleted file mode 100644 index e74fa6b315437..0000000000000 --- a/test/jdk/java/util/zip/ZipFile/GetDirEntry.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 1999, 2011, 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 4206838 - @summary getEntry() will search for a directory - even without an ending '/'. - */ - -import java.io.*; -import java.util.zip.*; - -public class GetDirEntry { - public static void main(String args[]) throws Exception { - try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), - "input.jar"))) { - ZipEntry ze = zf.getEntry("META-INF"); - if (ze == null) { - throw new Exception("failed to find a directory entry"); - } - } - } -} diff --git a/test/jdk/java/util/zip/ZipFile/ReadAfterClose.java b/test/jdk/java/util/zip/ZipFile/ReadAfterClose.java deleted file mode 100644 index 3488245175130..0000000000000 --- a/test/jdk/java/util/zip/ZipFile/ReadAfterClose.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2002, 2011, 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 4528128 6846616 - @summary Test if reading InputStream of a closed ZipFile crashes VM - @author kladko - */ - - -import java.util.zip.*; -import java.io.*; -import java.util.*; - -public class ReadAfterClose { - public static void main(String[] argv) throws Exception { - InputStream in; - try (ZipFile zf = new ZipFile( - new File(System.getProperty("test.src","."),"crash.jar"))) { - ZipEntry zent = zf.getEntry("Test.java"); - in = zf.getInputStream(zent); - } - // ensure zf is closed at this point - try { - in.read(); - } catch (IOException e) { - return; - } - throw new Exception("Test failed."); - } -} diff --git a/test/jdk/java/util/zip/ZipFile/ReadZip.java b/test/jdk/java/util/zip/ZipFile/ReadZip.java index 33db2552986da..5aa9ee82f0f11 100644 --- a/test/jdk/java/util/zip/ZipFile/ReadZip.java +++ b/test/jdk/java/util/zip/ZipFile/ReadZip.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -22,185 +22,359 @@ */ /* @test - @bug 4241361 4842702 4985614 6646605 5032358 6923692 6233323 8144977 8186464 + @bug 4241361 4842702 4985614 6646605 5032358 6923692 6233323 8144977 8186464 4401122 8322830 @summary Make sure we can read a zip file. - @key randomness @modules jdk.zipfs + @run junit ReadZip */ -import java.io.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; -import java.nio.file.Files; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.NoSuchFileException; -import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; -import java.util.List; +import java.nio.charset.StandardCharsets; +import java.nio.file.*; +import java.util.Collections; +import java.util.HexFormat; import java.util.Map; -import java.util.zip.*; +import java.util.zip.ZipEntry; +import java.util.zip.ZipException; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.junit.jupiter.api.Assertions.*; public class ReadZip { - private static void unreached (Object o) - throws Exception - { - // Should never get here - throw new Exception ("Expected exception was not thrown"); + + // ZIP file produced during tests + private Path zip = Path.of("read-zip.zip"); + + /** + * Create a sample ZIP file for use by tests + * @param name name of the ZIP file to create + * @return a sample ZIP file + * @throws IOException if an unexpected IOException occurs + */ + private Path createZip(String name) throws IOException { + Path zip = Path.of(name); + + try (OutputStream out = Files.newOutputStream(zip); + ZipOutputStream zo = new ZipOutputStream(out)) { + zo.putNextEntry(new ZipEntry("file.txt")); + zo.write("hello".getBytes(StandardCharsets.UTF_8)); + } + + return zip; } - public static void main(String args[]) throws Exception { - try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), - "input.zip"))) { - // Make sure we throw NPE on null objects - try { unreached (zf.getEntry(null)); } - catch (NullPointerException e) {} + /** + * Delete the ZIP file produced after each test method + * @throws IOException if an unexpected IOException occurs + */ + @AfterEach + public void cleanup() throws IOException { + Files.deleteIfExists(zip); + } - try { unreached (zf.getInputStream(null)); } - catch (NullPointerException e) {} + /** + * Make sure we throw NPE when calling getEntry or getInputStream with null params + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void nullPointerExceptionOnNullParams() throws IOException { + zip = createZip("null-params.zip"); + try (ZipFile zf = new ZipFile(zip.toFile())) { - ZipEntry ze = zf.getEntry("ReadZip.java"); - if (ze == null) { - throw new Exception("cannot read from zip file"); - } + assertThrows(NullPointerException.class, () -> zf.getEntry(null)); + assertThrows(NullPointerException.class, () -> zf.getInputStream(null)); + + // Sanity check that we can still read an entry + ZipEntry ze = zf.getEntry("file.txt"); + assertNotNull(ze, "cannot read from zip file"); } + } - // Make sure we can read the zip file that has some garbage - // bytes padded at the end. - File newZip = new File(System.getProperty("test.dir", "."), "input2.zip"); - Files.copy(Paths.get(System.getProperty("test.src", ""), "input.zip"), - newZip.toPath(), StandardCopyOption.REPLACE_EXISTING); + /** + * Read the zip file that has some garbage bytes padded at the end + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void bytesPaddedAtEnd() throws IOException { - newZip.setWritable(true); + zip = createZip("bytes-padded.zip"); // pad some bytes - try (OutputStream os = Files.newOutputStream(newZip.toPath(), - StandardOpenOption.APPEND)) { - os.write(1); os.write(3); os.write(5); os.write(7); + try (OutputStream os = Files.newOutputStream(zip, + StandardOpenOption.APPEND)) { + os.write(1); + os.write(3); + os.write(5); + os.write(7); } - try (ZipFile zf = new ZipFile(newZip)) { - ZipEntry ze = zf.getEntry("ReadZip.java"); - if (ze == null) { - throw new Exception("cannot read from zip file"); - } - } finally { - newZip.delete(); + try (ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry ze = zf.getEntry("file.txt"); + assertNotNull(ze, "cannot read from zip file"); + } + } + + /** + * Verify that we can read a comment from the ZIP + * file's 'End of Central Directory' header + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void readZipFileComment() throws IOException { + + // Create a zip file with a comment in the 'End of Central Directory' header + try (OutputStream out = Files.newOutputStream(zip); + ZipOutputStream zos = new ZipOutputStream(out)) { + ZipEntry ze = new ZipEntry("ZipEntry"); + zos.putNextEntry(ze); + zos.write(1); + zos.write(2); + zos.write(3); + zos.write(4); + zos.closeEntry(); + zos.setComment("This is the comment for testing"); } // Read zip file comment - try { - try (FileOutputStream fos = new FileOutputStream(newZip); - ZipOutputStream zos = new ZipOutputStream(fos)) - { - ZipEntry ze = new ZipEntry("ZipEntry"); - zos.putNextEntry(ze); - zos.write(1); zos.write(2); zos.write(3); zos.write(4); - zos.closeEntry(); - zos.setComment("This is the comment for testing"); - } + try (ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry ze = zf.getEntry("ZipEntry"); + assertNotNull(ze, "cannot read entry from zip file"); + assertEquals("This is the comment for testing", zf.getComment()); + } + } - try (ZipFile zf = new ZipFile(newZip)) { - ZipEntry ze = zf.getEntry("ZipEntry"); - if (ze == null) - throw new Exception("cannot read entry from zip file"); - if (!"This is the comment for testing".equals(zf.getComment())) - throw new Exception("cannot read comment from zip file"); - } - } finally { - newZip.delete(); - } - - // Read directory entry - try { - try (FileOutputStream fos = new FileOutputStream(newZip); - ZipOutputStream zos = new ZipOutputStream(fos)) - { - ZipEntry ze = new ZipEntry("directory/"); - zos.putNextEntry(ze); - zos.closeEntry(); - } - try (ZipFile zf = new ZipFile(newZip)) { - ZipEntry ze = zf.getEntry("directory/"); - if (ze == null || !ze.isDirectory()) - throw new RuntimeException("read entry \"directory/\" failed"); - try (InputStream is = zf.getInputStream(ze)) { - is.available(); - } catch (Exception x) { - x.printStackTrace(); - } - - ze = zf.getEntry("directory"); - if (ze == null || !ze.isDirectory()) - throw new RuntimeException("read entry \"directory\" failed"); - try (InputStream is = zf.getInputStream(ze)) { - is.available(); - } catch (Exception x) { - x.printStackTrace(); - } + /** + * Verify that a directory entry can be found using the + * name 'directory/' as well as 'directory/' + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void readDirectoryEntries() throws IOException { + + // Create a ZIP containing some directory entries + try (OutputStream fos = Files.newOutputStream(zip); + ZipOutputStream zos = new ZipOutputStream(fos)) { + // Add a META-INF directory with STORED compression type + ZipEntry metaInf = new ZipEntry("META-INF/"); + metaInf.setMethod(ZipEntry.STORED); + metaInf.setSize(0); + metaInf.setCrc(0); + zos.putNextEntry(metaInf); + + // Add a regular directory + ZipEntry dir = new ZipEntry("directory/"); + zos.putNextEntry(dir); + zos.closeEntry(); + } + + // Verify directory lookups + try (ZipFile zf = new ZipFile(zip.toFile())) { + // Look up 'directory/' using the full name + ZipEntry ze = zf.getEntry("directory/"); + assertNotNull(ze, "read entry \"directory/\" failed"); + assertTrue(ze.isDirectory(), "read entry \"directory/\" failed"); + assertEquals("directory/", ze.getName()); + + try (InputStream is = zf.getInputStream(ze)) { + is.available(); + } catch (Exception x) { + x.printStackTrace(); } - } finally { - newZip.delete(); - } - - // Throw a FNF exception when read a non-existing zip file - try { unreached (new ZipFile( - new File(System.getProperty("test.src", "."), - "input" - + String.valueOf(new java.util.Random().nextInt()) - + ".zip"))); - } catch (NoSuchFileException nsfe) {} - - // read a zip file with ZIP64 end - Path path = Paths.get(System.getProperty("test.dir", ""), "end64.zip"); - try { - URI uri = URI.create("jar:" + path.toUri()); - Map env = Map.of("create", "true", "forceZIP64End", "true"); - try (FileSystem fs = FileSystems.newFileSystem(uri, env)) { - Files.write(fs.getPath("hello"), "hello".getBytes()); + + // Look up 'directory/' without the trailing slash + ze = zf.getEntry("directory"); + assertNotNull(ze, "read entry \"directory\" failed"); + assertTrue(ze.isDirectory(), "read entry \"directory\" failed"); + assertEquals("directory/", ze.getName()); + + try (InputStream is = zf.getInputStream(ze)) { + is.available(); + } catch (Exception x) { + x.printStackTrace(); } - try (ZipFile zf = new ZipFile(path.toFile())) { - if (!"hello".equals(new String(zf.getInputStream(new ZipEntry("hello")) - .readAllBytes(), - US_ASCII))) - throw new RuntimeException("zipfile: read entry failed"); - } catch (IOException x) { - throw new RuntimeException("zipfile: zip64 end failed"); + // Sanity check that also META-INF/ can be looked up with or without the trailing slash + assertNotNull(zf.getEntry("META-INF")); + assertNotNull(zf.getEntry("META-INF/")); + assertEquals(zf.getEntry("META-INF").getName(), + zf.getEntry("META-INF/").getName()); + } + } + + /** + * Throw a NoSuchFileException exception when reading a non-existing zip file + */ + @Test + public void nonExistingFile() { + File nonExistingFile = new File("non-existing-file-f6804460f.zip"); + assertThrows(NoSuchFileException.class, () -> + new ZipFile(nonExistingFile)); + } + + /** + * Read a Zip file with a 'Zip64 End of Central Directory header' which was created + * using ZipFileSystem with the 'forceZIP64End' option. + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void readZip64EndZipFs() throws IOException { + + // Create zip file with Zip64 end + Map env = Map.of("create", "true", "forceZIP64End", "true"); + try (FileSystem fs = FileSystems.newFileSystem(zip, env)) { + Files.write(fs.getPath("hello"), "hello".getBytes()); + } + // Read using ZipFile + try (ZipFile zf = new ZipFile(zip.toFile())) { + try (InputStream in = zf.getInputStream(zf.getEntry("hello"))) { + assertEquals("hello", new String(in.readAllBytes(), StandardCharsets.US_ASCII)); } - try (FileSystem fs = FileSystems.newFileSystem(uri, Map.of())) { - if (!"hello".equals(new String(Files.readAllBytes(fs.getPath("hello"))))) - throw new RuntimeException("zipfs: read entry failed"); - } catch (IOException x) { - throw new RuntimeException("zipfile: zip64 end failed"); + } + // Read using ZipFileSystem + try (FileSystem fs = FileSystems.newFileSystem(zip, Map.of())) { + assertEquals("hello", new String(Files.readAllBytes(fs.getPath("hello")))); + } + } + + /** + * Read a zip file created via Info-ZIP in streaming mode, + * which includes a 'Zip64 End of Central Directory header'. + * + * @throws IOException if an unexpected IOException occurs + * @throws InterruptedException if an unexpected InterruptedException occurs + */ + @Test + public void readZip64EndInfoZIPStreaming() throws IOException, InterruptedException { + // ZIP created using: "echo -n hello | zip zip64.zip -" + // Hex encoded using: "cat zip64.zip | xxd -ps" + byte[] zipBytes = HexFormat.of().parseHex(""" + 504b03042d0000000000c441295886a61036ffffffffffffffff01001400 + 2d010010000500000000000000050000000000000068656c6c6f504b0102 + 1e032d0000000000c441295886a610360500000005000000010000000000 + 000001000000b011000000002d504b06062c000000000000001e032d0000 + 00000000000000010000000000000001000000000000002f000000000000 + 003800000000000000504b06070000000067000000000000000100000050 + 4b050600000000010001002f000000380000000000 + """.replaceAll("\n","") + ); + + Files.write(zip, zipBytes); + + try (ZipFile zf = new ZipFile(this.zip.toFile())) { + try (InputStream in = zf.getInputStream(zf.getEntry("-"))) { + String contents = new String(in.readAllBytes(), StandardCharsets.US_ASCII); + assertEquals("hello", contents); } - } finally { - Files.deleteIfExists(path); - } - - // read a zip file created via "echo hello | zip dst.zip -", which uses - // ZIP64 end record - if (Files.notExists(Paths.get("/usr/bin/zip"))) - return; - try { - Process zip = new ProcessBuilder("zip", path.toString().toString(), "-").start(); - OutputStream os = zip.getOutputStream(); - os.write("hello".getBytes(US_ASCII)); - os.close(); - zip.waitFor(); - if (zip.exitValue() == 0 && Files.exists(path)) { - try (ZipFile zf = new ZipFile(path.toFile())) { - if (!"hello".equals(new String(zf.getInputStream(new ZipEntry("-")) - .readAllBytes()))) - throw new RuntimeException("zipfile: read entry failed"); - } catch (IOException x) { - throw new RuntimeException("zipfile: zip64 end failed"); - } + } + } + + /** + * Check that the available() method overriden by the input stream returned by + * ZipFile.getInputStream correctly returns the number of remaining uncompressed bytes + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void availableShouldReturnRemainingUncompressedBytes() throws IOException { + // The number of uncompressed bytes to write to the sample ZIP entry + final int expectedBytes = 512; + + // Create a sample ZIP with deflated entry of a known uncompressed size + try (ZipOutputStream zo = new ZipOutputStream(Files.newOutputStream(zip))) { + zo.putNextEntry(new ZipEntry("file.txt")); + zo.write(new byte[expectedBytes]); + } + + // Verify the behavior of ZipFileInflaterInputStream.available() + try (ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry e = zf.getEntry("file.txt"); + try (InputStream in = zf.getInputStream(e)) { + // Initially, available() should return the full uncompressed size of the entry + assertEquals(expectedBytes, in.available(), + "wrong initial return value of available"); + + // Reading a few bytes should reduce the number of available bytes accordingly + int bytesToRead = 10; + in.read(new byte[bytesToRead]); + assertEquals(expectedBytes - bytesToRead, in.available()); + + // Reading all remaining bytes should reduce the number of available bytes to zero + in.transferTo(OutputStream.nullOutputStream()); + assertEquals(0, in.available()); + + // available on a closed input stream should return zero + in.close(); + assertEquals(0, in.available()); } - } finally { - Files.deleteIfExists(path); } } -} + + /** + * Verify that reading an InputStream from a closed ZipFile + * throws IOException as expected and does not crash the VM. + * See bugs: 4528128 6846616 + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void readAfterClose() throws IOException { + zip = createZip("read-after-close.zip"); + InputStream in; + try (ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry zent = zf.getEntry("file.txt"); + in = zf.getInputStream(zent); + } + + // zf is closed at this point + assertThrows(IOException.class, () -> { + in.read(); + }); + assertThrows(IOException.class, () -> { + in.read(new byte[10]); + }); + assertThrows(IOException.class, () -> { + byte[] buf = new byte[10]; + in.read(buf, 0, buf.length); + }); + assertThrows(IOException.class, () -> { + in.readAllBytes(); + }); + } + + /** + * Verify that ZipFile can open a ZIP file with zero entries + * + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void noEntries() throws IOException { + // Create a ZIP file with no entries + try (ZipOutputStream zo = new ZipOutputStream(Files.newOutputStream(zip))) { + } + + // Open the "empty" ZIP file + try (ZipFile zf = new ZipFile(zip.toFile())) { + // Verify size + assertEquals(0, zf.size()); + + // Verify entry lookup using ZipFile.getEntry() + assertNull(zf.getEntry("file.txt")); + + // Verify iteration using ZipFile.entries() + assertEquals(Collections.emptyList(), Collections.list(zf.entries())); + + // Verify iteration using ZipFile.stream() + assertEquals(Collections.emptyList(), zf.stream().toList()); + } + } +} \ No newline at end of file diff --git a/test/jdk/java/util/zip/ZipFile/ReleaseInflater.java b/test/jdk/java/util/zip/ZipFile/ReleaseInflater.java index f20fc12ecc1fe..49f676ba555c0 100644 --- a/test/jdk/java/util/zip/ZipFile/ReleaseInflater.java +++ b/test/jdk/java/util/zip/ZipFile/ReleaseInflater.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -25,31 +25,74 @@ * @bug 4214795 * @summary Make sure the same inflater will only be recycled * once. + * @run junit ReleaseInflater */ -import java.io.*; -import java.util.zip.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; public class ReleaseInflater { - public static void main(String[] args) throws Exception { - ZipFile zf = new ZipFile(new File(System.getProperty("test.src"), - "input.jar")); - ZipEntry e = zf.getEntry("ReleaseInflater.java"); + // ZIP file produced in this test + private Path zip = Path.of("release-inflater.zip"); + + /** + * Create a sample ZIP file for use by tests + * @param name name of the ZIP file to create + * @return a sample ZIP file + * @throws IOException if an unexpected IOException occurs + */ + @BeforeEach + public void setUp() throws IOException { + try (ZipOutputStream zo = new ZipOutputStream(Files.newOutputStream(zip))) { + zo.putNextEntry(new ZipEntry("file.txt")); + zo.write("helloworld".getBytes(StandardCharsets.UTF_8)); + } + } + + /** + * Delete the ZIP and JAR files produced after each test method + * @throws IOException if an unexpected IOException occurs + */ + + @AfterEach + public void cleanup() throws IOException { + Files.deleteIfExists(zip); + } + + /** + * Verify that the same Inflater is not recycled across input streams + * @throws IOException if an unexpected IOException occurs + */ + @Test + public void recycleInflaterOnlyOnce() throws IOException { + try (ZipFile zf = new ZipFile(zip.toFile())) { + ZipEntry e = zf.getEntry("file.txt"); - InputStream in1 = zf.getInputStream(e); - // close the stream, the inflater will be released - in1.close(); - // close the stream again, should be no-op - in1.close(); + InputStream in1 = zf.getInputStream(e); + // close the stream, the inflater will be released + in1.close(); + // close the stream again, should be no-op + in1.close(); - // create two new streams, allocating inflaters - InputStream in2 = zf.getInputStream(e); - InputStream in3 = zf.getInputStream(e); + // create two new streams, allocating inflaters + InputStream in2 = zf.getInputStream(e); + InputStream in3 = zf.getInputStream(e); - // check to see if they influence each other - if (in2.read() != in3.read()) { - throw new Exception("Stream is corrupted!"); + // check to see if they influence each other + assertEquals(in2.read(), in3.read(), "Stream is corrupted!"); } } } diff --git a/test/jdk/java/util/zip/ZipFile/StreamZipEntriesTest.java b/test/jdk/java/util/zip/ZipFile/StreamZipEntriesTest.java index 38199e4694c3a..eaa3708578ea9 100644 --- a/test/jdk/java/util/zip/ZipFile/StreamZipEntriesTest.java +++ b/test/jdk/java/util/zip/ZipFile/StreamZipEntriesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -23,74 +23,169 @@ /** * @test - * @run testng StreamZipEntriesTest + * @run junit StreamZipEntriesTest * @summary Make sure we can stream entries of a zip file. */ -import java.io.File; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + import java.io.IOException; -import java.lang.Object; -import java.lang.System; -import java.util.jar.JarFile; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.Set; import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.*; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; public class StreamZipEntriesTest { + // ZIP file produced in this test + private Path zip = Path.of("stream.zip"); + // JAR file produced in this test + private Path jar = Path.of("stream.jar"); + + /** + * Create sample ZIP and JAR files used in in this test + * @throws IOException if an unexpected IOException occurs + */ + @BeforeEach + public void setUp() throws IOException { + + try (OutputStream out = Files.newOutputStream(zip); + ZipOutputStream zo = new ZipOutputStream(out)) { + zo.putNextEntry(new ZipEntry("entry1.txt")); + zo.write("hello".getBytes(StandardCharsets.UTF_8)); + zo.putNextEntry(new ZipEntry("entry2.txt")); + zo.write("hello".getBytes(StandardCharsets.UTF_8)); + } + + try (OutputStream out = Files.newOutputStream(jar); + ZipOutputStream zo = new ZipOutputStream(out)) { + // A JAR file may start with a META-INF/ directory before the manifest + zo.putNextEntry(new ZipEntry("META-INF/")); + // Write the manifest + zo.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF")); + new Manifest().write(zo); + + // Write two regular entries + zo.putNextEntry(new ZipEntry("entry1.txt")); + zo.write("hello".getBytes(StandardCharsets.UTF_8)); + zo.putNextEntry(new ZipEntry("entry2.txt")); + zo.write("hello".getBytes(StandardCharsets.UTF_8)); + } + } + + /** + * Delete the ZIP file produced after each test method + * @throws IOException if an unexpected IOException occurs + */ + @AfterEach + public void cleanup() throws IOException { + Files.deleteIfExists(zip); + Files.deleteIfExists(jar); + } + + /** + * Verify that ZipFile.stream() produces the expected entries + * @throws IOException if an unexpected IOException occurs + */ @Test public void testStreamZip() throws IOException { - try (ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.zip"))) { - zf.stream().forEach(e -> assertTrue(e instanceof ZipEntry)); - zf.stream().forEach(e -> assertEquals(e.toString(), "ReadZip.java")); + Set names = new HashSet<>(Set.of("entry1.txt", "entry2.txt")); + + try (ZipFile zf = new ZipFile(zip.toFile())) { + zf.stream().forEach(e -> { + assertTrue(e instanceof ZipEntry); + String name = e.getName(); + assertNotNull(names.remove(name)); + String toString = e.toString(); + assertEquals(name, toString); + }); + + // Check that all expected names were processed + assertTrue(names.isEmpty()); + // Check that Stream.toArray produces the expected result Object elements[] = zf.stream().toArray(); - assertEquals(1, elements.length); - assertEquals(elements[0].toString(), "ReadZip.java"); + assertEquals(2, elements.length); + assertEquals(elements[0].toString(), "entry1.txt"); + assertEquals(elements[1].toString(), "entry2.txt"); } } + /** + * Verify that JarFile.stream() produces the expected entries + * @throws IOException if an unexpected IOException occurs + */ @Test public void testStreamJar() throws IOException { - try (JarFile jf = new JarFile(new File(System.getProperty("test.src", "."), "input.jar"))) { - jf.stream().forEach(e -> assertTrue(e instanceof JarEntry)); + try (JarFile jf = new JarFile(jar.toFile())) { + Set names = new HashSet<>(Set.of( + "META-INF/", + "META-INF/MANIFEST.MF", + "entry1.txt", + "entry2.txt" + )); + jf.stream().forEach(e -> { + assertTrue(e instanceof JarEntry); + String name = e.getName(); + assertNotNull(names.remove(name)); + String toString = e.toString(); + assertEquals(name, toString); + } + ); + + // Check that all expected names were processed + assertTrue(names.isEmpty(), "Unprocessed entries: " + names); + + + // Check that Stream.toArray produces the expected result Object elements[] = jf.stream().toArray(); - assertEquals(3, elements.length); + assertEquals(4, elements.length); assertEquals(elements[0].toString(), "META-INF/"); assertEquals(elements[1].toString(), "META-INF/MANIFEST.MF"); - assertEquals(elements[2].toString(), "ReleaseInflater.java"); + assertEquals(elements[2].toString(), "entry1.txt"); + assertEquals(elements[3].toString(), "entry2.txt"); } } + /** + * Calling ZipFile.stream() on a closed ZipFile should throw ISE + * @throws IOException if an unexpected IOException occurs + */ @Test public void testClosedZipFile() throws IOException { - ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.zip")); + ZipFile zf = new ZipFile(zip.toFile()); zf.close(); - try { + assertThrows(IllegalStateException.class, () -> { Stream s = zf.stream(); - fail("Should have thrown IllegalStateException"); - } catch (IllegalStateException e) { - // expected; - } + }); } + /** + * Calling JarFile.stream() on a closed JarFile should throw ISE + * @throws IOException if an unexpected IOException occurs + */ @Test public void testClosedJarFile() throws IOException { - JarFile jf = new JarFile(new File(System.getProperty("test.src", "."), "input.jar")); + JarFile jf = new JarFile(jar.toFile()); jf.close(); - try { + assertThrows(IllegalStateException.class, () -> { Stream s = jf.stream(); - fail("Should have thrown IllegalStateException"); - } catch (IllegalStateException e) { - // expected; - } + }); } } diff --git a/test/jdk/java/util/zip/ZipFile/crash.jar b/test/jdk/java/util/zip/ZipFile/crash.jar deleted file mode 100644 index 8de20e7582e68655eefcbf3360315964b6b54c64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 781 zcmWIWW@Zs#-~hr!Ikq|sNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv__A<*VcAd$DvC3#Y_O zNv#Z)>CZHOq^XHN6%QAizT}yhcEvN**O{M+J{B>8U2*Kh)srqjJ3tuW3Yjo;FEB8K zq!yRxWhIs+#s+T8Yc>#>^H6)9k)`aNl0K^-&54)zI(NB9#uywtapOdt!=kSG_nVn@ zUquU)zrQ#4+^WpA&MRE?E84w2M_K&a;(L`T{F}XyIj8sSciyXIigfq1PyWJjU-N>` z4)?|{FV|`<5InU(*(!D2b8e3Ex7Qn{Zft1#`wfmIRCH3lu_ohq>nErvwjn9Bl zr{mo0(^b;8hf+cN(7xd%tbMP2b8d%MZS@=RY3& zbcqJvmGhtFx4)l#_O#2#fL~oTLZM96bC#xAt#y8;VsTt8IkMa6rq;I%9j8p|;0B{F zb$nhU)VvZfcLXDlP4ns zgAXt%1b8zti7=ohB3KFmB_dP+PZgjfg{~DjT0uz&0c?RxxK^YDg=_*S`jH*RiO>#Y Y9R^}}VhHeNWdq4F1K}1R?F@D>0F5Q`?EnA( diff --git a/test/jdk/java/util/zip/ZipFile/input.jar b/test/jdk/java/util/zip/ZipFile/input.jar deleted file mode 100644 index f5e6f5733170307cea67fb88a8abf64a3c901ab9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 832 zcmWIWW@Zs#-~d9E%yKmbB*4kQ!rSd8f^@?z@c|G_`_Kry;J(@bo4yW>V|zd<9+S&lc$fK zGJ##@@MQ~M1km0vAV#>1AI)1Jmj$Kfq$U=pdgi6&B$lKW>18FBB`%#5n0?4V;Q0N| znte_SuL>@=+tsMRS0mB$bDN>tn#}S^YN|V5mHfCny(CoYU8cAEyI=cv$N$eXdU0^d z66FqY!y}((Fdirg6~CaePR~2>`&sY&0}_Wf8BI%2-qy7E;og(2LBd*f2ee+SSryJ@ zd}2xg-@K)h4xMa0H&r3?VK=MF7TZ3SpBqefv;{5jo0bwNzCK?e=V8zS{_HZoXY*&S z;pqML_`*8zHF5!-7EcQJqu%*B34KzFd?$NylK7-~YgR5h%o}UeJEW zuVzPcV#nXQs&|~H>)Wc|S-m{7DbFzY*vY)F;U6#kd|`i1Kk)JX1y*sK+nieMU&hAf zZqeyM}*a{jakbx9d{ezwv@ni^wHOp&&*Eh8w^n6X4Cr zB*K82*kCCMl-N)KJoSK*9=cZKs0KwS0@wnXaIHuQ57`7zl0bGCstMPDCSXe-0p6@^ PAbXgBa6gdF2D=>qQ1}$S diff --git a/test/jdk/java/util/zip/ZipFile/input.zip b/test/jdk/java/util/zip/ZipFile/input.zip deleted file mode 100644 index 2ca60bd4c0654b7966eb1f05403387cbd8d33c49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 450 zcmWIWW@Zs#U|`^25Xjl1X1ww-s~RH%!!ID_VGv~qN=;0O$}G^!N-RqZ4dG;9j{oat z?g7N16)X&u@>~q9fd{>q4F&c-*OqH+y&Dv?>ZrG1)yfBs0@cAbM{>)0->G>UWxnWxibX5`G$tS9xKixZ%(2I&sb{qvu%!<>5|odPiHe$m6yHW_)ja;{no7F(ykMw;-L%I z7jQ5Bw%=jiC&imGHY>xfbji(qJ7ux+xnT2_a@F}w+;KjI4}aV5FpFLAq)+^4kxojk zhS`SjK+pK4{Ok(P)6XkyZR__cX|>tgcgXp&h;q0l+vVn^-S6idZum>