1 //
  2 // Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3 // Copyright (c) 2020, Arm Ltd. All rights reserved.
  4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5 //
  6 // This code is free software; you can redistribute it and/or modify it
  7 // under the terms of the GNU General Public License version 2 only, as
  8 // published by the Free Software Foundation.
  9 //
 10 // This code is distributed in the hope that it will be useful, but WITHOUT
 11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13 // version 2 for more details (a copy is included in the LICENSE file that
 14 // accompanied this code).
 15 //
 16 // You should have received a copy of the GNU General Public License version
 17 // 2 along with this work; if not, write to the Free Software Foundation,
 18 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19 //
 20 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21 // or visit www.oracle.com if you need additional information or have any
 22 // questions.
 23 //
 24 //
 25 
 26 dnl Generate the warning
 27 // This file is automatically generated by running "m4 aarch64_sve_ad.m4". Do not edit ----
 28 dnl
 29 
 30 // AArch64 SVE Architecture Description File
 31 
 32 dnl
 33 dnl OPERAND_VMEMORYA_IMMEDIATE_OFFSET($1,            $2,       $3     )
 34 dnl OPERAND_VMEMORYA_IMMEDIATE_OFFSET(imm_type_abbr, imm_type, imm_len)
 35 define(`OPERAND_VMEMORYA_IMMEDIATE_OFFSET', `
 36 operand vmemA_imm$1Offset$3()
 37 %{
 38   predicate(Address::offset_ok_for_sve_immed(n->get_$2(), $3,
 39             Matcher::scalable_vector_reg_size(T_BYTE)));
 40   match(Con$1);
 41 
 42   op_cost(0);
 43   format %{ %}
 44   interface(CONST_INTER);
 45 %}')
 46 dnl
 47 // 4 bit signed offset -- for predicated load/store
 48 OPERAND_VMEMORYA_IMMEDIATE_OFFSET(I, int,  4)
 49 OPERAND_VMEMORYA_IMMEDIATE_OFFSET(L, long, 4)
 50 dnl
 51 dnl OPERAND_VMEMORYA_INDIRECT_OFFSET($1,            $2     )
 52 dnl OPERAND_VMEMORYA_INDIRECT_OFFSET(imm_type_abbr, imm_len)
 53 define(`OPERAND_VMEMORYA_INDIRECT_OFFSET', `
 54 operand vmemA_indOff$1$2(iRegP reg, vmemA_imm$1Offset$2 off)
 55 %{
 56   constraint(ALLOC_IN_RC(ptr_reg));
 57   match(AddP reg off);
 58   op_cost(0);
 59   format %{ "[$reg, $off, MUL VL]" %}
 60   interface(MEMORY_INTER) %{
 61     base($reg);
 62     `index'(0xffffffff);
 63     scale(0x0);
 64     disp($off);
 65   %}
 66 %}')
 67 dnl
 68 OPERAND_VMEMORYA_INDIRECT_OFFSET(I, 4)
 69 OPERAND_VMEMORYA_INDIRECT_OFFSET(L, 4)
 70 
 71 opclass vmemA(indirect, vmemA_indOffI4, vmemA_indOffL4);
 72 
 73 source_hpp %{
 74   bool op_sve_supported(int opcode);
 75 %}
 76 
 77 source %{
 78 
 79   static inline BasicType vector_element_basic_type(const MachNode* n) {
 80     const TypeVect* vt = n->bottom_type()->is_vect();
 81     return vt->element_basic_type();
 82   }
 83 
 84   static inline BasicType vector_element_basic_type(const MachNode* use, const MachOper* opnd) {
 85     int def_idx = use->operand_index(opnd);
 86     Node* def = use->in(def_idx);
 87     const TypeVect* vt = def->bottom_type()->is_vect();
 88     return vt->element_basic_type();
 89   }
 90 
 91   typedef void (C2_MacroAssembler::* sve_mem_insn_predicate)(FloatRegister Rt, Assembler::SIMD_RegVariant T,
 92                                                              PRegister Pg, const Address &adr);
 93 
 94   // Predicated load/store, with optional ptrue to all elements of given predicate register.
 95   static void loadStoreA_predicate(C2_MacroAssembler masm, bool is_store,
 96                                    FloatRegister reg, PRegister pg, BasicType bt,
 97                                    int opcode, Register base, int index, int size, int disp) {
 98     sve_mem_insn_predicate insn;
 99     Assembler::SIMD_RegVariant type;
100     int esize = type2aelembytes(bt);
101     if (index == -1) {
102       assert(size == 0, "unsupported address mode: scale size = %d", size);
103       switch(esize) {
104       case 1:
105         insn = is_store ? &C2_MacroAssembler::sve_st1b : &C2_MacroAssembler::sve_ld1b;
106         type = Assembler::B;
107         break;
108       case 2:
109         insn = is_store ? &C2_MacroAssembler::sve_st1h : &C2_MacroAssembler::sve_ld1h;
110         type = Assembler::H;
111         break;
112       case 4:
113         insn = is_store ? &C2_MacroAssembler::sve_st1w : &C2_MacroAssembler::sve_ld1w;
114         type = Assembler::S;
115         break;
116       case 8:
117         insn = is_store ? &C2_MacroAssembler::sve_st1d : &C2_MacroAssembler::sve_ld1d;
118         type = Assembler::D;
119         break;
120       default:
121         assert(false, "unsupported");
122         ShouldNotReachHere();
123       }
124       (masm.*insn)(reg, type, pg, Address(base, disp / Matcher::scalable_vector_reg_size(T_BYTE)));
125     } else {
126       assert(false, "unimplemented");
127       ShouldNotReachHere();
128     }
129   }
130 
131   bool op_sve_supported(int opcode) {
132     switch (opcode) {
133       case Op_MulAddVS2VI:
134         // No multiply reduction instructions
135       case Op_MulReductionVD:
136       case Op_MulReductionVF:
137       case Op_MulReductionVI:
138       case Op_MulReductionVL:
139         // Others
140       case Op_Extract:
141       case Op_ExtractB:
142       case Op_ExtractC:
143       case Op_ExtractD:
144       case Op_ExtractF:
145       case Op_ExtractI:
146       case Op_ExtractL:
147       case Op_ExtractS:
148       case Op_ExtractUB:
149         return false;
150       default:
151         return true;
152     }
153   }
154 
155 %}
156 
157 definitions %{
158   int_def SVE_COST             (200, 200);
159 %}
160 
161 
162 dnl
163 dnl ELEMENT_SHORT_CHART($1, $2)
164 dnl ELEMENT_SHORT_CHART(etype, node)
165 define(`ELEMENT_SHORT_CHAR',`ifelse(`$1', `T_SHORT',
166   `($2->bottom_type()->is_vect()->element_basic_type() == T_SHORT ||
167             ($2->bottom_type()->is_vect()->element_basic_type() == T_CHAR))',
168    `($2->bottom_type()->is_vect()->element_basic_type() == $1)')')
169 dnl
170 
171 // All SVE instructions
172 
173 // sve vector load/store
174 
175 // Use predicated vector load/store
176 instruct loadVA(vecA dst, vmemA mem) %{
177   predicate(UseSVE > 0 && n->as_LoadVector()->memory_size() >= 16);
178   match(Set dst (LoadVector mem));
179   ins_cost(SVE_COST);
180   format %{ "sve_ldr $dst, $mem\t # vector (sve)" %}
181   ins_encode %{
182     FloatRegister dst_reg = as_FloatRegister($dst$$reg);
183     loadStoreA_predicate(C2_MacroAssembler(&cbuf), false, dst_reg, ptrue,
184                          vector_element_basic_type(this), $mem->opcode(),
185                          as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
186   %}
187   ins_pipe(pipe_slow);
188 %}
189 
190 instruct storeVA(vecA src, vmemA mem) %{
191   predicate(UseSVE > 0 && n->as_StoreVector()->memory_size() >= 16);
192   match(Set mem (StoreVector mem src));
193   ins_cost(SVE_COST);
194   format %{ "sve_str $mem, $src\t # vector (sve)" %}
195   ins_encode %{
196     FloatRegister src_reg = as_FloatRegister($src$$reg);
197     loadStoreA_predicate(C2_MacroAssembler(&cbuf), true, src_reg, ptrue,
198                          vector_element_basic_type(this, $src), $mem->opcode(),
199                          as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
200   %}
201   ins_pipe(pipe_slow);
202 %}
203 
204 dnl
205 dnl UNARY_OP_TRUE_PREDICATE_ETYPE($1,        $2,      $3,           $4,   $5,          %6  )
206 dnl UNARY_OP_TRUE_PREDICATE_ETYPE(insn_name, op_name, element_type, size, min_vec_len, insn)
207 define(`UNARY_OP_TRUE_PREDICATE_ETYPE', `
208 instruct $1(vecA dst, vecA src) %{
209   predicate(UseSVE > 0 && n->as_Vector()->length() >= $5 &&
210             n->bottom_type()->is_vect()->element_basic_type() == $3);
211   match(Set dst ($2 src));
212   ins_cost(SVE_COST);
213   format %{ "$6 $dst, $src\t# vector (sve) ($4)" %}
214   ins_encode %{
215     __ $6(as_FloatRegister($dst$$reg), __ $4,
216          ptrue, as_FloatRegister($src$$reg));
217   %}
218   ins_pipe(pipe_slow);
219 %}')dnl
220 
221 // sve abs
222 UNARY_OP_TRUE_PREDICATE_ETYPE(vabsAB, AbsVB, T_BYTE,   B, 16, sve_abs)
223 UNARY_OP_TRUE_PREDICATE_ETYPE(vabsAS, AbsVS, T_SHORT,  H, 8,  sve_abs)
224 UNARY_OP_TRUE_PREDICATE_ETYPE(vabsAI, AbsVI, T_INT,    S, 4,  sve_abs)
225 UNARY_OP_TRUE_PREDICATE_ETYPE(vabsAL, AbsVL, T_LONG,   D, 2,  sve_abs)
226 UNARY_OP_TRUE_PREDICATE_ETYPE(vabsAF, AbsVF, T_FLOAT,  S, 4,  sve_fabs)
227 UNARY_OP_TRUE_PREDICATE_ETYPE(vabsAD, AbsVD, T_DOUBLE, D, 2,  sve_fabs)
228 dnl
229 dnl BINARY_OP_UNPREDICATED($1,        $2       $3,   $4           $5  )
230 dnl BINARY_OP_UNPREDICATED(insn_name, op_name, size, min_vec_len, insn)
231 define(`BINARY_OP_UNPREDICATED', `
232 instruct $1(vecA dst, vecA src1, vecA src2) %{
233   predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
234   match(Set dst ($2 src1 src2));
235   ins_cost(SVE_COST);
236   format %{ "$5 $dst, $src1, $src2\t # vector (sve) ($3)" %}
237   ins_encode %{
238     __ $5(as_FloatRegister($dst$$reg), __ $3,
239          as_FloatRegister($src1$$reg),
240          as_FloatRegister($src2$$reg));
241   %}
242   ins_pipe(pipe_slow);
243 %}')dnl
244 
245 // sve add
246 BINARY_OP_UNPREDICATED(vaddAB, AddVB, B, 16, sve_add)
247 BINARY_OP_UNPREDICATED(vaddAS, AddVS, H, 8,  sve_add)
248 BINARY_OP_UNPREDICATED(vaddAI, AddVI, S, 4,  sve_add)
249 BINARY_OP_UNPREDICATED(vaddAL, AddVL, D, 2,  sve_add)
250 BINARY_OP_UNPREDICATED(vaddAF, AddVF, S, 4,  sve_fadd)
251 BINARY_OP_UNPREDICATED(vaddAD, AddVD, D, 2,  sve_fadd)
252 dnl
253 dnl BINARY_OP_UNSIZED($1,        $2,      $3,          $4  )
254 dnl BINARY_OP_UNSIZED(insn_name, op_name, min_vec_len, insn)
255 define(`BINARY_OP_UNSIZED', `
256 instruct $1(vecA dst, vecA src1, vecA src2) %{
257   predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= $3);
258   match(Set dst ($2 src1 src2));
259   ins_cost(SVE_COST);
260   format %{ "$4  $dst, $src1, $src2\t# vector (sve)" %}
261   ins_encode %{
262     __ $4(as_FloatRegister($dst$$reg),
263          as_FloatRegister($src1$$reg),
264          as_FloatRegister($src2$$reg));
265   %}
266   ins_pipe(pipe_slow);
267 %}')dnl
268 
269 // sve and
270 BINARY_OP_UNSIZED(vandA, AndV, 16, sve_and)
271 
272 // sve or
273 BINARY_OP_UNSIZED(vorA, OrV, 16, sve_orr)
274 
275 // sve xor
276 BINARY_OP_UNSIZED(vxorA, XorV, 16, sve_eor)
277 dnl
278 dnl VDIVF($1,          $2  , $3         )
279 dnl VDIVF(name_suffix, size, min_vec_len)
280 define(`VDIVF', `
281 instruct vdivA$1(vecA dst_src1, vecA src2) %{
282   predicate(UseSVE > 0 && n->as_Vector()->length() >= $3);
283   match(Set dst_src1 (DivV$1 dst_src1 src2));
284   ins_cost(SVE_COST);
285   format %{ "sve_fdiv  $dst_src1, $dst_src1, $src2\t# vector (sve) ($2)" %}
286   ins_encode %{
287     __ sve_fdiv(as_FloatRegister($dst_src1$$reg), __ $2,
288          ptrue, as_FloatRegister($src2$$reg));
289   %}
290   ins_pipe(pipe_slow);
291 %}')dnl
292 
293 // sve float div
294 VDIVF(F, S, 4)
295 VDIVF(D, D, 2)
296 
297 dnl
298 dnl BINARY_OP_TRUE_PREDICATE_ETYPE($1,        $2,      $3,           $4,   $5,          $6  )
299 dnl BINARY_OP_TRUE_PREDICATE_ETYPE(insn_name, op_name, element_type, size, min_vec_len, insn)
300 define(`BINARY_OP_TRUE_PREDICATE_ETYPE', `
301 instruct $1(vecA dst_src1, vecA src2) %{
302   predicate(UseSVE > 0 && n->as_Vector()->length() >= $5 &&
303             n->bottom_type()->is_vect()->element_basic_type() == $3);
304   match(Set dst_src1 ($2 dst_src1 src2));
305   ins_cost(SVE_COST);
306   format %{ "$6 $dst_src1, $dst_src1, $src2\t # vector (sve) ($4)" %}
307   ins_encode %{
308     __ $6(as_FloatRegister($dst_src1$$reg), __ $4,
309          ptrue, as_FloatRegister($src2$$reg));
310   %}
311   ins_pipe(pipe_slow);
312 %}')dnl
313 dnl
314 // sve max
315 BINARY_OP_TRUE_PREDICATE_ETYPE(vmaxAF, MaxV, T_FLOAT,  S, 4,  sve_fmax)
316 BINARY_OP_TRUE_PREDICATE_ETYPE(vmaxAD, MaxV, T_DOUBLE, D, 2,  sve_fmax)
317 BINARY_OP_TRUE_PREDICATE_ETYPE(vminAF, MinV, T_FLOAT,  S, 4,  sve_fmin)
318 BINARY_OP_TRUE_PREDICATE_ETYPE(vminAD, MinV, T_DOUBLE, D, 2,  sve_fmin)
319 
320 dnl
321 dnl VFMLA($1           $2    $3         )
322 dnl VFMLA(name_suffix, size, min_vec_len)
323 define(`VFMLA', `
324 // dst_src1 = dst_src1 + src2 * src3
325 instruct vfmlaA$1(vecA dst_src1, vecA src2, vecA src3) %{
326   predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
327   match(Set dst_src1 (FmaV$1 dst_src1 (Binary src2 src3)));
328   ins_cost(SVE_COST);
329   format %{ "sve_fmla $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
330   ins_encode %{
331     __ sve_fmla(as_FloatRegister($dst_src1$$reg), __ $2,
332          ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
333   %}
334   ins_pipe(pipe_slow);
335 %}')dnl
336 dnl
337 // sve fmla
338 VFMLA(F, S, 4)
339 VFMLA(D, D, 2)
340 
341 dnl
342 dnl VFMLS($1           $2    $3         )
343 dnl VFMLS(name_suffix, size, min_vec_len)
344 define(`VFMLS', `
345 // dst_src1 = dst_src1 + -src2 * src3
346 // dst_src1 = dst_src1 + src2 * -src3
347 instruct vfmlsA$1(vecA dst_src1, vecA src2, vecA src3) %{
348   predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
349   match(Set dst_src1 (FmaV$1 dst_src1 (Binary (NegV$1 src2) src3)));
350   match(Set dst_src1 (FmaV$1 dst_src1 (Binary src2 (NegV$1 src3))));
351   ins_cost(SVE_COST);
352   format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
353   ins_encode %{
354     __ sve_fmls(as_FloatRegister($dst_src1$$reg), __ $2,
355          ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
356   %}
357   ins_pipe(pipe_slow);
358 %}')dnl
359 dnl
360 // sve fmls
361 VFMLS(F, S, 4)
362 VFMLS(D, D, 2)
363 
364 dnl
365 dnl VFNMLA($1           $2    $3         )
366 dnl VFNMLA(name_suffix, size, min_vec_len)
367 define(`VFNMLA', `
368 // dst_src1 = -dst_src1 + -src2 * src3
369 // dst_src1 = -dst_src1 + src2 * -src3
370 instruct vfnmlaA$1(vecA dst_src1, vecA src2, vecA src3) %{
371   predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
372   match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary (NegV$1 src2) src3)));
373   match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary src2 (NegV$1 src3))));
374   ins_cost(SVE_COST);
375   format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
376   ins_encode %{
377     __ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ $2,
378          ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
379   %}
380   ins_pipe(pipe_slow);
381 %}')dnl
382 dnl
383 // sve fnmla
384 VFNMLA(F, S, 4)
385 VFNMLA(D, D, 2)
386 
387 dnl
388 dnl VFNMLS($1           $2    $3         )
389 dnl VFNMLS(name_suffix, size, min_vec_len)
390 define(`VFNMLS', `
391 // dst_src1 = -dst_src1 + src2 * src3
392 instruct vfnmlsA$1(vecA dst_src1, vecA src2, vecA src3) %{
393   predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= $3);
394   match(Set dst_src1 (FmaV$1 (NegV$1 dst_src1) (Binary src2 src3)));
395   ins_cost(SVE_COST);
396   format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) ($2)" %}
397   ins_encode %{
398     __ sve_fnmls(as_FloatRegister($dst_src1$$reg), __ $2,
399          ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
400   %}
401   ins_pipe(pipe_slow);
402 %}')dnl
403 dnl
404 // sve fnmls
405 VFNMLS(F, S, 4)
406 VFNMLS(D, D, 2)
407 
408 dnl
409 dnl VMLA($1           $2    $3         )
410 dnl VMLA(name_suffix, size, min_vec_len)
411 define(`VMLA', `
412 // dst_src1 = dst_src1 + src2 * src3
413 instruct vmlaA$1(vecA dst_src1, vecA src2, vecA src3)
414 %{
415   predicate(UseSVE > 0 && n->as_Vector()->length() >= $3);
416   match(Set dst_src1 (AddV$1 dst_src1 (MulV$1 src2 src3)));
417   ins_cost(SVE_COST);
418   format %{ "sve_mla $dst_src1, src2, src3\t # vector (sve) ($2)" %}
419   ins_encode %{
420     __ sve_mla(as_FloatRegister($dst_src1$$reg), __ $2,
421       ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
422   %}
423   ins_pipe(pipe_slow);
424 %}')dnl
425 dnl
426 // sve mla
427 VMLA(B, B, 16)
428 VMLA(S, H, 8)
429 VMLA(I, S, 4)
430 VMLA(L, D, 2)
431 
432 dnl
433 dnl VMLS($1           $2    $3         )
434 dnl VMLS(name_suffix, size, min_vec_len)
435 define(`VMLS', `
436 // dst_src1 = dst_src1 - src2 * src3
437 instruct vmlsA$1(vecA dst_src1, vecA src2, vecA src3)
438 %{
439   predicate(UseSVE > 0 && n->as_Vector()->length() >= $3);
440   match(Set dst_src1 (SubV$1 dst_src1 (MulV$1 src2 src3)));
441   ins_cost(SVE_COST);
442   format %{ "sve_mls $dst_src1, src2, src3\t # vector (sve) ($2)" %}
443   ins_encode %{
444     __ sve_mls(as_FloatRegister($dst_src1$$reg), __ $2,
445       ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
446   %}
447   ins_pipe(pipe_slow);
448 %}')dnl
449 dnl
450 // sve mls
451 VMLS(B, B, 16)
452 VMLS(S, H, 8)
453 VMLS(I, S, 4)
454 VMLS(L, D, 2)
455 
456 dnl
457 dnl BINARY_OP_TRUE_PREDICATE($1,        $2,      $3,   $4,          $5  )
458 dnl BINARY_OP_TRUE_PREDICATE(insn_name, op_name, size, min_vec_len, insn)
459 define(`BINARY_OP_TRUE_PREDICATE', `
460 instruct $1(vecA dst_src1, vecA src2) %{
461   predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
462   match(Set dst_src1 ($2 dst_src1 src2));
463   ins_cost(SVE_COST);
464   format %{ "$5 $dst_src1, $dst_src1, $src2\t # vector (sve) ($3)" %}
465   ins_encode %{
466     __ $5(as_FloatRegister($dst_src1$$reg), __ $3,
467          ptrue, as_FloatRegister($src2$$reg));
468   %}
469   ins_pipe(pipe_slow);
470 %}')dnl
471 
472 // sve mul
473 BINARY_OP_TRUE_PREDICATE(vmulAB, MulVB, B, 16, sve_mul)
474 BINARY_OP_TRUE_PREDICATE(vmulAS, MulVS, H, 8,  sve_mul)
475 BINARY_OP_TRUE_PREDICATE(vmulAI, MulVI, S, 4,  sve_mul)
476 BINARY_OP_TRUE_PREDICATE(vmulAL, MulVL, D, 2,  sve_mul)
477 BINARY_OP_UNPREDICATED(vmulAF, MulVF, S, 4, sve_fmul)
478 BINARY_OP_UNPREDICATED(vmulAD, MulVD, D, 2, sve_fmul)
479 
480 dnl
481 dnl UNARY_OP_TRUE_PREDICATE($1,        $2,      $3,   $4,            $5  )
482 dnl UNARY_OP_TRUE_PREDICATE(insn_name, op_name, size, min_vec_bytes, insn)
483 define(`UNARY_OP_TRUE_PREDICATE', `
484 instruct $1(vecA dst, vecA src) %{
485   predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= $4);
486   match(Set dst ($2 src));
487   ins_cost(SVE_COST);
488   format %{ "$5 $dst, $src\t# vector (sve) ($3)" %}
489   ins_encode %{
490     __ $5(as_FloatRegister($dst$$reg), __ $3,
491          ptrue, as_FloatRegister($src$$reg));
492   %}
493   ins_pipe(pipe_slow);
494 %}')dnl
495 dnl
496 // sve fneg
497 UNARY_OP_TRUE_PREDICATE(vnegAF, NegVF, S, 16, sve_fneg)
498 UNARY_OP_TRUE_PREDICATE(vnegAD, NegVD, D, 16, sve_fneg)
499 
500 // sve popcount vector
501 
502 instruct vpopcountAI(vecA dst, vecA src) %{
503   predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
504   match(Set dst (PopCountVI src));
505   format %{ "sve_cnt $dst, $src\t# vector (sve) (S)\n\t"  %}
506   ins_encode %{
507      __ sve_cnt(as_FloatRegister($dst$$reg), __ S, ptrue, as_FloatRegister($src$$reg));
508   %}
509   ins_pipe(pipe_slow);
510 %}
511 
512 dnl
513 dnl REDUCE_ADD($1,        $2,      $3,      $4,      $5,   $6,        $7   )
514 dnl REDUCE_ADD(insn_name, op_name, reg_dst, reg_src, size, elem_type, insn1)
515 define(`REDUCE_ADD', `
516 instruct $1($3 dst, $4 src1, vecA src2, vRegD tmp) %{
517   predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16 &&
518             ELEMENT_SHORT_CHAR($6, n->in(2)));
519   match(Set dst ($2 src1 src2));
520   effect(TEMP_DEF dst, TEMP tmp);
521   ins_cost(SVE_COST);
522   format %{ "sve_uaddv $tmp, $src2\t# vector (sve) ($5)\n\t"
523             "umov  $dst, $tmp, $5, 0\n\t"
524             "$7  $dst, $dst, $src1\t # add reduction $5" %}
525   ins_encode %{
526     __ sve_uaddv(as_FloatRegister($tmp$$reg), __ $5,
527          ptrue, as_FloatRegister($src2$$reg));
528     __ umov($dst$$Register, as_FloatRegister($tmp$$reg), __ $5, 0);
529     __ $7($dst$$Register, $dst$$Register, $src1$$Register);
530   %}
531   ins_pipe(pipe_slow);
532 %}')dnl
533 dnl
534 dnl REDUCE_ADDF($1,        $2,      $3,      $4  )
535 dnl REDUCE_ADDF(insn_name, op_name, reg_dst, size)
536 define(`REDUCE_ADDF', `
537 instruct $1($3 src1_dst, vecA src2) %{
538   predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
539   match(Set src1_dst ($2 src1_dst src2));
540   ins_cost(SVE_COST);
541   format %{ "sve_fadda $src1_dst, $src1_dst, $src2\t# vector (sve) ($4)" %}
542   ins_encode %{
543     __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ $4,
544          ptrue, as_FloatRegister($src2$$reg));
545   %}
546   ins_pipe(pipe_slow);
547 %}')dnl
548 dnl
549 // sve add reduction
550 REDUCE_ADD(reduce_addAI, AddReductionVI, iRegINoSp, iRegIorL2I, S, T_INT, addw)
551 REDUCE_ADD(reduce_addAL, AddReductionVL, iRegLNoSp, iRegL, D, T_LONG, add)
552 REDUCE_ADDF(reduce_addAF, AddReductionVF, vRegF, S)
553 REDUCE_ADDF(reduce_addAD, AddReductionVD, vRegD, D)
554 
555 dnl
556 dnl REDUCE_FMINMAX($1,      $2,          $3,           $4,   $5         )
557 dnl REDUCE_FMINMAX(min_max, name_suffix, element_type, size, reg_src_dst)
558 define(`REDUCE_FMINMAX', `
559 instruct reduce_$1A$2($5 dst, $5 src1, vecA src2) %{
560   predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->element_basic_type() == $3 &&
561             n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
562   match(Set dst (translit($1, `m', `M')ReductionV src1 src2));
563   ins_cost(INSN_COST);
564   effect(TEMP_DEF dst);
565   format %{ "sve_f$1v $dst, $src2 # vector (sve) (S)\n\t"
566             "f$1s $dst, $dst, $src1\t # $1 reduction $2" %}
567   ins_encode %{
568     __ sve_f$1v(as_FloatRegister($dst$$reg), __ $4,
569          ptrue, as_FloatRegister($src2$$reg));
570     __ f`$1'translit($4, `SD', `sd')(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
571   %}
572   ins_pipe(pipe_slow);
573 %}')dnl
574 // sve max reduction
575 REDUCE_FMINMAX(max, F, T_FLOAT,  S, vRegF)
576 REDUCE_FMINMAX(max, D, T_DOUBLE, D, vRegD)
577 
578 // sve min reduction
579 REDUCE_FMINMAX(min, F, T_FLOAT,  S, vRegF)
580 REDUCE_FMINMAX(min, D, T_DOUBLE, D, vRegD)
581 
582 // sve vector Math.rint, floor, ceil
583 
584 instruct vroundAD(vecA dst, vecA src, immI rmode) %{
585   predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
586             n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
587   match(Set dst (RoundDoubleModeV src rmode));
588   format %{ "sve_frint $dst, $src, $rmode\t# vector (sve) (D)" %}
589   ins_encode %{
590     switch ($rmode$$constant) {
591       case RoundDoubleModeNode::rmode_rint:
592         __ sve_frintn(as_FloatRegister($dst$$reg), __ D,
593              ptrue, as_FloatRegister($src$$reg));
594         break;
595       case RoundDoubleModeNode::rmode_floor:
596         __ sve_frintm(as_FloatRegister($dst$$reg), __ D,
597              ptrue, as_FloatRegister($src$$reg));
598         break;
599       case RoundDoubleModeNode::rmode_ceil:
600         __ sve_frintp(as_FloatRegister($dst$$reg), __ D,
601              ptrue, as_FloatRegister($src$$reg));
602         break;
603     }
604   %}
605   ins_pipe(pipe_slow);
606 %}
607 dnl
608 dnl REPLICATE($1,        $2,      $3,      $4,   $5         )
609 dnl REPLICATE(insn_name, op_name, reg_src, size, min_vec_len)
610 define(`REPLICATE', `
611 instruct $1(vecA dst, $3 src) %{
612   predicate(UseSVE > 0 && n->as_Vector()->length() >= $5);
613   match(Set dst ($2 src));
614   ins_cost(SVE_COST);
615   format %{ "sve_dup  $dst, $src\t# vector (sve) ($4)" %}
616   ins_encode %{
617     __ sve_dup(as_FloatRegister($dst$$reg), __ $4, as_Register($src$$reg));
618   %}
619   ins_pipe(pipe_slow);
620 %}')dnl
621 dnl
622 dnl REPLICATE_IMM8($1,        $2,      $3,       $4,   $5         )
623 dnl REPLICATE_IMM8(insn_name, op_name, imm_type, size, min_vec_len)
624 define(`REPLICATE_IMM8', `
625 instruct $1(vecA dst, $3 con) %{
626   predicate(UseSVE > 0 && n->as_Vector()->length() >= $5);
627   match(Set dst ($2 con));
628   ins_cost(SVE_COST);
629   format %{ "sve_dup  $dst, $con\t# vector (sve) ($4)" %}
630   ins_encode %{
631     __ sve_dup(as_FloatRegister($dst$$reg), __ $4, $con$$constant);
632   %}
633   ins_pipe(pipe_slow);
634 %}')dnl
635 dnl
636 dnl FREPLICATE($1,        $2,      $3,      $4,   $5         )
637 dnl FREPLICATE(insn_name, op_name, reg_src, size, min_vec_len)
638 define(`FREPLICATE', `
639 instruct $1(vecA dst, $3 src) %{
640   predicate(UseSVE > 0 && n->as_Vector()->length() >= $5);
641   match(Set dst ($2 src));
642   ins_cost(SVE_COST);
643   format %{ "sve_cpy  $dst, $src\t# vector (sve) ($4)" %}
644   ins_encode %{
645     __ sve_cpy(as_FloatRegister($dst$$reg), __ $4,
646          ptrue, as_FloatRegister($src$$reg));
647   %}
648   ins_pipe(pipe_slow);
649 %}')dnl
650 
651 // sve replicate
652 REPLICATE(replicateAB, ReplicateB, iRegIorL2I, B, 16)
653 REPLICATE(replicateAS, ReplicateS, iRegIorL2I, H, 8)
654 REPLICATE(replicateAI, ReplicateI, iRegIorL2I, S, 4)
655 REPLICATE(replicateAL, ReplicateL, iRegL,      D, 2)
656 
657 REPLICATE_IMM8(replicateAB_imm8, ReplicateB, immI8,        B, 16)
658 REPLICATE_IMM8(replicateAS_imm8, ReplicateS, immI8_shift8, H, 8)
659 REPLICATE_IMM8(replicateAI_imm8, ReplicateI, immI8_shift8, S, 4)
660 REPLICATE_IMM8(replicateAL_imm8, ReplicateL, immL8_shift8, D, 2)
661 
662 FREPLICATE(replicateAF, ReplicateF, vRegF, S, 4)
663 FREPLICATE(replicateAD, ReplicateD, vRegD, D, 2)
664 dnl
665 dnl VSHIFT_TRUE_PREDICATE($1,        $2,      $3,   $4,          $5  )
666 dnl VSHIFT_TRUE_PREDICATE(insn_name, op_name, size, min_vec_len, insn)
667 define(`VSHIFT_TRUE_PREDICATE', `
668 instruct $1(vecA dst, vecA shift) %{
669   predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
670   match(Set dst ($2 dst shift));
671   ins_cost(SVE_COST);
672   format %{ "$5 $dst, $dst, $shift\t# vector (sve) ($3)" %}
673   ins_encode %{
674     __ $5(as_FloatRegister($dst$$reg), __ $3,
675          ptrue, as_FloatRegister($shift$$reg));
676   %}
677   ins_pipe(pipe_slow);
678 %}')dnl
679 dnl
680 dnl VSHIFT_IMM_UNPREDICATE($1,        $2,      $3,   $4,          $5  )
681 dnl VSHIFT_IMM_UNPREDICATE(insn_name, op_name, size, min_vec_len, insn)
682 define(`VSHIFT_IMM_UNPREDICATE', `
683 instruct $1(vecA dst, vecA src, immI shift) %{
684   predicate(UseSVE > 0 && n->as_Vector()->length() >= $4);
685   match(Set dst ($2 src shift));
686   ins_cost(SVE_COST);
687   format %{ "$5 $dst, $src, $shift\t# vector (sve) ($3)" %}
688   ins_encode %{
689     int con = (int)$shift$$constant;dnl
690 ifelse(eval(index(`$1', `vasr') == 0 || index(`$1', `vlsr') == 0), 1, `
691     if (con == 0) {
692       __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
693            as_FloatRegister($src$$reg));
694       return;
695     }')dnl
696 ifelse(eval(index(`$1', `vasr') == 0), 1, `ifelse(eval(index(`$3', `B') == 0), 1, `
697     if (con >= 8) con = 7;')ifelse(eval(index(`$3', `H') == 0), 1, `
698     if (con >= 16) con = 15;')')dnl
699 ifelse(eval((index(`$1', `vlsl') == 0 || index(`$1', `vlsr') == 0) && (index(`$3', `B') == 0 || index(`$3', `H') == 0)), 1, `
700     if (con >= 8) {
701       __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
702            as_FloatRegister($src$$reg));
703       return;
704     }')
705     __ $5(as_FloatRegister($dst$$reg), __ $3,
706          as_FloatRegister($src$$reg), con);
707   %}
708   ins_pipe(pipe_slow);
709 %}')dnl
710 dnl
711 dnl VSHIFT_COUNT($1,        $2,   $3,          $4  )
712 dnl VSHIFT_COUNT(insn_name, size, min_vec_len, type)
713 define(`VSHIFT_COUNT', `
714 instruct $1(vecA dst, iRegIorL2I cnt) %{
715   predicate(UseSVE > 0 && n->as_Vector()->length() >= $3 &&
716             ELEMENT_SHORT_CHAR($4, n));
717   match(Set dst (LShiftCntV cnt));
718   match(Set dst (RShiftCntV cnt));
719   format %{ "sve_dup $dst, $cnt\t# vector shift count (sve) ($2)" %}
720   ins_encode %{
721     __ sve_dup(as_FloatRegister($dst$$reg), __ $2, as_Register($cnt$$reg));
722   %}
723   ins_pipe(pipe_slow);
724 %}')dnl
725 
726 // sve shift
727 VSHIFT_TRUE_PREDICATE(vasrAB, RShiftVB,  B, 16, sve_asr)
728 VSHIFT_TRUE_PREDICATE(vasrAS, RShiftVS,  H,  8, sve_asr)
729 VSHIFT_TRUE_PREDICATE(vasrAI, RShiftVI,  S,  4, sve_asr)
730 VSHIFT_TRUE_PREDICATE(vasrAL, RShiftVL,  D,  2, sve_asr)
731 VSHIFT_TRUE_PREDICATE(vlslAB, LShiftVB,  B, 16, sve_lsl)
732 VSHIFT_TRUE_PREDICATE(vlslAS, LShiftVS,  H,  8, sve_lsl)
733 VSHIFT_TRUE_PREDICATE(vlslAI, LShiftVI,  S,  4, sve_lsl)
734 VSHIFT_TRUE_PREDICATE(vlslAL, LShiftVL,  D,  2, sve_lsl)
735 VSHIFT_TRUE_PREDICATE(vlsrAB, URShiftVB, B, 16, sve_lsr)
736 VSHIFT_TRUE_PREDICATE(vlsrAS, URShiftVS, H,  8, sve_lsr)
737 VSHIFT_TRUE_PREDICATE(vlsrAI, URShiftVI, S,  4, sve_lsr)
738 VSHIFT_TRUE_PREDICATE(vlsrAL, URShiftVL, D,  2, sve_lsr)
739 VSHIFT_IMM_UNPREDICATE(vasrAB_imm, RShiftVB,  B, 16, sve_asr)
740 VSHIFT_IMM_UNPREDICATE(vasrAS_imm, RShiftVS,  H,  8, sve_asr)
741 VSHIFT_IMM_UNPREDICATE(vasrAI_imm, RShiftVI,  S,  4, sve_asr)
742 VSHIFT_IMM_UNPREDICATE(vasrAL_imm, RShiftVL,  D,  2, sve_asr)
743 VSHIFT_IMM_UNPREDICATE(vlsrAB_imm, URShiftVB, B, 16, sve_lsr)
744 VSHIFT_IMM_UNPREDICATE(vlsrAS_imm, URShiftVS, H,  8, sve_lsr)
745 VSHIFT_IMM_UNPREDICATE(vlsrAI_imm, URShiftVI, S,  4, sve_lsr)
746 VSHIFT_IMM_UNPREDICATE(vlsrAL_imm, URShiftVL, D,  2, sve_lsr)
747 VSHIFT_IMM_UNPREDICATE(vlslAB_imm, LShiftVB,  B, 16, sve_lsl)
748 VSHIFT_IMM_UNPREDICATE(vlslAS_imm, LShiftVS,  H,  8, sve_lsl)
749 VSHIFT_IMM_UNPREDICATE(vlslAI_imm, LShiftVI,  S,  4, sve_lsl)
750 VSHIFT_IMM_UNPREDICATE(vlslAL_imm, LShiftVL,  D,  2, sve_lsl)
751 VSHIFT_COUNT(vshiftcntAB, B, 16, T_BYTE)
752 VSHIFT_COUNT(vshiftcntAS, H,  8, T_SHORT)
753 VSHIFT_COUNT(vshiftcntAI, S,  4, T_INT)
754 VSHIFT_COUNT(vshiftcntAL, D,  2, T_LONG)
755 
756 // sve sqrt
757 UNARY_OP_TRUE_PREDICATE(vsqrtAF, SqrtVF, S, 16, sve_fsqrt)
758 UNARY_OP_TRUE_PREDICATE(vsqrtAD, SqrtVD, D, 16, sve_fsqrt)
759 
760 // sve sub
761 BINARY_OP_UNPREDICATED(vsubAB, SubVB, B, 16, sve_sub)
762 BINARY_OP_UNPREDICATED(vsubAS, SubVS, H, 8, sve_sub)
763 BINARY_OP_UNPREDICATED(vsubAI, SubVI, S, 4, sve_sub)
764 BINARY_OP_UNPREDICATED(vsubAL, SubVL, D, 2, sve_sub)
765 BINARY_OP_UNPREDICATED(vsubAF, SubVF, S, 4, sve_fsub)
766 BINARY_OP_UNPREDICATED(vsubAD, SubVD, D, 2, sve_fsub)
767