| /* |
| * 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 8299179 |
| * @summary ArrayFill: if store is on backedge, last iteration is not to be executed. |
| * @library /test/lib |
| * @compile TestBackedgeLoadArrayFill.jasm |
| * @requires vm.compiler2.enabled |
| * @run main/othervm |
| * -XX:CompileCommand=compileonly,TestBackedgeLoadArrayFill*::test* |
| * -XX:-TieredCompilation -Xcomp -XX:+OptimizeFill |
| * TestBackedgeLoadArrayFillMain |
| * @run main/othervm |
| * -XX:CompileCommand=compileonly,TestBackedgeLoadArrayFill*::test* |
| * -XX:-TieredCompilation -Xcomp -XX:+OptimizeFill |
| * -XX:LoopUnrollLimit=1 |
| * TestBackedgeLoadArrayFillMain |
| */ |
| |
| import jdk.test.lib.Asserts; |
| |
| public class TestBackedgeLoadArrayFillMain { |
| static long[] longA; |
| static int[] intA; |
| static short[] shortA; |
| static byte[] byteA; |
| |
| static class Data { |
| long longValue; |
| int intValue; |
| short shortValue; |
| byte byteValue; |
| |
| Data(int value) { |
| longValue = (long) value; |
| intValue = (int) value; |
| shortValue = (short) value; |
| longValue = (byte) value; |
| } |
| } |
| |
| public static long longSum() { |
| long s = 0; |
| for (long v : longA) { s += v; } |
| return s; |
| } |
| |
| public static int intSum() { |
| int s = 0; |
| for (int v : intA) { s += v; } |
| return s; |
| } |
| |
| public static short shortSum() { |
| short s = 0; |
| for (short v : shortA) { s += v; } |
| return s; |
| } |
| |
| public static byte byteSum() { |
| byte s = 0; |
| for (byte v : byteA) { s += v; } |
| return s; |
| } |
| |
| static void test_001() { |
| // long seems not yet supported |
| int i = 6; |
| long arr[] = new long[22]; |
| do { |
| arr[i] = 1; |
| try { |
| arr[i] = arr[i]; |
| } catch (Exception e) { |
| } |
| } while (++i < 20); |
| longA = arr; |
| } |
| |
| static void test_002() { |
| // jint_fill |
| int i = 6; |
| int arr[] = new int[22]; |
| do { |
| arr[i] = 1; |
| try { |
| arr[i] = arr[i]; |
| } catch (Exception e) { |
| } |
| } while (++i < 20); |
| intA = arr; |
| } |
| |
| static void test_003() { |
| // jshort_fill |
| int i = 6; |
| short arr[] = new short[22]; |
| do { |
| // first block of loop: copied before loop, and onto backedge -> store on backedge |
| arr[i] = 1; |
| // second block of loop |
| try { |
| arr[i] = arr[i]; |
| } catch (Exception e) { |
| } |
| } while (++i < 20); |
| shortA = arr; |
| } |
| |
| static void test_004() { |
| // jbyte_fill |
| int i = 6; |
| byte arr[] = new byte[22]; |
| do { |
| arr[i] = 1; |
| try { |
| arr[i] = arr[i]; |
| } catch (Exception e) { |
| } |
| } while (++i < 20); |
| byteA = arr; |
| } |
| |
| static void test_005() { |
| // Note: currently unrolled, not intrinsified (unless -XX:LoopUnrollLimit=1) |
| int arr[] = new int[22]; |
| for (int i = 6; i < 20; i++) { |
| arr[i] = 1; |
| } |
| intA = arr; |
| } |
| |
| static void test_006() { |
| // Note: currently unrolled, not intrinsified (unless -XX:LoopUnrollLimit=1) |
| // Load in normal body, because not moved to backedge during parsing. |
| int i = 6; |
| int arr[] = new int[22]; |
| do { |
| arr[i] = 1; |
| } while (++i < 20); |
| intA = arr; |
| } |
| |
| static void test_007() { |
| int i = 6; |
| int arr[] = new int[22]; |
| do { |
| // still not on backedge [7,20) partial peel |
| arr[i] = 1; |
| try { int x = arr[i]; } catch (Exception e) {} |
| } while (++i < 20); |
| intA = arr; |
| } |
| |
| static void test_008(Data data) { |
| // Because of conditional in loop, at first not intrinsified, and also not unrolled. |
| // After unswitching both loops are intrinsified. |
| // I stole this idea from TestOptimizeFillWithStripMinedLoop.java |
| int i = 6; |
| int arr[] = new int[22]; |
| do { |
| arr[i] = (data == null) ? 1 : data.intValue; |
| } while (++i < 20); |
| intA = arr; |
| } |
| |
| static void test_009() { |
| // Cast to int leads to "missing use of index", not intrinsified |
| int arr[] = new int[22]; |
| for (long i = 6; i < 20; i++) { |
| arr[(int)i] = 1; |
| } |
| intA = arr; |
| } |
| |
| |
| public static void main(String[] strArr) { |
| test_001(); |
| Asserts.assertEQ(longSum(), (long)14); |
| test_002(); |
| Asserts.assertEQ(intSum(), 14); |
| test_003(); |
| Asserts.assertEQ(shortSum(), (short)14); |
| test_004(); |
| Asserts.assertEQ(byteSum(), (byte)14); |
| test_005(); |
| Asserts.assertEQ(intSum(), 14); |
| test_006(); |
| Asserts.assertEQ(intSum(), 14); |
| test_007(); |
| Asserts.assertEQ(intSum(), 14); |
| test_008(new Data(1)); |
| Asserts.assertEQ(intSum(), 14); |
| test_008(null); |
| Asserts.assertEQ(intSum(), 14); |
| test_009(); |
| Asserts.assertEQ(intSum(), 14); |
| TestBackedgeLoadArrayFill t = new TestBackedgeLoadArrayFill(); |
| t.test_101(); |
| Asserts.assertEQ(intSum(), 15); |
| t.test_102(); |
| Asserts.assertEQ(intSum(), 16); |
| t.test_103(); |
| Asserts.assertEQ(intSum(), 14); |
| t.test_104(); |
| Asserts.assertEQ(intSum(), 12); |
| } |
| } |
| |