1 ;; Machine description for optimization of RVV auto-vectorization.
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 ;; -----------------------------------------------------------------------------
22 ;; ---- Integer Compare Instructions Simplification
23 ;; -----------------------------------------------------------------------------
24 ;; Simplify OP(V, V) Instructions to VMCLR.m Includes:
30 ;; -----------------------------------------------------------------------------
31 ;; Simplify OP(V, V) Instructions to VMSET.m Includes:
37 ;; -----------------------------------------------------------------------------
40 [(set (match_operand:VB 0 "register_operand")
43 [(match_operand:VB 1 "vector_all_trues_mask_operand")
44 (match_operand 4 "vector_length_operand")
45 (match_operand 5 "const_int_operand")
46 (match_operand 6 "const_int_operand")
48 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
49 (match_operand:VB 3 "vector_move_operand")
50 (match_operand:VB 2 "vector_undef_operand")))]
54 emit_insn (gen_pred_mov (<MODE>mode, operands[0], CONST1_RTX (<MODE>mode),
55 RVV_VUNDEF (<MODE>mode), operands[3],
56 operands[4], operands[5]));
61 ;; -------------------------------------------------------------------------
62 ;; ---- Sign-extension for vmv.x.s.
63 ;; -------------------------------------------------------------------------
64 (define_insn "*pred_extract_first_sextdi<mode>"
65 [(set (match_operand:DI 0 "register_operand" "=r")
69 (match_operand:VI_QHS 1 "register_operand""vr")
70 (parallel [(const_int 0)]))
71 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))]
72 "TARGET_VECTOR && Pmode == DImode"
74 [(set_attr "type" "vimovvx")
75 (set_attr "mode" "<MODE>")])
77 (define_insn "*pred_extract_first_sextsi<mode>"
78 [(set (match_operand:SI 0 "register_operand" "=r")
82 (match_operand:VI_QH 1 "register_operand" "vr")
83 (parallel [(const_int 0)]))
84 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))]
85 "TARGET_VECTOR && Pmode == SImode"
87 [(set_attr "type" "vimovvx")
88 (set_attr "mode" "<MODE>")])
90 ;; =============================================================================
91 ;; All combine patterns for combine pass.
92 ;; =============================================================================
94 ;; =============================================================================
95 ;; Combine op + vmerge to cond_op
96 ;; =============================================================================
98 ;; Combine <op> and vcond_mask generated by midend into cond_len_<op>
99 ;; Currently supported operations:
101 (define_insn_and_split "*cond_abs<mode>"
102 [(set (match_operand:V_VLSF 0 "register_operand")
104 (match_operand:<VM> 1 "register_operand")
105 (abs:V_VLSF (match_operand:V_VLSF 2 "nonmemory_operand"))
106 (match_operand:V_VLSF 3 "register_operand")))]
107 "TARGET_VECTOR && can_create_pseudo_p ()"
112 insn_code icode = code_for_pred (ABS, <MODE>mode);
113 riscv_vector::expand_cond_unop (icode, operands);
116 [(set_attr "type" "vector")])
118 ;; Combine vfsqrt.v and cond_mask
119 (define_insn_and_split "*cond_<optab><mode>"
120 [(set (match_operand:V_VLSF 0 "register_operand")
122 (match_operand:<VM> 1 "register_operand")
123 (any_float_unop:V_VLSF
124 (match_operand:V_VLSF 2 "register_operand"))
125 (match_operand:V_VLSF 3 "register_operand")))]
126 "TARGET_VECTOR && can_create_pseudo_p ()"
131 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
132 riscv_vector::expand_cond_unop (icode, operands);
135 [(set_attr "type" "vector")])
137 ;; Combine sign_extend/zero_extend(vf2) and vcond_mask
138 (define_insn_and_split "*cond_<optab><v_double_trunc><mode>"
139 [(set (match_operand:VWEXTI 0 "register_operand")
141 (match_operand:<VM> 1 "register_operand")
142 (any_extend:VWEXTI (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
143 (match_operand:VWEXTI 3 "register_operand")))]
144 "TARGET_VECTOR && can_create_pseudo_p ()"
149 insn_code icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
150 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
151 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
152 riscv_vector::expand_cond_len_unop (icode, ops);
155 [(set_attr "type" "vector")])
157 ;; Combine sign_extend/zero_extend(vf4) and vcond_mask
158 (define_insn_and_split "*cond_<optab><v_quad_trunc><mode>"
159 [(set (match_operand:VQEXTI 0 "register_operand")
161 (match_operand:<VM> 1 "register_operand")
162 (any_extend:VQEXTI (match_operand:<V_QUAD_TRUNC> 2 "register_operand"))
163 (match_operand:VQEXTI 3 "register_operand")))]
164 "TARGET_VECTOR && can_create_pseudo_p ()"
169 insn_code icode = code_for_pred_vf4 (<CODE>, <MODE>mode);
170 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
171 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
172 riscv_vector::expand_cond_len_unop (icode, ops);
175 [(set_attr "type" "vector")])
177 ;; Combine sign_extend/zero_extend(vf8) and vcond_mask
178 (define_insn_and_split "*cond_<optab><v_oct_trunc><mode>"
179 [(set (match_operand:VOEXTI 0 "register_operand")
181 (match_operand:<VM> 1 "register_operand")
182 (any_extend:VOEXTI (match_operand:<V_OCT_TRUNC> 2 "register_operand"))
183 (match_operand:VOEXTI 3 "register_operand")))]
184 "TARGET_VECTOR && can_create_pseudo_p ()"
189 insn_code icode = code_for_pred_vf8 (<CODE>, <MODE>mode);
190 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
191 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
192 riscv_vector::expand_cond_len_unop (icode, ops);
195 [(set_attr "type" "vector")])
197 ;; Combine sign_extend/zero_extend(vf2) and vcond_mask_len
198 (define_insn_and_split "*cond_len_<optab><v_double_trunc><mode>"
199 [(set (match_operand:VWEXTI 0 "register_operand")
202 [(match_operand 4 "vector_length_operand")
203 (match_operand 5 "const_int_operand")
204 (match_operand 6 "const_int_operand")
206 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
208 (any_extend:VWEXTI (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
209 (match_operand:VWEXTI 1 "vector_merge_operand")
210 (match_operand:<VM> 3 "register_operand"))
217 emit_insn (gen_pred_<optab><mode>_vf2 (operands[0], operands[3], operands[1], operands[2],
218 operands[4], operands[5], operands[6], CONST0_RTX (Pmode)));
221 [(set_attr "type" "vector")])
223 ;; Combine sign_extend/zero_extend(vf4) and vcond_mask_len
224 (define_insn_and_split "*cond_len_<optab><v_quad_trunc><mode>"
225 [(set (match_operand:VQEXTI 0 "register_operand")
228 [(match_operand 4 "vector_length_operand")
229 (match_operand 5 "const_int_operand")
230 (match_operand 6 "const_int_operand")
232 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
234 (any_extend:VQEXTI (match_operand:<V_QUAD_TRUNC> 2 "register_operand"))
235 (match_operand:VQEXTI 1 "vector_merge_operand")
236 (match_operand:<VM> 3 "register_operand"))
243 emit_insn (gen_pred_<optab><mode>_vf4 (operands[0], operands[3], operands[1], operands[2],
244 operands[4], operands[5], operands[6], CONST0_RTX (Pmode)));
247 [(set_attr "type" "vector")])
249 ;; Combine sign_extend/zero_extend(vf8) and vcond_mask_len
250 (define_insn_and_split "*cond_len_<optab><v_oct_trunc><mode>"
251 [(set (match_operand:VOEXTI 0 "register_operand")
254 [(match_operand 4 "vector_length_operand")
255 (match_operand 5 "const_int_operand")
256 (match_operand 6 "const_int_operand")
258 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
260 (any_extend:VOEXTI (match_operand:<V_OCT_TRUNC> 2 "register_operand"))
261 (match_operand:VOEXTI 1 "vector_merge_operand")
262 (match_operand:<VM> 3 "register_operand"))
269 emit_insn (gen_pred_<optab><mode>_vf8 (operands[0], operands[3], operands[1], operands[2],
270 operands[4], operands[5], operands[6], CONST0_RTX (Pmode)));
273 [(set_attr "type" "vector")])
275 ;; Combine trunc(vf2) + vcond_mask
276 (define_insn_and_split "*cond_trunc<mode><v_double_trunc>"
277 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
278 (if_then_else:<V_DOUBLE_TRUNC>
279 (match_operand:<VM> 1 "register_operand")
280 (truncate:<V_DOUBLE_TRUNC>
281 (match_operand:VWEXTI 2 "register_operand"))
282 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))]
283 "TARGET_VECTOR && can_create_pseudo_p ()"
288 insn_code icode = code_for_pred_trunc (<MODE>mode);
289 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
290 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
291 riscv_vector::expand_cond_len_unop (icode, ops);
294 [(set_attr "type" "vector")])
296 ;; Combine FP extend(vf2) and vcond_mask
297 (define_insn_and_split "*cond_extend<v_double_trunc><mode>"
298 [(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand")
299 (if_then_else:VWEXTF_ZVFHMIN
300 (match_operand:<VM> 1 "register_operand")
301 (float_extend:VWEXTF_ZVFHMIN (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
302 (match_operand:VWEXTF_ZVFHMIN 3 "register_operand")))]
303 "TARGET_VECTOR && can_create_pseudo_p ()"
308 insn_code icode = code_for_pred_extend (<MODE>mode);
309 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
310 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
311 riscv_vector::expand_cond_len_unop (icode, ops);
314 [(set_attr "type" "vector")])
316 ;; Combine FP extend(vf2) and vcond_mask_len
317 (define_insn_and_split "*cond_len_extend<v_double_trunc><mode>"
318 [(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand")
319 (if_then_else:VWEXTF_ZVFHMIN
321 [(match_operand 4 "vector_length_operand")
322 (match_operand 5 "const_int_operand")
323 (match_operand 6 "const_int_operand")
325 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
326 (vec_merge:VWEXTF_ZVFHMIN
327 (float_extend:VWEXTF_ZVFHMIN (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
328 (match_operand:VWEXTF_ZVFHMIN 1 "vector_merge_operand")
329 (match_operand:<VM> 3 "register_operand"))
336 emit_insn (gen_pred_extend<mode> (operands[0], operands[3], operands[1], operands[2],
337 operands[4], operands[5], operands[6], CONST0_RTX (Pmode)));
340 [(set_attr "type" "vector")])
342 ;; Combine FP trunc(vf2) + vcond_mask
343 (define_insn_and_split "*cond_trunc<mode><v_double_trunc>"
344 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
345 (if_then_else:<V_DOUBLE_TRUNC>
346 (match_operand:<VM> 1 "register_operand")
347 (float_truncate:<V_DOUBLE_TRUNC>
348 (match_operand:VWEXTF_ZVFHMIN 2 "register_operand"))
349 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))]
350 "TARGET_VECTOR && can_create_pseudo_p ()"
355 insn_code icode = code_for_pred_trunc (<MODE>mode);
356 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
357 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
358 riscv_vector::expand_cond_len_unop (icode, ops);
361 [(set_attr "type" "vector")])
363 ;; Combine convert(FP->INT) + vcond_mask
364 (define_insn_and_split "*cond_<optab><mode><vconvert>"
365 [(set (match_operand:<VCONVERT> 0 "register_operand")
366 (if_then_else:<VCONVERT>
367 (match_operand:<VM> 1 "register_operand")
369 (match_operand:V_VLSF 2 "register_operand"))
370 (match_operand:<VCONVERT> 3 "register_operand")))]
371 "TARGET_VECTOR && can_create_pseudo_p ()"
376 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
377 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
378 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
379 riscv_vector::expand_cond_len_unop (icode, ops);
382 [(set_attr "type" "vector")])
384 ;; Combine convert(INT->FP) + vcond_mask
385 (define_insn_and_split "*cond_<float_cvt><vconvert><mode>"
386 [(set (match_operand:V_VLSF 0 "register_operand")
388 (match_operand:<VM> 1 "register_operand")
390 (match_operand:<VCONVERT> 2 "register_operand"))
391 (match_operand:V_VLSF 3 "register_operand")))]
392 "TARGET_VECTOR && can_create_pseudo_p ()"
397 insn_code icode = code_for_pred (<CODE>, <MODE>mode);
398 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
399 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
400 riscv_vector::expand_cond_len_unop (icode, ops);
403 [(set_attr "type" "vector")])
405 ;; Combine convert(FP->2xINT) + vcond_mask
406 (define_insn_and_split "*cond_<optab><vnconvert><mode>"
407 [(set (match_operand:VWCONVERTI 0 "register_operand")
408 (if_then_else:VWCONVERTI
409 (match_operand:<VM> 1 "register_operand")
411 (match_operand:<VNCONVERT> 2 "register_operand"))
412 (match_operand:VWCONVERTI 3 "register_operand")))]
413 "TARGET_VECTOR && can_create_pseudo_p ()"
418 insn_code icode = code_for_pred_widen (<CODE>, <MODE>mode);
419 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
420 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
421 riscv_vector::expand_cond_len_unop (icode, ops);
424 [(set_attr "type" "vector")])
426 ;; Combine convert(INT->2xFP) + vcond_mask
427 (define_insn_and_split "*cond_<float_cvt><vnconvert><mode>"
428 [(set (match_operand:V_VLSF 0 "register_operand")
430 (match_operand:<VM> 1 "register_operand")
432 (match_operand:<VNCONVERT> 2 "register_operand"))
433 (match_operand:V_VLSF 3 "register_operand")))]
434 "TARGET_VECTOR && can_create_pseudo_p ()"
439 insn_code icode = code_for_pred_widen (<CODE>, <MODE>mode);
440 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
441 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
442 riscv_vector::expand_cond_len_unop (icode, ops);
445 [(set_attr "type" "vector")])
447 ;; Combine convert(2xFP->INT) + vcond_mask
448 (define_insn_and_split "*cond_<optab><mode><vnconvert>"
449 [(set (match_operand:<VNCONVERT> 0 "register_operand")
450 (if_then_else:<VNCONVERT>
451 (match_operand:<VM> 1 "register_operand")
453 (match_operand:V_VLSF 2 "register_operand"))
454 (match_operand:<VNCONVERT> 3 "register_operand")))]
455 "TARGET_VECTOR && can_create_pseudo_p ()"
460 insn_code icode = code_for_pred_narrow (<CODE>, <MODE>mode);
461 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
462 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
463 riscv_vector::expand_cond_len_unop (icode, ops);
466 [(set_attr "type" "vector")])
468 ;; Combine convert(2xINT->FP) + vcond_mask
469 (define_insn_and_split "*cond_<float_cvt><mode><vnconvert>2"
470 [(set (match_operand:<VNCONVERT> 0 "register_operand")
471 (if_then_else:<VNCONVERT>
472 (match_operand:<VM> 1 "register_operand")
473 (any_float:<VNCONVERT>
474 (match_operand:VWCONVERTI 2 "register_operand"))
475 (match_operand:<VNCONVERT> 3 "register_operand")))]
476 "TARGET_VECTOR && can_create_pseudo_p ()"
481 insn_code icode = code_for_pred_narrow (<CODE>, <MODE>mode);
482 rtx ops[] = {operands[0], operands[1], operands[2], operands[3],
483 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
484 riscv_vector::expand_cond_len_unop (icode, ops);
487 [(set_attr "type" "vector")])
489 ;; Combine vnsra + vcond_mask
490 (define_insn_and_split "*cond_v<any_shiftrt:optab><any_extend:optab>trunc<mode>"
491 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
492 (if_then_else:<V_DOUBLE_TRUNC>
493 (match_operand:<VM> 1 "register_operand")
494 (truncate:<V_DOUBLE_TRUNC>
496 (match_operand:VWEXTI 2 "register_operand")
498 (match_operand:<V_DOUBLE_TRUNC> 3 "vector_shift_operand"))))
499 (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand")))]
500 "TARGET_VECTOR && can_create_pseudo_p ()"
505 insn_code icode = code_for_pred_narrow (<any_shiftrt:CODE>, <MODE>mode);
506 rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[4],
507 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
508 riscv_vector::expand_cond_len_binop (icode, ops);
511 [(set_attr "type" "vnshift")])
513 (define_insn_and_split "*cond_<any_shiftrt:optab>trunc<mode>"
514 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand")
515 (if_then_else:<V_DOUBLE_TRUNC>
516 (match_operand:<VM> 1 "register_operand")
517 (truncate:<V_DOUBLE_TRUNC>
519 (match_operand:VWEXTI 2 "register_operand")
520 (match_operand:<VEL> 3 "csr_operand")))
521 (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand")))]
522 "TARGET_VECTOR && can_create_pseudo_p ()"
527 insn_code icode = code_for_pred_narrow_scalar (<any_shiftrt:CODE>, <MODE>mode);
528 rtx ops[] = {operands[0], operands[1], operands[2], gen_lowpart (Pmode, operands[3]),
529 operands[4], gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
530 riscv_vector::expand_cond_len_binop (icode, ops);
533 [(set_attr "type" "vnshift")])
535 ;; Combine vmulh.vv/vmulhu.vv + vcond_mask
536 (define_insn_and_split "*cond_<mulh_table><mode>3_highpart"
537 [(set (match_operand:VFULLI 0 "register_operand")
539 (match_operand:<VM> 1 "register_operand")
541 (match_operand:VFULLI 2 "register_operand")
542 (match_operand:VFULLI 3 "register_operand"))
543 (match_operand:VFULLI 4 "register_operand")))]
544 "TARGET_VECTOR && can_create_pseudo_p ()"
549 insn_code icode = code_for_pred_mulh (<MULH_UNSPEC>, <MODE>mode);
550 rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[4],
551 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
552 riscv_vector::expand_cond_len_binop (icode, ops);
555 [(set_attr "type" "vector")])
557 ;; =============================================================================
558 ;; Combine binop + trunc to narrow_binop
559 ;; =============================================================================
561 ;; Combine vsr[la].vv + trunc to vnsr[la].wv
562 (define_insn_and_split "*narrow_<any_shiftrt:optab><any_extend:optab><mode>"
563 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr,vr")
564 (truncate:<V_DOUBLE_TRUNC>
566 (match_operand:VWEXTI 1 "register_operand" " vr,vr")
568 (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" " vr,vk")))))]
569 "TARGET_VECTOR && can_create_pseudo_p ()"
574 insn_code icode = code_for_pred_narrow (<any_shiftrt:CODE>, <MODE>mode);
575 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
578 [(set_attr "type" "vnshift")])
580 ;; Combine vsr[la].w[xi] + trunc to vnsr[la].w[xi]
581 (define_insn_and_split "*narrow_<any_shiftrt:optab><mode>_scalar"
582 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr")
583 (truncate:<V_DOUBLE_TRUNC>
585 (match_operand:VWEXTI 1 "register_operand" " vr")
586 (match_operand:<VEL> 2 "csr_operand" " rK"))))]
587 "TARGET_VECTOR && can_create_pseudo_p ()"
592 operands[2] = gen_lowpart (Pmode, operands[2]);
593 insn_code icode = code_for_pred_narrow_scalar (<any_shiftrt:CODE>, <MODE>mode);
594 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
597 [(set_attr "type" "vnshift")])
599 ;; =============================================================================
600 ;; Combine extend + binop to widen_binop
601 ;; =============================================================================
603 (define_insn_and_split "*dual_widen_<any_widen_binop:optab><any_extend:su><mode>"
604 [(set (match_operand:VWEXTI 0 "register_operand")
605 (any_widen_binop:VWEXTI
607 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
609 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
610 "TARGET_VECTOR && can_create_pseudo_p ()"
615 insn_code icode = code_for_pred_dual_widen (<any_widen_binop:CODE>,
618 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
621 [(set_attr "type" "vector")])
623 (define_insn_and_split "*single_widen_sub<any_extend:su><mode>"
624 [(set (match_operand:VWEXTI 0 "register_operand")
626 (match_operand:VWEXTI 1 "register_operand")
628 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
629 "TARGET_VECTOR && can_create_pseudo_p ()"
634 insn_code icode = code_for_pred_single_widen_sub (<any_extend:CODE>,
636 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
639 [(set_attr "type" "viwalu")])
641 (define_insn_and_split "*single_widen_add<any_extend:su><mode>"
642 [(set (match_operand:VWEXTI 0 "register_operand")
645 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
646 (match_operand:VWEXTI 1 "register_operand")))]
647 "TARGET_VECTOR && can_create_pseudo_p ()"
652 insn_code icode = code_for_pred_single_widen_add (<any_extend:CODE>,
654 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
657 [(set_attr "type" "viwalu")])
659 ;; This combine pattern does not correspond to an single instruction,
660 ;; i.e. there is no vwmul.wv instruction. This is a temporary pattern
661 ;; produced by a combine pass and if there is no further combine into
662 ;; vwmul.vv pattern, then fall back to extend pattern and vmul.vv pattern.
663 (define_insn_and_split "*single_widen_mul<any_extend:su><mode>"
664 [(set (match_operand:VWEXTI 0 "register_operand")
667 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
668 (match_operand:VWEXTI 1 "register_operand")))]
669 "TARGET_VECTOR && can_create_pseudo_p ()"
674 insn_code extend_icode = code_for_pred_vf2 (<any_extend:CODE>, <MODE>mode);
675 rtx tmp = gen_reg_rtx (<MODE>mode);
676 rtx extend_ops[] = {tmp, operands[2]};
677 riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops);
679 rtx ops[] = {operands[0], operands[1], tmp};
680 insn_code icode = code_for_pred (MULT, <MODE>mode);
681 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
684 [(set_attr "type" "viwmul")])
686 (define_insn_and_split "*dual_widen_mulsu<mode>"
687 [(set (match_operand:VWEXTI 0 "register_operand")
690 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
692 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
693 "TARGET_VECTOR && can_create_pseudo_p ()"
698 insn_code icode = code_for_pred_widen_mulsu (<MODE>mode);
699 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
702 [(set_attr "type" "vector")])
704 (define_insn_and_split "*dual_widen_mulus<mode>"
705 [(set (match_operand:VWEXTI 0 "register_operand")
708 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
710 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))))]
711 "TARGET_VECTOR && can_create_pseudo_p ()"
716 insn_code icode = code_for_pred_widen_mulsu (<MODE>mode);
717 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
720 [(set_attr "type" "vector")])
722 (define_insn_and_split "*dual_widen_<optab><mode>"
723 [(set (match_operand:VWEXTF 0 "register_operand")
724 (any_widen_binop:VWEXTF
726 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
728 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
729 "TARGET_VECTOR && can_create_pseudo_p ()"
734 insn_code icode = code_for_pred_dual_widen (<CODE>, <MODE>mode);
735 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
738 [(set_attr "type" "vector")])
740 (define_insn_and_split "*single_widen_add<mode>"
741 [(set (match_operand:VWEXTF 0 "register_operand")
744 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
745 (match_operand:VWEXTF 1 "register_operand")))]
746 "TARGET_VECTOR && can_create_pseudo_p ()"
751 insn_code icode = code_for_pred_single_widen_add (<MODE>mode);
752 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
755 [(set_attr "type" "vfwalu")])
757 (define_insn_and_split "*single_widen_sub<mode>"
758 [(set (match_operand:VWEXTF 0 "register_operand")
760 (match_operand:VWEXTF 1 "register_operand")
762 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
763 "TARGET_VECTOR && can_create_pseudo_p ()"
768 insn_code icode = code_for_pred_single_widen_sub (<MODE>mode);
769 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands);
772 [(set_attr "type" "vfwalu")])
774 ;; This combine pattern does not correspond to an single instruction,
775 ;; i.e. there is no vfwmul.wv instruction. This is a temporary pattern
776 ;; produced by a combine pass and if there is no further combine into
777 ;; vfwmul.vv pattern, then fall back to extend pattern and vfmul.vv pattern.
778 (define_insn_and_split "*single_widen_mul<mode>"
779 [(set (match_operand:VWEXTF 0 "register_operand")
782 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
783 (match_operand:VWEXTF 1 "register_operand")))]
784 "TARGET_VECTOR && can_create_pseudo_p ()"
789 insn_code extend_icode = code_for_pred_extend (<MODE>mode);
790 rtx tmp = gen_reg_rtx (<MODE>mode);
791 rtx extend_ops[] = {tmp, operands[2]};
792 riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops);
794 rtx ops[] = {operands[0], operands[1], tmp};
795 riscv_vector::emit_vlmax_insn (code_for_pred (MULT, <MODE>mode),
796 riscv_vector::BINARY_OP_FRM_DYN, ops);
799 [(set_attr "type" "vfwmul")])
801 ;; Combine extend + vredsum to vwredsum[u]
802 (define_insn_and_split "*widen_reduc_plus_scal_<mode>"
803 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
804 (unspec:<V_DOUBLE_EXTEND_VEL> [
805 (any_extend:<V_DOUBLE_EXTEND>
806 (match_operand:VI_QHS_NO_M8 1 "register_operand"))
807 ] UNSPEC_REDUC_SUM))]
808 "TARGET_VECTOR && can_create_pseudo_p ()"
813 riscv_vector::expand_reduction (<WREDUC_UNSPEC>, <WREDUC_UNSPEC_VL0_SAFE>,
814 riscv_vector::REDUCE_OP,
816 CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
819 [(set_attr "type" "vector")])
821 ;; Combine extend + vfredusum to vfwredusum
822 (define_insn_and_split "*widen_reduc_plus_scal_<mode>"
823 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
824 (unspec:<V_DOUBLE_EXTEND_VEL> [
825 (float_extend:<V_DOUBLE_EXTEND>
826 (match_operand:VF_HS_NO_M8 1 "register_operand"))
827 ] UNSPEC_REDUC_SUM_UNORDERED))]
828 "TARGET_VECTOR && can_create_pseudo_p ()"
833 riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
834 UNSPEC_WREDUC_SUM_UNORDERED_VL0_SAFE,
835 riscv_vector::REDUCE_OP_FRM_DYN,
837 CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
840 [(set_attr "type" "vector")])
842 ;; Combine extend + vfredosum to vfwredosum
843 (define_insn_and_split "*fold_left_widen_plus_<mode>"
844 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
845 (unspec:<V_DOUBLE_EXTEND_VEL> [
846 (float_extend:<V_DOUBLE_EXTEND>
847 (match_operand:VF_HS_NO_M8 1 "register_operand"))
848 (match_operand:<V_DOUBLE_EXTEND_VEL> 2 "register_operand")
849 ] UNSPEC_REDUC_SUM_ORDERED))]
850 "TARGET_VECTOR && can_create_pseudo_p ()"
855 riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_ORDERED,
856 UNSPEC_WREDUC_SUM_ORDERED_VL0_SAFE,
857 riscv_vector::REDUCE_OP_FRM_DYN,
858 operands, operands[2]);
861 [(set_attr "type" "vector")])
863 ;; Combine extend + mask vfredosum to mask vfwredosum
864 (define_insn_and_split "*mask_len_fold_left_widen_plus_<mode>"
865 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
866 (unspec:<V_DOUBLE_EXTEND_VEL> [
867 (float_extend:<V_DOUBLE_EXTEND>
868 (match_operand:VF_HS_NO_M8 2 "register_operand"))
869 (match_operand:<V_DOUBLE_EXTEND_VEL> 1 "register_operand")
870 (match_operand:<VM> 3 "vector_mask_operand")
871 (match_operand 4 "autovec_length_operand")
872 (match_operand 5 "const_0_operand")
873 ] UNSPEC_REDUC_SUM_ORDERED))]
874 "TARGET_VECTOR && can_create_pseudo_p ()"
879 if (rtx_equal_p (operands[4], const0_rtx))
880 emit_move_insn (operands[0], operands[1]);
883 rtx ops[] = {operands[0], operands[2], operands[3], operands[4]};
884 riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_ORDERED,
885 UNSPEC_WREDUC_SUM_ORDERED_VL0_SAFE,
886 riscv_vector::REDUCE_OP_M_FRM_DYN,
891 [(set_attr "type" "vector")])
893 ;; =============================================================================
894 ;; Combine extend + ternop to widen_ternop
895 ;; =============================================================================
897 ;; Combine ext + fma(vmacc,vmadd) to widen_fma (vwmacc[u])
898 (define_insn_and_split "*dual_widen_fma<su><mode>"
899 [(set (match_operand:VWEXTI 0 "register_operand")
903 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
905 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
906 (match_operand:VWEXTI 1 "register_operand")))]
907 "TARGET_VECTOR && can_create_pseudo_p ()"
912 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
913 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plus (<CODE>, <MODE>mode),
914 riscv_vector::WIDEN_TERNARY_OP, ops);
917 [(set_attr "type" "viwmuladd")])
919 ;; Combine sign_extend + zero_extend + fma to widen_fma (vwmaccsu)
920 (define_insn_and_split "*dual_widen_fmasu<mode>"
921 [(set (match_operand:VWEXTI 0 "register_operand")
925 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
927 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
928 (match_operand:VWEXTI 1 "register_operand")))]
929 "TARGET_VECTOR && can_create_pseudo_p ()"
934 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
935 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
936 riscv_vector::WIDEN_TERNARY_OP, ops);
939 [(set_attr "type" "viwmuladd")])
941 ;; Combine zero_extend + sign_extend + fma to widen_fma (vwmaccsu)
942 (define_insn_and_split "*dual_widen_fmaus<mode>"
943 [(set (match_operand:VWEXTI 0 "register_operand")
947 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"))
949 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
950 (match_operand:VWEXTI 1 "register_operand")))]
951 "TARGET_VECTOR && can_create_pseudo_p ()"
956 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
957 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
958 riscv_vector::WIDEN_TERNARY_OP, ops);
961 [(set_attr "type" "viwmuladd")])
963 ;; This combine pattern does not correspond to an single instruction.
964 ;; This is a temporary pattern produced by a combine pass and if there
965 ;; is no further combine into widen pattern, then fall back to extend
966 ;; pattern and non-widen fma pattern.
967 (define_insn_and_split "*single_widen_fma<su><mode>"
968 [(set (match_operand:VWEXTI 0 "register_operand")
972 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
973 (match_operand:VWEXTI 3 "register_operand"))
974 (match_operand:VWEXTI 1 "register_operand")))]
975 "TARGET_VECTOR && can_create_pseudo_p ()"
980 insn_code extend_icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
981 rtx tmp = gen_reg_rtx (<MODE>mode);
982 rtx extend_ops[] = {tmp, operands[2]};
983 riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP,
986 rtx ops[] = {operands[0], tmp, operands[3], operands[1],
987 RVV_VUNDEF(<MODE>mode)};
988 riscv_vector::emit_vlmax_insn (code_for_pred_mul_plus (<MODE>mode),
989 riscv_vector::TERNARY_OP, ops);
992 [(set_attr "type" "viwmuladd")])
994 ;; Combine extend + fma to widen_fma (vfwmacc)
995 (define_insn_and_split "*dual_widen_fma<mode>"
996 [(set (match_operand:VWEXTF 0 "register_operand")
1000 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1001 (float_extend:VWEXTF
1002 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
1003 (match_operand:VWEXTF 1 "register_operand")))]
1004 "TARGET_VECTOR && can_create_pseudo_p ()"
1009 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1010 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (PLUS, <MODE>mode),
1011 riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1014 [(set_attr "type" "vfwmuladd")])
1016 ;; This combine pattern does not correspond to an single instruction.
1017 ;; This is a temporary pattern produced by a combine pass and if there
1018 ;; is no further combine into widen pattern, then fall back to extend
1019 ;; pattern and non-widen fma pattern.
1020 (define_insn_and_split "*single_widen_fma<mode>"
1021 [(set (match_operand:VWEXTF 0 "register_operand")
1024 (float_extend:VWEXTF
1025 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1026 (match_operand:VWEXTF 3 "register_operand"))
1027 (match_operand:VWEXTF 1 "register_operand")))]
1028 "TARGET_VECTOR && can_create_pseudo_p ()"
1033 insn_code icode = code_for_pred_extend (<MODE>mode);
1034 rtx tmp = gen_reg_rtx (<MODE>mode);
1035 rtx ext_ops[] = {tmp, operands[2]};
1036 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1038 rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1039 RVV_VUNDEF(<MODE>mode)};
1040 riscv_vector::emit_vlmax_insn (code_for_pred_mul (PLUS, <MODE>mode),
1041 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1044 [(set_attr "type" "vfwmuladd")])
1046 ;; Combine extend + fnma to widen_fnma (vfwnmsac)
1047 (define_insn_and_split "*dual_widen_fnma<mode>"
1048 [(set (match_operand:VWEXTF 0 "register_operand")
1050 (match_operand:VWEXTF 1 "register_operand")
1052 (float_extend:VWEXTF
1053 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1054 (float_extend:VWEXTF
1055 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))))]
1056 "TARGET_VECTOR && can_create_pseudo_p ()"
1061 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1062 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (PLUS, <MODE>mode),
1063 riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1066 [(set_attr "type" "vfwmuladd")])
1068 ;; This combine pattern does not correspond to an single instruction.
1069 ;; This is a temporary pattern produced by a combine pass and if there
1070 ;; is no further combine into widen pattern, then fall back to extend
1071 ;; pattern and non-widen fnma pattern.
1072 (define_insn_and_split "*single_widen_fnma<mode>"
1073 [(set (match_operand:VWEXTF 0 "register_operand")
1075 (match_operand:VWEXTF 1 "register_operand")
1077 (float_extend:VWEXTF
1078 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1079 (match_operand:VWEXTF 3 "register_operand"))))]
1080 "TARGET_VECTOR && can_create_pseudo_p ()"
1085 insn_code icode = code_for_pred_extend (<MODE>mode);
1086 rtx tmp = gen_reg_rtx (<MODE>mode);
1087 rtx ext_ops[] = {tmp, operands[2]};
1088 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1090 rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1091 RVV_VUNDEF(<MODE>mode)};
1092 riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (PLUS, <MODE>mode),
1093 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1096 [(set_attr "type" "vfwmuladd")])
1098 ;; Combine extend + fms to widen_fms (vfwmsac)
1099 (define_insn_and_split "*dual_widen_fms<mode>"
1100 [(set (match_operand:VWEXTF 0 "register_operand")
1103 (float_extend:VWEXTF
1104 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1105 (float_extend:VWEXTF
1106 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
1107 (match_operand:VWEXTF 1 "register_operand")))]
1108 "TARGET_VECTOR && can_create_pseudo_p ()"
1113 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1114 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (MINUS, <MODE>mode),
1115 riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1118 [(set_attr "type" "vfwmuladd")])
1120 ;; This combine pattern does not correspond to an single instruction.
1121 ;; This is a temporary pattern produced by a combine pass and if there
1122 ;; is no further combine into widen pattern, then fall back to extend
1123 ;; pattern and non-widen fms pattern.
1124 (define_insn_and_split "*single_widen_fms<mode>"
1125 [(set (match_operand:VWEXTF 0 "register_operand")
1128 (float_extend:VWEXTF
1129 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1130 (match_operand:VWEXTF 3 "register_operand"))
1131 (match_operand:VWEXTF 1 "register_operand")))]
1132 "TARGET_VECTOR && can_create_pseudo_p ()"
1137 insn_code icode = code_for_pred_extend (<MODE>mode);
1138 rtx tmp = gen_reg_rtx (<MODE>mode);
1139 rtx ext_ops[] = {tmp, operands[2]};
1140 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1142 rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1143 RVV_VUNDEF(<MODE>mode)};
1144 riscv_vector::emit_vlmax_insn (code_for_pred_mul (MINUS, <MODE>mode),
1145 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1148 [(set_attr "type" "vfwmuladd")])
1150 ;; Combine extend + fnms to widen_fnms (vfwnmacc)
1151 (define_insn_and_split "*dual_widen_fnms<mode>"
1152 [(set (match_operand:VWEXTF 0 "register_operand")
1156 (float_extend:VWEXTF
1157 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
1158 (float_extend:VWEXTF
1159 (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
1160 (match_operand:VWEXTF 1 "register_operand")))]
1161 "TARGET_VECTOR && can_create_pseudo_p ()"
1166 rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1167 riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (MINUS, <MODE>mode),
1168 riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1171 [(set_attr "type" "vfwmuladd")])
1173 ;; This combine pattern does not correspond to an single instruction.
1174 ;; This is a temporary pattern produced by a combine pass and if there
1175 ;; is no further combine into widen pattern, then fall back to extend
1176 ;; pattern and non-widen fnms pattern.
1177 (define_insn_and_split "*single_widen_fnms<mode>"
1178 [(set (match_operand:VWEXTF 0 "register_operand")
1182 (match_operand:VWEXTF 3 "register_operand"))
1183 (float_extend:VWEXTF
1184 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
1185 (match_operand:VWEXTF 1 "register_operand")))]
1186 "TARGET_VECTOR && can_create_pseudo_p ()"
1191 insn_code icode = code_for_pred_extend (<MODE>mode);
1192 rtx tmp = gen_reg_rtx (<MODE>mode);
1193 rtx ext_ops[] = {tmp, operands[2]};
1194 riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1196 rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1197 RVV_VUNDEF(<MODE>mode)};
1198 riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (MINUS, <MODE>mode),
1199 riscv_vector::TERNARY_OP_FRM_DYN, ops);
1202 [(set_attr "type" "vfwmuladd")])
1204 ;; Combine mask_extend + vredsum to mask_vwredsum[u]
1205 ;; where the mrege of mask_extend is vector const 0
1206 (define_insn_and_split "*cond_widen_reduc_plus_scal_<mode>"
1207 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1208 (unspec:<V_DOUBLE_EXTEND_VEL> [
1209 (if_then_else:<V_DOUBLE_EXTEND>
1210 (match_operand:<VM> 1 "register_operand")
1211 (any_extend:<V_DOUBLE_EXTEND>
1212 (match_operand:VI_QHS_NO_M8 2 "register_operand"))
1213 (if_then_else:<V_DOUBLE_EXTEND>
1215 (match_operand:<VM> 3 "vector_all_trues_mask_operand")
1216 (match_operand 6 "vector_length_operand")
1217 (match_operand 7 "const_int_operand")
1218 (match_operand 8 "const_int_operand")
1219 (match_operand 9 "const_1_or_2_operand")
1221 (reg:SI VTYPE_REGNUM)
1222 ] UNSPEC_VPREDICATE)
1223 (match_operand:<V_DOUBLE_EXTEND> 5 "vector_const_0_operand")
1224 (match_operand:<V_DOUBLE_EXTEND> 4 "vector_merge_operand")))
1225 ] UNSPEC_REDUC_SUM))]
1226 "TARGET_VECTOR && can_create_pseudo_p ()"
1231 rtx ops[] = {operands[0], operands[2], operands[1],
1232 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
1233 riscv_vector::expand_reduction (<WREDUC_UNSPEC>,
1234 <WREDUC_UNSPEC_VL0_SAFE>,
1235 riscv_vector::REDUCE_OP_M,
1236 ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1239 [(set_attr "type" "vector")])
1241 ;; Combine mask_len_extend + vredsum to mask_vwredsum[u]
1242 ;; where the mrege of mask_len_extend is vector const 0
1243 (define_insn_and_split "*cond_len_widen_reduc_plus_scal_<mode>"
1244 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1245 (unspec:<V_DOUBLE_EXTEND_VEL> [
1246 (if_then_else:<V_DOUBLE_EXTEND>
1248 (match_operand 2 "vector_length_operand")
1252 (reg:SI VTYPE_REGNUM)
1253 ] UNSPEC_VPREDICATE)
1254 (vec_merge:<V_DOUBLE_EXTEND>
1255 (any_extend:<V_DOUBLE_EXTEND>
1256 (match_operand:VI_QHS_NO_M8 3 "register_operand"))
1257 (if_then_else:<V_DOUBLE_EXTEND>
1259 (match_operand:<VM> 4 "vector_all_trues_mask_operand")
1260 (match_operand 5 "vector_length_operand")
1261 (match_operand 6 "const_int_operand")
1262 (match_operand 7 "const_int_operand")
1263 (match_operand 8 "const_1_or_2_operand")
1265 (reg:SI VTYPE_REGNUM)
1266 ] UNSPEC_VPREDICATE)
1267 (match_operand:<V_DOUBLE_EXTEND> 9 "vector_const_0_operand")
1268 (match_operand:<V_DOUBLE_EXTEND> 10 "vector_merge_operand"))
1269 (match_operand:<VM> 1 "register_operand"))
1270 (if_then_else:<V_DOUBLE_EXTEND>
1278 (reg:SI VTYPE_REGNUM)
1279 ] UNSPEC_VPREDICATE)
1282 ] UNSPEC_REDUC_SUM))]
1283 "TARGET_VECTOR && can_create_pseudo_p ()"
1288 rtx ops[] = {operands[0], operands[3], operands[1], operands[2]};
1289 riscv_vector::expand_reduction (<WREDUC_UNSPEC>,
1290 <WREDUC_UNSPEC_VL0_SAFE>,
1291 riscv_vector::REDUCE_OP_M,
1292 ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1295 [(set_attr "type" "vector")])
1297 ;; Combine mask_extend + vfredsum to mask_vfwredusum
1298 ;; where the mrege of mask_extend is vector const 0
1299 (define_insn_and_split "*cond_widen_reduc_plus_scal_<mode>"
1300 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1301 (unspec:<V_DOUBLE_EXTEND_VEL> [
1302 (if_then_else:<V_DOUBLE_EXTEND>
1303 (match_operand:<VM> 1 "register_operand")
1304 (float_extend:<V_DOUBLE_EXTEND>
1305 (match_operand:VF_HS_NO_M8 2 "register_operand"))
1306 (if_then_else:<V_DOUBLE_EXTEND>
1308 (match_operand:<VM> 3 "vector_all_trues_mask_operand")
1309 (match_operand 6 "vector_length_operand")
1310 (match_operand 7 "const_int_operand")
1311 (match_operand 8 "const_int_operand")
1312 (match_operand 9 "const_1_or_2_operand")
1314 (reg:SI VTYPE_REGNUM)
1315 ] UNSPEC_VPREDICATE)
1316 (match_operand:<V_DOUBLE_EXTEND> 5 "vector_const_0_operand")
1317 (match_operand:<V_DOUBLE_EXTEND> 4 "vector_merge_operand")))
1318 ] UNSPEC_REDUC_SUM_UNORDERED))]
1319 "TARGET_VECTOR && can_create_pseudo_p ()"
1324 rtx ops[] = {operands[0], operands[2], operands[1],
1325 gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
1326 riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
1327 UNSPEC_WREDUC_SUM_UNORDERED_VL0_SAFE,
1328 riscv_vector::REDUCE_OP_M_FRM_DYN,
1329 ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1332 [(set_attr "type" "vector")])
1334 ;; Combine mask_len_extend + vredsum to mask_vwredsum[u]
1335 ;; where the mrege of mask_len_extend is vector const 0
1336 (define_insn_and_split "*cond_len_widen_reduc_plus_scal_<mode>"
1337 [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1338 (unspec:<V_DOUBLE_EXTEND_VEL> [
1339 (if_then_else:<V_DOUBLE_EXTEND>
1341 (match_operand 2 "vector_length_operand")
1345 (reg:SI VTYPE_REGNUM)
1346 ] UNSPEC_VPREDICATE)
1347 (vec_merge:<V_DOUBLE_EXTEND>
1348 (float_extend:<V_DOUBLE_EXTEND>
1349 (match_operand:VF_HS_NO_M8 3 "register_operand"))
1350 (if_then_else:<V_DOUBLE_EXTEND>
1352 (match_operand:<VM> 4 "vector_all_trues_mask_operand")
1353 (match_operand 5 "vector_length_operand")
1354 (match_operand 6 "const_int_operand")
1355 (match_operand 7 "const_int_operand")
1356 (match_operand 8 "const_1_or_2_operand")
1358 (reg:SI VTYPE_REGNUM)
1359 ] UNSPEC_VPREDICATE)
1360 (match_operand:<V_DOUBLE_EXTEND> 9 "vector_const_0_operand")
1361 (match_operand:<V_DOUBLE_EXTEND> 10 "vector_merge_operand"))
1362 (match_operand:<VM> 1 "register_operand"))
1363 (if_then_else:<V_DOUBLE_EXTEND>
1371 (reg:SI VTYPE_REGNUM)
1372 ] UNSPEC_VPREDICATE)
1375 ] UNSPEC_REDUC_SUM_UNORDERED))]
1376 "TARGET_VECTOR && can_create_pseudo_p ()"
1381 rtx ops[] = {operands[0], operands[3], operands[1], operands[2]};
1382 riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
1383 UNSPEC_WREDUC_SUM_UNORDERED_VL0_SAFE,
1384 riscv_vector::REDUCE_OP_M_FRM_DYN,
1385 ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1388 [(set_attr "type" "vector")])
1390 ;; =============================================================================
1391 ;; Misc combine patterns
1392 ;; =============================================================================
1394 ;; Combine neg + vfsgnj to vfsgnjn
1395 (define_insn_and_split "*copysign<mode>_neg"
1396 [(set (match_operand:VF 0 "register_operand")
1399 (match_operand:VF 1 "register_operand")
1400 (match_operand:VF 2 "register_operand")
1401 ] UNSPEC_VCOPYSIGN)))]
1402 "TARGET_VECTOR && can_create_pseudo_p ()"
1407 riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (<MODE>mode),
1408 riscv_vector::BINARY_OP, operands);
1411 [(set_attr "type" "vector")])
1413 ;; Combine vmand/vmor + vmnot to vmandnot/vmornot
1414 (define_insn_and_split "*<optab>not<mode>"
1415 [(set (match_operand:VB_VLS 0 "register_operand" "=vr")
1416 (bitmanip_bitwise:VB_VLS
1417 (not:VB_VLS (match_operand:VB_VLS 2 "register_operand" " vr"))
1418 (match_operand:VB_VLS 1 "register_operand" " vr")))]
1419 "TARGET_VECTOR && can_create_pseudo_p ()"
1424 insn_code icode = code_for_pred_not (<CODE>, <MODE>mode);
1425 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
1428 [(set_attr "type" "vmalu")])
1430 ;; Combine vmnot + vmand/vmor/vmxor to vmnand/vmnor/vmxnor
1431 (define_insn_and_split "*n<optab><mode>"
1432 [(set (match_operand:VB_VLS 0 "register_operand" "=vr")
1435 (match_operand:VB_VLS 1 "register_operand" " vr")
1436 (match_operand:VB_VLS 2 "register_operand" " vr"))))]
1437 "TARGET_VECTOR && can_create_pseudo_p ()"
1442 insn_code icode = code_for_pred_n (<CODE>, <MODE>mode);
1443 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
1446 [(set_attr "type" "vmalu")])
1448 ;; Optimization pattern for early break auto-vectorization
1449 ;; vcond_mask_len (mask, ones, zeros, len, bias) + vlmax popcount
1450 ;; -> non vlmax popcount (mask, len)
1451 (define_insn_and_split "*vcond_mask_len_popcount_<VB_VLS:mode><P:mode>"
1452 [(set (match_operand:P 0 "register_operand")
1456 (match_operand:VB_VLS 1 "register_operand")
1457 (match_operand:VB_VLS 2 "const_1_operand")
1458 (match_operand:VB_VLS 3 "const_0_operand")
1459 (match_operand 4 "autovec_length_operand")
1460 (match_operand 5 "const_0_operand")] UNSPEC_SELECT_MASK)
1461 (match_operand 6 "autovec_length_operand")
1464 (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))]
1466 && can_create_pseudo_p ()
1467 && riscv_vector::get_vector_mode (Pmode, GET_MODE_NUNITS (<VB_VLS:MODE>mode)).exists ()"
1472 riscv_vector::emit_nonvlmax_insn (
1473 code_for_pred_popcount (<VB_VLS:MODE>mode, Pmode),
1474 riscv_vector::CPOP_OP,
1475 operands, operands[4]);
1478 [(set_attr "type" "vector")])
1480 ;; vzext.vf2 + vsll = vwsll.
1481 (define_insn_and_split "*vwsll_zext1_<mode>"
1482 [(set (match_operand:VWEXTI 0 "register_operand" "=vr ")
1485 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand" " vr "))
1486 (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" "vrvk")))]
1487 "TARGET_ZVBB && can_create_pseudo_p ()"
1492 insn_code icode = code_for_pred_vwsll (<MODE>mode);
1493 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1496 [(set_attr "type" "vwsll")])
1498 (define_insn_and_split "*vwsll_zext2_<mode>"
1499 [(set (match_operand:VWEXTI 0 "register_operand" "=vr ")
1502 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand" " vr "))
1504 (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" "vrvk"))))]
1505 "TARGET_ZVBB && can_create_pseudo_p ()"
1510 insn_code icode = code_for_pred_vwsll (<MODE>mode);
1511 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1514 [(set_attr "type" "vwsll")])
1517 (define_insn_and_split "*vwsll_zext1_scalar_<mode>"
1518 [(set (match_operand:VWEXTI 0 "register_operand" "=vr")
1521 (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand" " vr"))
1522 (match_operand:<VEL> 2 "vector_scalar_shift_operand" " rK")))]
1523 "TARGET_ZVBB && can_create_pseudo_p ()"
1528 operands[2] = gen_lowpart (Pmode, operands[2]);
1529 insn_code icode = code_for_pred_vwsll_scalar (<MODE>mode);
1530 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1533 [(set_attr "type" "vwsll")])
1538 ;; dst = vwsll (a, b)
1539 ;; we seem to create
1542 ;; dst = (short) vwsll (aa, bb);
1543 ;; The following patterns help to combine this idiom into one vwsll.
1545 (define_insn_and_split "*vwsll_zext1_trunc_<mode>"
1546 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr ")
1547 (truncate:<V_DOUBLE_TRUNC>
1550 (match_operand:<V_QUAD_TRUNC> 1 "register_operand" " vr "))
1551 (match_operand:VQEXTI 2 "vector_shift_operand" "vrvk"))))]
1552 "TARGET_ZVBB && can_create_pseudo_p ()"
1557 rtx truncated = gen_reg_rtx (<V_QUAD_TRUNC>mode);
1558 emit_insn (gen_trunc<mode><v_quad_trunc>2 (truncated, operands[2]));
1559 operands[2] = truncated;
1561 insn_code icode = code_for_pred_vwsll (<V_DOUBLE_TRUNC>mode);
1562 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1565 [(set_attr "type" "vwsll")])
1567 (define_insn_and_split "*vwsll_zext2_trunc_<mode>"
1568 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr ")
1569 (truncate:<V_DOUBLE_TRUNC>
1572 (match_operand:<V_QUAD_TRUNC> 1 "register_operand" " vr "))
1574 (match_operand:<V_QUAD_TRUNC> 2 "vector_shift_operand" "vrvk")))))]
1575 "TARGET_ZVBB && can_create_pseudo_p ()"
1580 insn_code icode = code_for_pred_vwsll (<V_DOUBLE_TRUNC>mode);
1581 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1584 [(set_attr "type" "vwsll")])
1586 (define_insn_and_split "*vwsll_zext1_trunc_scalar_<mode>"
1587 [(set (match_operand:<V_DOUBLE_TRUNC> 0 "register_operand" "=vr ")
1588 (truncate:<V_DOUBLE_TRUNC>
1591 (match_operand:<V_QUAD_TRUNC> 1 "register_operand" " vr "))
1592 (match_operand:<VEL> 2 "vector_scalar_shift_operand" " rK"))))]
1593 "TARGET_ZVBB && can_create_pseudo_p ()"
1598 operands[2] = gen_lowpart (Pmode, operands[2]);
1599 insn_code icode = code_for_pred_vwsll_scalar (<V_DOUBLE_TRUNC>mode);
1600 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1603 [(set_attr "type" "vwsll")])
1605 ;; vnot + vand = vandn.
1606 (define_insn_and_split "*vandn_<mode>"
1607 [(set (match_operand:V_VLSI 0 "register_operand" "=vr")
1610 (match_operand:V_VLSI 2 "register_operand" "vr"))
1611 (match_operand:V_VLSI 1 "register_operand" "vr")))]
1612 "TARGET_ZVBB && can_create_pseudo_p ()"
1617 insn_code icode = code_for_pred_vandn (<MODE>mode);
1618 riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1621 [(set_attr "type" "vandn")])