< prev index next >

src/hotspot/cpu/aarch64/aarch64_sve.ad

Print this page

 132   bool op_sve_supported(int opcode, int vlen, BasicType bt) {
 133     int length_in_bytes = vlen * type2aelembytes(bt);
 134     switch (opcode) {
 135       case Op_MulAddVS2VI:
 136       // No multiply reduction instructions
 137       case Op_MulReductionVD:
 138       case Op_MulReductionVF:
 139       case Op_MulReductionVI:
 140       case Op_MulReductionVL:
 141       // Others
 142       case Op_ExtractC:
 143       case Op_ExtractUB:
 144         return false;
 145       // Vector API specific
 146       case Op_VectorLoadShuffle:
 147       case Op_VectorRearrange:
 148         return vlen >= 4 && length_in_bytes <= MaxVectorSize;
 149       case Op_LoadVector:
 150       case Op_StoreVector:
 151         return Matcher::vector_size_supported(bt, vlen);


 152       default:
 153         break;
 154     }
 155     // By default, we only support vector operations with no less than 8 bytes and 2 elements.
 156     return 8 <= length_in_bytes && length_in_bytes <= MaxVectorSize && vlen >= 2;
 157   }
 158 
 159   bool masked_op_sve_supported(int opcode, int vlen, BasicType bt) {
 160     if (opcode == Op_VectorRearrange) {
 161       return false;
 162     }
 163     return op_sve_supported(opcode, vlen, bt);
 164   }
 165 %}
 166 
 167 definitions %{
 168   int_def SVE_COST             (200, 200);
 169 %}
 170 
 171 

2180     __ sve_fneg(as_FloatRegister($dst_src$$reg), __ S,
2181             as_PRegister($pg$$reg),
2182             as_FloatRegister($dst_src$$reg));
2183   %}
2184   ins_pipe(pipe_slow);
2185 %}
2186 
2187 instruct vnegD_masked(vReg dst_src, pRegGov pg) %{
2188   predicate(UseSVE > 0);
2189   match(Set dst_src (NegVD dst_src pg));
2190   ins_cost(SVE_COST);
2191   format %{ "sve_fneg $dst_src, $pg, $dst_src\t# vector (sve) (D)" %}
2192   ins_encode %{
2193     __ sve_fneg(as_FloatRegister($dst_src$$reg), __ D,
2194             as_PRegister($pg$$reg),
2195             as_FloatRegister($dst_src$$reg));
2196   %}
2197   ins_pipe(pipe_slow);
2198 %}
2199 
2200 // popcount vector
2201 
2202 instruct vpopcountI(vReg dst, vReg src) %{
2203   predicate(UseSVE > 0);

2204   match(Set dst (PopCountVI src));
2205   format %{ "sve_cnt $dst, $src\t# vector (sve) (S)\n\t" %}







































2206   ins_encode %{
2207      __ sve_cnt(as_FloatRegister($dst$$reg), __ S, ptrue, as_FloatRegister($src$$reg));


































2208   %}
2209   ins_pipe(pipe_slow);
2210 %}
2211 
2212 // vector blend
2213 
2214 instruct vblend(vReg dst, vReg src1, vReg src2, pRegGov pg) %{
2215   predicate(UseSVE > 0);
2216   match(Set dst (VectorBlend (Binary src1 src2) pg));
2217   ins_cost(SVE_COST);
2218   format %{ "sve_sel $dst, $pg, $src2, $src1\t# vector blend (sve)" %}
2219   ins_encode %{
2220     Assembler::SIMD_RegVariant size =
2221                __ elemType_to_regVariant(Matcher::vector_element_basic_type(this));
2222     __ sve_sel(as_FloatRegister($dst$$reg), size, as_PRegister($pg$$reg),
2223                as_FloatRegister($src2$$reg), as_FloatRegister($src1$$reg));
2224   %}
2225   ins_pipe(pipe_slow);
2226 %}
2227 

5633                ptrue, as_FloatRegister($src$$reg), 0);
5634   %}
5635   ins_pipe(pipe_slow);
5636 %}
5637 
5638 instruct vloadmask_extend(pRegGov dst, vReg src, vReg tmp, rFlagsReg cr) %{
5639   predicate(UseSVE > 0 && n->bottom_type()->is_vect()->element_basic_type() != T_BYTE);
5640   match(Set dst (VectorLoadMask src));
5641   effect(TEMP tmp, KILL cr);
5642   ins_cost(3 * SVE_COST);
5643   format %{ "vloadmask $dst, $src\t# vector load mask (sve) (H/S/D)" %}
5644   ins_encode %{
5645     BasicType bt = Matcher::vector_element_basic_type(this);
5646     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5647     __ sve_vector_extend(as_FloatRegister($tmp$$reg), size, as_FloatRegister($src$$reg), __ B);
5648     __ sve_cmp(Assembler::NE, as_PRegister($dst$$reg), size, ptrue, as_FloatRegister($tmp$$reg), 0);
5649   %}
5650   ins_pipe(pipe_slow);
5651 %}
5652 


































































































5653 instruct vmask_gen(pRegGov pg, iRegL len, rFlagsReg cr) %{
5654   predicate(UseSVE > 0);
5655   match(Set pg (VectorMaskGen len));
5656   effect(KILL cr);
5657   ins_cost(SVE_COST);
5658   format %{ "sve_whilelo $pg, zr, $len\t # sve" %}
5659   ins_encode %{
5660     BasicType bt = Matcher::vector_element_basic_type(this);
5661     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5662     __ sve_whilelo(as_PRegister($pg$$reg), size, zr, as_Register($len$$reg));
5663   %}
5664   ins_pipe(pipe_slow);
5665 %}

















































































































































 132   bool op_sve_supported(int opcode, int vlen, BasicType bt) {
 133     int length_in_bytes = vlen * type2aelembytes(bt);
 134     switch (opcode) {
 135       case Op_MulAddVS2VI:
 136       // No multiply reduction instructions
 137       case Op_MulReductionVD:
 138       case Op_MulReductionVF:
 139       case Op_MulReductionVI:
 140       case Op_MulReductionVL:
 141       // Others
 142       case Op_ExtractC:
 143       case Op_ExtractUB:
 144         return false;
 145       // Vector API specific
 146       case Op_VectorLoadShuffle:
 147       case Op_VectorRearrange:
 148         return vlen >= 4 && length_in_bytes <= MaxVectorSize;
 149       case Op_LoadVector:
 150       case Op_StoreVector:
 151         return Matcher::vector_size_supported(bt, vlen);
 152       case Op_ExpandV:
 153         if (UseSVE < 2 || is_subword_type(bt)) return false;
 154       default:
 155         break;
 156     }
 157     // By default, we only support vector operations with no less than 8 bytes and 2 elements.
 158     return 8 <= length_in_bytes && length_in_bytes <= MaxVectorSize && vlen >= 2;
 159   }
 160 
 161   bool masked_op_sve_supported(int opcode, int vlen, BasicType bt) {
 162     if (opcode == Op_VectorRearrange) {
 163       return false;
 164     }
 165     return op_sve_supported(opcode, vlen, bt);
 166   }
 167 %}
 168 
 169 definitions %{
 170   int_def SVE_COST             (200, 200);
 171 %}
 172 
 173 

2182     __ sve_fneg(as_FloatRegister($dst_src$$reg), __ S,
2183             as_PRegister($pg$$reg),
2184             as_FloatRegister($dst_src$$reg));
2185   %}
2186   ins_pipe(pipe_slow);
2187 %}
2188 
2189 instruct vnegD_masked(vReg dst_src, pRegGov pg) %{
2190   predicate(UseSVE > 0);
2191   match(Set dst_src (NegVD dst_src pg));
2192   ins_cost(SVE_COST);
2193   format %{ "sve_fneg $dst_src, $pg, $dst_src\t# vector (sve) (D)" %}
2194   ins_encode %{
2195     __ sve_fneg(as_FloatRegister($dst_src$$reg), __ D,
2196             as_PRegister($pg$$reg),
2197             as_FloatRegister($dst_src$$reg));
2198   %}
2199   ins_pipe(pipe_slow);
2200 %}
2201 
2202 // vector popcount
2203 
2204 instruct vpopcountI(vReg dst, vReg src) %{
2205   predicate(UseSVE > 0 &&
2206             !n->as_Vector()->is_predicated_vector());
2207   match(Set dst (PopCountVI src));
2208   ins_cost(SVE_COST);
2209   format %{ "sve_cnt $dst, $src\t# vector (sve) (B/H/S)" %}
2210   ins_encode %{
2211     assert(UsePopCountInstruction, "unsupported");
2212     BasicType bt = Matcher::vector_element_basic_type(this);
2213     __ sve_cnt(as_FloatRegister($dst$$reg), __ elemType_to_regVariant(bt),
2214          ptrue, as_FloatRegister($src$$reg));
2215   %}
2216   ins_pipe(pipe_slow);
2217 %}
2218 
2219 instruct vpopcountL(vReg dst, vReg src) %{
2220   predicate(UseSVE > 0 &&
2221             !n->as_Vector()->is_predicated_vector() &&
2222             n->bottom_type()->is_vect()->element_basic_type() == T_LONG);
2223   match(Set dst (PopCountVL src));
2224   ins_cost(SVE_COST);
2225   format %{ "sve_cnt $dst, $src\t# vector (sve) (D)" %}
2226   ins_encode %{
2227     assert(UsePopCountInstruction, "unsupported");
2228     __ sve_cnt(as_FloatRegister($dst$$reg), __ D,
2229          ptrue, as_FloatRegister($src$$reg));
2230   %}
2231   ins_pipe(pipe_slow);
2232 %}
2233 
2234 // If the PopCountVL is generated by auto-vectorization, the dst basic
2235 // type is T_INT. And once we have unified the type definition for
2236 // Vector API and auto-vectorization, this rule can be merged with
2237 // "vpopcountL" rule.
2238 instruct vpopcountLI(vReg dst, vReg src, vReg vtmp) %{
2239   predicate(UseSVE > 0 &&
2240             !n->as_Vector()->is_predicated_vector() &&
2241             n->bottom_type()->is_vect()->element_basic_type() == T_INT);
2242   match(Set dst (PopCountVL src));
2243   effect(TEMP_DEF dst, TEMP vtmp);
2244   ins_cost(3 * SVE_COST);
2245   format %{ "sve_cnt $dst, $src\n\t"
2246             "sve_dup $vtmp, #0\n\t"
2247             "sve_uzp1 $dst, $dst, $vtmp\t# vector (sve) (S)" %}
2248   ins_encode %{
2249     assert(UsePopCountInstruction, "unsupported");
2250     __ sve_cnt(as_FloatRegister($dst$$reg), __ D,
2251          ptrue, as_FloatRegister($src$$reg));
2252     __ sve_vector_narrow(as_FloatRegister($dst$$reg), __ S,
2253          as_FloatRegister($dst$$reg), __ D, as_FloatRegister($vtmp$$reg));
2254   %}
2255   ins_pipe(pipe_slow);
2256 %}
2257 
2258 // vector popcount - predicated
2259 
2260 instruct vpopcountI_masked(vReg dst_src, pRegGov pg) %{
2261   predicate(UseSVE > 0);
2262   match(Set dst_src (PopCountVI dst_src pg));
2263   ins_cost(SVE_COST);
2264   format %{ "sve_cnt $dst_src, $pg, $dst_src\t# vector (sve) (B/H/S)" %}
2265   ins_encode %{
2266     assert(UsePopCountInstruction, "unsupported");
2267     BasicType bt = Matcher::vector_element_basic_type(this);
2268     __ sve_cnt(as_FloatRegister($dst_src$$reg), __ elemType_to_regVariant(bt),
2269          as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
2270   %}
2271   ins_pipe(pipe_slow);
2272 %}
2273 
2274 instruct vpopcountL_masked(vReg dst_src, pRegGov pg) %{
2275   predicate(UseSVE > 0 &&
2276             n->bottom_type()->is_vect()->element_basic_type() == T_LONG);
2277   match(Set dst_src (PopCountVL dst_src pg));
2278   ins_cost(SVE_COST);
2279   format %{ "sve_cnt $dst_src, $pg, $dst_src\t# vector (sve) (D)" %}
2280   ins_encode %{
2281     assert(UsePopCountInstruction, "unsupported");
2282     __ sve_cnt(as_FloatRegister($dst_src$$reg), __ D,
2283          as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
2284   %}
2285   ins_pipe(pipe_slow);
2286 %}
2287 
2288 // vector blend
2289 
2290 instruct vblend(vReg dst, vReg src1, vReg src2, pRegGov pg) %{
2291   predicate(UseSVE > 0);
2292   match(Set dst (VectorBlend (Binary src1 src2) pg));
2293   ins_cost(SVE_COST);
2294   format %{ "sve_sel $dst, $pg, $src2, $src1\t# vector blend (sve)" %}
2295   ins_encode %{
2296     Assembler::SIMD_RegVariant size =
2297                __ elemType_to_regVariant(Matcher::vector_element_basic_type(this));
2298     __ sve_sel(as_FloatRegister($dst$$reg), size, as_PRegister($pg$$reg),
2299                as_FloatRegister($src2$$reg), as_FloatRegister($src1$$reg));
2300   %}
2301   ins_pipe(pipe_slow);
2302 %}
2303 

5709                ptrue, as_FloatRegister($src$$reg), 0);
5710   %}
5711   ins_pipe(pipe_slow);
5712 %}
5713 
5714 instruct vloadmask_extend(pRegGov dst, vReg src, vReg tmp, rFlagsReg cr) %{
5715   predicate(UseSVE > 0 && n->bottom_type()->is_vect()->element_basic_type() != T_BYTE);
5716   match(Set dst (VectorLoadMask src));
5717   effect(TEMP tmp, KILL cr);
5718   ins_cost(3 * SVE_COST);
5719   format %{ "vloadmask $dst, $src\t# vector load mask (sve) (H/S/D)" %}
5720   ins_encode %{
5721     BasicType bt = Matcher::vector_element_basic_type(this);
5722     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5723     __ sve_vector_extend(as_FloatRegister($tmp$$reg), size, as_FloatRegister($src$$reg), __ B);
5724     __ sve_cmp(Assembler::NE, as_PRegister($dst$$reg), size, ptrue, as_FloatRegister($tmp$$reg), 0);
5725   %}
5726   ins_pipe(pipe_slow);
5727 %}
5728 
5729 // ---------------------------- Compress/Expand Operations ---------------------------
5730 
5731 instruct mcompress(pReg dst, pReg pg, rFlagsReg cr) %{
5732   predicate(UseSVE > 0);
5733   match(Set dst (CompressM pg));
5734   effect(KILL cr);
5735   ins_cost(2 * SVE_COST);
5736   format %{ "sve_cntp rscratch1, $pg\n\t"
5737             "sve_whilelo $dst, zr, rscratch1\t# mask compress (B/H/S/D)" %}
5738   ins_encode %{
5739     BasicType bt = Matcher::vector_element_basic_type(this);
5740     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5741     __ sve_cntp(rscratch1, size, ptrue, as_PRegister($pg$$reg));
5742     __ sve_whilelo(as_PRegister($dst$$reg), size, zr, rscratch1);
5743   %}
5744   ins_pipe(pipe_slow);
5745 %}
5746 
5747 instruct vcompress(vReg dst, vReg src, pRegGov pg) %{
5748   predicate(UseSVE > 0 &&
5749             (n->bottom_type()->is_vect()->element_basic_type() == T_INT ||
5750              n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT ||
5751              n->bottom_type()->is_vect()->element_basic_type() == T_LONG ||
5752              n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE));
5753   match(Set dst (CompressV src pg));
5754   ins_cost(SVE_COST);
5755   format %{ "sve_compact $dst, $src, $pg\t# vector compress (S/D)" %}
5756   ins_encode %{
5757     BasicType bt = Matcher::vector_element_basic_type(this);
5758     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5759     __ sve_compact(as_FloatRegister($dst$$reg), size, as_FloatRegister($src$$reg), as_PRegister($pg$$reg));
5760   %}
5761   ins_pipe(pipe_slow);
5762 %}
5763 
5764 instruct vcompressB(vReg dst, vReg src, pReg pg, vReg vtmp1, vReg vtmp2, vReg vtmp3, vReg vtmp4,
5765                     pReg ptmp, pRegGov pgtmp) %{
5766   predicate(UseSVE > 0 && n->bottom_type()->is_vect()->element_basic_type() == T_BYTE);
5767   effect(TEMP_DEF dst, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP vtmp4, TEMP ptmp, TEMP pgtmp);
5768   match(Set dst (CompressV src pg));
5769   ins_cost(13 * SVE_COST);
5770   format %{ "sve_compact $dst, $src, $pg\t# vector compress (B)" %}
5771   ins_encode %{
5772     __ sve_compress_byte(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), as_PRegister($pg$$reg),
5773                          as_FloatRegister($vtmp1$$reg),as_FloatRegister($vtmp2$$reg),
5774                          as_FloatRegister($vtmp3$$reg),as_FloatRegister($vtmp4$$reg),
5775                          as_PRegister($ptmp$$reg), as_PRegister($pgtmp$$reg));
5776   %}
5777   ins_pipe(pipe_slow);
5778 %}
5779 
5780 instruct vcompressS(vReg dst, vReg src, pReg pg, vReg vtmp1, vReg vtmp2, pRegGov pgtmp) %{
5781   predicate(UseSVE > 0 && n->bottom_type()->is_vect()->element_basic_type() == T_SHORT);
5782   effect(TEMP_DEF dst, TEMP vtmp1, TEMP vtmp2, TEMP pgtmp);
5783   match(Set dst (CompressV src pg));
5784   ins_cost(38 * SVE_COST);
5785   format %{ "sve_compact $dst, $src, $pg\t# vector compress (H)" %}
5786   ins_encode %{
5787     __ sve_compress_short(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), as_PRegister($pg$$reg),
5788                           as_FloatRegister($vtmp1$$reg),as_FloatRegister($vtmp2$$reg), as_PRegister($pgtmp$$reg));
5789   %}
5790   ins_pipe(pipe_slow);
5791 %}
5792 
5793 instruct vexpand(vReg dst, vReg src, pRegGov pg) %{
5794   match(Set dst (ExpandV src pg));
5795   effect(TEMP_DEF dst);
5796   ins_cost(4 * SVE_COST);
5797   format %{ "sve_dup $dst, S/D, 0\n\t"
5798             "sve_histcnt $dst, S/D, $pg, $dst, $dst\n\t"
5799             "sve_sub $dst, S/D, 1\n\t"
5800             "sve_tbl $dst, S/D, $src, $dst\t# vector expand (S/D)" %}
5801   ins_encode %{
5802     // Example input:   src   = 1 2 3 4 5 6 7 8
5803     //                  pg    = 1 0 0 1 1 0 1 1
5804     // Expected result: dst   = 4 0 0 5 6 0 7 8
5805 
5806     // The basic idea is to use TBL which can shuffle the elements in the given
5807     // vector flexibly. HISTCNT + SUB is used to generate the second source input
5808     // for TBL whose value is used to select the indexed element from src vector.
5809 
5810     BasicType bt = Matcher::vector_element_basic_type(this);
5811     assert(UseSVE == 2 && !is_subword_type(bt), "unsupported");
5812     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5813     // dst = 0 0 0 0 0 0 0 0
5814     __ sve_dup(as_FloatRegister($dst$$reg), size, 0);
5815     // dst = 5 0 0 4 3 0 2 1
5816     __ sve_histcnt(as_FloatRegister($dst$$reg), size, as_PRegister($pg$$reg),
5817                    as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg));
5818     // dst = 4 -1 -1 3 2 -1 1 0
5819     __ sve_sub(as_FloatRegister($dst$$reg), size, 1);
5820     // dst = 4 0 0 5 6 0 7 8
5821     __ sve_tbl(as_FloatRegister($dst$$reg), size, as_FloatRegister($src$$reg),
5822                as_FloatRegister($dst$$reg));
5823   %}
5824   ins_pipe(pipe_slow);
5825 %}
5826 
5827 instruct vmask_gen(pRegGov pg, iRegL len, rFlagsReg cr) %{
5828   predicate(UseSVE > 0);
5829   match(Set pg (VectorMaskGen len));
5830   effect(KILL cr);
5831   ins_cost(SVE_COST);
5832   format %{ "sve_whilelo $pg, zr, $len\t # sve" %}
5833   ins_encode %{
5834     BasicType bt = Matcher::vector_element_basic_type(this);
5835     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5836     __ sve_whilelo(as_PRegister($pg$$reg), size, zr, as_Register($len$$reg));
5837   %}
5838   ins_pipe(pipe_slow);
5839 %}
5840 
5841 // ------------------------------ CountLeadingZerosV ------------------------------
5842 
5843 instruct vcountLeadingZeros(vReg dst, vReg src) %{
5844   predicate(UseSVE > 0 &&
5845             !n->as_Vector()->is_predicated_vector());
5846   match(Set dst (CountLeadingZerosV src));
5847   ins_cost(SVE_COST);
5848   format %{ "sve_clz $dst, $src\t# vector (sve)" %}
5849   ins_encode %{
5850     BasicType bt = Matcher::vector_element_basic_type(this);
5851     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5852     __ sve_clz(as_FloatRegister($dst$$reg), size, ptrue, as_FloatRegister($src$$reg));
5853   %}
5854   ins_pipe(pipe_slow);
5855 %}
5856 
5857 // The dst and src should use the same register to make sure the
5858 // inactive lanes in dst save the same elements as src.
5859 instruct vcountLeadingZeros_masked(vReg dst_src, pRegGov pg) %{
5860   predicate(UseSVE > 0);
5861   match(Set dst_src (CountLeadingZerosV dst_src pg));
5862   ins_cost(SVE_COST);
5863   format %{ "sve_clz $dst_src, $pg, $dst_src\t# vector (sve)" %}
5864   ins_encode %{
5865     BasicType bt = Matcher::vector_element_basic_type(this);
5866     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5867     __ sve_clz(as_FloatRegister($dst_src$$reg), size,
5868         as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
5869   %}
5870   ins_pipe(pipe_slow);
5871 %}
5872 
5873 // ------------------------------ CountTrailingZerosV -----------------------------
5874 
5875 instruct vcountTrailingZeros(vReg dst, vReg src) %{
5876   predicate(UseSVE > 0 &&
5877             !n->as_Vector()->is_predicated_vector());
5878   match(Set dst (CountTrailingZerosV src));
5879   ins_cost(2 * SVE_COST);
5880   format %{ "sve_rbit $dst, $src\n\t"
5881             "sve_clz  $dst, $dst\t# vector (sve)" %}
5882   ins_encode %{
5883     BasicType bt = Matcher::vector_element_basic_type(this);
5884     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5885     __ sve_rbit(as_FloatRegister($dst$$reg), size, ptrue, as_FloatRegister($src$$reg));
5886     __ sve_clz(as_FloatRegister($dst$$reg), size, ptrue, as_FloatRegister($dst$$reg));
5887   %}
5888   ins_pipe(pipe_slow);
5889 %}
5890 
5891 // The dst and src should use the same register to make sure the
5892 // inactive lanes in dst save the same elements as src.
5893 instruct vcountTrailingZeros_masked(vReg dst_src, pRegGov pg) %{
5894   predicate(UseSVE > 0);
5895   match(Set dst_src (CountTrailingZerosV dst_src pg));
5896   ins_cost(2 * SVE_COST);
5897   format %{ "sve_rbit $dst_src, $pg, $dst_src\n\t"
5898             "sve_clz  $dst_src, $pg, $dst_src\t# vector (sve)" %}
5899   ins_encode %{
5900     BasicType bt = Matcher::vector_element_basic_type(this);
5901     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5902     __ sve_rbit(as_FloatRegister($dst_src$$reg), size,
5903         as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
5904     __ sve_clz(as_FloatRegister($dst_src$$reg), size,
5905         as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
5906   %}
5907   ins_pipe(pipe_slow);
5908 %}
5909 
5910 // ---------------------------------- ReverseV ------------------------------------
5911 
5912 instruct vreverse(vReg dst, vReg src) %{
5913   predicate(UseSVE > 0 &&
5914             !n->as_Vector()->is_predicated_vector());
5915   match(Set dst (ReverseV src));
5916   ins_cost(SVE_COST);
5917   format %{ "sve_rbit $dst, $src\t# vector (sve)" %}
5918   ins_encode %{
5919     BasicType bt = Matcher::vector_element_basic_type(this);
5920     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5921     __ sve_rbit(as_FloatRegister($dst$$reg), size, ptrue, as_FloatRegister($src$$reg));
5922   %}
5923   ins_pipe(pipe_slow);
5924 %}
5925 
5926 // The dst and src should use the same register to make sure the
5927 // inactive lanes in dst save the same elements as src.
5928 instruct vreverse_masked(vReg dst_src, pRegGov pg) %{
5929   predicate(UseSVE > 0);
5930   match(Set dst_src (ReverseV dst_src pg));
5931   ins_cost(SVE_COST);
5932   format %{ "sve_rbit $dst_src, $pg, $dst_src\t# vector (sve)" %}
5933   ins_encode %{
5934     BasicType bt = Matcher::vector_element_basic_type(this);
5935     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5936     __ sve_rbit(as_FloatRegister($dst_src$$reg), size,
5937         as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
5938   %}
5939   ins_pipe(pipe_slow);
5940 %}
5941 
5942 // -------------------------------- ReverseBytesV ---------------------------------
5943 
5944 instruct vreverseBytes(vReg dst, vReg src) %{
5945   predicate(UseSVE > 0 &&
5946             !n->as_Vector()->is_predicated_vector());
5947   match(Set dst (ReverseBytesV src));
5948   ins_cost(SVE_COST);
5949   format %{ "sve_revb $dst, $src\t# vector (sve)" %}
5950   ins_encode %{
5951     BasicType bt = Matcher::vector_element_basic_type(this);
5952     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5953     if (bt == T_BYTE) {
5954       if (as_FloatRegister($dst$$reg) != as_FloatRegister($src$$reg)) {
5955         __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), as_FloatRegister($src$$reg));
5956       }
5957     } else {
5958       __ sve_revb(as_FloatRegister($dst$$reg), size, ptrue, as_FloatRegister($src$$reg));
5959     }
5960   %}
5961   ins_pipe(pipe_slow);
5962 %}
5963 
5964 // The dst and src should use the same register to make sure the
5965 // inactive lanes in dst save the same elements as src.
5966 instruct vreverseBytes_masked(vReg dst_src, pRegGov pg) %{
5967   predicate(UseSVE > 0);
5968   match(Set dst_src (ReverseBytesV dst_src pg));
5969   ins_cost(SVE_COST);
5970   format %{ "sve_revb $dst_src, $pg, $dst_src\t# vector (sve)" %}
5971   ins_encode %{
5972     BasicType bt = Matcher::vector_element_basic_type(this);
5973     Assembler::SIMD_RegVariant size = __ elemType_to_regVariant(bt);
5974     if (bt == T_BYTE) {
5975       // do nothing
5976     } else {
5977       __ sve_revb(as_FloatRegister($dst_src$$reg), size,
5978           as_PRegister($pg$$reg), as_FloatRegister($dst_src$$reg));
5979     }
5980   %}
5981   ins_pipe(pipe_slow);
5982 %}
5983 
< prev index next >