Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 4 additions & 21 deletions src/hotspot/cpu/riscv/riscv_v.ad
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@ source %{
case Op_PopCountVI:
case Op_ReverseBytesV:
case Op_ReverseV:
return UseZvbb;
case Op_RotateLeftV:
case Op_RotateRightV:
if (bt != T_INT && bt != T_LONG) {
return false;
}
return UseZvbb;
case Op_LoadVectorGather:
case Op_LoadVectorGatherMasked:
Expand Down Expand Up @@ -3413,27 +3417,6 @@ instruct vshiftcnt(vReg dst, iRegIorL2I cnt) %{
%}

// --------------------------------- Vector Rotation ----------------------------------
//
// Following rotate instruct's are shared by vectorization (in SLP, superword.cpp) and Vector API.
//
// Rotate behaviour in vectorization is defined by java API, which includes:
// 1. Integer.rorateRight, Integer.rorateLeft.
// `rotation by any multiple of 32 is a no-op, so all but the last five bits of the rotation distance can be ignored`.
// 2. Long.rorateRight, Long.rorateLeft.
// `rotation by any multiple of 64 is a no-op, so all but the last six bits of the rotation distance can be ignored`.
//
// Rotate behaviour in Vector API is defined as below, e.g.
// 1. For Byte ROR, `a ROR b` is: (byte)(((((byte)a) & 0xFF) >>> (b & 7)) | ((((byte)a) & 0xFF) << (8 - (b & 7))))
// 2. For Short ROR, `a ROR b` is: (short)(((((short)a) & 0xFFFF) >>> (b & 15)) | ((((short)a) & 0xFFFF) << (16 - (b & 15))))
// 3. For Integer ROR, `a ROR b` is: Integer.rotateRight(a, ((int)b))
// 4. For Long ROR, `a ROR b` is: Long.rotateRight(a, ((int)b))
//
// Basically, the behaviour between vectorization and Vector API is the same for Long and Integer, except that Vector API
// also supports Byte and Short rotation. But we can still share the intrinsics between vectorization and Vector API.
//
// NOTE: As vror.vi encodes 6-bits immediate rotate amount, which is different from other vector-immediate instructions,
// implementation of vector rotation for long and other types can be unified.

// Rotate right

instruct vrotate_right(vReg dst, vReg src, vReg shift) %{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2022, Loongson Technology Co. Ltd. All rights reserved.
* Copyright (c) 2022, 2025 Loongson Technology Co. Ltd. All rights reserved.
* Copyright (c) 2025, Rivos 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
Expand All @@ -23,15 +24,16 @@

/**
* @test
* @bug 8286847
* @bug 8286847 8353600
* @key randomness
* @summary Test vectorization of rotate byte and short
* @library /test/lib
* @run main/othervm -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestRotateByteAndShortVector::testRotate* -Xbatch TestRotateByteAndShortVector
* @library /test/lib /
* @run main/othervm TestRotateByteAndShortVector
*/

import java.util.Random;
import jdk.test.lib.Utils;
import compiler.lib.ir_framework.*;

public class TestRotateByteAndShortVector {
private static final Random random = Utils.getRandomInstance();
Expand All @@ -49,27 +51,7 @@ public class TestRotateByteAndShortVector {
private static short resShort = 0;

public static void main(String[] args) {
System.out.println("warmup");
warmup();

System.out.println("Testing...");
runRotateLeftByteTest();
runRotateRightByteTest();
runRotateLeftShortTest();
runRotateRightShortTest();

System.out.println("PASSED");
}

static void warmup() {
random.nextBytes(arrByte);
randomShorts();
for (int i = 0; i < ITERS; i++) {
testRotateLeftByte(rolByte, arrByte, i);
testRotateRightByte(rorByte, arrByte, i);
testRotateLeftShort(rolShort, arrShort, i);
testRotateRightShort(rorShort, arrShort, i);
}
TestFramework.run();
}

static void randomShorts() {
Expand All @@ -78,6 +60,7 @@ static void randomShorts() {
}
}

@Run(test = { "testRotateLeftByte" })
static void runRotateLeftByteTest() {
for (int shift = 0; shift < 64; shift++) {
random.nextBytes(arrByte);
Expand All @@ -91,6 +74,7 @@ static void runRotateLeftByteTest() {
}
}

@Run(test = { "testRotateRightByte" })
static void runRotateRightByteTest() {
for (int shift = 0; shift < 64; shift++) {
random.nextBytes(arrByte);
Expand All @@ -104,6 +88,7 @@ static void runRotateRightByteTest() {
}
}

@Run(test = { "testRotateLeftShort" })
static void runRotateLeftShortTest() {
for (int shift = 0; shift < 64; shift++) {
randomShorts();
Expand All @@ -117,6 +102,7 @@ static void runRotateLeftShortTest() {
}
}

@Run(test = { "testRotateRightShort" })
static void runRotateRightShortTest() {
for (int shift = 0; shift < 64; shift++) {
randomShorts();
Expand All @@ -130,24 +116,39 @@ static void runRotateRightShortTest() {
}
}

// NOTE: currently, there is no platform supporting RotateLeftV/RotateRightV intrinsic.
// If there is some implementation, it could probably in a wrong way which is different
// from what java language spec expects.
@Test
@IR(failOn = { IRNode.ROTATE_LEFT_V })
@IR(failOn = { IRNode.ROTATE_RIGHT_V })
static void testRotateLeftByte(byte[] test, byte[] arr, int shift) {
for (int i = 0; i < ARRLEN; i++) {
test[i] = (byte) ((arr[i] << shift) | (arr[i] >>> -shift));
}
}

@Test
@IR(failOn = { IRNode.ROTATE_LEFT_V })
@IR(failOn = { IRNode.ROTATE_RIGHT_V })
static void testRotateRightByte(byte[] test, byte[] arr, int shift) {
for (int i = 0; i < ARRLEN; i++) {
test[i] = (byte) ((arr[i] >>> shift) | (arr[i] << -shift));
}
}

@Test
@IR(failOn = { IRNode.ROTATE_LEFT_V })
@IR(failOn = { IRNode.ROTATE_RIGHT_V })
static void testRotateLeftShort(short[] test, short[] arr, int shift) {
for (int i = 0; i < ARRLEN; i++) {
test[i] = (short) ((arr[i] << shift) | (arr[i] >>> -shift));
}
}

@Test
@IR(failOn = { IRNode.ROTATE_LEFT_V })
@IR(failOn = { IRNode.ROTATE_RIGHT_V })
static void testRotateRightShort(short[] test, short[] arr, int shift) {
for (int i = 0; i < ARRLEN; i++) {
test[i] = (short) ((arr[i] >>> shift) | (arr[i] << -shift));
Expand Down