1//
2// Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
3// Copyright (c) 2020, 2021, Arm Limited. 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// This file is automatically generated by running "m4 aarch64_sve_ad.m4". Do not edit ----
27
28// AArch64 SVE Architecture Description File
29
30
31// 4 bit signed offset -- for predicated load/store
32
33operand vmemA_immIOffset4()
34%{
35  predicate(Address::offset_ok_for_sve_immed(n->get_int(), 4,
36            Matcher::scalable_vector_reg_size(T_BYTE)));
37  match(ConI);
38
39  op_cost(0);
40  format %{ %}
41  interface(CONST_INTER);
42%}
43
44operand vmemA_immLOffset4()
45%{
46  predicate(Address::offset_ok_for_sve_immed(n->get_long(), 4,
47            Matcher::scalable_vector_reg_size(T_BYTE)));
48  match(ConL);
49
50  op_cost(0);
51  format %{ %}
52  interface(CONST_INTER);
53%}
54
55operand vmemA_indOffI4(iRegP reg, vmemA_immIOffset4 off)
56%{
57  constraint(ALLOC_IN_RC(ptr_reg));
58  match(AddP reg off);
59  op_cost(0);
60  format %{ "[$reg, $off, MUL VL]" %}
61  interface(MEMORY_INTER) %{
62    base($reg);
63    index(0xffffffff);
64    scale(0x0);
65    disp($off);
66  %}
67%}
68
69operand vmemA_indOffL4(iRegP reg, vmemA_immLOffset4 off)
70%{
71  constraint(ALLOC_IN_RC(ptr_reg));
72  match(AddP reg off);
73  op_cost(0);
74  format %{ "[$reg, $off, MUL VL]" %}
75  interface(MEMORY_INTER) %{
76    base($reg);
77    index(0xffffffff);
78    scale(0x0);
79    disp($off);
80  %}
81%}
82
83opclass vmemA(indirect, vmemA_indOffI4, vmemA_indOffL4);
84
85source_hpp %{
86  bool op_sve_supported(int opcode);
87%}
88
89source %{
90  static inline BasicType vector_element_basic_type(const MachNode* n) {
91    const TypeVect* vt = n->bottom_type()->is_vect();
92    return vt->element_basic_type();
93  }
94
95  static inline BasicType vector_element_basic_type(const MachNode* use, const MachOper* opnd) {
96    int def_idx = use->operand_index(opnd);
97    Node* def = use->in(def_idx);
98    const TypeVect* vt = def->bottom_type()->is_vect();
99    return vt->element_basic_type();
100  }
101
102  static Assembler::SIMD_RegVariant elemBytes_to_regVariant(int esize) {
103    switch(esize) {
104      case 1:
105        return Assembler::B;
106      case 2:
107        return Assembler::H;
108      case 4:
109        return Assembler::S;
110      case 8:
111        return Assembler::D;
112      default:
113        assert(false, "unsupported");
114        ShouldNotReachHere();
115    }
116    return Assembler::INVALID;
117  }
118
119  static Assembler::SIMD_RegVariant elemType_to_regVariant(BasicType bt) {
120    return elemBytes_to_regVariant(type2aelembytes(bt));
121  }
122
123  typedef void (C2_MacroAssembler::* sve_mem_insn_predicate)(FloatRegister Rt, Assembler::SIMD_RegVariant T,
124                                                             PRegister Pg, const Address &adr);
125
126  // Predicated load/store, with optional ptrue to all elements of given predicate register.
127  static void loadStoreA_predicate(C2_MacroAssembler masm, bool is_store,
128                                   FloatRegister reg, PRegister pg, BasicType bt,
129                                   int opcode, Register base, int index, int size, int disp) {
130    sve_mem_insn_predicate insn;
131    Assembler::SIMD_RegVariant type;
132    int esize = type2aelembytes(bt);
133    if (index == -1) {
134      assert(size == 0, "unsupported address mode: scale size = %d", size);
135      switch(esize) {
136      case 1:
137        insn = is_store ? &C2_MacroAssembler::sve_st1b : &C2_MacroAssembler::sve_ld1b;
138        type = Assembler::B;
139        break;
140      case 2:
141        insn = is_store ? &C2_MacroAssembler::sve_st1h : &C2_MacroAssembler::sve_ld1h;
142        type = Assembler::H;
143        break;
144      case 4:
145        insn = is_store ? &C2_MacroAssembler::sve_st1w : &C2_MacroAssembler::sve_ld1w;
146        type = Assembler::S;
147        break;
148      case 8:
149        insn = is_store ? &C2_MacroAssembler::sve_st1d : &C2_MacroAssembler::sve_ld1d;
150        type = Assembler::D;
151        break;
152      default:
153        assert(false, "unsupported");
154        ShouldNotReachHere();
155      }
156      (masm.*insn)(reg, type, pg, Address(base, disp / Matcher::scalable_vector_reg_size(T_BYTE)));
157    } else {
158      assert(false, "unimplemented");
159      ShouldNotReachHere();
160    }
161  }
162
163  bool op_sve_supported(int opcode) {
164    switch (opcode) {
165      case Op_MulAddVS2VI:
166        // No multiply reduction instructions
167      case Op_MulReductionVD:
168      case Op_MulReductionVF:
169      case Op_MulReductionVI:
170      case Op_MulReductionVL:
171        // Others
172      case Op_Extract:
173      case Op_ExtractB:
174      case Op_ExtractC:
175      case Op_ExtractD:
176      case Op_ExtractF:
177      case Op_ExtractI:
178      case Op_ExtractL:
179      case Op_ExtractS:
180      case Op_ExtractUB:
181      // Vector API specific
182      case Op_AndReductionV:
183      case Op_OrReductionV:
184      case Op_XorReductionV:
185      case Op_MaxReductionV:
186      case Op_MinReductionV:
187      case Op_LoadVectorGather:
188      case Op_StoreVectorScatter:
189      case Op_VectorBlend:
190      case Op_VectorCast:
191      case Op_VectorCastB2X:
192      case Op_VectorCastD2X:
193      case Op_VectorCastF2X:
194      case Op_VectorCastI2X:
195      case Op_VectorCastL2X:
196      case Op_VectorCastS2X:
197      case Op_VectorInsert:
198      case Op_VectorLoadConst:
199      case Op_VectorLoadMask:
200      case Op_VectorLoadShuffle:
201      case Op_VectorMaskCmp:
202      case Op_VectorRearrange:
203      case Op_VectorReinterpret:
204      case Op_VectorStoreMask:
205      case Op_VectorTest:
206        return false;
207      default:
208        return true;
209    }
210  }
211%}
212
213definitions %{
214  int_def SVE_COST             (200, 200);
215%}
216
217
218// All SVE instructions
219
220// vector load/store
221
222// Use predicated vector load/store
223instruct loadV(vReg dst, vmemA mem) %{
224  predicate(UseSVE > 0 && n->as_LoadVector()->memory_size() >= 16);
225  match(Set dst (LoadVector mem));
226  ins_cost(SVE_COST);
227  format %{ "sve_ldr $dst, $mem\t # vector (sve)" %}
228  ins_encode %{
229    FloatRegister dst_reg = as_FloatRegister($dst$$reg);
230    loadStoreA_predicate(C2_MacroAssembler(&cbuf), false, dst_reg, ptrue,
231                         vector_element_basic_type(this), $mem->opcode(),
232                         as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
233  %}
234  ins_pipe(pipe_slow);
235%}
236
237instruct storeV(vReg src, vmemA mem) %{
238  predicate(UseSVE > 0 && n->as_StoreVector()->memory_size() >= 16);
239  match(Set mem (StoreVector mem src));
240  ins_cost(SVE_COST);
241  format %{ "sve_str $mem, $src\t # vector (sve)" %}
242  ins_encode %{
243    FloatRegister src_reg = as_FloatRegister($src$$reg);
244    loadStoreA_predicate(C2_MacroAssembler(&cbuf), true, src_reg, ptrue,
245                         vector_element_basic_type(this, $src), $mem->opcode(),
246                         as_Register($mem$$base), $mem$$index, $mem$$scale, $mem$$disp);
247  %}
248  ins_pipe(pipe_slow);
249%}
250
251// vector abs
252
253instruct vabsB(vReg dst, vReg src) %{
254  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16 &&
255            n->bottom_type()->is_vect()->element_basic_type() == T_BYTE);
256  match(Set dst (AbsVB src));
257  ins_cost(SVE_COST);
258  format %{ "sve_abs $dst, $src\t# vector (sve) (B)" %}
259  ins_encode %{
260    __ sve_abs(as_FloatRegister($dst$$reg), __ B,
261         ptrue, as_FloatRegister($src$$reg));
262  %}
263  ins_pipe(pipe_slow);
264%}
265
266instruct vabsS(vReg dst, vReg src) %{
267  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8 &&
268            n->bottom_type()->is_vect()->element_basic_type() == T_SHORT);
269  match(Set dst (AbsVS src));
270  ins_cost(SVE_COST);
271  format %{ "sve_abs $dst, $src\t# vector (sve) (H)" %}
272  ins_encode %{
273    __ sve_abs(as_FloatRegister($dst$$reg), __ H,
274         ptrue, as_FloatRegister($src$$reg));
275  %}
276  ins_pipe(pipe_slow);
277%}
278
279instruct vabsI(vReg dst, vReg src) %{
280  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4 &&
281            n->bottom_type()->is_vect()->element_basic_type() == T_INT);
282  match(Set dst (AbsVI src));
283  ins_cost(SVE_COST);
284  format %{ "sve_abs $dst, $src\t# vector (sve) (S)" %}
285  ins_encode %{
286    __ sve_abs(as_FloatRegister($dst$$reg), __ S,
287         ptrue, as_FloatRegister($src$$reg));
288  %}
289  ins_pipe(pipe_slow);
290%}
291
292instruct vabsL(vReg dst, vReg src) %{
293  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
294            n->bottom_type()->is_vect()->element_basic_type() == T_LONG);
295  match(Set dst (AbsVL src));
296  ins_cost(SVE_COST);
297  format %{ "sve_abs $dst, $src\t# vector (sve) (D)" %}
298  ins_encode %{
299    __ sve_abs(as_FloatRegister($dst$$reg), __ D,
300         ptrue, as_FloatRegister($src$$reg));
301  %}
302  ins_pipe(pipe_slow);
303%}
304
305instruct vabsF(vReg dst, vReg src) %{
306  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4 &&
307            n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT);
308  match(Set dst (AbsVF src));
309  ins_cost(SVE_COST);
310  format %{ "sve_fabs $dst, $src\t# vector (sve) (S)" %}
311  ins_encode %{
312    __ sve_fabs(as_FloatRegister($dst$$reg), __ S,
313         ptrue, as_FloatRegister($src$$reg));
314  %}
315  ins_pipe(pipe_slow);
316%}
317
318instruct vabsD(vReg dst, vReg src) %{
319  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
320            n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
321  match(Set dst (AbsVD src));
322  ins_cost(SVE_COST);
323  format %{ "sve_fabs $dst, $src\t# vector (sve) (D)" %}
324  ins_encode %{
325    __ sve_fabs(as_FloatRegister($dst$$reg), __ D,
326         ptrue, as_FloatRegister($src$$reg));
327  %}
328  ins_pipe(pipe_slow);
329%}
330
331// vector add
332
333instruct vaddB(vReg dst, vReg src1, vReg src2) %{
334  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
335  match(Set dst (AddVB src1 src2));
336  ins_cost(SVE_COST);
337  format %{ "sve_add $dst, $src1, $src2\t # vector (sve) (B)" %}
338  ins_encode %{
339    __ sve_add(as_FloatRegister($dst$$reg), __ B,
340         as_FloatRegister($src1$$reg),
341         as_FloatRegister($src2$$reg));
342  %}
343  ins_pipe(pipe_slow);
344%}
345
346instruct vaddS(vReg dst, vReg src1, vReg src2) %{
347  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
348  match(Set dst (AddVS src1 src2));
349  ins_cost(SVE_COST);
350  format %{ "sve_add $dst, $src1, $src2\t # vector (sve) (H)" %}
351  ins_encode %{
352    __ sve_add(as_FloatRegister($dst$$reg), __ H,
353         as_FloatRegister($src1$$reg),
354         as_FloatRegister($src2$$reg));
355  %}
356  ins_pipe(pipe_slow);
357%}
358
359instruct vaddI(vReg dst, vReg src1, vReg src2) %{
360  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
361  match(Set dst (AddVI src1 src2));
362  ins_cost(SVE_COST);
363  format %{ "sve_add $dst, $src1, $src2\t # vector (sve) (S)" %}
364  ins_encode %{
365    __ sve_add(as_FloatRegister($dst$$reg), __ S,
366         as_FloatRegister($src1$$reg),
367         as_FloatRegister($src2$$reg));
368  %}
369  ins_pipe(pipe_slow);
370%}
371
372instruct vaddL(vReg dst, vReg src1, vReg src2) %{
373  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
374  match(Set dst (AddVL src1 src2));
375  ins_cost(SVE_COST);
376  format %{ "sve_add $dst, $src1, $src2\t # vector (sve) (D)" %}
377  ins_encode %{
378    __ sve_add(as_FloatRegister($dst$$reg), __ D,
379         as_FloatRegister($src1$$reg),
380         as_FloatRegister($src2$$reg));
381  %}
382  ins_pipe(pipe_slow);
383%}
384
385instruct vaddF(vReg dst, vReg src1, vReg src2) %{
386  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
387  match(Set dst (AddVF src1 src2));
388  ins_cost(SVE_COST);
389  format %{ "sve_fadd $dst, $src1, $src2\t # vector (sve) (S)" %}
390  ins_encode %{
391    __ sve_fadd(as_FloatRegister($dst$$reg), __ S,
392         as_FloatRegister($src1$$reg),
393         as_FloatRegister($src2$$reg));
394  %}
395  ins_pipe(pipe_slow);
396%}
397
398instruct vaddD(vReg dst, vReg src1, vReg src2) %{
399  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
400  match(Set dst (AddVD src1 src2));
401  ins_cost(SVE_COST);
402  format %{ "sve_fadd $dst, $src1, $src2\t # vector (sve) (D)" %}
403  ins_encode %{
404    __ sve_fadd(as_FloatRegister($dst$$reg), __ D,
405         as_FloatRegister($src1$$reg),
406         as_FloatRegister($src2$$reg));
407  %}
408  ins_pipe(pipe_slow);
409%}
410
411// vector and
412
413instruct vand(vReg dst, vReg src1, vReg src2) %{
414  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
415  match(Set dst (AndV src1 src2));
416  ins_cost(SVE_COST);
417  format %{ "sve_and  $dst, $src1, $src2\t# vector (sve)" %}
418  ins_encode %{
419    __ sve_and(as_FloatRegister($dst$$reg),
420         as_FloatRegister($src1$$reg),
421         as_FloatRegister($src2$$reg));
422  %}
423  ins_pipe(pipe_slow);
424%}
425
426// vector or
427
428instruct vor(vReg dst, vReg src1, vReg src2) %{
429  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
430  match(Set dst (OrV src1 src2));
431  ins_cost(SVE_COST);
432  format %{ "sve_orr  $dst, $src1, $src2\t# vector (sve)" %}
433  ins_encode %{
434    __ sve_orr(as_FloatRegister($dst$$reg),
435         as_FloatRegister($src1$$reg),
436         as_FloatRegister($src2$$reg));
437  %}
438  ins_pipe(pipe_slow);
439%}
440
441// vector xor
442
443instruct vxor(vReg dst, vReg src1, vReg src2) %{
444  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
445  match(Set dst (XorV src1 src2));
446  ins_cost(SVE_COST);
447  format %{ "sve_eor  $dst, $src1, $src2\t# vector (sve)" %}
448  ins_encode %{
449    __ sve_eor(as_FloatRegister($dst$$reg),
450         as_FloatRegister($src1$$reg),
451         as_FloatRegister($src2$$reg));
452  %}
453  ins_pipe(pipe_slow);
454%}
455
456// vector not
457
458instruct vnotI(vReg dst, vReg src, immI_M1 m1) %{
459  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
460  match(Set dst (XorV src (ReplicateB m1)));
461  match(Set dst (XorV src (ReplicateS m1)));
462  match(Set dst (XorV src (ReplicateI m1)));
463  ins_cost(SVE_COST);
464  format %{ "sve_not $dst, $src\t# vector (sve) B/H/S" %}
465  ins_encode %{
466    __ sve_not(as_FloatRegister($dst$$reg), __ D,
467               ptrue, as_FloatRegister($src$$reg));
468  %}
469  ins_pipe(pipe_slow);
470%}
471
472instruct vnotL(vReg dst, vReg src, immL_M1 m1) %{
473  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
474  match(Set dst (XorV src (ReplicateL m1)));
475  ins_cost(SVE_COST);
476  format %{ "sve_not $dst, $src\t# vector (sve) D" %}
477  ins_encode %{
478    __ sve_not(as_FloatRegister($dst$$reg), __ D,
479               ptrue, as_FloatRegister($src$$reg));
480  %}
481  ins_pipe(pipe_slow);
482%}
483
484
485// vector and_not
486
487instruct vand_notI(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{
488  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
489  match(Set dst (AndV src1 (XorV src2 (ReplicateB m1))));
490  match(Set dst (AndV src1 (XorV src2 (ReplicateS m1))));
491  match(Set dst (AndV src1 (XorV src2 (ReplicateI m1))));
492  ins_cost(SVE_COST);
493  format %{ "sve_bic $dst, $src1, $src2\t# vector (sve) B/H/S" %}
494  ins_encode %{
495    __ sve_bic(as_FloatRegister($dst$$reg),
496               as_FloatRegister($src1$$reg),
497               as_FloatRegister($src2$$reg));
498  %}
499  ins_pipe(pipe_slow);
500%}
501
502instruct vand_notL(vReg dst, vReg src1, vReg src2, immL_M1 m1) %{
503  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
504  match(Set dst (AndV src1 (XorV src2 (ReplicateL m1))));
505  ins_cost(SVE_COST);
506  format %{ "sve_bic $dst, $src1, $src2\t# vector (sve) D" %}
507  ins_encode %{
508    __ sve_bic(as_FloatRegister($dst$$reg),
509               as_FloatRegister($src1$$reg),
510               as_FloatRegister($src2$$reg));
511  %}
512  ins_pipe(pipe_slow);
513%}
514
515
516// vector float div
517
518instruct vdivF(vReg dst_src1, vReg src2) %{
519  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
520  match(Set dst_src1 (DivVF dst_src1 src2));
521  ins_cost(SVE_COST);
522  format %{ "sve_fdiv  $dst_src1, $dst_src1, $src2\t# vector (sve) (S)" %}
523  ins_encode %{
524    __ sve_fdiv(as_FloatRegister($dst_src1$$reg), __ S,
525         ptrue, as_FloatRegister($src2$$reg));
526  %}
527  ins_pipe(pipe_slow);
528%}
529
530instruct vdivD(vReg dst_src1, vReg src2) %{
531  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
532  match(Set dst_src1 (DivVD dst_src1 src2));
533  ins_cost(SVE_COST);
534  format %{ "sve_fdiv  $dst_src1, $dst_src1, $src2\t# vector (sve) (D)" %}
535  ins_encode %{
536    __ sve_fdiv(as_FloatRegister($dst_src1$$reg), __ D,
537         ptrue, as_FloatRegister($src2$$reg));
538  %}
539  ins_pipe(pipe_slow);
540%}
541
542// vector min/max
543
544instruct vmin(vReg dst_src1, vReg src2) %{
545  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
546  match(Set dst_src1 (MinV dst_src1 src2));
547  ins_cost(SVE_COST);
548  format %{ "sve_min $dst_src1, $dst_src1, $src2\t # vector (sve)" %}
549  ins_encode %{
550    BasicType bt = vector_element_basic_type(this);
551    Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt);
552    if (is_floating_point_type(bt)) {
553      __ sve_fmin(as_FloatRegister($dst_src1$$reg), size,
554                  ptrue, as_FloatRegister($src2$$reg));
555    } else {
556      assert(is_integral_type(bt), "Unsupported type");
557      __ sve_smin(as_FloatRegister($dst_src1$$reg), size,
558                  ptrue, as_FloatRegister($src2$$reg));
559    }
560  %}
561  ins_pipe(pipe_slow);
562%}
563
564instruct vmax(vReg dst_src1, vReg src2) %{
565  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
566  match(Set dst_src1 (MaxV dst_src1 src2));
567  ins_cost(SVE_COST);
568  format %{ "sve_max $dst_src1, $dst_src1, $src2\t # vector (sve)" %}
569  ins_encode %{
570    BasicType bt = vector_element_basic_type(this);
571    Assembler::SIMD_RegVariant size = elemType_to_regVariant(bt);
572    if (is_floating_point_type(bt)) {
573      __ sve_fmax(as_FloatRegister($dst_src1$$reg), size,
574                  ptrue, as_FloatRegister($src2$$reg));
575    } else {
576      assert(is_integral_type(bt), "Unsupported type");
577      __ sve_smax(as_FloatRegister($dst_src1$$reg), size,
578                  ptrue, as_FloatRegister($src2$$reg));
579    }
580  %}
581  ins_pipe(pipe_slow);
582%}
583
584// vector fmla
585
586// dst_src1 = dst_src1 + src2 * src3
587instruct vfmlaF(vReg dst_src1, vReg src2, vReg src3) %{
588  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 4);
589  match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3)));
590  ins_cost(SVE_COST);
591  format %{ "sve_fmla $dst_src1, $src2, $src3\t # vector (sve) (S)" %}
592  ins_encode %{
593    __ sve_fmla(as_FloatRegister($dst_src1$$reg), __ S,
594         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
595  %}
596  ins_pipe(pipe_slow);
597%}
598
599// dst_src1 = dst_src1 + src2 * src3
600instruct vfmlaD(vReg dst_src1, vReg src2, vReg src3) %{
601  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 2);
602  match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3)));
603  ins_cost(SVE_COST);
604  format %{ "sve_fmla $dst_src1, $src2, $src3\t # vector (sve) (D)" %}
605  ins_encode %{
606    __ sve_fmla(as_FloatRegister($dst_src1$$reg), __ D,
607         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
608  %}
609  ins_pipe(pipe_slow);
610%}
611
612// vector fmls
613
614// dst_src1 = dst_src1 + -src2 * src3
615// dst_src1 = dst_src1 + src2 * -src3
616instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{
617  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 4);
618  match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3)));
619  match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3))));
620  ins_cost(SVE_COST);
621  format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) (S)" %}
622  ins_encode %{
623    __ sve_fmls(as_FloatRegister($dst_src1$$reg), __ S,
624         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
625  %}
626  ins_pipe(pipe_slow);
627%}
628
629// dst_src1 = dst_src1 + -src2 * src3
630// dst_src1 = dst_src1 + src2 * -src3
631instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{
632  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 2);
633  match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3)));
634  match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3))));
635  ins_cost(SVE_COST);
636  format %{ "sve_fmls $dst_src1, $src2, $src3\t # vector (sve) (D)" %}
637  ins_encode %{
638    __ sve_fmls(as_FloatRegister($dst_src1$$reg), __ D,
639         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
640  %}
641  ins_pipe(pipe_slow);
642%}
643
644// vector fnmla
645
646// dst_src1 = -dst_src1 + -src2 * src3
647// dst_src1 = -dst_src1 + src2 * -src3
648instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{
649  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 4);
650  match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3)));
651  match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3))));
652  ins_cost(SVE_COST);
653  format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) (S)" %}
654  ins_encode %{
655    __ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ S,
656         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
657  %}
658  ins_pipe(pipe_slow);
659%}
660
661// dst_src1 = -dst_src1 + -src2 * src3
662// dst_src1 = -dst_src1 + src2 * -src3
663instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{
664  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 2);
665  match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3)));
666  match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3))));
667  ins_cost(SVE_COST);
668  format %{ "sve_fnmla $dst_src1, $src2, $src3\t # vector (sve) (D)" %}
669  ins_encode %{
670    __ sve_fnmla(as_FloatRegister($dst_src1$$reg), __ D,
671         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
672  %}
673  ins_pipe(pipe_slow);
674%}
675
676// vector fnmls
677
678// dst_src1 = -dst_src1 + src2 * src3
679instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{
680  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 4);
681  match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3)));
682  ins_cost(SVE_COST);
683  format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) (S)" %}
684  ins_encode %{
685    __ sve_fnmls(as_FloatRegister($dst_src1$$reg), __ S,
686         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
687  %}
688  ins_pipe(pipe_slow);
689%}
690
691// dst_src1 = -dst_src1 + src2 * src3
692instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{
693  predicate(UseFMA && UseSVE > 0 && n->as_Vector()->length() >= 2);
694  match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3)));
695  ins_cost(SVE_COST);
696  format %{ "sve_fnmls $dst_src1, $src2, $src3\t # vector (sve) (D)" %}
697  ins_encode %{
698    __ sve_fnmls(as_FloatRegister($dst_src1$$reg), __ D,
699         ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
700  %}
701  ins_pipe(pipe_slow);
702%}
703
704// vector mla
705
706// dst_src1 = dst_src1 + src2 * src3
707instruct vmlaB(vReg dst_src1, vReg src2, vReg src3)
708%{
709  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
710  match(Set dst_src1 (AddVB dst_src1 (MulVB src2 src3)));
711  ins_cost(SVE_COST);
712  format %{ "sve_mla $dst_src1, src2, src3\t # vector (sve) (B)" %}
713  ins_encode %{
714    __ sve_mla(as_FloatRegister($dst_src1$$reg), __ B,
715      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
716  %}
717  ins_pipe(pipe_slow);
718%}
719
720// dst_src1 = dst_src1 + src2 * src3
721instruct vmlaS(vReg dst_src1, vReg src2, vReg src3)
722%{
723  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
724  match(Set dst_src1 (AddVS dst_src1 (MulVS src2 src3)));
725  ins_cost(SVE_COST);
726  format %{ "sve_mla $dst_src1, src2, src3\t # vector (sve) (H)" %}
727  ins_encode %{
728    __ sve_mla(as_FloatRegister($dst_src1$$reg), __ H,
729      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
730  %}
731  ins_pipe(pipe_slow);
732%}
733
734// dst_src1 = dst_src1 + src2 * src3
735instruct vmlaI(vReg dst_src1, vReg src2, vReg src3)
736%{
737  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
738  match(Set dst_src1 (AddVI dst_src1 (MulVI src2 src3)));
739  ins_cost(SVE_COST);
740  format %{ "sve_mla $dst_src1, src2, src3\t # vector (sve) (S)" %}
741  ins_encode %{
742    __ sve_mla(as_FloatRegister($dst_src1$$reg), __ S,
743      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
744  %}
745  ins_pipe(pipe_slow);
746%}
747
748// dst_src1 = dst_src1 + src2 * src3
749instruct vmlaL(vReg dst_src1, vReg src2, vReg src3)
750%{
751  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
752  match(Set dst_src1 (AddVL dst_src1 (MulVL src2 src3)));
753  ins_cost(SVE_COST);
754  format %{ "sve_mla $dst_src1, src2, src3\t # vector (sve) (D)" %}
755  ins_encode %{
756    __ sve_mla(as_FloatRegister($dst_src1$$reg), __ D,
757      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
758  %}
759  ins_pipe(pipe_slow);
760%}
761
762// vector mls
763
764// dst_src1 = dst_src1 - src2 * src3
765instruct vmlsB(vReg dst_src1, vReg src2, vReg src3)
766%{
767  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
768  match(Set dst_src1 (SubVB dst_src1 (MulVB src2 src3)));
769  ins_cost(SVE_COST);
770  format %{ "sve_mls $dst_src1, src2, src3\t # vector (sve) (B)" %}
771  ins_encode %{
772    __ sve_mls(as_FloatRegister($dst_src1$$reg), __ B,
773      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
774  %}
775  ins_pipe(pipe_slow);
776%}
777
778// dst_src1 = dst_src1 - src2 * src3
779instruct vmlsS(vReg dst_src1, vReg src2, vReg src3)
780%{
781  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
782  match(Set dst_src1 (SubVS dst_src1 (MulVS src2 src3)));
783  ins_cost(SVE_COST);
784  format %{ "sve_mls $dst_src1, src2, src3\t # vector (sve) (H)" %}
785  ins_encode %{
786    __ sve_mls(as_FloatRegister($dst_src1$$reg), __ H,
787      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
788  %}
789  ins_pipe(pipe_slow);
790%}
791
792// dst_src1 = dst_src1 - src2 * src3
793instruct vmlsI(vReg dst_src1, vReg src2, vReg src3)
794%{
795  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
796  match(Set dst_src1 (SubVI dst_src1 (MulVI src2 src3)));
797  ins_cost(SVE_COST);
798  format %{ "sve_mls $dst_src1, src2, src3\t # vector (sve) (S)" %}
799  ins_encode %{
800    __ sve_mls(as_FloatRegister($dst_src1$$reg), __ S,
801      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
802  %}
803  ins_pipe(pipe_slow);
804%}
805
806// dst_src1 = dst_src1 - src2 * src3
807instruct vmlsL(vReg dst_src1, vReg src2, vReg src3)
808%{
809  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
810  match(Set dst_src1 (SubVL dst_src1 (MulVL src2 src3)));
811  ins_cost(SVE_COST);
812  format %{ "sve_mls $dst_src1, src2, src3\t # vector (sve) (D)" %}
813  ins_encode %{
814    __ sve_mls(as_FloatRegister($dst_src1$$reg), __ D,
815      ptrue, as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg));
816  %}
817  ins_pipe(pipe_slow);
818%}
819
820
821// vector mul
822
823instruct vmulB(vReg dst_src1, vReg src2) %{
824  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
825  match(Set dst_src1 (MulVB dst_src1 src2));
826  ins_cost(SVE_COST);
827  format %{ "sve_mul $dst_src1, $dst_src1, $src2\t # vector (sve) (B)" %}
828  ins_encode %{
829    __ sve_mul(as_FloatRegister($dst_src1$$reg), __ B,
830         ptrue, as_FloatRegister($src2$$reg));
831  %}
832  ins_pipe(pipe_slow);
833%}
834
835instruct vmulS(vReg dst_src1, vReg src2) %{
836  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
837  match(Set dst_src1 (MulVS dst_src1 src2));
838  ins_cost(SVE_COST);
839  format %{ "sve_mul $dst_src1, $dst_src1, $src2\t # vector (sve) (H)" %}
840  ins_encode %{
841    __ sve_mul(as_FloatRegister($dst_src1$$reg), __ H,
842         ptrue, as_FloatRegister($src2$$reg));
843  %}
844  ins_pipe(pipe_slow);
845%}
846
847instruct vmulI(vReg dst_src1, vReg src2) %{
848  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
849  match(Set dst_src1 (MulVI dst_src1 src2));
850  ins_cost(SVE_COST);
851  format %{ "sve_mul $dst_src1, $dst_src1, $src2\t # vector (sve) (S)" %}
852  ins_encode %{
853    __ sve_mul(as_FloatRegister($dst_src1$$reg), __ S,
854         ptrue, as_FloatRegister($src2$$reg));
855  %}
856  ins_pipe(pipe_slow);
857%}
858
859instruct vmulL(vReg dst_src1, vReg src2) %{
860  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
861  match(Set dst_src1 (MulVL dst_src1 src2));
862  ins_cost(SVE_COST);
863  format %{ "sve_mul $dst_src1, $dst_src1, $src2\t # vector (sve) (D)" %}
864  ins_encode %{
865    __ sve_mul(as_FloatRegister($dst_src1$$reg), __ D,
866         ptrue, as_FloatRegister($src2$$reg));
867  %}
868  ins_pipe(pipe_slow);
869%}
870
871instruct vmulF(vReg dst, vReg src1, vReg src2) %{
872  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
873  match(Set dst (MulVF src1 src2));
874  ins_cost(SVE_COST);
875  format %{ "sve_fmul $dst, $src1, $src2\t # vector (sve) (S)" %}
876  ins_encode %{
877    __ sve_fmul(as_FloatRegister($dst$$reg), __ S,
878         as_FloatRegister($src1$$reg),
879         as_FloatRegister($src2$$reg));
880  %}
881  ins_pipe(pipe_slow);
882%}
883
884instruct vmulD(vReg dst, vReg src1, vReg src2) %{
885  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
886  match(Set dst (MulVD src1 src2));
887  ins_cost(SVE_COST);
888  format %{ "sve_fmul $dst, $src1, $src2\t # vector (sve) (D)" %}
889  ins_encode %{
890    __ sve_fmul(as_FloatRegister($dst$$reg), __ D,
891         as_FloatRegister($src1$$reg),
892         as_FloatRegister($src2$$reg));
893  %}
894  ins_pipe(pipe_slow);
895%}
896
897// vector fneg
898
899instruct vnegF(vReg dst, vReg src) %{
900  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
901  match(Set dst (NegVF src));
902  ins_cost(SVE_COST);
903  format %{ "sve_fneg $dst, $src\t# vector (sve) (S)" %}
904  ins_encode %{
905    __ sve_fneg(as_FloatRegister($dst$$reg), __ S,
906         ptrue, as_FloatRegister($src$$reg));
907  %}
908  ins_pipe(pipe_slow);
909%}
910
911instruct vnegD(vReg dst, vReg src) %{
912  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
913  match(Set dst (NegVD src));
914  ins_cost(SVE_COST);
915  format %{ "sve_fneg $dst, $src\t# vector (sve) (D)" %}
916  ins_encode %{
917    __ sve_fneg(as_FloatRegister($dst$$reg), __ D,
918         ptrue, as_FloatRegister($src$$reg));
919  %}
920  ins_pipe(pipe_slow);
921%}
922
923// popcount vector
924
925instruct vpopcountI(vReg dst, vReg src) %{
926  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
927  match(Set dst (PopCountVI src));
928  format %{ "sve_cnt $dst, $src\t# vector (sve) (S)\n\t"  %}
929  ins_encode %{
930     __ sve_cnt(as_FloatRegister($dst$$reg), __ S, ptrue, as_FloatRegister($src$$reg));
931  %}
932  ins_pipe(pipe_slow);
933%}
934
935// vector add reduction
936
937instruct reduce_addB(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD tmp) %{
938  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16 &&
939            n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE);
940  match(Set dst (AddReductionVI src1 src2));
941  effect(TEMP_DEF dst, TEMP tmp);
942  ins_cost(SVE_COST);
943  format %{ "sve_uaddv $tmp, $src2\t# vector (sve) (B)\n\t"
944            "smov  $dst, $tmp, B, 0\n\t"
945            "addw  $dst, $dst, $src1\n\t"
946            "sxtb  $dst, $dst\t # add reduction B" %}
947  ins_encode %{
948    __ sve_uaddv(as_FloatRegister($tmp$$reg), __ B,
949         ptrue, as_FloatRegister($src2$$reg));
950    __ smov($dst$$Register, as_FloatRegister($tmp$$reg), __ B, 0);
951    __ addw($dst$$Register, $dst$$Register, $src1$$Register);
952    __ sxtb($dst$$Register, $dst$$Register);
953  %}
954  ins_pipe(pipe_slow);
955%}
956
957instruct reduce_addS(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD tmp) %{
958  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16 &&
959            n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT);
960  match(Set dst (AddReductionVI src1 src2));
961  effect(TEMP_DEF dst, TEMP tmp);
962  ins_cost(SVE_COST);
963  format %{ "sve_uaddv $tmp, $src2\t# vector (sve) (H)\n\t"
964            "smov  $dst, $tmp, H, 0\n\t"
965            "addw  $dst, $dst, $src1\n\t"
966            "sxth  $dst, $dst\t # add reduction H" %}
967  ins_encode %{
968    __ sve_uaddv(as_FloatRegister($tmp$$reg), __ H,
969         ptrue, as_FloatRegister($src2$$reg));
970    __ smov($dst$$Register, as_FloatRegister($tmp$$reg), __ H, 0);
971    __ addw($dst$$Register, $dst$$Register, $src1$$Register);
972    __ sxth($dst$$Register, $dst$$Register);
973  %}
974  ins_pipe(pipe_slow);
975%}
976
977instruct reduce_addI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vRegD tmp) %{
978  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16 &&
979            n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT);
980  match(Set dst (AddReductionVI src1 src2));
981  effect(TEMP_DEF dst, TEMP tmp);
982  ins_cost(SVE_COST);
983  format %{ "sve_uaddv $tmp, $src2\t# vector (sve) (S)\n\t"
984            "umov  $dst, $tmp, S, 0\n\t"
985            "addw  $dst, $dst, $src1\t # add reduction S" %}
986  ins_encode %{
987    __ sve_uaddv(as_FloatRegister($tmp$$reg), __ S,
988         ptrue, as_FloatRegister($src2$$reg));
989    __ umov($dst$$Register, as_FloatRegister($tmp$$reg), __ S, 0);
990    __ addw($dst$$Register, $dst$$Register, $src1$$Register);
991  %}
992  ins_pipe(pipe_slow);
993%}
994
995instruct reduce_addL(iRegLNoSp dst, iRegL src1, vReg src2, vRegD tmp) %{
996  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16 &&
997            n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG);
998  match(Set dst (AddReductionVL src1 src2));
999  effect(TEMP_DEF dst, TEMP tmp);
1000  ins_cost(SVE_COST);
1001  format %{ "sve_uaddv $tmp, $src2\t# vector (sve) (D)\n\t"
1002            "umov  $dst, $tmp, D, 0\n\t"
1003            "add  $dst, $dst, $src1\t # add reduction D" %}
1004  ins_encode %{
1005    __ sve_uaddv(as_FloatRegister($tmp$$reg), __ D,
1006         ptrue, as_FloatRegister($src2$$reg));
1007    __ umov($dst$$Register, as_FloatRegister($tmp$$reg), __ D, 0);
1008    __ add($dst$$Register, $dst$$Register, $src1$$Register);
1009  %}
1010  ins_pipe(pipe_slow);
1011%}
1012
1013instruct reduce_addF(vRegF src1_dst, vReg src2) %{
1014  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
1015  match(Set src1_dst (AddReductionVF src1_dst src2));
1016  ins_cost(SVE_COST);
1017  format %{ "sve_fadda $src1_dst, $src1_dst, $src2\t# vector (sve) (S)" %}
1018  ins_encode %{
1019    __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ S,
1020         ptrue, as_FloatRegister($src2$$reg));
1021  %}
1022  ins_pipe(pipe_slow);
1023%}
1024
1025instruct reduce_addD(vRegD src1_dst, vReg src2) %{
1026  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
1027  match(Set src1_dst (AddReductionVD src1_dst src2));
1028  ins_cost(SVE_COST);
1029  format %{ "sve_fadda $src1_dst, $src1_dst, $src2\t# vector (sve) (D)" %}
1030  ins_encode %{
1031    __ sve_fadda(as_FloatRegister($src1_dst$$reg), __ D,
1032         ptrue, as_FloatRegister($src2$$reg));
1033  %}
1034  ins_pipe(pipe_slow);
1035%}
1036
1037// vector max reduction
1038
1039instruct reduce_maxF(vRegF dst, vRegF src1, vReg src2) %{
1040  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT &&
1041            n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
1042  match(Set dst (MaxReductionV src1 src2));
1043  ins_cost(INSN_COST);
1044  effect(TEMP_DEF dst);
1045  format %{ "sve_fmaxv $dst, $src2 # vector (sve) (S)\n\t"
1046            "fmaxs $dst, $dst, $src1\t # max reduction F" %}
1047  ins_encode %{
1048    __ sve_fmaxv(as_FloatRegister($dst$$reg), __ S,
1049         ptrue, as_FloatRegister($src2$$reg));
1050    __ fmaxs(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
1051  %}
1052  ins_pipe(pipe_slow);
1053%}
1054
1055instruct reduce_maxD(vRegD dst, vRegD src1, vReg src2) %{
1056  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE &&
1057            n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
1058  match(Set dst (MaxReductionV src1 src2));
1059  ins_cost(INSN_COST);
1060  effect(TEMP_DEF dst);
1061  format %{ "sve_fmaxv $dst, $src2 # vector (sve) (S)\n\t"
1062            "fmaxs $dst, $dst, $src1\t # max reduction D" %}
1063  ins_encode %{
1064    __ sve_fmaxv(as_FloatRegister($dst$$reg), __ D,
1065         ptrue, as_FloatRegister($src2$$reg));
1066    __ fmaxd(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
1067  %}
1068  ins_pipe(pipe_slow);
1069%}
1070
1071// vector min reduction
1072
1073instruct reduce_minF(vRegF dst, vRegF src1, vReg src2) %{
1074  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT &&
1075            n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
1076  match(Set dst (MinReductionV src1 src2));
1077  ins_cost(INSN_COST);
1078  effect(TEMP_DEF dst);
1079  format %{ "sve_fminv $dst, $src2 # vector (sve) (S)\n\t"
1080            "fmins $dst, $dst, $src1\t # min reduction F" %}
1081  ins_encode %{
1082    __ sve_fminv(as_FloatRegister($dst$$reg), __ S,
1083         ptrue, as_FloatRegister($src2$$reg));
1084    __ fmins(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
1085  %}
1086  ins_pipe(pipe_slow);
1087%}
1088
1089instruct reduce_minD(vRegD dst, vRegD src1, vReg src2) %{
1090  predicate(UseSVE > 0 && n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE &&
1091            n->in(2)->bottom_type()->is_vect()->length_in_bytes() >= 16);
1092  match(Set dst (MinReductionV src1 src2));
1093  ins_cost(INSN_COST);
1094  effect(TEMP_DEF dst);
1095  format %{ "sve_fminv $dst, $src2 # vector (sve) (S)\n\t"
1096            "fmins $dst, $dst, $src1\t # min reduction D" %}
1097  ins_encode %{
1098    __ sve_fminv(as_FloatRegister($dst$$reg), __ D,
1099         ptrue, as_FloatRegister($src2$$reg));
1100    __ fmind(as_FloatRegister($dst$$reg), as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg));
1101  %}
1102  ins_pipe(pipe_slow);
1103%}
1104
1105// vector Math.rint, floor, ceil
1106
1107instruct vroundD(vReg dst, vReg src, immI rmode) %{
1108  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
1109            n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE);
1110  match(Set dst (RoundDoubleModeV src rmode));
1111  format %{ "sve_frint $dst, $src, $rmode\t# vector (sve) (D)" %}
1112  ins_encode %{
1113    switch ($rmode$$constant) {
1114      case RoundDoubleModeNode::rmode_rint:
1115        __ sve_frintn(as_FloatRegister($dst$$reg), __ D,
1116             ptrue, as_FloatRegister($src$$reg));
1117        break;
1118      case RoundDoubleModeNode::rmode_floor:
1119        __ sve_frintm(as_FloatRegister($dst$$reg), __ D,
1120             ptrue, as_FloatRegister($src$$reg));
1121        break;
1122      case RoundDoubleModeNode::rmode_ceil:
1123        __ sve_frintp(as_FloatRegister($dst$$reg), __ D,
1124             ptrue, as_FloatRegister($src$$reg));
1125        break;
1126    }
1127  %}
1128  ins_pipe(pipe_slow);
1129%}
1130
1131// vector replicate
1132
1133instruct replicateB(vReg dst, iRegIorL2I src) %{
1134  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1135  match(Set dst (ReplicateB src));
1136  ins_cost(SVE_COST);
1137  format %{ "sve_dup  $dst, $src\t# vector (sve) (B)" %}
1138  ins_encode %{
1139    __ sve_dup(as_FloatRegister($dst$$reg), __ B, as_Register($src$$reg));
1140  %}
1141  ins_pipe(pipe_slow);
1142%}
1143
1144instruct replicateS(vReg dst, iRegIorL2I src) %{
1145  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1146  match(Set dst (ReplicateS src));
1147  ins_cost(SVE_COST);
1148  format %{ "sve_dup  $dst, $src\t# vector (sve) (H)" %}
1149  ins_encode %{
1150    __ sve_dup(as_FloatRegister($dst$$reg), __ H, as_Register($src$$reg));
1151  %}
1152  ins_pipe(pipe_slow);
1153%}
1154
1155instruct replicateI(vReg dst, iRegIorL2I src) %{
1156  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1157  match(Set dst (ReplicateI src));
1158  ins_cost(SVE_COST);
1159  format %{ "sve_dup  $dst, $src\t# vector (sve) (S)" %}
1160  ins_encode %{
1161    __ sve_dup(as_FloatRegister($dst$$reg), __ S, as_Register($src$$reg));
1162  %}
1163  ins_pipe(pipe_slow);
1164%}
1165
1166instruct replicateL(vReg dst, iRegL src) %{
1167  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1168  match(Set dst (ReplicateL src));
1169  ins_cost(SVE_COST);
1170  format %{ "sve_dup  $dst, $src\t# vector (sve) (D)" %}
1171  ins_encode %{
1172    __ sve_dup(as_FloatRegister($dst$$reg), __ D, as_Register($src$$reg));
1173  %}
1174  ins_pipe(pipe_slow);
1175%}
1176
1177instruct replicateB_imm8(vReg dst, immI8 con) %{
1178  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1179  match(Set dst (ReplicateB con));
1180  ins_cost(SVE_COST);
1181  format %{ "sve_dup  $dst, $con\t# vector (sve) (B)" %}
1182  ins_encode %{
1183    __ sve_dup(as_FloatRegister($dst$$reg), __ B, $con$$constant);
1184  %}
1185  ins_pipe(pipe_slow);
1186%}
1187
1188instruct replicateS_imm8(vReg dst, immI8_shift8 con) %{
1189  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1190  match(Set dst (ReplicateS con));
1191  ins_cost(SVE_COST);
1192  format %{ "sve_dup  $dst, $con\t# vector (sve) (H)" %}
1193  ins_encode %{
1194    __ sve_dup(as_FloatRegister($dst$$reg), __ H, $con$$constant);
1195  %}
1196  ins_pipe(pipe_slow);
1197%}
1198
1199instruct replicateI_imm8(vReg dst, immI8_shift8 con) %{
1200  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1201  match(Set dst (ReplicateI con));
1202  ins_cost(SVE_COST);
1203  format %{ "sve_dup  $dst, $con\t# vector (sve) (S)" %}
1204  ins_encode %{
1205    __ sve_dup(as_FloatRegister($dst$$reg), __ S, $con$$constant);
1206  %}
1207  ins_pipe(pipe_slow);
1208%}
1209
1210instruct replicateL_imm8(vReg dst, immL8_shift8 con) %{
1211  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1212  match(Set dst (ReplicateL con));
1213  ins_cost(SVE_COST);
1214  format %{ "sve_dup  $dst, $con\t# vector (sve) (D)" %}
1215  ins_encode %{
1216    __ sve_dup(as_FloatRegister($dst$$reg), __ D, $con$$constant);
1217  %}
1218  ins_pipe(pipe_slow);
1219%}
1220
1221instruct replicateF(vReg dst, vRegF src) %{
1222  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1223  match(Set dst (ReplicateF src));
1224  ins_cost(SVE_COST);
1225  format %{ "sve_cpy  $dst, $src\t# vector (sve) (S)" %}
1226  ins_encode %{
1227    __ sve_cpy(as_FloatRegister($dst$$reg), __ S,
1228         ptrue, as_FloatRegister($src$$reg));
1229  %}
1230  ins_pipe(pipe_slow);
1231%}
1232
1233instruct replicateD(vReg dst, vRegD src) %{
1234  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1235  match(Set dst (ReplicateD src));
1236  ins_cost(SVE_COST);
1237  format %{ "sve_cpy  $dst, $src\t# vector (sve) (D)" %}
1238  ins_encode %{
1239    __ sve_cpy(as_FloatRegister($dst$$reg), __ D,
1240         ptrue, as_FloatRegister($src$$reg));
1241  %}
1242  ins_pipe(pipe_slow);
1243%}
1244
1245// vector shift
1246
1247instruct vasrB(vReg dst, vReg shift) %{
1248  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1249  match(Set dst (RShiftVB dst shift));
1250  ins_cost(SVE_COST);
1251  format %{ "sve_asr $dst, $dst, $shift\t# vector (sve) (B)" %}
1252  ins_encode %{
1253    __ sve_asr(as_FloatRegister($dst$$reg), __ B,
1254         ptrue, as_FloatRegister($shift$$reg));
1255  %}
1256  ins_pipe(pipe_slow);
1257%}
1258
1259instruct vasrS(vReg dst, vReg shift) %{
1260  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1261  match(Set dst (RShiftVS dst shift));
1262  ins_cost(SVE_COST);
1263  format %{ "sve_asr $dst, $dst, $shift\t# vector (sve) (H)" %}
1264  ins_encode %{
1265    __ sve_asr(as_FloatRegister($dst$$reg), __ H,
1266         ptrue, as_FloatRegister($shift$$reg));
1267  %}
1268  ins_pipe(pipe_slow);
1269%}
1270
1271instruct vasrI(vReg dst, vReg shift) %{
1272  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1273  match(Set dst (RShiftVI dst shift));
1274  ins_cost(SVE_COST);
1275  format %{ "sve_asr $dst, $dst, $shift\t# vector (sve) (S)" %}
1276  ins_encode %{
1277    __ sve_asr(as_FloatRegister($dst$$reg), __ S,
1278         ptrue, as_FloatRegister($shift$$reg));
1279  %}
1280  ins_pipe(pipe_slow);
1281%}
1282
1283instruct vasrL(vReg dst, vReg shift) %{
1284  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1285  match(Set dst (RShiftVL dst shift));
1286  ins_cost(SVE_COST);
1287  format %{ "sve_asr $dst, $dst, $shift\t# vector (sve) (D)" %}
1288  ins_encode %{
1289    __ sve_asr(as_FloatRegister($dst$$reg), __ D,
1290         ptrue, as_FloatRegister($shift$$reg));
1291  %}
1292  ins_pipe(pipe_slow);
1293%}
1294
1295instruct vlslB(vReg dst, vReg shift) %{
1296  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1297  match(Set dst (LShiftVB dst shift));
1298  ins_cost(SVE_COST);
1299  format %{ "sve_lsl $dst, $dst, $shift\t# vector (sve) (B)" %}
1300  ins_encode %{
1301    __ sve_lsl(as_FloatRegister($dst$$reg), __ B,
1302         ptrue, as_FloatRegister($shift$$reg));
1303  %}
1304  ins_pipe(pipe_slow);
1305%}
1306
1307instruct vlslS(vReg dst, vReg shift) %{
1308  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1309  match(Set dst (LShiftVS dst shift));
1310  ins_cost(SVE_COST);
1311  format %{ "sve_lsl $dst, $dst, $shift\t# vector (sve) (H)" %}
1312  ins_encode %{
1313    __ sve_lsl(as_FloatRegister($dst$$reg), __ H,
1314         ptrue, as_FloatRegister($shift$$reg));
1315  %}
1316  ins_pipe(pipe_slow);
1317%}
1318
1319instruct vlslI(vReg dst, vReg shift) %{
1320  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1321  match(Set dst (LShiftVI dst shift));
1322  ins_cost(SVE_COST);
1323  format %{ "sve_lsl $dst, $dst, $shift\t# vector (sve) (S)" %}
1324  ins_encode %{
1325    __ sve_lsl(as_FloatRegister($dst$$reg), __ S,
1326         ptrue, as_FloatRegister($shift$$reg));
1327  %}
1328  ins_pipe(pipe_slow);
1329%}
1330
1331instruct vlslL(vReg dst, vReg shift) %{
1332  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1333  match(Set dst (LShiftVL dst shift));
1334  ins_cost(SVE_COST);
1335  format %{ "sve_lsl $dst, $dst, $shift\t# vector (sve) (D)" %}
1336  ins_encode %{
1337    __ sve_lsl(as_FloatRegister($dst$$reg), __ D,
1338         ptrue, as_FloatRegister($shift$$reg));
1339  %}
1340  ins_pipe(pipe_slow);
1341%}
1342
1343instruct vlsrB(vReg dst, vReg shift) %{
1344  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1345  match(Set dst (URShiftVB dst shift));
1346  ins_cost(SVE_COST);
1347  format %{ "sve_lsr $dst, $dst, $shift\t# vector (sve) (B)" %}
1348  ins_encode %{
1349    __ sve_lsr(as_FloatRegister($dst$$reg), __ B,
1350         ptrue, as_FloatRegister($shift$$reg));
1351  %}
1352  ins_pipe(pipe_slow);
1353%}
1354
1355instruct vlsrS(vReg dst, vReg shift) %{
1356  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1357  match(Set dst (URShiftVS dst shift));
1358  ins_cost(SVE_COST);
1359  format %{ "sve_lsr $dst, $dst, $shift\t# vector (sve) (H)" %}
1360  ins_encode %{
1361    __ sve_lsr(as_FloatRegister($dst$$reg), __ H,
1362         ptrue, as_FloatRegister($shift$$reg));
1363  %}
1364  ins_pipe(pipe_slow);
1365%}
1366
1367instruct vlsrI(vReg dst, vReg shift) %{
1368  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1369  match(Set dst (URShiftVI dst shift));
1370  ins_cost(SVE_COST);
1371  format %{ "sve_lsr $dst, $dst, $shift\t# vector (sve) (S)" %}
1372  ins_encode %{
1373    __ sve_lsr(as_FloatRegister($dst$$reg), __ S,
1374         ptrue, as_FloatRegister($shift$$reg));
1375  %}
1376  ins_pipe(pipe_slow);
1377%}
1378
1379instruct vlsrL(vReg dst, vReg shift) %{
1380  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1381  match(Set dst (URShiftVL dst shift));
1382  ins_cost(SVE_COST);
1383  format %{ "sve_lsr $dst, $dst, $shift\t# vector (sve) (D)" %}
1384  ins_encode %{
1385    __ sve_lsr(as_FloatRegister($dst$$reg), __ D,
1386         ptrue, as_FloatRegister($shift$$reg));
1387  %}
1388  ins_pipe(pipe_slow);
1389%}
1390
1391instruct vasrB_imm(vReg dst, vReg src, immI shift) %{
1392  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1393  match(Set dst (RShiftVB src (RShiftCntV shift)));
1394  ins_cost(SVE_COST);
1395  format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (B)" %}
1396  ins_encode %{
1397    int con = (int)$shift$$constant;
1398    if (con == 0) {
1399      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1400           as_FloatRegister($src$$reg));
1401      return;
1402    }
1403    if (con >= 8) con = 7;
1404    __ sve_asr(as_FloatRegister($dst$$reg), __ B,
1405         as_FloatRegister($src$$reg), con);
1406  %}
1407  ins_pipe(pipe_slow);
1408%}
1409
1410instruct vasrS_imm(vReg dst, vReg src, immI shift) %{
1411  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1412  match(Set dst (RShiftVS src (RShiftCntV shift)));
1413  ins_cost(SVE_COST);
1414  format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (H)" %}
1415  ins_encode %{
1416    int con = (int)$shift$$constant;
1417    if (con == 0) {
1418      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1419           as_FloatRegister($src$$reg));
1420      return;
1421    }
1422    if (con >= 16) con = 15;
1423    __ sve_asr(as_FloatRegister($dst$$reg), __ H,
1424         as_FloatRegister($src$$reg), con);
1425  %}
1426  ins_pipe(pipe_slow);
1427%}
1428
1429instruct vasrI_imm(vReg dst, vReg src, immI shift) %{
1430  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1431  match(Set dst (RShiftVI src (RShiftCntV shift)));
1432  ins_cost(SVE_COST);
1433  format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (S)" %}
1434  ins_encode %{
1435    int con = (int)$shift$$constant;
1436    if (con == 0) {
1437      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1438           as_FloatRegister($src$$reg));
1439      return;
1440    }
1441    __ sve_asr(as_FloatRegister($dst$$reg), __ S,
1442         as_FloatRegister($src$$reg), con);
1443  %}
1444  ins_pipe(pipe_slow);
1445%}
1446
1447instruct vasrL_imm(vReg dst, vReg src, immI shift) %{
1448  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1449  match(Set dst (RShiftVL src (RShiftCntV shift)));
1450  ins_cost(SVE_COST);
1451  format %{ "sve_asr $dst, $src, $shift\t# vector (sve) (D)" %}
1452  ins_encode %{
1453    int con = (int)$shift$$constant;
1454    if (con == 0) {
1455      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1456           as_FloatRegister($src$$reg));
1457      return;
1458    }
1459    __ sve_asr(as_FloatRegister($dst$$reg), __ D,
1460         as_FloatRegister($src$$reg), con);
1461  %}
1462  ins_pipe(pipe_slow);
1463%}
1464
1465instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{
1466  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1467  match(Set dst (URShiftVB src (RShiftCntV shift)));
1468  ins_cost(SVE_COST);
1469  format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (B)" %}
1470  ins_encode %{
1471    int con = (int)$shift$$constant;
1472    if (con == 0) {
1473      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1474           as_FloatRegister($src$$reg));
1475      return;
1476    }
1477    if (con >= 8) {
1478      __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1479           as_FloatRegister($src$$reg));
1480      return;
1481    }
1482    __ sve_lsr(as_FloatRegister($dst$$reg), __ B,
1483         as_FloatRegister($src$$reg), con);
1484  %}
1485  ins_pipe(pipe_slow);
1486%}
1487
1488instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{
1489  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1490  match(Set dst (URShiftVS src (RShiftCntV shift)));
1491  ins_cost(SVE_COST);
1492  format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (H)" %}
1493  ins_encode %{
1494    int con = (int)$shift$$constant;
1495    if (con == 0) {
1496      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1497           as_FloatRegister($src$$reg));
1498      return;
1499    }
1500    if (con >= 16) {
1501      __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1502           as_FloatRegister($src$$reg));
1503      return;
1504    }
1505    __ sve_lsr(as_FloatRegister($dst$$reg), __ H,
1506         as_FloatRegister($src$$reg), con);
1507  %}
1508  ins_pipe(pipe_slow);
1509%}
1510
1511instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{
1512  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1513  match(Set dst (URShiftVI src (RShiftCntV shift)));
1514  ins_cost(SVE_COST);
1515  format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (S)" %}
1516  ins_encode %{
1517    int con = (int)$shift$$constant;
1518    if (con == 0) {
1519      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1520           as_FloatRegister($src$$reg));
1521      return;
1522    }
1523    __ sve_lsr(as_FloatRegister($dst$$reg), __ S,
1524         as_FloatRegister($src$$reg), con);
1525  %}
1526  ins_pipe(pipe_slow);
1527%}
1528
1529instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{
1530  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1531  match(Set dst (URShiftVL src (RShiftCntV shift)));
1532  ins_cost(SVE_COST);
1533  format %{ "sve_lsr $dst, $src, $shift\t# vector (sve) (D)" %}
1534  ins_encode %{
1535    int con = (int)$shift$$constant;
1536    if (con == 0) {
1537      __ sve_orr(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1538           as_FloatRegister($src$$reg));
1539      return;
1540    }
1541    __ sve_lsr(as_FloatRegister($dst$$reg), __ D,
1542         as_FloatRegister($src$$reg), con);
1543  %}
1544  ins_pipe(pipe_slow);
1545%}
1546
1547instruct vlslB_imm(vReg dst, vReg src, immI shift) %{
1548  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1549  match(Set dst (LShiftVB src (LShiftCntV shift)));
1550  ins_cost(SVE_COST);
1551  format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (B)" %}
1552  ins_encode %{
1553    int con = (int)$shift$$constant;
1554    if (con >= 8) {
1555      __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1556           as_FloatRegister($src$$reg));
1557      return;
1558    }
1559    __ sve_lsl(as_FloatRegister($dst$$reg), __ B,
1560         as_FloatRegister($src$$reg), con);
1561  %}
1562  ins_pipe(pipe_slow);
1563%}
1564
1565instruct vlslS_imm(vReg dst, vReg src, immI shift) %{
1566  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1567  match(Set dst (LShiftVS src (LShiftCntV shift)));
1568  ins_cost(SVE_COST);
1569  format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (H)" %}
1570  ins_encode %{
1571    int con = (int)$shift$$constant;
1572    if (con >= 16) {
1573      __ sve_eor(as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg),
1574           as_FloatRegister($src$$reg));
1575      return;
1576    }
1577    __ sve_lsl(as_FloatRegister($dst$$reg), __ H,
1578         as_FloatRegister($src$$reg), con);
1579  %}
1580  ins_pipe(pipe_slow);
1581%}
1582
1583instruct vlslI_imm(vReg dst, vReg src, immI shift) %{
1584  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1585  match(Set dst (LShiftVI src (LShiftCntV shift)));
1586  ins_cost(SVE_COST);
1587  format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (S)" %}
1588  ins_encode %{
1589    int con = (int)$shift$$constant;
1590    __ sve_lsl(as_FloatRegister($dst$$reg), __ S,
1591         as_FloatRegister($src$$reg), con);
1592  %}
1593  ins_pipe(pipe_slow);
1594%}
1595
1596instruct vlslL_imm(vReg dst, vReg src, immI shift) %{
1597  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1598  match(Set dst (LShiftVL src (LShiftCntV shift)));
1599  ins_cost(SVE_COST);
1600  format %{ "sve_lsl $dst, $src, $shift\t# vector (sve) (D)" %}
1601  ins_encode %{
1602    int con = (int)$shift$$constant;
1603    __ sve_lsl(as_FloatRegister($dst$$reg), __ D,
1604         as_FloatRegister($src$$reg), con);
1605  %}
1606  ins_pipe(pipe_slow);
1607%}
1608
1609instruct vshiftcntB(vReg dst, iRegIorL2I cnt) %{
1610  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16 &&
1611            (n->bottom_type()->is_vect()->element_basic_type() == T_BYTE));
1612  match(Set dst (LShiftCntV cnt));
1613  match(Set dst (RShiftCntV cnt));
1614  format %{ "sve_dup $dst, $cnt\t# vector shift count (sve) (B)" %}
1615  ins_encode %{
1616    __ sve_dup(as_FloatRegister($dst$$reg), __ B, as_Register($cnt$$reg));
1617  %}
1618  ins_pipe(pipe_slow);
1619%}
1620
1621instruct vshiftcntS(vReg dst, iRegIorL2I cnt) %{
1622  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8 &&
1623            (n->bottom_type()->is_vect()->element_basic_type() == T_SHORT ||
1624            (n->bottom_type()->is_vect()->element_basic_type() == T_CHAR)));
1625  match(Set dst (LShiftCntV cnt));
1626  match(Set dst (RShiftCntV cnt));
1627  format %{ "sve_dup $dst, $cnt\t# vector shift count (sve) (H)" %}
1628  ins_encode %{
1629    __ sve_dup(as_FloatRegister($dst$$reg), __ H, as_Register($cnt$$reg));
1630  %}
1631  ins_pipe(pipe_slow);
1632%}
1633
1634instruct vshiftcntI(vReg dst, iRegIorL2I cnt) %{
1635  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4 &&
1636            (n->bottom_type()->is_vect()->element_basic_type() == T_INT));
1637  match(Set dst (LShiftCntV cnt));
1638  match(Set dst (RShiftCntV cnt));
1639  format %{ "sve_dup $dst, $cnt\t# vector shift count (sve) (S)" %}
1640  ins_encode %{
1641    __ sve_dup(as_FloatRegister($dst$$reg), __ S, as_Register($cnt$$reg));
1642  %}
1643  ins_pipe(pipe_slow);
1644%}
1645
1646instruct vshiftcntL(vReg dst, iRegIorL2I cnt) %{
1647  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2 &&
1648            (n->bottom_type()->is_vect()->element_basic_type() == T_LONG));
1649  match(Set dst (LShiftCntV cnt));
1650  match(Set dst (RShiftCntV cnt));
1651  format %{ "sve_dup $dst, $cnt\t# vector shift count (sve) (D)" %}
1652  ins_encode %{
1653    __ sve_dup(as_FloatRegister($dst$$reg), __ D, as_Register($cnt$$reg));
1654  %}
1655  ins_pipe(pipe_slow);
1656%}
1657
1658// vector sqrt
1659
1660instruct vsqrtF(vReg dst, vReg src) %{
1661  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
1662  match(Set dst (SqrtVF src));
1663  ins_cost(SVE_COST);
1664  format %{ "sve_fsqrt $dst, $src\t# vector (sve) (S)" %}
1665  ins_encode %{
1666    __ sve_fsqrt(as_FloatRegister($dst$$reg), __ S,
1667         ptrue, as_FloatRegister($src$$reg));
1668  %}
1669  ins_pipe(pipe_slow);
1670%}
1671
1672instruct vsqrtD(vReg dst, vReg src) %{
1673  predicate(UseSVE > 0 && n->as_Vector()->length_in_bytes() >= 16);
1674  match(Set dst (SqrtVD src));
1675  ins_cost(SVE_COST);
1676  format %{ "sve_fsqrt $dst, $src\t# vector (sve) (D)" %}
1677  ins_encode %{
1678    __ sve_fsqrt(as_FloatRegister($dst$$reg), __ D,
1679         ptrue, as_FloatRegister($src$$reg));
1680  %}
1681  ins_pipe(pipe_slow);
1682%}
1683
1684// vector sub
1685
1686instruct vsubB(vReg dst, vReg src1, vReg src2) %{
1687  predicate(UseSVE > 0 && n->as_Vector()->length() >= 16);
1688  match(Set dst (SubVB src1 src2));
1689  ins_cost(SVE_COST);
1690  format %{ "sve_sub $dst, $src1, $src2\t # vector (sve) (B)" %}
1691  ins_encode %{
1692    __ sve_sub(as_FloatRegister($dst$$reg), __ B,
1693         as_FloatRegister($src1$$reg),
1694         as_FloatRegister($src2$$reg));
1695  %}
1696  ins_pipe(pipe_slow);
1697%}
1698
1699instruct vsubS(vReg dst, vReg src1, vReg src2) %{
1700  predicate(UseSVE > 0 && n->as_Vector()->length() >= 8);
1701  match(Set dst (SubVS src1 src2));
1702  ins_cost(SVE_COST);
1703  format %{ "sve_sub $dst, $src1, $src2\t # vector (sve) (H)" %}
1704  ins_encode %{
1705    __ sve_sub(as_FloatRegister($dst$$reg), __ H,
1706         as_FloatRegister($src1$$reg),
1707         as_FloatRegister($src2$$reg));
1708  %}
1709  ins_pipe(pipe_slow);
1710%}
1711
1712instruct vsubI(vReg dst, vReg src1, vReg src2) %{
1713  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1714  match(Set dst (SubVI src1 src2));
1715  ins_cost(SVE_COST);
1716  format %{ "sve_sub $dst, $src1, $src2\t # vector (sve) (S)" %}
1717  ins_encode %{
1718    __ sve_sub(as_FloatRegister($dst$$reg), __ S,
1719         as_FloatRegister($src1$$reg),
1720         as_FloatRegister($src2$$reg));
1721  %}
1722  ins_pipe(pipe_slow);
1723%}
1724
1725instruct vsubL(vReg dst, vReg src1, vReg src2) %{
1726  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1727  match(Set dst (SubVL src1 src2));
1728  ins_cost(SVE_COST);
1729  format %{ "sve_sub $dst, $src1, $src2\t # vector (sve) (D)" %}
1730  ins_encode %{
1731    __ sve_sub(as_FloatRegister($dst$$reg), __ D,
1732         as_FloatRegister($src1$$reg),
1733         as_FloatRegister($src2$$reg));
1734  %}
1735  ins_pipe(pipe_slow);
1736%}
1737
1738instruct vsubF(vReg dst, vReg src1, vReg src2) %{
1739  predicate(UseSVE > 0 && n->as_Vector()->length() >= 4);
1740  match(Set dst (SubVF src1 src2));
1741  ins_cost(SVE_COST);
1742  format %{ "sve_fsub $dst, $src1, $src2\t # vector (sve) (S)" %}
1743  ins_encode %{
1744    __ sve_fsub(as_FloatRegister($dst$$reg), __ S,
1745         as_FloatRegister($src1$$reg),
1746         as_FloatRegister($src2$$reg));
1747  %}
1748  ins_pipe(pipe_slow);
1749%}
1750
1751instruct vsubD(vReg dst, vReg src1, vReg src2) %{
1752  predicate(UseSVE > 0 && n->as_Vector()->length() >= 2);
1753  match(Set dst (SubVD src1 src2));
1754  ins_cost(SVE_COST);
1755  format %{ "sve_fsub $dst, $src1, $src2\t # vector (sve) (D)" %}
1756  ins_encode %{
1757    __ sve_fsub(as_FloatRegister($dst$$reg), __ D,
1758         as_FloatRegister($src1$$reg),
1759         as_FloatRegister($src2$$reg));
1760  %}
1761  ins_pipe(pipe_slow);
1762%}
1763
1764// vector mask cast
1765
1766instruct vmaskcast(vReg dst) %{
1767  predicate(UseSVE > 0 && n->bottom_type()->is_vect()->length() == n->in(1)->bottom_type()->is_vect()->length() &&
1768            n->bottom_type()->is_vect()->length_in_bytes() == n->in(1)->bottom_type()->is_vect()->length_in_bytes());
1769  match(Set dst (VectorMaskCast dst));
1770  ins_cost(0);
1771  format %{ "vmaskcast $dst\t# empty (sve)" %}
1772  ins_encode %{
1773    // empty
1774  %}
1775  ins_pipe(pipe_class_empty);
1776%}
1777
1778