11/*
2- * Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+ * Copyright (c) 2025, 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323
2424/*
2525* @test
26- * @bug 8356760
26+ * @bug 8356760 8370863
2727* @key randomness
2828* @library /test/lib /
29- * @summary Optimize VectorMask.fromLong for all-true/all-false cases
29+ * @summary test VectorMaskCast Identity() optimizations
3030* @modules jdk.incubator.vector
3131*
3232* @run driver compiler.vectorapi.VectorMaskCastIdentityTest
@@ -50,70 +50,88 @@ public class VectorMaskCastIdentityTest {
5050 }
5151
5252 @ Test
53- @ IR (counts = { IRNode .VECTOR_MASK_CAST , "= 2" }, applyIfCPUFeatureOr = {"asimd" , "true" , "rvv" , "true" })
54- public static int testTwoCastToDifferentType () {
55- // The types before and after the two casts are not the same, so the cast cannot be eliminated.
56- VectorMask <Float > mFloat64 = VectorMask .fromArray (FloatVector .SPECIES_64 , mr , 0 );
57- VectorMask <Double > mDouble128 = mFloat64 .cast (DoubleVector .SPECIES_128 );
58- VectorMask <Integer > mInt64 = mDouble128 .cast (IntVector .SPECIES_64 );
59- return mInt64 .trueCount ();
60- }
61-
62- @ Run (test = "testTwoCastToDifferentType" )
63- public static void testTwoCastToDifferentType_runner () {
64- int count = testTwoCastToDifferentType ();
65- VectorMask <Float > mFloat64 = VectorMask .fromArray (FloatVector .SPECIES_64 , mr , 0 );
66- Asserts .assertEquals (count , mFloat64 .trueCount ());
67- }
68-
69- @ Test
70- @ IR (counts = { IRNode .VECTOR_MASK_CAST , "= 2" }, applyIfCPUFeatureOr = {"avx2" , "true" })
71- public static int testTwoCastToDifferentType2 () {
72- // The types before and after the two casts are not the same, so the cast cannot be eliminated.
53+ @ IR (counts = { IRNode .LOAD_VECTOR_Z , IRNode .VECTOR_SIZE_4 , "> 0" ,
54+ IRNode .VECTOR_MASK_CAST , "= 0" },
55+ applyIfCPUFeatureOr = { "asimd" , "true" , "avx2" , "true" , "rvv" , "true" },
56+ applyIf = { "MaxVectorSize" , ">= 16" })
57+ public static int testOneCastToSameType () {
58+ // The types before and after the cast sequence are the same,
59+ // so the casts will be eliminated.
7360 VectorMask <Integer > mInt128 = VectorMask .fromArray (IntVector .SPECIES_128 , mr , 0 );
74- VectorMask <Double > mDouble256 = mInt128 .cast (DoubleVector .SPECIES_256 );
75- VectorMask <Short > mShort64 = mDouble256 .cast (ShortVector .SPECIES_64 );
76- return mShort64 .trueCount ();
61+ mInt128 = mInt128 .cast (IntVector .SPECIES_128 );
62+ // Insert a not() to prevent the casts being optimized by the optimization:
63+ // (VectorStoreMask (VectorMaskCast* (VectorLoadMask x))) => x
64+ return mInt128 .not ().trueCount ();
7765 }
7866
79- @ Run (test = "testTwoCastToDifferentType2 " )
80- public static void testTwoCastToDifferentType2_runner () {
81- int count = testTwoCastToDifferentType2 ();
67+ @ Run (test = "testOneCastToSameType " )
68+ public static void testOneCastToSameType_runner () {
69+ int count = testOneCastToSameType ();
8270 VectorMask <Integer > mInt128 = VectorMask .fromArray (IntVector .SPECIES_128 , mr , 0 );
83- Asserts .assertEquals (count , mInt128 .trueCount ());
71+ Asserts .assertEquals (count , mInt128 .not (). trueCount ());
8472 }
8573
8674 @ Test
87- @ IR (counts = { IRNode .VECTOR_MASK_CAST , "= 0" }, applyIfCPUFeatureOr = {"avx2" , "true" , "asimd" , "true" , "rvv" , "true" })
75+ @ IR (counts = { IRNode .LOAD_VECTOR_Z , IRNode .VECTOR_SIZE_4 , "> 0" ,
76+ IRNode .VECTOR_MASK_CAST , "= 0" },
77+ applyIfCPUFeatureOr = { "asimd" , "true" , "avx2" , "true" , "rvv" , "true" },
78+ applyIf = { "MaxVectorSize" , ">= 16" })
8879 public static int testTwoCastToSameType () {
89- // The types before and after the two casts are the same, so the cast will be eliminated.
80+ // The types before and after the cast sequence are the same,
81+ // so the casts will be eliminated.
9082 VectorMask <Integer > mInt128 = VectorMask .fromArray (IntVector .SPECIES_128 , mr , 0 );
9183 VectorMask <Float > mFloat128 = mInt128 .cast (FloatVector .SPECIES_128 );
9284 VectorMask <Integer > mInt128_2 = mFloat128 .cast (IntVector .SPECIES_128 );
93- return mInt128_2 .trueCount ();
85+ return mInt128_2 .not (). trueCount ();
9486 }
9587
9688 @ Run (test = "testTwoCastToSameType" )
9789 public static void testTwoCastToSameType_runner () {
9890 int count = testTwoCastToSameType ();
9991 VectorMask <Integer > mInt128 = VectorMask .fromArray (IntVector .SPECIES_128 , mr , 0 );
100- Asserts .assertEquals (count , mInt128 .trueCount ());
92+ Asserts .assertEquals (count , mInt128 .not (). trueCount ());
10193 }
10294
10395 @ Test
104- @ IR (counts = { IRNode .VECTOR_MASK_CAST , "= 1" }, applyIfCPUFeatureOr = {"avx2" , "true" , "asimd" , "true" , "rvv" , "true" })
96+ @ IR (counts = { IRNode .LOAD_VECTOR_Z , IRNode .VECTOR_SIZE_4 , "> 0" ,
97+ IRNode .VECTOR_MASK_CAST , "= 1" },
98+ applyIfCPUFeatureOr = { "asimd" , "true" , "avx2" , "true" , "rvv" , "true" },
99+ applyIf = { "MaxVectorSize" , ">= 16" })
105100 public static int testOneCastToDifferentType () {
106- // The types before and after the only cast are different, the cast will not be eliminated.
107- VectorMask <Float > mFloat128 = VectorMask .fromArray (FloatVector .SPECIES_128 , mr , 0 ).not ();
108- VectorMask <Integer > mInt128 = mFloat128 .cast (IntVector .SPECIES_128 );
109- return mInt128 .trueCount ();
101+ // The types before and after the cast sequence are different,
102+ // so the casts will not be eliminated.
103+ VectorMask <Integer > mInt128 = VectorMask .fromArray (IntVector .SPECIES_128 , mr , 0 );
104+ VectorMask <Short > mShort64 = mInt128 .cast (ShortVector .SPECIES_64 );
105+ return mShort64 .not ().trueCount ();
110106 }
111107
112108 @ Run (test = "testOneCastToDifferentType" )
113109 public static void testOneCastToDifferentType_runner () {
114110 int count = testOneCastToDifferentType ();
115- VectorMask <Float > mInt128 = VectorMask .fromArray (FloatVector .SPECIES_128 , mr , 0 ).not ();
116- Asserts .assertEquals (count , mInt128 .trueCount ());
111+ VectorMask <Integer > mInt128 = VectorMask .fromArray (IntVector .SPECIES_128 , mr , 0 );
112+ Asserts .assertEquals (count , mInt128 .not ().trueCount ());
113+ }
114+
115+ @ Test
116+ @ IR (counts = { IRNode .LOAD_VECTOR_Z , IRNode .VECTOR_SIZE_4 , "> 0" ,
117+ IRNode .VECTOR_MASK_CAST , "= 2" },
118+ applyIfCPUFeatureOr = { "asimd" , "true" , "avx2" , "true" , "rvv" , "true" },
119+ applyIf = { "MaxVectorSize" , ">= 16" })
120+ public static int testTwoCastToDifferentType () {
121+ // The types before and after the cast sequence are different, so the
122+ // casts are not eliminated. We should probably be able to eliminate
123+ // the intermediate cast, so that we only need a cast from short to int.
124+ VectorMask <Short > mShort64 = VectorMask .fromArray (ShortVector .SPECIES_64 , mr , 0 );
125+ VectorMask <Float > mFloat128 = mShort64 .cast (FloatVector .SPECIES_128 );
126+ VectorMask <Integer > mInt128 = mFloat128 .cast (IntVector .SPECIES_128 );
127+ return mInt128 .not ().trueCount ();
128+ }
129+
130+ @ Run (test = "testTwoCastToDifferentType" )
131+ public static void testTwoCastToDifferentType_runner () {
132+ int count = testTwoCastToDifferentType ();
133+ VectorMask <Short > mShort64 = VectorMask .fromArray (ShortVector .SPECIES_64 , mr , 0 );
134+ Asserts .assertEquals (count , mShort64 .not ().trueCount ());
117135 }
118136
119137 public static void main (String [] args ) {
0 commit comments