mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-03 06:35:31 +00:00
8386155: C2 Vector API: missing truncation in VectorNode::push_through_replicate
Reviewed-by: chagedorn Backport-of: ee9616d4a43006f932774f9a5d421dc46a91d5d6
This commit is contained in:
parent
2b3b9901fc
commit
601a464a0c
@ -1415,6 +1415,13 @@ Node* VectorNode::push_through_replicate(PhaseGVN* phase) {
|
||||
|
||||
sop = phase->transform(sop);
|
||||
|
||||
// For subword types, the scalar operation computes at int width and may
|
||||
// produce values outside the subword range. Narrow the result unconditionally
|
||||
// before feeding it to Replicate.
|
||||
if (is_subword_type(bt)) {
|
||||
sop = Compile::narrow_value(bt, sop, Type::get_const_basic_type(bt), phase, true);
|
||||
}
|
||||
|
||||
return new ReplicateNode(sop, vect_type());
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,447 @@
|
||||
/*
|
||||
* Copyright (c) 2026, 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 8386155
|
||||
* @summary Test missing trunctation after subword vector operation reassociation
|
||||
* @modules jdk.incubator.vector
|
||||
* @library /test/lib /
|
||||
* @run driver compiler.vectorapi.TestTruncationAfterReassociation
|
||||
*/
|
||||
|
||||
package compiler.vectorapi;
|
||||
|
||||
import compiler.lib.generators.Generator;
|
||||
import compiler.lib.generators.Generators;
|
||||
import compiler.lib.ir_framework.*;
|
||||
import compiler.lib.verify.Verify;
|
||||
import jdk.incubator.vector.*;
|
||||
|
||||
public class TestTruncationAfterReassociation {
|
||||
|
||||
public static void main(String[] args) {
|
||||
TestFramework.runWithFlags("--add-modules=jdk.incubator.vector");
|
||||
}
|
||||
|
||||
static final VectorSpecies<Byte> BSP = ByteVector.SPECIES_PREFERRED;
|
||||
static final VectorSpecies<Short> SSP = ShortVector.SPECIES_PREFERRED;
|
||||
|
||||
// Random value source (covers the full integer range, biased towards
|
||||
// interesting/special values such as 0, MIN, MAX and powers of two).
|
||||
static final Generator<Integer> INT_GEN = Generators.G.ints();
|
||||
|
||||
static final int RAND_ITERS = 2048;
|
||||
|
||||
static byte B_127 = (byte) 127;
|
||||
static byte B_N16 = (byte) -16;
|
||||
static byte B_N7 = (byte) -7;
|
||||
static byte B_100 = (byte) 100;
|
||||
static byte B_4 = (byte) 4;
|
||||
static byte B_5 = (byte) 5;
|
||||
static byte B_10 = (byte) 10;
|
||||
static byte B_N128 = (byte) -128;
|
||||
static byte B_1 = (byte) 1;
|
||||
|
||||
static short S_32767 = (short) 32767;
|
||||
static short S_N16 = (short) -16;
|
||||
static short S_N7 = (short) -7;
|
||||
static short S_200 = (short) 200;
|
||||
static short S_5 = (short) 5;
|
||||
static short S_10 = (short) 10;
|
||||
static short S_N32768 = (short) -32768;
|
||||
static short S_1 = (short) 1;
|
||||
|
||||
static byte bmul(byte x, byte y) { return (byte) (x * y); }
|
||||
static byte badd(byte x, byte y) { return (byte) (x + y); }
|
||||
static byte bsub(byte x, byte y) { return (byte) (x - y); }
|
||||
static byte bmax(byte x, byte y) { return (byte) Math.max(x, y); }
|
||||
static byte bmin(byte x, byte y) { return (byte) Math.min(x, y); }
|
||||
|
||||
static short smul(short x, short y) { return (short) (x * y); }
|
||||
static short sadd(short x, short y) { return (short) (x + y); }
|
||||
static short ssub(short x, short y) { return (short) (x - y); }
|
||||
static short smax(short x, short y) { return (short) Math.max(x, y); }
|
||||
static short smin(short x, short y) { return (short) Math.min(x, y); }
|
||||
|
||||
@Test
|
||||
static byte bug_8386155_reproducer() {
|
||||
return ByteVector.broadcast(ByteVector.SPECIES_64, (byte) 127)
|
||||
// Expected: mul is truncated to signed byte: 127 * -16 = (byte)-2032 = 16
|
||||
.mul((byte) -16)
|
||||
// Expected: max(16, -7) = 16
|
||||
.max((byte) -7)
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "bug_8386155_reproducer")
|
||||
static void run_bug_8386155_reproducer() {
|
||||
Verify.checkEQ(bug_8386155_reproducer(), (byte) 16);
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* BYTE: <overflowing ADD/SUB/MUL> then <MAX/MIN>.
|
||||
* ========================================================= */
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VB, IRNode.MAX_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_mul_then_max() {
|
||||
return ByteVector.broadcast(BSP, B_127)
|
||||
.mul(ByteVector.broadcast(BSP, B_N16))
|
||||
.max(ByteVector.broadcast(BSP, B_N7))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_mul_then_max")
|
||||
static void run_byte_mul_then_max() {
|
||||
Verify.checkEQ(byte_mul_then_max(), bmax(bmul(B_127, B_N16), B_N7));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VB, IRNode.MIN_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_mul_then_min() {
|
||||
return ByteVector.broadcast(BSP, B_100)
|
||||
.mul(ByteVector.broadcast(BSP, B_4))
|
||||
.min(ByteVector.broadcast(BSP, B_5))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_mul_then_min")
|
||||
static void run_byte_mul_then_min() {
|
||||
Verify.checkEQ(byte_mul_then_min(), bmin(bmul(B_100, B_4), B_5));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.ADD_VB, IRNode.MAX_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.ADD_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_add_then_max() {
|
||||
return ByteVector.broadcast(BSP, B_127)
|
||||
.add(ByteVector.broadcast(BSP, B_127))
|
||||
.max(ByteVector.broadcast(BSP, B_5))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_add_then_max")
|
||||
static void run_byte_add_then_max() {
|
||||
Verify.checkEQ(byte_add_then_max(), bmax(badd(B_127, B_127), B_5));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.ADD_VB, IRNode.MIN_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.ADD_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_add_then_min() {
|
||||
return ByteVector.broadcast(BSP, B_127)
|
||||
.add(ByteVector.broadcast(BSP, B_127))
|
||||
.min(ByteVector.broadcast(BSP, B_10))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_add_then_min")
|
||||
static void run_byte_add_then_min() {
|
||||
Verify.checkEQ(byte_add_then_min(), bmin(badd(B_127, B_127), B_10));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.SUB_VB, IRNode.MAX_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.SUB_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_sub_then_max() {
|
||||
return ByteVector.broadcast(BSP, B_N128)
|
||||
.sub(ByteVector.broadcast(BSP, B_1))
|
||||
.max(ByteVector.broadcast(BSP, B_10))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_sub_then_max")
|
||||
static void run_byte_sub_then_max() {
|
||||
Verify.checkEQ(byte_sub_then_max(), bmax(bsub(B_N128, B_1), B_10));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.SUB_VB, IRNode.MIN_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.SUB_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_sub_then_min() {
|
||||
return ByteVector.broadcast(BSP, B_N128)
|
||||
.sub(ByteVector.broadcast(BSP, B_1))
|
||||
.min(ByteVector.broadcast(BSP, B_10))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_sub_then_min")
|
||||
static void run_byte_sub_then_min() {
|
||||
Verify.checkEQ(byte_sub_then_min(), bmin(bsub(B_N128, B_1), B_10));
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* SHORT: <overflowing ADD/SUB/MUL> then <MAX/MIN>.
|
||||
* ========================================================= */
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VS, IRNode.MAX_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short short_mul_then_max() {
|
||||
return ShortVector.broadcast(SSP, S_32767)
|
||||
.mul(ShortVector.broadcast(SSP, S_N16))
|
||||
.max(ShortVector.broadcast(SSP, S_N7))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "short_mul_then_max")
|
||||
static void run_short_mul_then_max() {
|
||||
Verify.checkEQ(short_mul_then_max(), smax(smul(S_32767, S_N16), S_N7));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VS, IRNode.MIN_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short short_mul_then_min() {
|
||||
return ShortVector.broadcast(SSP, S_200)
|
||||
.mul(ShortVector.broadcast(SSP, S_200))
|
||||
.min(ShortVector.broadcast(SSP, S_5))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "short_mul_then_min")
|
||||
static void run_short_mul_then_min() {
|
||||
Verify.checkEQ(short_mul_then_min(), smin(smul(S_200, S_200), S_5));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.ADD_VS, IRNode.MAX_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.ADD_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short short_add_then_max() {
|
||||
return ShortVector.broadcast(SSP, S_32767)
|
||||
.add(ShortVector.broadcast(SSP, S_32767))
|
||||
.max(ShortVector.broadcast(SSP, S_5))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "short_add_then_max")
|
||||
static void run_short_add_then_max() {
|
||||
Verify.checkEQ(short_add_then_max(), smax(sadd(S_32767, S_32767), S_5));
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.SUB_VS, IRNode.MIN_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.SUB_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short short_sub_then_min() {
|
||||
return ShortVector.broadcast(SSP, S_N32768)
|
||||
.sub(ShortVector.broadcast(SSP, S_1))
|
||||
.min(ShortVector.broadcast(SSP, S_10))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "short_sub_then_min")
|
||||
static void run_short_sub_then_min() {
|
||||
Verify.checkEQ(short_sub_then_min(), smin(ssub(S_N32768, S_1), S_10));
|
||||
}
|
||||
|
||||
// Two independent overflowing products feeding a single max
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VB, IRNode.MAX_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_two_muls_then_max() {
|
||||
return ByteVector.broadcast(BSP, B_127).mul(ByteVector.broadcast(BSP, B_N16))
|
||||
.max(ByteVector.broadcast(BSP, B_100).mul(ByteVector.broadcast(BSP, B_4)))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_two_muls_then_max")
|
||||
static void run_byte_two_muls_then_max() {
|
||||
Verify.checkEQ(byte_two_muls_then_max(),
|
||||
bmax(bmul(B_127, B_N16), bmul(B_100, B_4)));
|
||||
}
|
||||
|
||||
// Chained (reassociated) adds whose running value overflows, then a max
|
||||
@Test
|
||||
@IR(failOn = { IRNode.ADD_VB, IRNode.MAX_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.ADD_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_chain_add_then_max() {
|
||||
return ByteVector.broadcast(BSP, B_127)
|
||||
.add(ByteVector.broadcast(BSP, B_127))
|
||||
.add(ByteVector.broadcast(BSP, B_127))
|
||||
.max(ByteVector.broadcast(BSP, B_127))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_chain_add_then_max")
|
||||
static void run_byte_chain_add_then_max() {
|
||||
Verify.checkEQ(byte_chain_add_then_max(),
|
||||
bmax(badd(badd(B_127, B_127), B_127), B_127));
|
||||
}
|
||||
|
||||
// Overflowing product feeding max then min:
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VB, IRNode.MAX_VB, IRNode.MIN_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MAX_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte byte_mul_max_then_min() {
|
||||
return ByteVector.broadcast(BSP, B_127)
|
||||
.mul(ByteVector.broadcast(BSP, B_N16))
|
||||
.max(ByteVector.broadcast(BSP, B_N7))
|
||||
.min(ByteVector.broadcast(BSP, B_10))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "byte_mul_max_then_min")
|
||||
static void run_byte_mul_max_then_min() {
|
||||
Verify.checkEQ(byte_mul_max_then_min(),
|
||||
bmin(bmax(bmul(B_127, B_N16), B_N7), B_10));
|
||||
}
|
||||
|
||||
// Two overflowing short products feeding a single min
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VS, IRNode.MIN_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short short_two_muls_then_min() {
|
||||
return ShortVector.broadcast(SSP, S_200).mul(ShortVector.broadcast(SSP, S_200))
|
||||
.min(ShortVector.broadcast(SSP, S_32767).mul(ShortVector.broadcast(SSP, S_N16)))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "short_two_muls_then_min")
|
||||
static void run_short_two_muls_then_min() {
|
||||
Verify.checkEQ(short_two_muls_then_min(),
|
||||
smin(smul(S_200, S_200), smul(S_32767, S_N16)));
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* Randomized coverage (Generators).
|
||||
* ========================================================= */
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VB, IRNode.MAX_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte rand_byte_mul_then_max(byte a, byte b, byte c) {
|
||||
return ByteVector.broadcast(BSP, a)
|
||||
.mul(ByteVector.broadcast(BSP, b))
|
||||
.max(ByteVector.broadcast(BSP, c))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "rand_byte_mul_then_max")
|
||||
static void run_rand_byte_mul_then_max() {
|
||||
for (int i = 0; i < RAND_ITERS; i++) {
|
||||
byte a = INT_GEN.next().byteValue();
|
||||
byte b = INT_GEN.next().byteValue();
|
||||
byte c = INT_GEN.next().byteValue();
|
||||
Verify.checkEQ(rand_byte_mul_then_max(a, b, c), bmax(bmul(a, b), c));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VB, IRNode.MIN_VB },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static byte rand_byte_mul_then_min(byte a, byte b, byte c) {
|
||||
return ByteVector.broadcast(BSP, a)
|
||||
.mul(ByteVector.broadcast(BSP, b))
|
||||
.min(ByteVector.broadcast(BSP, c))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "rand_byte_mul_then_min")
|
||||
static void run_rand_byte_mul_then_min() {
|
||||
for (int i = 0; i < RAND_ITERS; i++) {
|
||||
byte a = INT_GEN.next().byteValue();
|
||||
byte b = INT_GEN.next().byteValue();
|
||||
byte c = INT_GEN.next().byteValue();
|
||||
Verify.checkEQ(rand_byte_mul_then_min(a, b, c), bmin(bmul(a, b), c));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VS, IRNode.MAX_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MAX_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short rand_short_mul_then_max(short a, short b, short c) {
|
||||
return ShortVector.broadcast(SSP, a)
|
||||
.mul(ShortVector.broadcast(SSP, b))
|
||||
.max(ShortVector.broadcast(SSP, c))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "rand_short_mul_then_max")
|
||||
static void run_rand_short_mul_then_max() {
|
||||
for (int i = 0; i < RAND_ITERS; i++) {
|
||||
short a = INT_GEN.next().shortValue();
|
||||
short b = INT_GEN.next().shortValue();
|
||||
short c = INT_GEN.next().shortValue();
|
||||
Verify.checkEQ(rand_short_mul_then_max(a, b, c), smax(smul(a, b), c));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@IR(failOn = { IRNode.MUL_VS, IRNode.MIN_VS },
|
||||
applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"},
|
||||
counts = { IRNode.MUL_I, ">= 1", IRNode.MIN_I, ">= 1",
|
||||
IRNode.LSHIFT_I, ">= 1", IRNode.RSHIFT_I, ">= 1" })
|
||||
static short rand_short_mul_then_min(short a, short b, short c) {
|
||||
return ShortVector.broadcast(SSP, a)
|
||||
.mul(ShortVector.broadcast(SSP, b))
|
||||
.min(ShortVector.broadcast(SSP, c))
|
||||
.lane(0);
|
||||
}
|
||||
|
||||
@Run(test = "rand_short_mul_then_min")
|
||||
static void run_rand_short_mul_then_min() {
|
||||
for (int i = 0; i < RAND_ITERS; i++) {
|
||||
short a = INT_GEN.next().shortValue();
|
||||
short b = INT_GEN.next().shortValue();
|
||||
short c = INT_GEN.next().shortValue();
|
||||
Verify.checkEQ(rand_short_mul_then_min(a, b, c), smin(smul(a, b), c));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user