diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 388e7f9eb94..0fe91d99066 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1904,6 +1904,16 @@ enum Nf { #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 Basic Bit-manipulation (Zvbb) Extension + INSN(vcpop_v, 0b1010111, 0b010, 0b01110, 0b010010); + +#undef INSN + #undef patch_VArith // ==================================== diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index e22456cacc6..c39b29f6ee4 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -115,6 +115,7 @@ 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, UseZvbb, false, EXPERIMENTAL, "Use Zvbb instructions") \ product(bool, UseZvfh, false, EXPERIMENTAL, "Use Zvfh instructions") \ product(bool, UseZvkn, false, EXPERIMENTAL, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 7869d6156e5..0879f62600e 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -73,6 +73,9 @@ source %{ return false; } break; + case Op_PopCountVL: + case Op_PopCountVI: + return UseZvbb; case Op_LoadVectorGather: case Op_LoadVectorGatherMasked: if (is_subword_type(bt)) { @@ -3784,6 +3787,37 @@ instruct vconvF2HF(vReg dst, vReg src, vReg vtmp, vRegMask_V0 v0, iRegINoSp tmp) ins_pipe(pipe_slow); %} + +// ------------------------------ Popcount vector ------------------------------ + +instruct vpopcount_mask(vReg dst, vReg src, vRegMask_V0 v0) %{ + match(Set dst (PopCountVI src v0)); + match(Set dst (PopCountVL src v0)); + ins_cost(VEC_COST); + format %{ "vcpop_v $dst, $src, $v0\t# vcpop_v with mask" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vcpop_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), Assembler::v0_t); + %} + ins_pipe(pipe_slow); +%} + +instruct vpopcount(vReg dst, vReg src) %{ + match(Set dst (PopCountVI src)); + match(Set dst (PopCountVL src)); + ins_cost(VEC_COST); + format %{ "vcpop_v $dst, $src\t# vcpop_v without mask" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + uint vlen = Matcher::vector_length(this); + __ vsetvli_helper(bt, vlen); + __ vcpop_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); + %} + ins_pipe(pipe_slow); +%} + // ------------------------------ Vector Load Gather --------------------------- instruct gather_load(vReg dst, indirect mem, vReg idx) %{ diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 848ffe709d8..995e8b72248 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -245,6 +245,12 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false); } + // UseZvbb (depends on RVV). + if (UseZvbb && !UseRVV) { + FLAG_SET_DEFAULT(UseZvbb, false); + warning("Cannot enable UseZvbb on cpu without RVV support."); + } + // SHA's if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index d26b16941db..f3a834b7237 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -161,6 +161,7 @@ class VM_Version : public Abstract_VM_Version { decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \ decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \ decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \ + decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvbb)) \ decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvfh)) \ decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZvkn)) \ decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index 939267234bd..47cec9f5e13 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -102,7 +102,9 @@ public class IREncodingPrinter { // AArch64 "sha3", "asimd", - "sve" + "sve", + // Riscv64 + "zvbb" )); public IREncodingPrinter() { diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java index 60ecaf0e4c8..2a27aad8d5a 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestGeneralizedReductions.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 @@ -144,6 +144,11 @@ public class TestGeneralizedReductions { applyIfAnd = {"SuperWordReductions", "true","UsePopCountInstruction", "true"}, counts = {IRNode.ADD_REDUCTION_VI, ">= 1", IRNode.POPCOUNT_VL, ">= 1"}) + @IR(applyIfPlatform = {"riscv64", "true"}, + applyIfCPUFeature = {"zvbb", "true"}, + applyIfAnd = {"SuperWordReductions", "true","UsePopCountInstruction", "true"}, + counts = {IRNode.ADD_REDUCTION_VI, ">= 1", + IRNode.POPCOUNT_VL, ">= 1"}) private static long testMapReductionOnGlobalAccumulator(long[] array) { acc = 0; for (int i = 0; i < array.length; i++) { diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java index a6daa5bce06..4a4370fd2d1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 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 @@ -40,18 +40,22 @@ public class TestPopCountVector { public static void main(String args[]) { TestPopCountVector test = new TestPopCountVector(); + int err = 0; for (int i = 0; i < 10_000; ++i) { test.vectorizeBitCount(); } System.out.println("Checking popcount result"); - test.checkResult(); + err += test.checkResult(); for (int i = 0; i < 10_000; ++i) { test.vectorizeBitCount(); } System.out.println("Checking popcount result"); - test.checkResult(); + err += test.checkResult(); + if (err > 0) { + throw new RuntimeException("Error!"); + } } public TestPopCountVector() { @@ -68,13 +72,17 @@ public class TestPopCountVector { } } - public void checkResult() { + public int checkResult() { + int err = 0; for (int i = 0; i < LEN; ++i) { int expected = Integer.bitCount(input[i]); if (output[i] != expected) { - throw new RuntimeException("Invalid result: output[" + i + "] = " + output[i] + " != " + expected); + err++; + System.err.println("Invalid result: output[" + i + "] = " + output[i] + " != " + expected + + ", input[" + i + "] == " + Integer.toBinaryString(input[i])); } } + return err; } } diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java index 20912582b7f..e382e828790 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 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 @@ -26,12 +26,14 @@ * @summary Test vectorization of popcount for Long * @requires vm.compiler2.enabled * @requires ((os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") & vm.cpu.features ~= ".*avx512bw.*") | -* os.simpleArch == "aarch64" +* os.simpleArch == "aarch64" | +* (os.arch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") * @library /test/lib / * @run driver compiler.vectorization.TestPopCountVectorLong */ package compiler.vectorization; + import compiler.lib.ir_framework.*; import java.util.Random; @@ -62,16 +64,22 @@ public class TestPopCountVectorLong { for (int i = 0; i < LEN; ++i) { output[i] = Long.bitCount(input[i]); } - checkResult(); + if (checkResult() > 0) { + throw new RuntimeException("Error!"); + } } - public void checkResult() { + public int checkResult() { + int err = 0; for (int i = 0; i < LEN; ++i) { int expected = Long.bitCount(input[i]); if (output[i] != expected) { - throw new RuntimeException("Invalid result: output[" + i + "] = " + output[i] + " != " + expected); + err++; + System.err.println("Invalid result: output[" + i + "] = " + output[i] + " != " + expected + + ", input[" + i + "] == " + Long.toBinaryString(input[i])); } } + return err; } }