1 ;; Machine description for auto-vectorization using RVV for GNU compiler.
2 ;; Copyright (C) 2023-2025 Free Software Foundation, Inc.
3 ;; Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd.
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; =========================================================================
23 ;; =========================================================================
25 (define_expand "mask_len_load<mode><vm>"
26 [(match_operand:V 0 "register_operand")
27 (match_operand:V 1 "memory_operand")
28 (match_operand:<VM> 2 "vector_mask_operand")
29 (match_operand:V 3 "maskload_else_operand")
30 (match_operand 4 "autovec_length_operand")
31 (match_operand 5 "const_0_operand")]
34 riscv_vector::expand_load_store (operands, true);
38 (define_expand "mask_len_store<mode><vm>"
39 [(match_operand:V 0 "memory_operand")
40 (match_operand:V 1 "register_operand")
41 (match_operand:<VM> 2 "vector_mask_operand")
42 (match_operand 3 "autovec_length_operand")
43 (match_operand 4 "const_0_operand")]
46 riscv_vector::expand_load_store (operands, false);
50 ;; =========================================================================
52 ;; =========================================================================
54 (define_expand "mask_len_gather_load<RATIO64:mode><RATIO64I:mode>"
55 [(match_operand:RATIO64 0 "register_operand")
56 (match_operand 1 "pmode_reg_or_0_operand")
57 (match_operand:RATIO64I 2 "register_operand")
58 (match_operand 3 "<RATIO64:gs_extension>")
59 (match_operand 4 "<RATIO64:gs_scale>")
60 (match_operand:<RATIO64:VM> 5 "vector_mask_operand")
61 (match_operand 6 "maskload_else_operand")
62 (match_operand 7 "autovec_length_operand")
63 (match_operand 8 "const_0_operand")]
64 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO64I:MODE>mode)"
66 riscv_vector::expand_gather_scatter (operands, true);
70 (define_expand "mask_len_gather_load<RATIO32:mode><RATIO32I:mode>"
71 [(match_operand:RATIO32 0 "register_operand")
72 (match_operand 1 "pmode_reg_or_0_operand")
73 (match_operand:RATIO32I 2 "register_operand")
74 (match_operand 3 "<RATIO32:gs_extension>")
75 (match_operand 4 "<RATIO32:gs_scale>")
76 (match_operand:<RATIO32:VM> 5 "vector_mask_operand")
77 (match_operand 6 "maskload_else_operand")
78 (match_operand 7 "autovec_length_operand")
79 (match_operand 8 "const_0_operand")]
80 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO32I:MODE>mode)"
82 riscv_vector::expand_gather_scatter (operands, true);
86 (define_expand "mask_len_gather_load<RATIO16:mode><RATIO16I:mode>"
87 [(match_operand:RATIO16 0 "register_operand")
88 (match_operand 1 "pmode_reg_or_0_operand")
89 (match_operand:RATIO16I 2 "register_operand")
90 (match_operand 3 "<RATIO16:gs_extension>")
91 (match_operand 4 "<RATIO16:gs_scale>")
92 (match_operand:<RATIO16:VM> 5 "vector_mask_operand")
93 (match_operand 6 "maskload_else_operand")
94 (match_operand 7 "autovec_length_operand")
95 (match_operand 8 "const_0_operand")]
96 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO16I:MODE>mode)"
98 riscv_vector::expand_gather_scatter (operands, true);
102 (define_expand "mask_len_gather_load<RATIO8:mode><RATIO8I:mode>"
103 [(match_operand:RATIO8 0 "register_operand")
104 (match_operand 1 "pmode_reg_or_0_operand")
105 (match_operand:RATIO8I 2 "register_operand")
106 (match_operand 3 "<RATIO8:gs_extension>")
107 (match_operand 4 "<RATIO8:gs_scale>")
108 (match_operand:<RATIO8:VM> 5 "vector_mask_operand")
109 (match_operand 6 "maskload_else_operand")
110 (match_operand 7 "autovec_length_operand")
111 (match_operand 8 "const_0_operand")]
112 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO8I:MODE>mode)"
114 riscv_vector::expand_gather_scatter (operands, true);
118 (define_expand "mask_len_gather_load<RATIO4:mode><RATIO4I:mode>"
119 [(match_operand:RATIO4 0 "register_operand")
120 (match_operand 1 "pmode_reg_or_0_operand")
121 (match_operand:RATIO4I 2 "register_operand")
122 (match_operand 3 "<RATIO4:gs_extension>")
123 (match_operand 4 "<RATIO4:gs_scale>")
124 (match_operand:<RATIO4:VM> 5 "vector_mask_operand")
125 (match_operand 6 "maskload_else_operand")
126 (match_operand 7 "autovec_length_operand")
127 (match_operand 8 "const_0_operand")]
128 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO4I:MODE>mode)"
130 riscv_vector::expand_gather_scatter (operands, true);
134 (define_expand "mask_len_gather_load<RATIO2:mode><RATIO2I:mode>"
135 [(match_operand:RATIO2 0 "register_operand")
136 (match_operand 1 "pmode_reg_or_0_operand")
137 (match_operand:RATIO2I 2 "register_operand")
138 (match_operand 3 "<RATIO2:gs_extension>")
139 (match_operand 4 "<RATIO2:gs_scale>")
140 (match_operand:<RATIO2:VM> 5 "vector_mask_operand")
141 (match_operand 6 "maskload_else_operand")
142 (match_operand 7 "autovec_length_operand")
143 (match_operand 8 "const_0_operand")]
144 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO2I:MODE>mode)"
146 riscv_vector::expand_gather_scatter (operands, true);
150 ;; When SEW = 8 and LMUL = 8, we can't find any index mode with
151 ;; larger SEW. Since RVV indexed load/store support zero extend
152 ;; implicitly and not support scaling, we should only allow
153 ;; operands[3] and operands[4] to be const_1_operand.
154 (define_expand "mask_len_gather_load<mode><mode>"
155 [(match_operand:RATIO1 0 "register_operand")
156 (match_operand 1 "pmode_reg_or_0_operand")
157 (match_operand:RATIO1 2 "register_operand")
158 (match_operand 3 "<gs_extension>")
159 (match_operand 4 "<gs_scale>")
160 (match_operand:<VM> 5 "vector_mask_operand")
161 (match_operand 6 "maskload_else_operand")
162 (match_operand 7 "autovec_length_operand")
163 (match_operand 8 "const_0_operand")]
166 riscv_vector::expand_gather_scatter (operands, true);
170 ;; =========================================================================
172 ;; =========================================================================
174 (define_expand "mask_len_scatter_store<RATIO64:mode><RATIO64I:mode>"
175 [(match_operand 0 "pmode_reg_or_0_operand")
176 (match_operand:RATIO64I 1 "register_operand")
177 (match_operand 2 "<RATIO64:gs_extension>")
178 (match_operand 3 "<RATIO64:gs_scale>")
179 (match_operand:RATIO64 4 "register_operand")
180 (match_operand:<RATIO64:VM> 5 "vector_mask_operand")
181 (match_operand 6 "autovec_length_operand")
182 (match_operand 7 "const_0_operand")]
183 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO64I:MODE>mode)"
185 riscv_vector::expand_gather_scatter (operands, false);
189 (define_expand "mask_len_scatter_store<RATIO32:mode><RATIO32I:mode>"
190 [(match_operand 0 "pmode_reg_or_0_operand")
191 (match_operand:RATIO32I 1 "register_operand")
192 (match_operand 2 "<RATIO32:gs_extension>")
193 (match_operand 3 "<RATIO32:gs_scale>")
194 (match_operand:RATIO32 4 "register_operand")
195 (match_operand:<RATIO32:VM> 5 "vector_mask_operand")
196 (match_operand 6 "autovec_length_operand")
197 (match_operand 7 "const_0_operand")]
198 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO32I:MODE>mode)"
200 riscv_vector::expand_gather_scatter (operands, false);
204 (define_expand "mask_len_scatter_store<RATIO16:mode><RATIO16I:mode>"
205 [(match_operand 0 "pmode_reg_or_0_operand")
206 (match_operand:RATIO16I 1 "register_operand")
207 (match_operand 2 "<RATIO16:gs_extension>")
208 (match_operand 3 "<RATIO16:gs_scale>")
209 (match_operand:RATIO16 4 "register_operand")
210 (match_operand:<RATIO16:VM> 5 "vector_mask_operand")
211 (match_operand 6 "autovec_length_operand")
212 (match_operand 7 "const_0_operand")]
213 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO16I:MODE>mode)"
215 riscv_vector::expand_gather_scatter (operands, false);
219 (define_expand "mask_len_scatter_store<RATIO8:mode><RATIO8I:mode>"
220 [(match_operand 0 "pmode_reg_or_0_operand")
221 (match_operand:RATIO8I 1 "register_operand")
222 (match_operand 2 "<RATIO8:gs_extension>")
223 (match_operand 3 "<RATIO8:gs_scale>")
224 (match_operand:RATIO8 4 "register_operand")
225 (match_operand:<RATIO8:VM> 5 "vector_mask_operand")
226 (match_operand 6 "autovec_length_operand")
227 (match_operand 7 "const_0_operand")]
228 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO8I:MODE>mode)"
230 riscv_vector::expand_gather_scatter (operands, false);
234 (define_expand "mask_len_scatter_store<RATIO4:mode><RATIO4I:mode>"
235 [(match_operand 0 "pmode_reg_or_0_operand")
236 (match_operand:RATIO4I 1 "register_operand")
237 (match_operand 2 "<RATIO4:gs_extension>")
238 (match_operand 3 "<RATIO4:gs_scale>")
239 (match_operand:RATIO4 4 "register_operand")
240 (match_operand:<RATIO4:VM> 5 "vector_mask_operand")
241 (match_operand 6 "autovec_length_operand")
242 (match_operand 7 "const_0_operand")]
243 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO4I:MODE>mode)"
245 riscv_vector::expand_gather_scatter (operands, false);
249 (define_expand "mask_len_scatter_store<RATIO2:mode><RATIO2I:mode>"
250 [(match_operand 0 "pmode_reg_or_0_operand")
251 (match_operand:RATIO2I 1 "register_operand")
252 (match_operand 2 "<RATIO2:gs_extension>")
253 (match_operand 3 "<RATIO2:gs_scale>")
254 (match_operand:RATIO2 4 "register_operand")
255 (match_operand:<RATIO2:VM> 5 "vector_mask_operand")
256 (match_operand 6 "autovec_length_operand")
257 (match_operand 7 "const_0_operand")]
258 "TARGET_VECTOR && riscv_vector::gather_scatter_valid_offset_p (<RATIO2I:MODE>mode)"
260 riscv_vector::expand_gather_scatter (operands, false);
264 ;; When SEW = 8 and LMUL = 8, we can't find any index mode with
265 ;; larger SEW. Since RVV indexed load/store support zero extend
266 ;; implicitly and not support scaling, we should only allow
267 ;; operands[3] and operands[4] to be const_1_operand.
268 (define_expand "mask_len_scatter_store<mode><mode>"
269 [(match_operand 0 "pmode_reg_or_0_operand")
270 (match_operand:RATIO1 1 "register_operand")
271 (match_operand 2 "<gs_extension>")
272 (match_operand 3 "<gs_scale>")
273 (match_operand:RATIO1 4 "register_operand")
274 (match_operand:<VM> 5 "vector_mask_operand")
275 (match_operand 6 "autovec_length_operand")
276 (match_operand 7 "const_0_operand")]
279 riscv_vector::expand_gather_scatter (operands, false);
283 ;; =========================================================================
284 ;; == Array Load/Store
285 ;; =========================================================================
287 (define_expand "vec_mask_len_load_lanes<mode><vsingle>"
288 [(match_operand:VT 0 "register_operand")
289 (match_operand:VT 1 "memory_operand")
290 (match_operand:<VM> 2 "vector_mask_operand")
291 (match_operand 3 "maskload_else_operand")
292 (match_operand 4 "autovec_length_operand")
293 (match_operand 5 "const_0_operand")]
294 "TARGET_VECTOR_AUTOVEC_SEGMENT"
296 riscv_vector::expand_lanes_load_store (operands, true);
301 (define_expand "vec_mask_len_store_lanes<mode><vsingle>"
302 [(match_operand:VT 0 "memory_operand")
303 (match_operand:VT 1 "register_operand")
304 (match_operand:<VM> 2 "vector_mask_operand")
305 (match_operand 3 "autovec_length_operand")
306 (match_operand 4 "const_0_operand")]
307 "TARGET_VECTOR_AUTOVEC_SEGMENT"
309 riscv_vector::expand_lanes_load_store (operands, false);
314 ;; =========================================================================
315 ;; == Vector creation
316 ;; =========================================================================
318 ;; -------------------------------------------------------------------------
319 ;; ---- [BOOL] Duplicate element
320 ;; -------------------------------------------------------------------------
321 ;; The patterns in this section are synthetic.
322 ;; -------------------------------------------------------------------------
324 ;; Implement a predicate broadcast by shifting the low bit of the scalar
325 ;; input into the top bit by duplicate the input and do a compare with zero.
326 (define_expand "vec_duplicate<mode>"
327 [(set (match_operand:VB 0 "register_operand")
328 (vec_duplicate:VB (match_operand:QI 1 "register_operand")))]
331 poly_int64 nunits = GET_MODE_NUNITS (<MODE>mode);
332 machine_mode mode = riscv_vector::get_vector_mode (QImode, nunits).require ();
333 rtx dup = expand_vector_broadcast (mode, operands[1]);
334 riscv_vector::expand_vec_cmp (operands[0], NE, dup, CONST0_RTX (mode));
339 ;; -------------------------------------------------------------------------
340 ;; ---- [INT] Linear series
341 ;; -------------------------------------------------------------------------
346 ;; -------------------------------------------------------------------------
348 (define_expand "vec_series<mode>"
349 [(match_operand:V_VLSI 0 "register_operand")
350 (match_operand:<VEL> 1 "reg_or_int_operand")
351 (match_operand:<VEL> 2 "reg_or_int_operand")]
354 riscv_vector::expand_vec_series (operands[0], operands[1], operands[2]);
359 ;; -------------------------------------------------------------------------
360 ;; ---- [INT,FP] permutation
361 ;; -------------------------------------------------------------------------
362 ;; This is the pattern permutes the vector
363 ;; -------------------------------------------------------------------------
365 (define_expand "vec_perm<mode>"
366 [(match_operand:V_VLS 0 "register_operand")
367 (match_operand:V_VLS 1 "register_operand")
368 (match_operand:V_VLS 2 "register_operand")
369 (match_operand:<VINDEX> 3 "vector_perm_operand")]
370 "TARGET_VECTOR && GET_MODE_NUNITS (<MODE>mode).is_constant ()"
372 riscv_vector::expand_vec_perm (operands[0], operands[1],
373 operands[2], operands[3]);
378 ;; -------------------------------------------------------------------------
379 ;; ---- [INT,FP] Initialize from individual elements
380 ;; -------------------------------------------------------------------------
381 ;; This is the pattern initialize the vector
382 ;; -------------------------------------------------------------------------
384 (define_expand "vec_init<mode><vel>"
385 [(match_operand:V_VLSI 0 "register_operand")
386 (match_operand 1 "")]
389 riscv_vector::expand_vec_init (operands[0], operands[1]);
394 ;; We split RVV floating-point because we are going to
395 ;; use vfslide1down/vfslide1up for FP16 which need TARGET_ZVFH.
396 (define_expand "vec_init<mode><vel>"
397 [(match_operand:V_VLSF 0 "register_operand")
398 (match_operand 1 "")]
401 riscv_vector::expand_vec_init (operands[0], operands[1]);
406 ;; Provide a vec_init for mask registers by initializing
407 ;; a QImode vector and comparing it against 0.
408 (define_expand "vec_init<mode>qi"
409 [(match_operand:VB 0 "register_operand")
410 (match_operand 1 "")]
413 machine_mode qimode = riscv_vector::get_vector_mode
414 (QImode, GET_MODE_NUNITS (<MODE>mode)).require ();
415 rtx tmp = gen_reg_rtx (qimode);
416 riscv_vector::expand_vec_init (tmp, operands[1]);
417 riscv_vector::expand_vec_cmp (operands[0], NE, tmp, CONST0_RTX (qimode));
422 ;; Slide an RVV vector left and insert a scalar into element 0.
423 (define_expand "vec_shl_insert_<mode>"
424 [(match_operand:VI 0 "register_operand")
425 (match_operand:VI 1 "register_operand")
426 (match_operand:<VEL> 2 "reg_or_0_operand")]
429 insn_code icode = code_for_pred_slide (UNSPEC_VSLIDE1UP, <MODE>mode);
430 rtx ops[] = {operands[0], operands[1], operands[2]};
431 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
435 (define_expand "vec_shl_insert_<mode>"
436 [(match_operand:VF 0 "register_operand")
437 (match_operand:VF 1 "register_operand")
438 (match_operand:<VEL> 2 "register_operand")]
441 insn_code icode = code_for_pred_slide (UNSPEC_VFSLIDE1UP, <MODE>mode);
442 rtx ops[] = {operands[0], operands[1], operands[2]};
443 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
447 ;; ========================================================================
448 ;; == Vector operations
449 ;; =========================================================================
451 ;; -------------------------------------------------------------------------
452 ;; ---- [INT] Binary operations
453 ;; -------------------------------------------------------------------------
455 ;; - vadd.vv/vsub.vv/...
456 ;; - vadd.vi/vsub.vi/...
457 ;; -------------------------------------------------------------------------
459 (define_insn_and_split "<optab><mode>3"
460 [(set (match_operand:V_VLSI 0 "register_operand")
461 (any_int_binop_no_shift:V_VLSI
462 (match_operand:V_VLSI 1 "<binop_rhs1_predicate>")
463 (match_operand:V_VLSI 2 "<binop_rhs2_predicate>")))]
464 "TARGET_VECTOR && can_create_pseudo_p ()"
469 riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
470 riscv_vector::BINARY_OP, operands);
473 [(set_attr "type" "vialu")])
475 ;; -------------------------------------------------------------------------
476 ;; ---- [INT] Binary shifts by scalar.
477 ;; -------------------------------------------------------------------------
479 ;; - vsll.vx/vsra.vx/vsrl.vx
480 ;; - vsll.vi/vsra.vi/vsrl.vi
481 ;; -------------------------------------------------------------------------
483 (define_insn_and_split "<optab><mode>3"
484 [(set (match_operand:V_VLSI 0 "register_operand" "=vr")
486 (match_operand:V_VLSI 1 "register_operand" " vr")
487 (match_operand:<VEL> 2 "vector_scalar_shift_operand" " rK")))]
488 "TARGET_VECTOR && can_create_pseudo_p ()"
493 operands[2] = gen_lowpart (Pmode, operands[2]);
494 riscv_vector::emit_vlmax_insn (code_for_pred_scalar (<CODE>, <MODE>mode),
495 riscv_vector::BINARY_OP, operands);
498 [(set_attr "type" "vshift")
499 (set_attr "mode" "<MODE>")])
501 ;; -------------------------------------------------------------------------
502 ;; ---- [INT] Binary shifts by vector.
503 ;; -------------------------------------------------------------------------
505 ;; - vsll.vv/vsra.vv/vsrl.vv
506 ;; -------------------------------------------------------------------------
508 (define_insn_and_split "v<optab><mode>3"
509 [(set (match_operand:V_VLSI 0 "register_operand" "=vr,vr")
511 (match_operand:V_VLSI 1 "register_operand" " vr,vr")
512 (match_operand:V_VLSI 2 "vector_shift_operand" " vr,vk")))]
513 "TARGET_VECTOR && can_create_pseudo_p ()"
518 riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
519 riscv_vector::BINARY_OP, operands);
522 [(set_attr "type" "vshift")
523 (set_attr "mode" "<MODE>")])
525 ;; -------------------------------------------------------------------------
526 ;; ---- [BOOL] Binary logical operations
527 ;; -------------------------------------------------------------------------
532 ;; -------------------------------------------------------------------------
534 (define_insn_and_split "<optab><mode>3"
535 [(set (match_operand:VB_VLS 0 "register_operand" "=vr")
536 (any_bitwise:VB_VLS (match_operand:VB_VLS 1 "register_operand" " vr")
537 (match_operand:VB_VLS 2 "register_operand" " vr")))]
538 "TARGET_VECTOR && can_create_pseudo_p ()"
543 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
544 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
547 [(set_attr "type" "vmalu")
548 (set_attr "mode" "<MODE>")])
550 ;; -------------------------------------------------------------------------
551 ;; ---- [BOOL] Inverse
552 ;; -------------------------------------------------------------------------
555 ;; -------------------------------------------------------------------------
557 (define_insn_and_split "one_cmpl<mode>2"
558 [(set (match_operand:VB_VLS 0 "register_operand" "=vr")
559 (not:VB_VLS (match_operand:VB_VLS 1 "register_operand" " vr")))]
560 "TARGET_VECTOR && can_create_pseudo_p ()"
565 insn_code icode = code_for_pred_not (<MODE>mode);
566 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_MASK_OP, operands);
569 [(set_attr "type" "vmalu")
570 (set_attr "mode" "<MODE>")])
572 ;; =========================================================================
573 ;; == Comparisons and selects
574 ;; =========================================================================
576 ;; -------------------------------------------------------------------------
577 ;; ---- [INT,FP] Select based on masks
578 ;; -------------------------------------------------------------------------
579 ;; Includes merging patterns for:
583 ;; -------------------------------------------------------------------------
585 (define_insn_and_split "vcond_mask_<mode><vm>"
586 [(set (match_operand:V_VLS 0 "register_operand")
588 (match_operand:<VM> 3 "register_operand")
589 (match_operand:V_VLS 1 "nonmemory_operand")
590 (match_operand:V_VLS 2 "register_operand")))]
591 "TARGET_VECTOR && can_create_pseudo_p ()"
596 /* The order of vcond_mask is opposite to pred_merge. */
597 std::swap (operands[1], operands[2]);
598 riscv_vector::emit_vlmax_insn (code_for_pred_merge (<MODE>mode),
599 riscv_vector::MERGE_OP, operands);
602 [(set_attr "type" "vector")]
605 (define_expand "vcond_mask_len_<mode>"
606 [(match_operand:V 0 "register_operand")
607 (match_operand:<VM> 1 "nonmemory_operand")
608 (match_operand:V 2 "nonmemory_operand")
609 (match_operand:V 3 "autovec_else_operand")
610 (match_operand 4 "autovec_length_operand")
611 (match_operand 5 "const_0_operand")]
614 if (satisfies_constraint_Wc1 (operands[1]))
615 riscv_vector::expand_cond_len_unop (code_for_pred_mov (<MODE>mode),
619 /* The order of then and else is opposite to pred_merge. */
620 rtx ops[] = {operands[0], operands[3], operands[3], operands[2],
622 riscv_vector::emit_nonvlmax_insn (code_for_pred_merge (<MODE>mode),
623 riscv_vector::MERGE_OP_TU,
628 [(set_attr "type" "vector")]
631 ;; -------------------------------------------------------------------------
632 ;; ---- [BOOL] Select based on masks
633 ;; -------------------------------------------------------------------------
634 ;; Includes merging patterns for:
638 ;; -------------------------------------------------------------------------
640 (define_expand "vcond_mask_<mode><mode>"
641 [(match_operand:VB_VLS 0 "register_operand")
642 (match_operand:VB_VLS 1 "register_operand")
643 (match_operand:VB_VLS 2 "register_operand")
644 (match_operand:VB_VLS 3 "register_operand")]
647 /* mask1 = operands[3] & operands[1]. */
648 rtx mask1 = expand_binop (<MODE>mode, and_optab, operands[1],
649 operands[3], NULL_RTX, 0,
651 /* mask2 = ~operands[3] & operands[2]. */
652 rtx inverse = expand_unop (<MODE>mode, one_cmpl_optab, operands[3],
654 rtx mask2 = expand_binop (<MODE>mode, and_optab, operands[2],
655 inverse, NULL_RTX, 0,
657 /* result = mask1 | mask2. */
658 rtx result = expand_binop (<MODE>mode, ior_optab, mask1,
661 emit_move_insn (operands[0], result);
665 ;; -------------------------------------------------------------------------
666 ;; ---- [INT,FP] Comparisons
667 ;; -------------------------------------------------------------------------
669 ;; - vms<eq/ne/ltu/lt/leu/le/gtu/gt>.<vv/vx/vi>
670 ;; -------------------------------------------------------------------------
672 (define_expand "vec_cmp<mode><vm>"
673 [(set (match_operand:<VM> 0 "register_operand")
674 (match_operator:<VM> 1 "comparison_operator"
675 [(match_operand:V_VLSI 2 "register_operand")
676 (match_operand:V_VLSI 3 "nonmemory_operand")]))]
679 riscv_vector::expand_vec_cmp (operands[0], GET_CODE (operands[1]),
680 operands[2], operands[3]);
685 (define_expand "vec_cmpu<mode><vm>"
686 [(set (match_operand:<VM> 0 "register_operand")
687 (match_operator:<VM> 1 "comparison_operator"
688 [(match_operand:V_VLSI 2 "register_operand")
689 (match_operand:V_VLSI 3 "nonmemory_operand")]))]
692 riscv_vector::expand_vec_cmp (operands[0], GET_CODE (operands[1]),
693 operands[2], operands[3]);
698 (define_expand "vec_cmp<mode><vm>"
699 [(set (match_operand:<VM> 0 "register_operand")
700 (match_operator:<VM> 1 "comparison_operator"
701 [(match_operand:V_VLSF 2 "register_operand")
702 (match_operand:V_VLSF 3 "register_operand")]))]
705 riscv_vector::expand_vec_cmp_float (operands[0], GET_CODE (operands[1]),
706 operands[2], operands[3], false);
711 ;; -------------------------------------------------------------------------
712 ;; ---- [INT] Sign and zero extension
713 ;; -------------------------------------------------------------------------
717 ;; -------------------------------------------------------------------------
719 ;; Use define_insn_and_split to define vsext.vf2/vzext.vf2 will help
720 ;; to combine instructions as below:
721 ;; vsext.vf2 + vsext.vf2 + vadd.vv ==> vwadd.vv
722 (define_insn_and_split "<optab><v_double_trunc><mode>2"
723 [(set (match_operand:VWEXTI 0 "register_operand" "=&vr")
725 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand" "vr")))]
726 "TARGET_VECTOR && can_create_pseudo_p ()"
731 insn_code icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
732 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
735 [(set_attr "type" "vext")
736 (set_attr "mode" "<MODE>")])
738 (define_insn_and_split "<optab><v_quad_trunc><mode>2"
739 [(set (match_operand:VQEXTI 0 "register_operand")
741 (match_operand:<V_QUAD_TRUNC> 1 "register_operand")))]
742 "TARGET_VECTOR && can_create_pseudo_p ()"
747 insn_code icode = code_for_pred_vf4 (<CODE>, <MODE>mode);
748 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
751 [(set_attr "type" "vext")])
753 (define_insn_and_split "<optab><v_oct_trunc><mode>2"
754 [(set (match_operand:VOEXTI 0 "register_operand")
756 (match_operand:<V_OCT_TRUNC> 1 "register_operand")))]
757 "TARGET_VECTOR && can_create_pseudo_p ()"
762 insn_code icode = code_for_pred_vf8 (<CODE>, <MODE>mode);
763 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
766 [(set_attr "type" "vext")])
768 ;; -------------------------------------------------------------------------
769 ;; ---- [INT] Truncation
770 ;; -------------------------------------------------------------------------
772 ;; -------------------------------------------------------------------------
773 (define_insn_and_split "trunc<mode><v_double_trunc>2"
774 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr")
775 (truncate:<V_DOUBLE_TRUNC>
776 (match_operand:VWEXTI 1 "register_operand" " vr")))]
777 "TARGET_VECTOR && can_create_pseudo_p ()"
782 insn_code icode = code_for_pred_trunc (<MODE>mode);
783 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
786 [(set_attr "type" "vshift")
787 (set_attr "mode" "<MODE>")])
789 ;; -------------------------------------------------------------------------
790 ;; Truncation to a mode whose inner mode size is a quarter of mode's.
791 ;; We emulate this with two consecutive vncvts.
792 ;; -------------------------------------------------------------------------
793 (define_expand "trunc<mode><v_quad_trunc>2"
794 [(set (match_operand:<V_QUAD_TRUNC> 0 "register_operand")
795 (truncate:<V_QUAD_TRUNC>
796 (match_operand:VQEXTI 1 "register_operand")))]
799 rtx half = gen_reg_rtx (<V_DOUBLE_TRUNC>mode);
800 emit_insn (gen_trunc<mode><v_double_trunc>2 (half, operands[1]));
801 emit_insn (gen_trunc<v_double_trunc><v_quad_trunc>2 (operands[0], half));
805 ;; -------------------------------------------------------------------------
806 ;; Truncation to a mode whose inner mode size is an eighth of mode's.
807 ;; We emulate this with three consecutive vncvts.
808 ;; -------------------------------------------------------------------------
809 (define_expand "trunc<mode><v_oct_trunc>2"
810 [(set (match_operand:<V_OCT_TRUNC> 0 "register_operand")
811 (truncate:<V_OCT_TRUNC>
812 (match_operand:VOEXTI 1 "register_operand")))]
815 rtx quarter = gen_reg_rtx (<V_QUAD_TRUNC>mode);
816 emit_insn (gen_trunc<mode><v_quad_trunc>2 (quarter, operands[1]));
817 emit_insn (gen_trunc<v_quad_trunc><v_oct_trunc>2 (operands[0], quarter));
821 ;; -------------------------------------------------------------------------
822 ;; ---- [FP] Widening.
823 ;; -------------------------------------------------------------------------
825 ;; -------------------------------------------------------------------------
826 (define_insn_and_split "extend<v_double_trunc><mode>2"
827 [(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand" "=&vr")
828 (float_extend:VWEXTF_ZVFHMIN
829 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand" " vr")))]
830 "TARGET_VECTOR && can_create_pseudo_p ()"
835 insn_code icode = code_for_pred_extend (<MODE>mode);
836 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
839 [(set_attr "type" "vfwcvtftof")
840 (set_attr "mode" "<MODE>")])
842 (define_expand "extend<v_quad_trunc><mode>2"
843 [(set (match_operand:VQEXTF 0 "register_operand")
845 (match_operand:<V_QUAD_TRUNC> 1 "register_operand")))]
846 "TARGET_VECTOR && (TARGET_ZVFHMIN || TARGET_ZVFH)"
848 rtx dblw = gen_reg_rtx (<V_DOUBLE_TRUNC>mode);
849 emit_insn (gen_extend<v_quad_trunc><v_double_trunc>2 (dblw, operands[1]));
850 emit_insn (gen_extend<v_double_trunc><mode>2 (operands[0], dblw));
854 ;; -------------------------------------------------------------------------
855 ;; ---- [FP] Narrowing.
856 ;; -------------------------------------------------------------------------
858 ;; -------------------------------------------------------------------------
859 (define_insn_and_split "trunc<mode><v_double_trunc>2"
860 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr")
861 (float_truncate:<V_DOUBLE_TRUNC>
862 (match_operand:VWEXTF_ZVFHMIN 1 "register_operand" " vr")))]
863 "TARGET_VECTOR && can_create_pseudo_p ()"
868 insn_code icode = code_for_pred_trunc (<MODE>mode);
869 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
872 [(set_attr "type" "vfncvtftof")
873 (set_attr "mode" "<MODE>")])
875 ;; -------------------------------------------------------------------------
876 ;; Narrowing to a mode whose inner mode size is a quarter of mode's.
877 ;; We emulate this with two consecutive vfncvts.
878 ;; -------------------------------------------------------------------------
879 (define_expand "trunc<mode><v_quad_trunc>2"
880 [(set (match_operand:<V_QUAD_TRUNC> 0 "register_operand")
881 (float_truncate:<V_QUAD_TRUNC>
882 (match_operand:VQEXTF 1 "register_operand")))]
883 "TARGET_VECTOR && (TARGET_ZVFHMIN || TARGET_ZVFH)"
885 rtx half = gen_reg_rtx (<V_DOUBLE_TRUNC>mode);
886 rtx opshalf[] = {half, operands[1]};
888 /* According to the RISC-V V Spec 13.19. we need to use
889 vfncvt.rod.f.f.w for all steps but the last. */
890 insn_code icode = code_for_pred_rod_trunc (<MODE>mode);
891 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, opshalf);
893 emit_insn (gen_trunc<v_double_trunc><v_quad_trunc>2 (operands[0], half));
898 ;; =========================================================================
900 ;; =========================================================================
902 ;; -------------------------------------------------------------------------
903 ;; ---- [INT<-FP] Conversions
904 ;; -------------------------------------------------------------------------
906 ;; - vfcvt.rtz.xu.f.v
908 ;; -------------------------------------------------------------------------
910 (define_insn_and_split "<optab><mode><vconvert>2"
911 [(set (match_operand:<VCONVERT> 0 "register_operand")
913 (match_operand:V_VLSF 1 "register_operand")))]
914 "TARGET_VECTOR && can_create_pseudo_p ()"
919 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
920 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
923 [(set_attr "type" "vfcvtftoi")])
925 ;; -------------------------------------------------------------------------
926 ;; ---- [FP<-INT] Conversions
927 ;; -------------------------------------------------------------------------
931 ;; -------------------------------------------------------------------------
933 (define_insn_and_split "<float_cvt><vconvert><mode>2"
934 [(set (match_operand:V_VLSF 0 "register_operand")
936 (match_operand:<VCONVERT> 1 "register_operand")))]
937 "TARGET_VECTOR && can_create_pseudo_p ()"
942 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
943 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
946 [(set_attr "type" "vfcvtitof")])
948 ;; =========================================================================
949 ;; == Widening/narrowing Conversions
950 ;; =========================================================================
952 ;; -------------------------------------------------------------------------
953 ;; ---- [INT<-FP] Widening Conversions
954 ;; -------------------------------------------------------------------------
956 ;; - vfwcvt.rtz.xu.f.v
957 ;; - vfwcvt.rtz.x.f.v
958 ;; -------------------------------------------------------------------------
959 (define_insn_and_split "<optab><vnconvert><mode>2"
960 [(set (match_operand:VWCONVERTI 0 "register_operand")
962 (match_operand:<VNCONVERT> 1 "register_operand")))]
963 "TARGET_VECTOR && can_create_pseudo_p ()"
968 insn_code icode = code_for_pred_widen (<CODE>, <MODE>mode);
969 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
972 [(set_attr "type" "vfwcvtftoi")])
974 ;; -------------------------------------------------------------------------
975 ;; ---- [FP<-INT] Widening Conversions
976 ;; -------------------------------------------------------------------------
980 ;; -------------------------------------------------------------------------
981 (define_insn_and_split "<float_cvt><vnconvert><mode>2"
982 [(set (match_operand:V_VLSF 0 "register_operand")
984 (match_operand:<VNCONVERT> 1 "register_operand")))]
985 "TARGET_VECTOR && can_create_pseudo_p ()"
990 insn_code icode = code_for_pred_widen (<CODE>, <MODE>mode);
991 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
994 [(set_attr "type" "vfwcvtitof")])
996 ;; -------------------------------------------------------------------------
997 ;; ---- [INT<-FP] Narrowing Conversions
998 ;; -------------------------------------------------------------------------
1000 ;; - vfncvt.rtz.xu.f.v
1001 ;; - vfncvt.rtz.x.f.v
1002 ;; -------------------------------------------------------------------------
1003 (define_insn_and_split "<optab><mode><vnconvert>2"
1004 [(set (match_operand:<VNCONVERT> 0 "register_operand")
1005 (any_fix:<VNCONVERT>
1006 (match_operand:V_VLSF 1 "register_operand")))]
1007 "TARGET_VECTOR && can_create_pseudo_p ()"
1012 insn_code icode = code_for_pred_narrow (<CODE>, <MODE>mode);
1013 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
1016 [(set_attr "type" "vfncvtftoi")])
1018 ;; -------------------------------------------------------------------------
1019 ;; ---- [FP<-INT] Narrowing Conversions
1020 ;; -------------------------------------------------------------------------
1024 ;; -------------------------------------------------------------------------
1025 (define_insn_and_split "<float_cvt><mode><vnconvert>2"
1026 [(set (match_operand:<VNCONVERT> 0 "register_operand")
1027 (any_float:<VNCONVERT>
1028 (match_operand:VWCONVERTI 1 "register_operand")))]
1029 "TARGET_VECTOR && can_create_pseudo_p ()"
1034 insn_code icode = code_for_pred_narrow (<CODE>, <MODE>mode);
1035 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
1038 [(set_attr "type" "vfncvtitof")])
1040 ;; This operation can be performed in the loop vectorizer but unfortunately
1041 ;; not applicable for now. We can remove this pattern after loop vectorizer
1042 ;; is able to take care of INT64 to FP16 conversion.
1043 (define_expand "<float_cvt><mode><vnnconvert>2"
1044 [(set (match_operand:<VNNCONVERT> 0 "register_operand")
1045 (any_float:<VNNCONVERT>
1046 (match_operand:VWWCONVERTI 1 "register_operand")))]
1047 "TARGET_VECTOR && TARGET_ZVFH && can_create_pseudo_p () && !flag_trapping_math"
1049 rtx single = gen_reg_rtx (<VNCONVERT>mode); /* Get vector SF mode. */
1051 /* Step-1, INT64 => FP32. */
1052 emit_insn (gen_<float_cvt><mode><vnconvert>2 (single, operands[1]));
1053 /* Step-2, FP32 => FP16. */
1054 emit_insn (gen_trunc<vnconvert><vnnconvert>2 (operands[0], single));
1059 ;; =========================================================================
1060 ;; == Unary arithmetic
1061 ;; =========================================================================
1063 ;; -------------------------------------------------------------------------------
1064 ;; ---- [INT] Unary operations
1065 ;; -------------------------------------------------------------------------------
1068 ;; -------------------------------------------------------------------------------
1069 (define_insn_and_split "<optab><mode>2"
1070 [(set (match_operand:V_VLSI 0 "register_operand")
1071 (any_int_unop:V_VLSI
1072 (match_operand:V_VLSI 1 "register_operand")))]
1073 "TARGET_VECTOR && can_create_pseudo_p ()"
1078 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1079 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
1082 [(set_attr "type" "vialu")])
1084 ;; -------------------------------------------------------------------------------
1085 ;; - [INT] ABS expansion to vneg and vmax.
1086 ;; -------------------------------------------------------------------------------
1088 (define_expand "abs<mode>2"
1089 [(set (match_operand:V_VLSI 0 "register_operand")
1093 (match_operand:V_VLSI 1 "register_operand"))))]
1099 ;; -------------------------------------------------------------------------------
1100 ;; ---- [FP] Unary operations
1101 ;; -------------------------------------------------------------------------------
1103 ;; - vfneg.v/vfabs.v
1104 ;; -------------------------------------------------------------------------------
1105 (define_insn_and_split "<optab><mode>2"
1106 [(set (match_operand:V_VLSF 0 "register_operand")
1107 (any_float_unop_nofrm:V_VLSF
1108 (match_operand:V_VLSF 1 "register_operand")))]
1109 "TARGET_VECTOR && can_create_pseudo_p ()"
1114 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1115 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
1118 [(set_attr "type" "vector")])
1120 ;; -------------------------------------------------------------------------------
1121 ;; - [FP] Square root
1122 ;; -------------------------------------------------------------------------------
1125 ;; -------------------------------------------------------------------------------
1126 (define_insn_and_split "<optab><mode>2"
1127 [(set (match_operand:V_VLSF 0 "register_operand")
1128 (any_float_unop:V_VLSF
1129 (match_operand:V_VLSF 1 "register_operand")))]
1130 "TARGET_VECTOR && can_create_pseudo_p ()"
1135 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1136 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
1139 [(set_attr "type" "vfsqrt")])
1141 ;; =========================================================================
1142 ;; == Ternary arithmetic
1143 ;; =========================================================================
1145 ;; -------------------------------------------------------------------------
1146 ;; ---- [INT] VMACC and VMADD
1147 ;; -------------------------------------------------------------------------
1151 ;; -------------------------------------------------------------------------
1153 (define_insn_and_split "fma<mode>4"
1154 [(set (match_operand:V_VLSI 0 "register_operand")
1157 (match_operand:V_VLSI 1 "register_operand")
1158 (match_operand:V_VLSI 2 "register_operand"))
1159 (match_operand:V_VLSI 3 "register_operand")))]
1160 "TARGET_VECTOR && can_create_pseudo_p ()"
1165 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
1166 RVV_VUNDEF(<MODE>mode)};
1167 riscv_vector::emit_vlmax_insn (code_for_pred_mul_plus (<MODE>mode),
1168 riscv_vector::TERNARY_OP, ops);
1171 [(set_attr "type" "vector")])
1173 ;; -------------------------------------------------------------------------
1174 ;; ---- [INT] VNMSAC and VNMSUB
1175 ;; -------------------------------------------------------------------------
1179 ;; -------------------------------------------------------------------------
1181 (define_insn_and_split "fnma<mode>4"
1182 [(set (match_operand:V_VLSI 0 "register_operand")
1184 (match_operand:V_VLSI 3 "register_operand")
1186 (match_operand:V_VLSI 1 "register_operand")
1187 (match_operand:V_VLSI 2 "register_operand"))))]
1188 "TARGET_VECTOR && can_create_pseudo_p ()"
1193 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
1194 RVV_VUNDEF(<MODE>mode)};
1195 riscv_vector::emit_vlmax_insn (code_for_pred_minus_mul (<MODE>mode),
1196 riscv_vector::TERNARY_OP, ops);
1199 [(set_attr "type" "vector")])
1201 ;; -------------------------------------------------------------------------
1202 ;; ---- [FP] VFMACC and VFMADD
1203 ;; -------------------------------------------------------------------------
1207 ;; -------------------------------------------------------------------------
1209 (define_insn_and_split "fma<mode>4"
1210 [(set (match_operand:V_VLSF 0 "register_operand")
1213 (match_operand:V_VLSF 1 "register_operand")
1214 (match_operand:V_VLSF 2 "register_operand"))
1215 (match_operand:V_VLSF 3 "register_operand")))]
1216 "TARGET_VECTOR && can_create_pseudo_p ()"
1221 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
1222 RVV_VUNDEF(<MODE>mode)};
1223 riscv_vector::emit_vlmax_insn (code_for_pred_mul (PLUS, <MODE>mode),
1224 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1227 [(set_attr "type" "vector")])
1229 ;; -------------------------------------------------------------------------
1230 ;; ---- [FP] VFNMSAC and VFNMSUB
1231 ;; -------------------------------------------------------------------------
1235 ;; -------------------------------------------------------------------------
1237 (define_insn_and_split "fnma<mode>4"
1238 [(set (match_operand:V_VLSF 0 "register_operand")
1240 (match_operand:V_VLSF 3 "register_operand")
1242 (match_operand:V_VLSF 1 "register_operand")
1243 (match_operand:V_VLSF 2 "register_operand"))))]
1244 "TARGET_VECTOR && can_create_pseudo_p ()"
1249 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
1250 RVV_VUNDEF(<MODE>mode)};
1251 riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (PLUS, <MODE>mode),
1252 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1255 [(set_attr "type" "vector")])
1257 ;; -------------------------------------------------------------------------
1258 ;; ---- [FP] VFMSAC and VFMSUB
1259 ;; -------------------------------------------------------------------------
1263 ;; -------------------------------------------------------------------------
1265 (define_insn_and_split "fms<mode>4"
1266 [(set (match_operand:V_VLSF 0 "register_operand")
1269 (match_operand:V_VLSF 1 "register_operand")
1270 (match_operand:V_VLSF 2 "register_operand"))
1271 (match_operand:V_VLSF 3 "register_operand")))]
1272 "TARGET_VECTOR && can_create_pseudo_p ()"
1277 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
1278 RVV_VUNDEF(<MODE>mode)};
1279 riscv_vector::emit_vlmax_insn (code_for_pred_mul (MINUS, <MODE>mode),
1280 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1283 [(set_attr "type" "vector")])
1285 ;; -------------------------------------------------------------------------
1286 ;; ---- [FP] VFNMACC and VFNMADD
1287 ;; -------------------------------------------------------------------------
1291 ;; -------------------------------------------------------------------------
1293 (define_insn_and_split "fnms<mode>4"
1294 [(set (match_operand:V_VLSF 0 "register_operand")
1298 (match_operand:V_VLSF 1 "register_operand")
1299 (match_operand:V_VLSF 2 "register_operand")))
1300 (match_operand:V_VLSF 3 "register_operand")))]
1301 "TARGET_VECTOR && can_create_pseudo_p ()"
1306 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
1307 RVV_VUNDEF(<MODE>mode)};
1308 riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (MINUS, <MODE>mode),
1309 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1312 [(set_attr "type" "vector")])
1314 ;; =========================================================================
1316 ;; =========================================================================
1318 (define_expand "select_vl<mode>"
1319 [(match_operand:P 0 "register_operand")
1320 (match_operand:P 1 "vector_length_operand")
1321 (match_operand:P 2 "")]
1324 riscv_vector::expand_select_vl (operands);
1328 ;; -------------------------------------------------------------------------
1329 ;; ---- [INT,FP] Insert a vector element.
1330 ;; -------------------------------------------------------------------------
1332 (define_expand "vec_set<mode>"
1333 [(match_operand:V_VLS 0 "register_operand")
1334 (match_operand:<VEL> 1 "register_operand")
1335 (match_operand 2 "nonmemory_operand")]
1338 /* If we set the first element, emit an v(f)mv.s.[xf]. */
1339 if (operands[2] == const0_rtx)
1341 rtx ops[] = {operands[0], operands[0], operands[1]};
1342 riscv_vector::emit_nonvlmax_insn (code_for_pred_broadcast (<MODE>mode),
1343 riscv_vector::SCALAR_MOVE_MERGED_OP_TU,
1344 ops, CONST1_RTX (Pmode));
1348 /* Move the desired value into a vector register and insert
1349 it at the proper position using vslideup with an
1350 "effective length" of 1 i.e. a VL 1 past the offset. */
1352 /* Here we set VL = offset + 1. */
1353 rtx length = gen_reg_rtx (Pmode);
1354 operands[2] = gen_lowpart (Pmode, operands[2]);
1355 if (CONST_INT_P (operands[2]))
1356 emit_move_insn (length, GEN_INT (INTVAL (operands[2]) + 1));
1359 rtx add = gen_rtx_PLUS (GET_MODE (operands[2]),
1360 operands[2], GEN_INT (1));
1361 emit_move_insn (length, add);
1364 /* Move operands[1] into a vector register via vmv.v.x using the same
1365 VL we need for the slide. */
1366 rtx tmp = gen_reg_rtx (<MODE>mode);
1367 rtx ops1[] = {tmp, operands[1]};
1368 emit_nonvlmax_insn (code_for_pred_broadcast (<MODE>mode),
1369 riscv_vector::UNARY_OP, ops1, length);
1371 /* Slide exactly one element up leaving the tail elements
1373 rtx ops2[] = {operands[0], operands[0], tmp, operands[2]};
1374 riscv_vector::emit_nonvlmax_insn
1375 (code_for_pred_slide (UNSPEC_VSLIDEUP, <MODE>mode), riscv_vector::BINARY_OP_TUMA, ops2, length);
1380 ;; -------------------------------------------------------------------------
1381 ;; ---- [INT,FP] Extract a vector element.
1382 ;; -------------------------------------------------------------------------
1383 (define_expand "vec_extract<mode><vel>"
1384 [(set (match_operand:<VEL> 0 "register_operand")
1386 (match_operand:V_VLS_ZVFH 1 "register_operand")
1388 [(match_operand 2 "nonmemory_operand")])))]
1391 /* Element extraction can be done by sliding down the requested element
1392 to index 0 and then v(f)mv.[xf].s it to a scalar register. */
1394 /* When extracting any other than the first element we need to slide
1397 if (operands[2] != const0_rtx)
1399 /* Properly convert a poly_int value and put the result into a
1401 if (CONST_POLY_INT_P (operands[2]))
1403 rtx pos = gen_reg_rtx (Pmode);
1404 riscv_legitimize_poly_move (Pmode, pos, gen_reg_rtx (Pmode),
1409 /* Emit the slide down to index 0 in a new vector. */
1410 tmp = gen_reg_rtx (<MODE>mode);
1411 operands[2] = gen_lowpart (Pmode, operands[2]);
1412 rtx ops[] = {tmp, operands[1], operands[2]};
1413 riscv_vector::emit_vlmax_insn
1414 (code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode),
1415 riscv_vector::BINARY_OP, ops);
1418 /* Emit v(f)mv.[xf].s. */
1419 emit_insn (gen_pred_extract_first (<MODE>mode, operands[0],
1420 tmp ? tmp : operands[1]));
1424 ;; -------------------------------------------------------------------------
1425 ;; This extracts a bit (via QImode) from a bitmask vector.
1426 ;; -------------------------------------------------------------------------
1427 (define_expand "vec_extract<mode>qi"
1428 [(set (match_operand:QI 0 "register_operand")
1430 (match_operand:VB_VLS 1 "register_operand")
1432 [(match_operand 2 "nonmemory_operand")])))]
1435 /* Create an empty byte vector and set it to one under mask. */
1436 machine_mode qimode = riscv_vector::get_vector_mode
1437 (QImode, GET_MODE_NUNITS (<MODE>mode)).require ();
1439 rtx tmp1 = gen_reg_rtx (qimode);
1440 emit_move_insn (tmp1, gen_const_vec_duplicate (qimode, GEN_INT (0)));
1441 rtx ones = gen_const_vec_duplicate (qimode, GEN_INT (1));
1443 rtx ops1[] = {tmp1, tmp1, ones, operands[1]};
1444 riscv_vector::emit_vlmax_insn (code_for_pred_merge (qimode),
1445 riscv_vector::MERGE_OP, ops1);
1447 /* Extract from it. */
1448 riscv_vector::emit_vec_extract (operands[0], tmp1, operands[2]);
1452 ;; Same for a BImode but still return a QImode.
1453 (define_expand "vec_extract<mode>bi"
1454 [(set (match_operand:QI 0 "register_operand")
1456 (match_operand:VB_VLS 1 "register_operand")
1458 [(match_operand 2 "nonmemory_operand")])))]
1461 emit_insn (gen_vec_extract<mode>qi (operands[0], operands[1], operands[2]));
1465 ;; -------------------------------------------------------------------------
1466 ;; ---- [INT,FP] Extract a vector from a vector.
1467 ;; -------------------------------------------------------------------------
1468 ;; TODO: This can be extended to allow basically any extract mode.
1469 ;; For now this helps optimize VLS subregs like (subreg:V2DI (reg:V4DI) 16)
1470 ;; that would otherwise need to go via memory.
1472 (define_expand "vec_extract<mode><vls_half>"
1473 [(set (match_operand:<VLS_HALF> 0 "nonimmediate_operand")
1474 (vec_select:<VLS_HALF>
1475 (match_operand:VLS_HAS_HALF 1 "register_operand")
1477 [(match_operand 2 "immediate_operand")])))]
1480 int sz = GET_MODE_NUNITS (<VLS_HALF>mode).to_constant ();
1481 int part = INTVAL (operands[2]);
1483 rtx start = GEN_INT (part * sz);
1484 rtx tmp = operands[1];
1488 tmp = gen_reg_rtx (<MODE>mode);
1490 rtx ops[] = {tmp, operands[1], start};
1491 riscv_vector::emit_vlmax_insn
1492 (code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode),
1493 riscv_vector::BINARY_OP, ops);
1496 emit_move_insn (operands[0], gen_lowpart (<VLS_HALF>mode, tmp));
1500 (define_expand "vec_extract<mode><vls_quarter>"
1501 [(set (match_operand:<VLS_QUARTER> 0 "nonimmediate_operand")
1502 (vec_select:<VLS_QUARTER>
1503 (match_operand:VLS_HAS_QUARTER 1 "register_operand")
1505 [(match_operand 2 "immediate_operand")])))]
1508 int sz = GET_MODE_NUNITS (<VLS_QUARTER>mode).to_constant ();
1509 int part = INTVAL (operands[2]);
1511 rtx start = GEN_INT (part * sz);
1512 rtx tmp = operands[1];
1516 tmp = gen_reg_rtx (<MODE>mode);
1518 rtx ops[] = {tmp, operands[1], start};
1519 riscv_vector::emit_vlmax_insn
1520 (code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode),
1521 riscv_vector::BINARY_OP, ops);
1524 emit_move_insn (operands[0], gen_lowpart (<VLS_QUARTER>mode, tmp));
1528 ;; -------------------------------------------------------------------------
1529 ;; ---- [FP] Binary operations
1530 ;; -------------------------------------------------------------------------
1532 ;; - vfadd.vv/vfsub.vv/...
1533 ;; - vfadd.vf/vfsub.vf/...
1534 ;; -------------------------------------------------------------------------
1535 (define_insn_and_split "<optab><mode>3"
1536 [(set (match_operand:V_VLSF 0 "register_operand")
1537 (any_float_binop:V_VLSF
1538 (match_operand:V_VLSF 1 "register_operand")
1539 (match_operand:V_VLSF 2 "register_operand")))]
1540 "TARGET_VECTOR && can_create_pseudo_p ()"
1545 riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
1546 riscv_vector::BINARY_OP_FRM_DYN, operands);
1549 [(set_attr "type" "vfalu")])
1551 ;; -------------------------------------------------------------------------
1553 ;; - vfmin.vv/vfmax.vv
1554 ;; - vfmin.vf/vfmax.vf
1555 ;; -------------------------------------------------------------------------
1556 (define_insn_and_split "<optab><mode>3"
1557 [(set (match_operand:V_VLSF 0 "register_operand")
1558 (any_float_binop_nofrm:V_VLSF
1559 (match_operand:V_VLSF 1 "register_operand")
1560 (match_operand:V_VLSF 2 "register_operand")))]
1561 "TARGET_VECTOR && can_create_pseudo_p ()"
1566 riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
1567 riscv_vector::BINARY_OP, operands);
1570 [(set_attr "type" "vfminmax")])
1572 (define_insn_and_split "<ieee_fmaxmin_op><mode>3"
1573 [(set (match_operand:V_VLSF 0 "register_operand")
1575 [(match_operand:V_VLSF 1 "register_operand")
1576 (match_operand:V_VLSF 2 "register_operand")] UNSPEC_VFMAXMIN))]
1577 "TARGET_VECTOR && !HONOR_SNANS (<MODE>mode) && can_create_pseudo_p ()"
1582 riscv_vector::emit_vlmax_insn (code_for_pred (<IEEE_FMAXMIN_OP>, <MODE>mode),
1583 riscv_vector::BINARY_OP, operands);
1586 [(set_attr "type" "vfminmax")])
1588 ;; -------------------------------------------------------------------------------
1589 ;; ---- [FP] Sign copying
1590 ;; -------------------------------------------------------------------------------
1592 ;; - vfsgnj.vv/vfsgnjn.vv
1593 ;; - vfsgnj.vf/vfsgnjn.vf
1594 ;; -------------------------------------------------------------------------------
1596 ;; Leave the pattern like this as to still allow combine to match
1597 ;; a negated copysign (see vector.md) before adding the UNSPEC_VPREDICATE later.
1598 (define_insn_and_split "copysign<mode>3"
1599 [(set (match_operand:V_VLSF 0 "register_operand" "=vd, vd, vr, vr")
1601 [(match_operand:V_VLSF 1 "register_operand" " vr, vr, vr, vr")
1602 (match_operand:V_VLSF 2 "register_operand" " vr, vr, vr, vr")] UNSPEC_VCOPYSIGN))]
1603 "TARGET_VECTOR && can_create_pseudo_p ()"
1608 riscv_vector::emit_vlmax_insn (code_for_pred (UNSPEC_VCOPYSIGN, <MODE>mode),
1609 riscv_vector::BINARY_OP, operands);
1612 [(set_attr "type" "vfsgnj")
1613 (set_attr "mode" "<MODE>")])
1615 ;; -------------------------------------------------------------------------------
1619 ;; -------------------------------------------------------------------------------
1620 (define_expand "xorsign<mode>3"
1621 [(match_operand:V_VLSF 0 "register_operand")
1622 (match_operand:V_VLSF 1 "register_operand")
1623 (match_operand:V_VLSF 2 "register_operand")]
1626 riscv_vector::emit_vlmax_insn (code_for_pred (UNSPEC_VXORSIGN, <MODE>mode),
1627 riscv_vector::BINARY_OP, operands);
1631 ;; -------------------------------------------------------------------------------
1632 ;; - [INT] POPCOUNT, CTZ and CLZ.
1633 ;; -------------------------------------------------------------------------------
1635 (define_expand "popcount<mode>2"
1636 [(match_operand:V_VLSI 0 "register_operand")
1637 (match_operand:V_VLSI 1 "register_operand")]
1641 riscv_vector::expand_popcount (operands);
1644 riscv_vector::emit_vlmax_insn (code_for_pred_v (POPCOUNT, <MODE>mode),
1645 riscv_vector::CPOP_OP, operands);
1650 (define_expand "ctz<mode>2"
1651 [(match_operand:V_VLSI 0 "register_operand")
1652 (match_operand:V_VLSI 1 "register_operand")]
1655 riscv_vector::emit_vlmax_insn (code_for_pred_v (CTZ, <MODE>mode),
1656 riscv_vector::CPOP_OP, operands);
1660 (define_expand "clz<mode>2"
1661 [(match_operand:V_VLSI 0 "register_operand")
1662 (match_operand:V_VLSI 1 "register_operand")]
1665 riscv_vector::emit_vlmax_insn (code_for_pred_v (CLZ, <MODE>mode),
1666 riscv_vector::CPOP_OP, operands);
1671 ;; -------------------------------------------------------------------------
1672 ;; ---- [INT] Highpart multiplication
1673 ;; -------------------------------------------------------------------------
1677 ;; -------------------------------------------------------------------------
1679 (define_insn_and_split "<mulh_table><mode>3_highpart"
1680 [(set (match_operand:VFULLI 0 "register_operand")
1682 (match_operand:VFULLI 1 "register_operand")
1683 (match_operand:VFULLI 2 "register_operand")))]
1684 "TARGET_VECTOR && can_create_pseudo_p ()"
1689 insn_code icode = code_for_pred_mulh (<MULH_UNSPEC>, <MODE>mode);
1690 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1693 [(set_attr "type" "vimul")])
1695 ;; -------------------------------------------------------------------------
1696 ;; ---- [INT] Conditional unary operations
1697 ;; -------------------------------------------------------------------------
1700 ;; -------------------------------------------------------------------------
1702 (define_expand "cond_<optab><mode>"
1703 [(match_operand:V_VLSI 0 "register_operand")
1704 (match_operand:<VM> 1 "vector_mask_operand")
1705 (any_int_unop:V_VLSI
1706 (match_operand:V_VLSI 2 "register_operand"))
1707 (match_operand:V_VLSI 3 "autovec_else_operand")]
1710 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1711 riscv_vector::expand_cond_unop (icode, operands);
1715 (define_expand "cond_len_<optab><mode>"
1716 [(match_operand:VI 0 "register_operand")
1717 (match_operand:<VM> 1 "vector_mask_operand")
1719 (match_operand:VI 2 "register_operand"))
1720 (match_operand:VI 3 "autovec_else_operand")
1721 (match_operand 4 "autovec_length_operand")
1722 (match_operand 5 "const_0_operand")]
1725 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1726 riscv_vector::expand_cond_len_unop (icode, operands);
1730 ;; -------------------------------------------------------------------------
1731 ;; ---- [FP] Conditional unary operations
1732 ;; -------------------------------------------------------------------------
1735 ;; -------------------------------------------------------------------------
1737 (define_expand "cond_<optab><mode>"
1738 [(match_operand:V_VLSF 0 "register_operand")
1739 (match_operand:<VM> 1 "vector_mask_operand")
1740 (any_float_unop_nofrm:V_VLSF
1741 (match_operand:V_VLSF 2 "register_operand"))
1742 (match_operand:V_VLSF 3 "autovec_else_operand")]
1745 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1746 riscv_vector::expand_cond_unop (icode, operands);
1750 (define_expand "cond_len_<optab><mode>"
1751 [(match_operand:VF 0 "register_operand")
1752 (match_operand:<VM> 1 "vector_mask_operand")
1753 (any_float_unop_nofrm:VF
1754 (match_operand:VF 2 "register_operand"))
1755 (match_operand:VF 3 "autovec_else_operand")
1756 (match_operand 4 "autovec_length_operand")
1757 (match_operand 5 "const_0_operand")]
1760 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1761 riscv_vector::expand_cond_len_unop (icode, operands);
1765 ;; -------------------------------------------------------------------------
1766 ;; ---- [INT] Conditional binary operations
1767 ;; -------------------------------------------------------------------------
1770 ;; -------------------------------------------------------------------------
1772 (define_expand "cond_<optab><mode>"
1773 [(match_operand:V_VLSI 0 "register_operand")
1774 (match_operand:<VM> 1 "vector_mask_operand")
1776 (match_operand:V_VLSI 2 "register_operand")
1777 (match_operand:V_VLSI 3 "vector_shift_operand"))
1778 (match_operand:V_VLSI 4 "autovec_else_operand")]
1781 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1782 riscv_vector::expand_cond_binop (icode, operands);
1786 (define_expand "cond_len_<optab><mode>"
1787 [(match_operand:VI 0 "register_operand")
1788 (match_operand:<VM> 1 "vector_mask_operand")
1790 (match_operand:VI 2 "register_operand")
1791 (match_operand:VI 3 "vector_shift_operand"))
1792 (match_operand:VI 4 "autovec_else_operand")
1793 (match_operand 5 "autovec_length_operand")
1794 (match_operand 6 "const_0_operand")]
1797 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1798 riscv_vector::expand_cond_len_binop (icode, operands);
1802 ;; -------------------------------------------------------------------------
1803 ;; ---- [INT] Conditional binary operations
1804 ;; -------------------------------------------------------------------------
1806 ;; - vadd.vv/vsub.vv/...
1807 ;; - vadd.vi/vsub.vi/...
1808 ;; -------------------------------------------------------------------------
1810 (define_expand "cond_<optab><mode>"
1811 [(match_operand:V_VLSI 0 "register_operand")
1812 (match_operand:<VM> 1 "vector_mask_operand")
1813 (any_int_binop_no_shift:V_VLSI
1814 (match_operand:V_VLSI 2 "<binop_rhs1_predicate>")
1815 (match_operand:V_VLSI 3 "<binop_rhs2_predicate>"))
1816 (match_operand:V_VLSI 4 "autovec_else_operand")]
1819 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1820 riscv_vector::expand_cond_binop (icode, operands);
1824 (define_expand "cond_len_<optab><mode>"
1825 [(match_operand:VI 0 "register_operand")
1826 (match_operand:<VM> 1 "vector_mask_operand")
1827 (any_int_binop_no_shift:VI
1828 (match_operand:VI 2 "<binop_rhs1_predicate>")
1829 (match_operand:VI 3 "<binop_rhs2_predicate>"))
1830 (match_operand:VI 4 "autovec_else_operand")
1831 (match_operand 5 "autovec_length_operand")
1832 (match_operand 6 "const_0_operand")]
1835 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1836 riscv_vector::expand_cond_len_binop (icode, operands);
1840 ;; -------------------------------------------------------------------------
1841 ;; ---- [FP] Conditional binary operations
1842 ;; -------------------------------------------------------------------------
1844 ;; - vfadd.vv/vfsub.vv/...
1845 ;; - vfadd.vf/vfsub.vf/...
1846 ;; -------------------------------------------------------------------------
1848 (define_expand "cond_<optab><mode>"
1849 [(match_operand:V_VLSF 0 "register_operand")
1850 (match_operand:<VM> 1 "vector_mask_operand")
1851 (any_float_binop:V_VLSF
1852 (match_operand:V_VLSF 2 "register_operand")
1853 (match_operand:V_VLSF 3 "register_operand"))
1854 (match_operand:V_VLSF 4 "autovec_else_operand")]
1857 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1858 riscv_vector::expand_cond_binop (icode, operands);
1862 (define_expand "cond_len_<optab><mode>"
1863 [(match_operand:VF 0 "register_operand")
1864 (match_operand:<VM> 1 "vector_mask_operand")
1866 (match_operand:VF 2 "register_operand")
1867 (match_operand:VF 3 "register_operand"))
1868 (match_operand:VF 4 "autovec_else_operand")
1869 (match_operand 5 "autovec_length_operand")
1870 (match_operand 6 "const_0_operand")]
1873 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1874 riscv_vector::expand_cond_len_binop (icode, operands);
1878 ;; -------------------------------------------------------------------------
1880 ;; - vfmin.vv/vfmax.vv
1881 ;; - vfmin.vf/vfmax.vf
1882 ;; -------------------------------------------------------------------------
1884 (define_expand "cond_<optab><mode>"
1885 [(match_operand:V_VLSF 0 "register_operand")
1886 (match_operand:<VM> 1 "vector_mask_operand")
1887 (any_float_binop_nofrm:V_VLSF
1888 (match_operand:V_VLSF 2 "register_operand")
1889 (match_operand:V_VLSF 3 "register_operand"))
1890 (match_operand:V_VLSF 4 "autovec_else_operand")]
1893 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1894 riscv_vector::expand_cond_binop (icode, operands);
1898 (define_expand "cond_len_<optab><mode>"
1899 [(match_operand:VF 0 "register_operand")
1900 (match_operand:<VM> 1 "vector_mask_operand")
1901 (any_float_binop_nofrm:VF
1902 (match_operand:VF 2 "register_operand")
1903 (match_operand:VF 3 "register_operand"))
1904 (match_operand:VF 4 "autovec_else_operand")
1905 (match_operand 5 "autovec_length_operand")
1906 (match_operand 6 "const_0_operand")]
1909 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
1910 riscv_vector::expand_cond_len_binop (icode, operands);
1914 (define_expand "cond_<ieee_fmaxmin_op><mode>"
1915 [(match_operand:V_VLSF 0 "register_operand")
1916 (match_operand:<VM> 1 "vector_mask_operand")
1918 [(match_operand:V_VLSF 2 "register_operand")
1919 (match_operand:V_VLSF 3 "register_operand")] UNSPEC_VFMAXMIN)
1920 (match_operand:V_VLSF 4 "autovec_else_operand")]
1921 "TARGET_VECTOR && !HONOR_SNANS (<MODE>mode)"
1923 insn_code icode = code_for_pred (<IEEE_FMAXMIN_OP>, <MODE>mode);
1924 riscv_vector::expand_cond_binop (icode, operands);
1928 (define_expand "cond_len_<ieee_fmaxmin_op><mode>"
1929 [(match_operand:VF 0 "register_operand")
1930 (match_operand:<VM> 1 "vector_mask_operand")
1932 [(match_operand:VF 2 "register_operand")
1933 (match_operand:VF 3 "register_operand")] UNSPEC_VFMAXMIN)
1934 (match_operand:VF 4 "autovec_else_operand")
1935 (match_operand 5 "autovec_length_operand")
1936 (match_operand 6 "const_0_operand")]
1937 "TARGET_VECTOR && !HONOR_SNANS (<MODE>mode)"
1939 insn_code icode = code_for_pred (<IEEE_FMAXMIN_OP>, <MODE>mode);
1940 riscv_vector::expand_cond_len_binop (icode, operands);
1944 ;; -------------------------------------------------------------------------
1945 ;; ---- [FP] Conditional copysign operations
1946 ;; -------------------------------------------------------------------------
1949 ;; -------------------------------------------------------------------------
1951 (define_expand "cond_copysign<mode>"
1952 [(match_operand:V_VLSF 0 "register_operand")
1953 (match_operand:<VM> 1 "register_operand")
1954 (match_operand:V_VLSF 2 "register_operand")
1955 (match_operand:V_VLSF 3 "register_operand")
1956 (match_operand:V_VLSF 4 "register_operand")]
1959 insn_code icode = code_for_pred (UNSPEC_VCOPYSIGN, <MODE>mode);
1960 rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[4],
1961 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
1962 riscv_vector::expand_cond_len_binop (icode, ops);
1966 ;; -------------------------------------------------------------------------
1967 ;; ---- [INT] Conditional ternary operations
1968 ;; -------------------------------------------------------------------------
1971 ;; -------------------------------------------------------------------------
1973 (define_expand "cond_fma<mode>"
1974 [(match_operand:V_VLSI 0 "register_operand")
1975 (match_operand:<VM> 1 "vector_mask_operand")
1976 (match_operand:V_VLSI 2 "register_operand")
1977 (match_operand:V_VLSI 3 "register_operand")
1978 (match_operand:V_VLSI 4 "register_operand")
1979 (match_operand:V_VLSI 5 "autovec_else_operand")]
1982 insn_code icode = code_for_pred_mul_plus (<MODE>mode);
1983 riscv_vector::expand_cond_ternop (icode, operands);
1987 (define_expand "cond_len_fma<mode>"
1988 [(match_operand:VI 0 "register_operand")
1989 (match_operand:<VM> 1 "vector_mask_operand")
1990 (match_operand:VI 2 "register_operand")
1991 (match_operand:VI 3 "register_operand")
1992 (match_operand:VI 4 "register_operand")
1993 (match_operand:VI 5 "autovec_else_operand")
1994 (match_operand 6 "autovec_length_operand")
1995 (match_operand 7 "const_0_operand")]
1998 insn_code icode = code_for_pred_mul_plus (<MODE>mode);
1999 riscv_vector::expand_cond_len_ternop (icode, operands);
2003 (define_expand "cond_fnma<mode>"
2004 [(match_operand:V_VLSI 0 "register_operand")
2005 (match_operand:<VM> 1 "vector_mask_operand")
2006 (match_operand:V_VLSI 2 "register_operand")
2007 (match_operand:V_VLSI 3 "register_operand")
2008 (match_operand:V_VLSI 4 "register_operand")
2009 (match_operand:V_VLSI 5 "autovec_else_operand")]
2012 insn_code icode = code_for_pred_minus_mul (<MODE>mode);
2013 riscv_vector::expand_cond_ternop (icode, operands);
2017 (define_expand "cond_len_fnma<mode>"
2018 [(match_operand:VI 0 "register_operand")
2019 (match_operand:<VM> 1 "vector_mask_operand")
2020 (match_operand:VI 2 "register_operand")
2021 (match_operand:VI 3 "register_operand")
2022 (match_operand:VI 4 "register_operand")
2023 (match_operand:VI 5 "autovec_else_operand")
2024 (match_operand 6 "autovec_length_operand")
2025 (match_operand 7 "const_0_operand")]
2028 insn_code icode = code_for_pred_minus_mul (<MODE>mode);
2029 riscv_vector::expand_cond_len_ternop (icode, operands);
2033 ;; -------------------------------------------------------------------------
2034 ;; ---- [FP] Conditional ternary operations
2035 ;; -------------------------------------------------------------------------
2038 ;; -------------------------------------------------------------------------
2040 (define_expand "cond_fma<mode>"
2041 [(match_operand:V_VLSF 0 "register_operand")
2042 (match_operand:<VM> 1 "vector_mask_operand")
2043 (match_operand:V_VLSF 2 "register_operand")
2044 (match_operand:V_VLSF 3 "register_operand")
2045 (match_operand:V_VLSF 4 "register_operand")
2046 (match_operand:V_VLSF 5 "autovec_else_operand")]
2049 insn_code icode = code_for_pred_mul (PLUS, <MODE>mode);
2050 riscv_vector::expand_cond_ternop (icode, operands);
2054 (define_expand "cond_len_fma<mode>"
2055 [(match_operand:VF 0 "register_operand")
2056 (match_operand:<VM> 1 "vector_mask_operand")
2057 (match_operand:VF 2 "register_operand")
2058 (match_operand:VF 3 "register_operand")
2059 (match_operand:VF 4 "register_operand")
2060 (match_operand:VF 5 "autovec_else_operand")
2061 (match_operand 6 "autovec_length_operand")
2062 (match_operand 7 "const_0_operand")]
2065 insn_code icode = code_for_pred_mul (PLUS, <MODE>mode);
2066 riscv_vector::expand_cond_len_ternop (icode, operands);
2070 (define_expand "cond_fnma<mode>"
2071 [(match_operand:V_VLSF 0 "register_operand")
2072 (match_operand:<VM> 1 "vector_mask_operand")
2073 (match_operand:V_VLSF 2 "register_operand")
2074 (match_operand:V_VLSF 3 "register_operand")
2075 (match_operand:V_VLSF 4 "register_operand")
2076 (match_operand:V_VLSF 5 "autovec_else_operand")]
2079 insn_code icode = code_for_pred_mul_neg (PLUS, <MODE>mode);
2080 riscv_vector::expand_cond_ternop (icode, operands);
2084 (define_expand "cond_len_fnma<mode>"
2085 [(match_operand:VF 0 "register_operand")
2086 (match_operand:<VM> 1 "vector_mask_operand")
2087 (match_operand:VF 2 "register_operand")
2088 (match_operand:VF 3 "register_operand")
2089 (match_operand:VF 4 "register_operand")
2090 (match_operand:VF 5 "autovec_else_operand")
2091 (match_operand 6 "autovec_length_operand")
2092 (match_operand 7 "const_0_operand")]
2095 insn_code icode = code_for_pred_mul_neg (PLUS, <MODE>mode);
2096 riscv_vector::expand_cond_len_ternop (icode, operands);
2100 (define_expand "cond_fms<mode>"
2101 [(match_operand:V_VLSF 0 "register_operand")
2102 (match_operand:<VM> 1 "vector_mask_operand")
2103 (match_operand:V_VLSF 2 "register_operand")
2104 (match_operand:V_VLSF 3 "register_operand")
2105 (match_operand:V_VLSF 4 "register_operand")
2106 (match_operand:V_VLSF 5 "autovec_else_operand")]
2109 insn_code icode = code_for_pred_mul (MINUS, <MODE>mode);
2110 riscv_vector::expand_cond_ternop (icode, operands);
2114 (define_expand "cond_len_fms<mode>"
2115 [(match_operand:VF 0 "register_operand")
2116 (match_operand:<VM> 1 "vector_mask_operand")
2117 (match_operand:VF 2 "register_operand")
2118 (match_operand:VF 3 "register_operand")
2119 (match_operand:VF 4 "register_operand")
2120 (match_operand:VF 5 "autovec_else_operand")
2121 (match_operand 6 "autovec_length_operand")
2122 (match_operand 7 "const_0_operand")]
2125 insn_code icode = code_for_pred_mul (MINUS, <MODE>mode);
2126 riscv_vector::expand_cond_len_ternop (icode, operands);
2130 (define_expand "cond_fnms<mode>"
2131 [(match_operand:V_VLSF 0 "register_operand")
2132 (match_operand:<VM> 1 "vector_mask_operand")
2133 (match_operand:V_VLSF 2 "register_operand")
2134 (match_operand:V_VLSF 3 "register_operand")
2135 (match_operand:V_VLSF 4 "register_operand")
2136 (match_operand:V_VLSF 5 "autovec_else_operand")]
2139 insn_code icode = code_for_pred_mul_neg (MINUS, <MODE>mode);
2140 riscv_vector::expand_cond_ternop (icode, operands);
2144 (define_expand "cond_len_fnms<mode>"
2145 [(match_operand:VF 0 "register_operand")
2146 (match_operand:<VM> 1 "vector_mask_operand")
2147 (match_operand:VF 2 "register_operand")
2148 (match_operand:VF 3 "register_operand")
2149 (match_operand:VF 4 "register_operand")
2150 (match_operand:VF 5 "autovec_else_operand")
2151 (match_operand 6 "autovec_length_operand")
2152 (match_operand 7 "const_0_operand")]
2155 insn_code icode = code_for_pred_mul_neg (MINUS, <MODE>mode);
2156 riscv_vector::expand_cond_len_ternop (icode, operands);
2160 ;; =========================================================================
2162 ;; =========================================================================
2164 ;; -------------------------------------------------------------------------
2165 ;; ---- [INT] Tree reductions
2166 ;; -------------------------------------------------------------------------
2176 ;; -------------------------------------------------------------------------
2178 (define_insn_and_split "reduc_plus_scal_<mode>"
2179 [(set (match_operand:<VEL> 0 "register_operand")
2181 (match_operand:V_VLSI 1 "register_operand")
2182 ] UNSPEC_REDUC_SUM))]
2183 "TARGET_VECTOR && can_create_pseudo_p ()"
2188 riscv_vector::expand_reduction (UNSPEC_REDUC_SUM,
2189 UNSPEC_REDUC_SUM_VL0_SAFE,
2190 riscv_vector::REDUCE_OP,
2191 operands, CONST0_RTX (<VEL>mode));
2194 [(set_attr "type" "vector")])
2196 (define_expand "reduc_smax_scal_<mode>"
2197 [(match_operand:<VEL> 0 "register_operand")
2198 (match_operand:V_VLSI 1 "register_operand")]
2201 int prec = GET_MODE_PRECISION (<VEL>mode);
2202 rtx min = immed_wide_int_const (wi::min_value (prec, SIGNED), <VEL>mode);
2203 riscv_vector::expand_reduction (UNSPEC_REDUC_MAX,
2204 UNSPEC_REDUC_MAX_VL0_SAFE,
2205 riscv_vector::REDUCE_OP,
2210 (define_expand "reduc_umax_scal_<mode>"
2211 [(match_operand:<VEL> 0 "register_operand")
2212 (match_operand:V_VLSI 1 "register_operand")]
2215 riscv_vector::expand_reduction (UNSPEC_REDUC_MAXU,
2216 UNSPEC_REDUC_MAXU_VL0_SAFE,
2217 riscv_vector::REDUCE_OP,
2218 operands, CONST0_RTX (<VEL>mode));
2222 (define_expand "reduc_smin_scal_<mode>"
2223 [(match_operand:<VEL> 0 "register_operand")
2224 (match_operand:V_VLSI 1 "register_operand")]
2227 int prec = GET_MODE_PRECISION (<VEL>mode);
2228 rtx max = immed_wide_int_const (wi::max_value (prec, SIGNED), <VEL>mode);
2229 riscv_vector::expand_reduction (UNSPEC_REDUC_MIN,
2230 UNSPEC_REDUC_MIN_VL0_SAFE,
2231 riscv_vector::REDUCE_OP,
2236 (define_expand "reduc_umin_scal_<mode>"
2237 [(match_operand:<VEL> 0 "register_operand")
2238 (match_operand:V_VLSI 1 "register_operand")]
2241 int prec = GET_MODE_PRECISION (<VEL>mode);
2242 rtx max = immed_wide_int_const (wi::max_value (prec, UNSIGNED), <VEL>mode);
2243 riscv_vector::expand_reduction (UNSPEC_REDUC_MINU,
2244 UNSPEC_REDUC_MINU_VL0_SAFE,
2245 riscv_vector::REDUCE_OP,
2250 (define_expand "reduc_and_scal_<mode>"
2251 [(match_operand:<VEL> 0 "register_operand")
2252 (match_operand:V_VLSI 1 "register_operand")]
2255 riscv_vector::expand_reduction (UNSPEC_REDUC_AND,
2256 UNSPEC_REDUC_AND_VL0_SAFE,
2257 riscv_vector::REDUCE_OP,
2258 operands, CONSTM1_RTX (<VEL>mode));
2262 (define_expand "reduc_ior_scal_<mode>"
2263 [(match_operand:<VEL> 0 "register_operand")
2264 (match_operand:V_VLSI 1 "register_operand")]
2267 riscv_vector::expand_reduction (UNSPEC_REDUC_OR,
2268 UNSPEC_REDUC_OR_VL0_SAFE,
2269 riscv_vector::REDUCE_OP,
2270 operands, CONST0_RTX (<VEL>mode));
2274 (define_expand "reduc_xor_scal_<mode>"
2275 [(match_operand:<VEL> 0 "register_operand")
2276 (match_operand:V_VLSI 1 "register_operand")]
2279 riscv_vector::expand_reduction (UNSPEC_REDUC_XOR,
2280 UNSPEC_REDUC_XOR_VL0_SAFE,
2281 riscv_vector::REDUCE_OP,
2282 operands, CONST0_RTX (<VEL>mode));
2286 ;; -------------------------------------------------------------------------
2287 ;; ---- [FP] Tree reductions
2288 ;; -------------------------------------------------------------------------
2293 ;; -------------------------------------------------------------------------
2295 (define_insn_and_split "reduc_plus_scal_<mode>"
2296 [(set (match_operand:<VEL> 0 "register_operand")
2298 (match_operand:V_VLSF 1 "register_operand")
2299 ] UNSPEC_REDUC_SUM_UNORDERED))]
2300 "TARGET_VECTOR && can_create_pseudo_p ()"
2305 riscv_vector::expand_reduction (UNSPEC_REDUC_SUM_UNORDERED,
2306 UNSPEC_REDUC_SUM_UNORDERED_VL0_SAFE,
2307 riscv_vector::REDUCE_OP_FRM_DYN,
2308 operands, CONST0_RTX (<VEL>mode));
2311 [(set_attr "type" "vector")])
2313 (define_expand "reduc_smax_scal_<mode>"
2314 [(match_operand:<VEL> 0 "register_operand")
2315 (match_operand:V_VLSF 1 "register_operand")]
2319 real_inf (&rv, true);
2320 rtx f = const_double_from_real_value (rv, <VEL>mode);
2321 riscv_vector::expand_reduction (UNSPEC_REDUC_MAX,
2322 UNSPEC_REDUC_MAX_VL0_SAFE,
2323 riscv_vector::REDUCE_OP,
2328 (define_expand "reduc_smin_scal_<mode>"
2329 [(match_operand:<VEL> 0 "register_operand")
2330 (match_operand:V_VLSF 1 "register_operand")]
2334 real_inf (&rv, false);
2335 rtx f = const_double_from_real_value (rv, <VEL>mode);
2336 riscv_vector::expand_reduction (UNSPEC_REDUC_MIN,
2337 UNSPEC_REDUC_MIN_VL0_SAFE,
2338 riscv_vector::REDUCE_OP,
2343 (define_expand "reduc_fmax_scal_<mode>"
2344 [(match_operand:<VEL> 0 "register_operand")
2345 (match_operand:V_VLSF 1 "register_operand")]
2346 "TARGET_VECTOR && !HONOR_SNANS (<MODE>mode)"
2349 real_inf (&rv, true);
2350 rtx f = const_double_from_real_value (rv, <VEL>mode);
2351 riscv_vector::expand_reduction (UNSPEC_REDUC_MAX,
2352 UNSPEC_REDUC_MAX_VL0_SAFE,
2353 riscv_vector::REDUCE_OP,
2358 (define_expand "reduc_fmin_scal_<mode>"
2359 [(match_operand:<VEL> 0 "register_operand")
2360 (match_operand:V_VLSF 1 "register_operand")]
2361 "TARGET_VECTOR && !HONOR_SNANS (<MODE>mode)"
2364 real_inf (&rv, false);
2365 rtx f = const_double_from_real_value (rv, <VEL>mode);
2366 riscv_vector::expand_reduction (UNSPEC_REDUC_MIN,
2367 UNSPEC_REDUC_MIN_VL0_SAFE,
2368 riscv_vector::REDUCE_OP,
2373 ;; -------------------------------------------------------------------------
2374 ;; ---- [FP] Left-to-right reductions
2375 ;; -------------------------------------------------------------------------
2378 ;; -------------------------------------------------------------------------
2380 ;; Unpredicated in-order FP reductions.
2381 (define_insn_and_split "fold_left_plus_<mode>"
2382 [(set (match_operand:<VEL> 0 "register_operand")
2384 (match_operand:V_VLSF 2 "register_operand")
2385 (match_operand:<VEL> 1 "register_operand")
2386 ] UNSPEC_REDUC_SUM_ORDERED))]
2387 "TARGET_VECTOR && can_create_pseudo_p ()"
2392 rtx ops[] = {operands[0], operands[2]};
2393 riscv_vector::expand_reduction (UNSPEC_REDUC_SUM_ORDERED,
2394 UNSPEC_REDUC_SUM_ORDERED_VL0_SAFE,
2395 riscv_vector::REDUCE_OP_FRM_DYN,
2399 [(set_attr "type" "vector")])
2401 ;; Predicated in-order FP reductions.
2402 (define_insn_and_split "mask_len_fold_left_plus_<mode>"
2403 [(set (match_operand:<VEL> 0 "register_operand")
2405 (match_operand:VF 2 "register_operand")
2406 (match_operand:<VEL> 1 "register_operand")
2407 (match_operand:<VM> 3 "vector_mask_operand")
2408 (match_operand 4 "autovec_length_operand")
2409 (match_operand 5 "const_0_operand")
2410 ] UNSPEC_REDUC_SUM_ORDERED))]
2411 "TARGET_VECTOR && can_create_pseudo_p ()"
2416 if (rtx_equal_p (operands[4], const0_rtx))
2417 emit_move_insn (operands[0], operands[1]);
2420 rtx ops[] = {operands[0], operands[2], operands[3], operands[4]};
2421 riscv_vector::expand_reduction (UNSPEC_REDUC_SUM_ORDERED,
2422 UNSPEC_REDUC_SUM_ORDERED_VL0_SAFE,
2423 riscv_vector::REDUCE_OP_M_FRM_DYN,
2428 [(set_attr "type" "vector")])
2430 ;; -------------------------------------------------------------------------
2431 ;; ---- [INT,FP] Extract active element
2432 ;; -------------------------------------------------------------------------
2439 ;; -------------------------------------------------------------------------
2441 (define_expand "len_fold_extract_last_<mode>"
2442 [(match_operand:<VEL> 0 "register_operand")
2443 (match_operand:<VEL> 1 "register_operand")
2444 (match_operand:<VM> 2 "register_operand")
2445 (match_operand:V 3 "register_operand")
2446 (match_operand 4 "autovec_length_operand")
2447 (match_operand 5 "const_0_operand")]
2450 riscv_vector::expand_fold_extract_last (operands);
2454 ;; -------------------------------------------------------------------------
2455 ;; ---- [INT] Average.
2456 ;; -------------------------------------------------------------------------
2457 ;; Implements the following "average" patterns:
2459 ;; op[0] = (narrow) ((wide) op[1] + (wide) op[2]) >> 1;
2461 ;; op[0] = (narrow) ((wide) op[1] + (wide) op[2] + 1)) >> 1;
2462 ;; -------------------------------------------------------------------------
2464 (define_expand "avg<v_double_trunc>3_floor"
2465 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
2466 (truncate:<V_DOUBLE_TRUNC>
2470 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
2472 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))))]
2475 /* First emit a widening addition. */
2476 rtx tmp1 = gen_reg_rtx (<MODE>mode);
2477 rtx ops1[] = {tmp1, operands[1], operands[2]};
2478 insn_code icode = code_for_pred_dual_widen (PLUS, SIGN_EXTEND, <MODE>mode);
2479 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
2481 /* Then a narrowing shift. */
2482 rtx ops2[] = {operands[0], tmp1, const1_rtx};
2483 icode = code_for_pred_narrow_scalar (ASHIFTRT, <MODE>mode);
2484 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
2488 (define_expand "avg<v_double_trunc>3_ceil"
2489 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
2490 (truncate:<V_DOUBLE_TRUNC>
2495 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
2497 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
2501 /* First emit a widening addition. */
2502 rtx tmp1 = gen_reg_rtx (<MODE>mode);
2503 rtx ops1[] = {tmp1, operands[1], operands[2]};
2504 insn_code icode = code_for_pred_dual_widen (PLUS, SIGN_EXTEND, <MODE>mode);
2505 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
2508 rtx tmp2 = gen_reg_rtx (<MODE>mode);
2509 rtx ops2[] = {tmp2, tmp1, const1_rtx};
2510 icode = code_for_pred_scalar (PLUS, <MODE>mode);
2511 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
2513 /* Finally, a narrowing shift. */
2514 rtx ops3[] = {operands[0], tmp2, const1_rtx};
2515 icode = code_for_pred_narrow_scalar (ASHIFTRT, <MODE>mode);
2516 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3);
2521 ;; vaaddu.vv vd, vs2, vs1
2522 (define_expand "uavg<mode>3_floor"
2523 [(match_operand:V_VLSI 0 "register_operand")
2524 (match_operand:V_VLSI 1 "register_operand")
2525 (match_operand:V_VLSI 2 "register_operand")]
2528 insn_code icode = code_for_pred (UNSPEC_VAADDU, <MODE>mode);
2529 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RDN, operands);
2534 ;; vaaddu.vv vd, vs2, vs1
2535 (define_expand "uavg<mode>3_ceil"
2536 [(match_operand:V_VLSI 0 "register_operand")
2537 (match_operand:V_VLSI 1 "register_operand")
2538 (match_operand:V_VLSI 2 "register_operand")]
2541 insn_code icode = code_for_pred (UNSPEC_VAADDU, <MODE>mode);
2542 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_VXRM_RNU, operands);
2546 ;; -------------------------------------------------------------------------
2547 ;; ---- [FP] Rounding.
2548 ;; -------------------------------------------------------------------------
2552 ;; - nearbyint/nearbyintf
2556 ;; - roundeven/roundevenf
2561 ;; -------------------------------------------------------------------------
2562 (define_expand "ceil<mode>2"
2563 [(match_operand:V_VLSF 0 "register_operand")
2564 (match_operand:V_VLSF 1 "register_operand")]
2565 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2567 riscv_vector::expand_vec_ceil (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2572 (define_expand "floor<mode>2"
2573 [(match_operand:V_VLSF 0 "register_operand")
2574 (match_operand:V_VLSF 1 "register_operand")]
2575 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2577 riscv_vector::expand_vec_floor (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2582 (define_expand "nearbyint<mode>2"
2583 [(match_operand:V_VLSF 0 "register_operand")
2584 (match_operand:V_VLSF 1 "register_operand")]
2585 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2587 riscv_vector::expand_vec_nearbyint (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2592 (define_expand "rint<mode>2"
2593 [(match_operand:V_VLSF 0 "register_operand")
2594 (match_operand:V_VLSF 1 "register_operand")]
2595 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2597 riscv_vector::expand_vec_rint (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2602 (define_expand "round<mode>2"
2603 [(match_operand:V_VLSF 0 "register_operand")
2604 (match_operand:V_VLSF 1 "register_operand")]
2605 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2607 riscv_vector::expand_vec_round (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2612 (define_expand "btrunc<mode>2"
2613 [(match_operand:V_VLSF 0 "register_operand")
2614 (match_operand:V_VLSF 1 "register_operand")]
2615 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2617 riscv_vector::expand_vec_trunc (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2622 (define_expand "roundeven<mode>2"
2623 [(match_operand:V_VLSF 0 "register_operand")
2624 (match_operand:V_VLSF 1 "register_operand")]
2625 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2627 riscv_vector::expand_vec_roundeven (operands[0], operands[1], <MODE>mode, <VCONVERT>mode);
2632 (define_expand "lrint<mode><v_f2si_convert>2"
2633 [(match_operand:<V_F2SI_CONVERT> 0 "register_operand")
2634 (match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
2635 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2637 riscv_vector::expand_vec_lrint (operands[0], operands[1], <MODE>mode,
2638 <V_F2SI_CONVERT>mode, VOIDmode);
2643 (define_expand "lrint<mode><v_f2di_convert>2"
2644 [(match_operand:<V_F2DI_CONVERT> 0 "register_operand")
2645 (match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
2646 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2648 riscv_vector::expand_vec_lrint (operands[0], operands[1], <MODE>mode,
2649 <V_F2DI_CONVERT>mode,
2650 <V_F2DI_CONVERT_BRIDGE>mode);
2655 (define_expand "lround<mode><v_f2si_convert>2"
2656 [(match_operand:<V_F2SI_CONVERT> 0 "register_operand")
2657 (match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
2658 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2660 riscv_vector::expand_vec_lround (operands[0], operands[1], <MODE>mode,
2661 <V_F2SI_CONVERT>mode, VOIDmode);
2666 (define_expand "lround<mode><v_f2di_convert>2"
2667 [(match_operand:<V_F2DI_CONVERT> 0 "register_operand")
2668 (match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
2669 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2671 riscv_vector::expand_vec_lround (operands[0], operands[1], <MODE>mode,
2672 <V_F2DI_CONVERT>mode,
2673 <V_F2DI_CONVERT_BRIDGE>mode);
2679 (define_expand "lceil<mode><v_f2si_convert>2"
2680 [(match_operand:<V_F2SI_CONVERT> 0 "register_operand")
2681 (match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
2682 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2684 riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode, <V_F2SI_CONVERT>mode);
2689 (define_expand "lceil<mode><v_f2di_convert>2"
2690 [(match_operand:<V_F2DI_CONVERT> 0 "register_operand")
2691 (match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
2692 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2694 riscv_vector::expand_vec_lceil (operands[0], operands[1], <MODE>mode, <V_F2DI_CONVERT>mode);
2699 (define_expand "lfloor<mode><v_f2si_convert>2"
2700 [(match_operand:<V_F2SI_CONVERT> 0 "register_operand")
2701 (match_operand:V_VLS_F_CONVERT_SI 1 "register_operand")]
2702 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2704 riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode, <V_F2SI_CONVERT>mode);
2709 (define_expand "lfloor<mode><v_f2di_convert>2"
2710 [(match_operand:<V_F2DI_CONVERT> 0 "register_operand")
2711 (match_operand:V_VLS_F_CONVERT_DI 1 "register_operand")]
2712 "TARGET_VECTOR && !flag_trapping_math && !flag_rounding_math"
2714 riscv_vector::expand_vec_lfloor (operands[0], operands[1], <MODE>mode, <V_F2DI_CONVERT>mode);
2719 ;; Implement rawmemchr[qi|si|hi].
2720 (define_expand "rawmemchr<ANYI:mode>"
2721 [(match_operand 0 "register_operand")
2722 (match_operand 1 "memory_operand")
2723 (match_operand:ANYI 2 "const_int_operand")]
2724 "TARGET_VECTOR && !TARGET_XTHEADVECTOR"
2726 riscv_vector::expand_rawmemchr(<MODE>mode, operands[0], operands[1],
2732 ;; =========================================================================
2733 ;; == [INT] Saturation ALU.
2734 ;; =========================================================================
2739 ;; =========================================================================
2740 (define_expand "usadd<mode>3"
2741 [(match_operand:V_VLSI 0 "register_operand")
2742 (match_operand:V_VLSI 1 "register_operand")
2743 (match_operand:V_VLSI 2 "register_operand")]
2746 riscv_vector::expand_vec_usadd (operands[0], operands[1], operands[2], <MODE>mode);
2751 (define_expand "ssadd<mode>3"
2752 [(match_operand:V_VLSI 0 "register_operand")
2753 (match_operand:V_VLSI 1 "register_operand")
2754 (match_operand:V_VLSI 2 "register_operand")]
2757 riscv_vector::expand_vec_ssadd (operands[0], operands[1], operands[2], <MODE>mode);
2762 (define_expand "ussub<mode>3"
2763 [(match_operand:V_VLSI 0 "register_operand")
2764 (match_operand:V_VLSI 1 "register_operand")
2765 (match_operand:V_VLSI 2 "register_operand")]
2768 riscv_vector::expand_vec_ussub (operands[0], operands[1], operands[2], <MODE>mode);
2773 (define_expand "sssub<mode>3"
2774 [(match_operand:V_VLSI 0 "register_operand")
2775 (match_operand:V_VLSI 1 "register_operand")
2776 (match_operand:V_VLSI 2 "register_operand")]
2779 riscv_vector::expand_vec_sssub (operands[0], operands[1], operands[2], <MODE>mode);
2784 (define_expand "ustrunc<mode><v_double_trunc>2"
2785 [(match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
2786 (match_operand:VWEXTI 1 "register_operand")]
2789 riscv_vector::expand_vec_double_ustrunc (operands[0], operands[1],
2795 (define_expand "ustrunc<mode><v_quad_trunc>2"
2796 [(match_operand:<V_QUAD_TRUNC> 0 "register_operand")
2797 (match_operand:VQEXTI 1 "register_operand")]
2800 riscv_vector::expand_vec_quad_ustrunc (operands[0], operands[1], <MODE>mode,
2801 <V_DOUBLE_TRUNC>mode);
2806 (define_expand "ustrunc<mode><v_oct_trunc>2"
2807 [(match_operand:<V_OCT_TRUNC> 0 "register_operand")
2808 (match_operand:VOEXTI 1 "register_operand")]
2811 riscv_vector::expand_vec_oct_ustrunc (operands[0], operands[1], <MODE>mode,
2812 <V_DOUBLE_TRUNC>mode,
2813 <V_QUAD_TRUNC>mode);
2818 (define_expand "sstrunc<mode><v_double_trunc>2"
2819 [(match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
2820 (match_operand:VWEXTI 1 "register_operand")]
2823 riscv_vector::expand_vec_double_sstrunc (operands[0], operands[1],
2829 (define_expand "sstrunc<mode><v_quad_trunc>2"
2830 [(match_operand:<V_QUAD_TRUNC> 0 "register_operand")
2831 (match_operand:VQEXTI 1 "register_operand")]
2834 riscv_vector::expand_vec_quad_sstrunc (operands[0], operands[1], <MODE>mode,
2835 <V_DOUBLE_TRUNC>mode);
2840 (define_expand "sstrunc<mode><v_oct_trunc>2"
2841 [(match_operand:<V_OCT_TRUNC> 0 "register_operand")
2842 (match_operand:VOEXTI 1 "register_operand")]
2845 riscv_vector::expand_vec_oct_sstrunc (operands[0], operands[1], <MODE>mode,
2846 <V_DOUBLE_TRUNC>mode,
2847 <V_QUAD_TRUNC>mode);
2852 ;; =========================================================================
2853 ;; == Early break auto-vectorization patterns
2854 ;; =========================================================================
2856 ;; vcond_mask_len (mask, 1s, 0s, len, bias)
2857 ;; => mask[i] = mask[i] && i < len ? 1 : 0
2858 (define_insn_and_split "vcond_mask_len_<mode>"
2859 [(set (match_operand:VB 0 "register_operand")
2861 (match_operand:VB 1 "register_operand")
2862 (match_operand:VB 2 "const_1_operand")
2863 (match_operand:VB 3 "const_0_operand")
2864 (match_operand 4 "autovec_length_operand")
2865 (match_operand 5 "const_0_operand")] UNSPEC_SELECT_MASK))]
2867 && can_create_pseudo_p ()
2868 && riscv_vector::get_vector_mode (Pmode, GET_MODE_NUNITS (<MODE>mode)).exists ()"
2873 machine_mode mode = riscv_vector::get_vector_mode (Pmode,
2874 GET_MODE_NUNITS (<MODE>mode)).require ();
2875 rtx reg = gen_reg_rtx (mode);
2876 riscv_vector::expand_vec_series (reg, const0_rtx, const1_rtx);
2877 rtx dup_rtx = gen_rtx_VEC_DUPLICATE (mode, operands[4]);
2878 insn_code icode = code_for_pred_cmp_scalar (mode);
2879 rtx cmp = gen_rtx_fmt_ee (LTU, <MODE>mode, reg, dup_rtx);
2880 rtx ops[] = {operands[0], operands[1], operands[1], cmp, reg, operands[4]};
2881 emit_vlmax_insn (icode, riscv_vector::COMPARE_OP_MU, ops);
2884 [(set_attr "type" "vector")])
2887 (define_expand "cbranch<mode>4"
2890 (match_operator 0 "equality_operator"
2891 [(match_operand:VB_VLS 1 "register_operand")
2892 (match_operand:VB_VLS 2 "reg_or_0_operand")])
2893 (label_ref (match_operand 3 ""))
2898 if (operands[2] == CONST0_RTX (<MODE>mode))
2901 pred = expand_binop (<MODE>mode, xor_optab, operands[1],
2902 operands[2], NULL_RTX, 0,
2904 rtx reg = gen_reg_rtx (Pmode);
2905 rtx cpop_ops[] = {reg, pred};
2906 emit_vlmax_insn (code_for_pred_popcount (<MODE>mode, Pmode),
2907 riscv_vector::CPOP_OP, cpop_ops);
2909 operands[2] = const0_rtx;
2913 ;; -------------------------------------------------------------------------
2914 ;; - vrol.vv vror.vv
2915 ;; -------------------------------------------------------------------------
2916 (define_expand "v<bitmanip_optab><mode>3"
2917 [(set (match_operand:VI 0 "register_operand")
2919 (match_operand:VI 1 "register_operand")
2920 (match_operand:VI 2 "register_operand")))]
2921 "TARGET_ZVBB || TARGET_ZVKB"
2923 riscv_vector::emit_vlmax_insn (code_for_pred_v (<CODE>, <MODE>mode),
2924 riscv_vector::BINARY_OP, operands);
2929 ;; =========================================================================
2930 ;; == Strided Load/Store
2931 ;; =========================================================================
2932 (define_expand "mask_len_strided_load_<mode>"
2933 [(match_operand:V_VLS 0 "register_operand")
2934 (match_operand 1 "pmode_reg_or_0_operand")
2935 (match_operand 2 "pmode_reg_or_0_operand")
2936 (match_operand:<VM> 3 "vector_mask_operand")
2937 (match_operand 4 "maskload_else_operand")
2938 (match_operand 5 "autovec_length_operand")
2939 (match_operand 6 "const_0_operand")]
2942 riscv_vector::expand_strided_load (<MODE>mode, operands);
2946 (define_expand "mask_len_strided_store_<mode>"
2947 [(match_operand 0 "pmode_reg_or_0_operand")
2948 (match_operand 1 "pmode_reg_or_0_operand")
2949 (match_operand:V_VLS 2 "register_operand")
2950 (match_operand:<VM> 3 "vector_mask_operand")
2951 (match_operand 4 "autovec_length_operand")
2952 (match_operand 5 "const_0_operand")]
2955 riscv_vector::expand_strided_store (<MODE>mode, operands);
2960 ; == Absolute difference (not including sum)
2962 (define_expand "uabd<mode>3"
2963 [(match_operand:V_VLSI 0 "register_operand")
2964 (match_operand:V_VLSI 1 "register_operand")
2965 (match_operand:V_VLSI 2 "register_operand")]
2968 rtx max = gen_reg_rtx (<MODE>mode);
2969 insn_code icode = code_for_pred (UMAX, <MODE>mode);
2970 rtx ops1[] = {max, operands[1], operands[2]};
2971 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
2973 rtx min = gen_reg_rtx (<MODE>mode);
2974 icode = code_for_pred (UMIN, <MODE>mode);
2975 rtx ops2[] = {min, operands[1], operands[2]};
2976 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
2978 icode = code_for_pred (MINUS, <MODE>mode);
2979 rtx ops3[] = {operands[0], max, min};
2980 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3);