/* * Copyright (c) 2022, 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 8283894 * @key randomness * @summary To test various transforms added for bit COMPRESS_BITS and EXPAND_BITS operations * @requires vm.compiler2.enabled * @requires (((os.arch=="x86" | os.arch=="amd64" | os.arch=="x86_64") & * (vm.cpu.features ~= ".*bmi2.*" & vm.cpu.features ~= ".*bmi1.*" & * vm.cpu.features ~= ".*sse2.*")) | * (os.arch=="aarch64" & vm.cpu.features ~= ".*svebitperm.*") | * (os.arch=="riscv64" & vm.cpu.features ~= ".*rvv.*")) * @library /test/lib / * @run driver compiler.intrinsics.TestBitShuffleOpers */ package compiler.intrinsics; import java.util.concurrent.Callable; import compiler.lib.ir_framework.*; import jdk.test.lib.Utils; import java.util.Random; public class TestBitShuffleOpers { int [] ri; int [] ai; int [] bi; long [] rl; long [] al; long [] bl; //===================== Compress Bits Transforms ================ @Test @IR(counts = {IRNode.RSHIFT_I, " > 0 ", IRNode.AND_I, " > 0"}) public void test1(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.compress(ai[i], 1 << bi[i]); } } @Run(test = {"test1"}, mode = RunMode.STANDALONE) public void kernel_test1() { for (int i = 0; i < 5000; i++) { test1(ri, ai, bi); } } @Test @IR(counts = {IRNode.URSHIFT_I, " > 0 "}) public void test2(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.compress(ai[i], -1 << bi[i]); } } @Run(test = {"test2"}, mode = RunMode.STANDALONE) public void kernel_test2() { for (int i = 0; i < 5000; i++) { test2(ri, ai, bi); } } @Test @IR(counts = {IRNode.COMPRESS_BITS, " > 0 ", IRNode.AND_I , " > 0 "}) public void test3(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.compress(Integer.expand(ai[i], bi[i]), bi[i]); } } @Run(test = {"test3"}, mode = RunMode.STANDALONE) public void kernel_test3() { for (int i = 0; i < 5000; i++) { test3(ri, ai, bi); } } @Test @IR(counts = {IRNode.RSHIFT_L, " > 0 ", IRNode.AND_L, " > 0"}) public void test4(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.compress(al[i], 1L << bl[i]); } } @Run(test = {"test4"}, mode = RunMode.STANDALONE) public void kernel_test4() { for (int i = 0; i < 5000; i++) { test4(rl, al, bl); } } @Test @IR(counts = {IRNode.URSHIFT_L, " > 0 "}) public void test5(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.compress(al[i], -1L << bl[i]); } } @Run(test = {"test5"}, mode = RunMode.STANDALONE) public void kernel_test5() { for (int i = 0; i < 5000; i++) { test5(rl, al, bl); } } @Test @IR(counts = {IRNode.COMPRESS_BITS, " > 0 ", IRNode.AND_L , " > 0 "}) public void test6(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.compress(Long.expand(al[i], bl[i]), bl[i]); } } @Run(test = {"test6"}, mode = RunMode.STANDALONE) public void kernel_test6() { for (int i = 0; i < 5000; i++) { test6(rl, al, bl); } } //===================== Expand Bits Transforms ================ @Test @IR(counts = {IRNode.LSHIFT_I, " > 0 ", IRNode.AND_I, " > 0"}) public void test7(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.expand(ai[i], 1 << bi[i]); } } @Run(test = {"test7"}, mode = RunMode.STANDALONE) public void kernel_test7() { for (int i = 0; i < 5000; i++) { test7(ri, ai, bi); } } @Test @IR(counts = {IRNode.LSHIFT_I, " > 0 "}) public void test8(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.expand(ai[i], -1 << bi[i]); } } @Run(test = {"test8"}, mode = RunMode.STANDALONE) public void kernel_test8() { for (int i = 0; i < 5000; i++) { test8(ri, ai, bi); } } @Test @IR(counts = {IRNode.AND_I , " > 0 "}) public void test9(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.expand(Integer.compress(ai[i], bi[i]), bi[i]); } } @Run(test = {"test9"}, mode = RunMode.STANDALONE) public void kernel_test9() { for (int i = 0; i < 5000; i++) { test9(ri, ai, bi); } } @Test @IR(counts = {IRNode.LSHIFT_L, " > 0 ", IRNode.AND_L, " > 0"}) public void test10(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.expand(al[i], 1L << bl[i]); } } @Run(test = {"test10"}, mode = RunMode.STANDALONE) public void kernel_test10() { for (int i = 0; i < 5000; i++) { test10(rl, al, bl); } } @Test @IR(counts = {IRNode.LSHIFT_L, " > 0 "}) public void test11(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.expand(al[i], -1L << bl[i]); } } @Run(test = {"test11"}, mode = RunMode.STANDALONE) public void kernel_test11() { for (int i = 0; i < 5000; i++) { test11(rl, al, bl); } } @Test @IR(counts = {IRNode.AND_L , " > 0 "}) public void test12(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.expand(Long.compress(al[i], bl[i]), bl[i]); } } @Run(test = {"test12"}, mode = RunMode.STANDALONE) public void kernel_test12() { for (int i = 0; i < 5000; i++) { test12(rl, al, bl); } } // ================ Compress/ExpandBits Vanilla ================= // @Test @IR(counts = {IRNode.COMPRESS_BITS, " > 0 "}) public void test13(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.compress(ai[i], bi[i]); } } @Run(test = {"test13"}, mode = RunMode.STANDALONE) public void kernel_test13() { for (int i = 0; i < 5000; i++) { test13(ri, ai, bi); } verifyCompressInts(ri, ai, bi); } @Test @IR(counts = {IRNode.COMPRESS_BITS, " > 0 "}) public void test14(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.compress(al[i], bl[i]); } } @Run(test = {"test14"}, mode = RunMode.STANDALONE) public void kernel_test14() { for (int i = 0; i < 5000; i++) { test14(rl, al, bl); } verifyCompressLongs(rl, al, bl); } @Test @IR(counts = {IRNode.EXPAND_BITS, " > 0 "}) public void test15(int[] ri, int[] ai, int[] bi) { for (int i = 0; i < ri.length; i++) { ri[i] = Integer.expand(ai[i], bi[i]); } } @Run(test = {"test15"}, mode = RunMode.STANDALONE) public void kernel_test15() { for (int i = 0; i < 5000; i++) { test15(ri, ai, bi); } verifyExpandInts(ri, ai, bi); } @Test @IR(counts = {IRNode.EXPAND_BITS, " > 0 "}) public void test16(long[] rl, long[] al, long[] bl) { for (int i = 0; i < rl.length; i++) { rl[i] = Long.expand(al[i], bl[i]); } } @Run(test = {"test16"}, mode = RunMode.STANDALONE) public void kernel_test16() { for (int i = 0; i < 5000; i++) { test16(rl, al, bl); } verifyExpandLongs(rl, al, bl); } @Test public void test17() { int resI = 0; long resL = 0L; for (int i = 0; i < 5000; i++) { resI = Integer.expand(-1, -1); verifyExpandInt(resI, -1, -1); resI = Integer.compress(-1, -1); verifyCompressInt(resI, -1, -1); resI = Integer.expand(ai[i&(SIZE-1)], -1); verifyExpandInt(resI, ai[i&(SIZE-1)], -1); resI = Integer.expand(ai[i&(SIZE-1)], -2); verifyExpandInt(resI, ai[i&(SIZE-1)], -2); resI = Integer.expand(ai[i&(SIZE-1)], 5); verifyExpandInt(resI, ai[i&(SIZE-1)], 5); resI = Integer.compress(ai[i&(SIZE-1)], -1); verifyCompressInt(resI, ai[i&(SIZE-1)], -1); resI = Integer.compress(ai[i&(SIZE-1)], -2); verifyCompressInt(resI, ai[i&(SIZE-1)], -2); resI = Integer.compress(ai[i&(SIZE-1)], 5); verifyCompressInt(resI, ai[i&(SIZE-1)], 5); resI = Integer.expand(ai[i&(SIZE-1)], bi[i&(SIZE-1)] & ~(0x10000000)); verifyExpandInt(resI, ai[i&(SIZE-1)], bi[i&(SIZE-1)] & ~(0x10000000)); resI = Integer.expand(ai[i&(SIZE-1)], bi[i&(SIZE-1)] | (0x10000000)); verifyExpandInt(resI, ai[i&(SIZE-1)], bi[i&(SIZE-1)] | (0x10000000)); resI = Integer.compress(ai[i&(SIZE-1)], bi[i&(SIZE-1)] & ~(0x10000000)); verifyCompressInt(resI, ai[i&(SIZE-1)], bi[i&(SIZE-1)] & ~(0x10000000)); resI = Integer.compress(ai[i&(SIZE-1)], bi[i&(SIZE-1)] | (0x10000000)); verifyCompressInt(resI, ai[i&(SIZE-1)], bi[i&(SIZE-1)] | (0x10000000)); resI = Integer.compress(0x12123434, 0xFF00FF00); verifyCompressInt(resI, 0x12123434, 0xFF00FF00); resI = Integer.expand(0x12123434, 0xFF00FF00); verifyExpandInt(resI, 0x12123434, 0xFF00FF00); resL = Long.expand(-1L, -1L); verifyExpandLong(resL, -1L, -1L); resL = Long.compress(-1L, -1L); verifyCompressLong(resL, -1L, -1L); resL = Long.compress(0x1212343412123434L, 0xFF00FF00FF00FF00L); verifyCompressLong(resL, 0x1212343412123434L, 0xFF00FF00FF00FF00L); resL = Long.expand(0x1212343412123434L, 0xFF00FF00FF00FF00L); verifyExpandLong(resL, 0x1212343412123434L, 0xFF00FF00FF00FF00L); resL = Long.expand(al[i&(SIZE-1)], -1); verifyExpandLong(resL, al[i&(SIZE-1)], -1); resL = Long.expand(al[i&(SIZE-1)], -2); verifyExpandLong(resL, al[i&(SIZE-1)], -2); resL = Long.expand(al[i&(SIZE-1)], 5); verifyExpandLong(resL, al[i&(SIZE-1)], 5); resL = Long.compress(al[i&(SIZE-1)], -1); verifyCompressLong(resL, al[i&(SIZE-1)], -1); resL = Long.compress(al[i&(SIZE-1)], -2); verifyCompressLong(resL, al[i&(SIZE-1)], -2); resL = Long.compress(al[i&(SIZE-1)], 5); verifyCompressLong(resL, al[i&(SIZE-1)], 5); resL = Long.expand(al[i&(SIZE-1)], bl[i&(SIZE-1)] & ~(0x10000000)); verifyExpandLong(resL, al[i&(SIZE-1)], bl[i&(SIZE-1)] & ~(0x10000000)); resL = Long.expand(al[i&(SIZE-1)], bl[i&(SIZE-1)] | (0x10000000)); verifyExpandLong(resL, al[i&(SIZE-1)], bl[i&(SIZE-1)] | (0x10000000)); resL = Long.compress(al[i&(SIZE-1)], bl[i&(SIZE-1)] & ~(0x10000000)); verifyCompressLong(resL, al[i&(SIZE-1)], bl[i&(SIZE-1)] & ~(0x10000000)); resL = Long.compress(al[i&(SIZE-1)], bl[i&(SIZE-1)] | (0x10000000)); verifyCompressLong(resL, al[i&(SIZE-1)], bl[i&(SIZE-1)] | (0x10000000)); } } private static final Random R = Utils.getRandomInstance(); static int[] fillIntRandom(Callable factory) { try { int[] arr = factory.call(); for (int i = 0; i < arr.length; i++) { arr[i] = R.nextInt(); } return arr; } catch (Exception e) { throw new InternalError(e); } } static long[] fillLongRandom(Callable factory) { try { long[] arr = factory.call(); for (int i = 0; i < arr.length; i++) { arr[i] = R.nextLong(); } return arr; } catch (Exception e) { throw new InternalError(e); } } static void verifyExpandInt(int actual, int src, int mask) { int exp = 0; for(int j = 0, k = 0; j < Integer.SIZE; j++) { if ((mask & 0x1) == 1) { exp |= (src & 0x1) << j; src >>= 1; } mask >>= 1; } if (actual != exp) { throw new Error("expand_int: src = " + src + " mask = " + mask + " acutal = " + actual + " expected = " + exp); } } static void verifyExpandInts(int [] actual_res, int [] inp_arr, int [] mask_arr) { assert inp_arr.length == mask_arr.length && inp_arr.length == actual_res.length; for(int i = 0; i < actual_res.length; i++) { verifyExpandInt(actual_res[i], inp_arr[i], mask_arr[i]); } } static void verifyExpandLong(long actual, long src, long mask) { long exp = 0; for(int j = 0, k = 0; j < Long.SIZE; j++) { if ((mask & 0x1) == 1) { exp |= (src & 0x1) << j; src >>= 1; } mask >>= 1; } if (actual != exp) { throw new Error("expand_long: src = " + src + " mask = " + mask + " acutal = " + actual + " expected = " + exp); } } static void verifyExpandLongs(long [] actual_res, long [] inp_arr, long [] mask_arr) { assert inp_arr.length == mask_arr.length && inp_arr.length == actual_res.length; for(int i = 0; i < actual_res.length; i++) { verifyExpandLong(actual_res[i], inp_arr[i], mask_arr[i]); } } static void verifyCompressInt(int actual, int src, int mask) { int exp = 0; for(int j = 0, k = 0; j < Integer.SIZE; j++) { if ((mask & 0x1) == 1) { exp |= (src & 0x1) << k++; } mask >>= 1; src >>= 1; } if (actual != exp) { throw new Error("compress_int: src = " + src + " mask = " + mask + " acutal = " + actual + " expected = " + exp); } } static void verifyCompressInts(int [] actual_res, int [] inp_arr, int [] mask_arr) { assert inp_arr.length == mask_arr.length && inp_arr.length == actual_res.length; for(int i = 0; i < actual_res.length; i++) { verifyCompressInt(actual_res[i], inp_arr[i], mask_arr[i]); } } static void verifyCompressLong(long actual, long src, long mask) { long exp = 0; for(int j = 0, k = 0; j < Long.SIZE; j++) { if ((mask & 0x1) == 1) { exp |= (src & 0x1) << k++; } mask >>= 1; src >>= 1; } if (actual != exp) { throw new Error("compress_long: src = " + src + " mask = " + mask + " acutal = " + actual + " expected = " + exp); } } static void verifyCompressLongs(long [] actual_res, long [] inp_arr, long [] mask_arr) { assert inp_arr.length == mask_arr.length && inp_arr.length == actual_res.length; for(int i = 0; i < actual_res.length; i++) { verifyCompressLong(actual_res[i], inp_arr[i], mask_arr[i]); } } // ===================================================== // static final int SIZE = 512; public TestBitShuffleOpers() { ri = new int[SIZE]; ai = fillIntRandom(()-> new int[SIZE]); bi = fillIntRandom(()-> new int[SIZE]); rl = new long[SIZE]; al = fillLongRandom(() -> new long[SIZE]); bl = fillLongRandom(() -> new long[SIZE]); } public static void main(String[] args) { TestFramework.runWithFlags("-XX:-TieredCompilation", "-XX:CompileThresholdScaling=0.3"); } }