Daily bump.
[official-gcc.git] / gcc / config / riscv / autovec-opt.md
blob53431863441c71e7ce5a66b58c1fce2b6ded8e36
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)
10 ;; any later version.
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:
25 ;; - 1.  VMSNE
26 ;; - 2.  VMSLT
27 ;; - 3.  VMSLTU
28 ;; - 4.  VMSGT
29 ;; - 5.  VMSGTU
30 ;; -----------------------------------------------------------------------------
31 ;; Simplify OP(V, V) Instructions to VMSET.m Includes:
32 ;; - 1.  VMSEQ
33 ;; - 2.  VMSLE
34 ;; - 3.  VMSLEU
35 ;; - 4.  VMSGE
36 ;; - 5.  VMSGEU
37 ;; -----------------------------------------------------------------------------
39 (define_split
40   [(set (match_operand:VB      0 "register_operand")
41         (if_then_else:VB
42           (unspec:VB
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")
47              (reg:SI VL_REGNUM)
48              (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
49           (match_operand:VB    3 "vector_move_operand")
50           (match_operand:VB    2 "vector_undef_operand")))]
51   "TARGET_VECTOR"
52   [(const_int 0)]
53   {
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]));
57     DONE;
58   }
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")
66         (sign_extend:DI
67           (unspec:<VEL>
68             [(vec_select:<VEL>
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"
73   "vmv.x.s\t%0,%1"
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")
79         (sign_extend:SI
80           (unspec:<VEL>
81             [(vec_select:<VEL>
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"
86   "vmv.x.s\t%0,%1"
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:
100 ;;   abs(FP)
101 (define_insn_and_split "*cond_abs<mode>"
102   [(set (match_operand:V_VLSF 0 "register_operand")
103         (if_then_else:V_VLSF
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 ()"
108   "#"
109   "&& 1"
110   [(const_int 0)]
112   insn_code icode = code_for_pred (ABS, <MODE>mode);
113   riscv_vector::expand_cond_unop (icode, operands);
114   DONE;
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")
121      (if_then_else:V_VLSF
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 ()"
127   "#"
128   "&& 1"
129   [(const_int 0)]
131   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
132   riscv_vector::expand_cond_unop (icode, operands);
133   DONE;
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")
140         (if_then_else:VWEXTI
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 ()"
145   "#"
146   "&& 1"
147   [(const_int 0)]
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);
153   DONE;
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")
160         (if_then_else:VQEXTI
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 ()"
165   "#"
166   "&& 1"
167   [(const_int 0)]
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);
173   DONE;
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")
180         (if_then_else:VOEXTI
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 ()"
185   "#"
186   "&& 1"
187   [(const_int 0)]
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);
193   DONE;
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")
200     (if_then_else:VWEXTI
201       (unspec:<VM>
202         [(match_operand 4 "vector_length_operand")
203          (match_operand 5 "const_int_operand")
204          (match_operand 6 "const_int_operand")
205          (reg:SI VL_REGNUM)
206          (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
207       (vec_merge:VWEXTI
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"))
211       (match_dup 1)))]
212   "TARGET_VECTOR"
213   "#"
214   "&& 1"
215   [(const_int 0)]
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)));
219   DONE;
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")
226     (if_then_else:VQEXTI
227       (unspec:<VM>
228         [(match_operand 4 "vector_length_operand")
229          (match_operand 5 "const_int_operand")
230          (match_operand 6 "const_int_operand")
231          (reg:SI VL_REGNUM)
232          (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
233       (vec_merge:VQEXTI
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"))
237       (match_dup 1)))]
238   "TARGET_VECTOR"
239   "#"
240   "&& 1"
241   [(const_int 0)]
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)));
245   DONE;
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")
252     (if_then_else:VOEXTI
253       (unspec:<VM>
254         [(match_operand 4 "vector_length_operand")
255          (match_operand 5 "const_int_operand")
256          (match_operand 6 "const_int_operand")
257          (reg:SI VL_REGNUM)
258          (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
259       (vec_merge:VOEXTI
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"))
263       (match_dup 1)))]
264   "TARGET_VECTOR"
265   "#"
266   "&& 1"
267   [(const_int 0)]
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)));
271   DONE;
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 ()"
284   "#"
285   "&& 1"
286   [(const_int 0)]
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);
292   DONE;
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 ()"
304   "#"
305   "&& 1"
306   [(const_int 0)]
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);
312   DONE;
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
320       (unspec:<VM>
321         [(match_operand 4 "vector_length_operand")
322          (match_operand 5 "const_int_operand")
323          (match_operand 6 "const_int_operand")
324          (reg:SI VL_REGNUM)
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"))
330       (match_dup 1)))]
331   "TARGET_VECTOR"
332   "#"
333   "&& 1"
334   [(const_int 0)]
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)));
338   DONE;
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 ()"
351   "#"
352   "&& 1"
353   [(const_int 0)]
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);
359   DONE;
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")
368           (any_fix:<VCONVERT>
369             (match_operand:V_VLSF 2 "register_operand"))
370           (match_operand:<VCONVERT> 3 "register_operand")))]
371   "TARGET_VECTOR && can_create_pseudo_p ()"
372   "#"
373   "&& 1"
374   [(const_int 0)]
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);
380   DONE;
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")
387         (if_then_else:V_VLSF
388           (match_operand:<VM> 1 "register_operand")
389           (any_float:V_VLSF
390             (match_operand:<VCONVERT> 2 "register_operand"))
391           (match_operand:V_VLSF 3 "register_operand")))]
392   "TARGET_VECTOR && can_create_pseudo_p ()"
393   "#"
394   "&& 1"
395   [(const_int 0)]
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);
401   DONE;
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")
410           (any_fix:VWCONVERTI
411             (match_operand:<VNCONVERT> 2 "register_operand"))
412           (match_operand:VWCONVERTI 3 "register_operand")))]
413   "TARGET_VECTOR && can_create_pseudo_p ()"
414   "#"
415   "&& 1"
416   [(const_int 0)]
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);
422   DONE;
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")
429         (if_then_else:V_VLSF
430           (match_operand:<VM> 1 "register_operand")
431           (any_float:V_VLSF
432             (match_operand:<VNCONVERT> 2 "register_operand"))
433           (match_operand:V_VLSF 3 "register_operand")))]
434   "TARGET_VECTOR && can_create_pseudo_p ()"
435   "#"
436   "&& 1"
437   [(const_int 0)]
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);
443   DONE;
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")
452           (any_fix:<VNCONVERT>
453             (match_operand:V_VLSF 2 "register_operand"))
454           (match_operand:<VNCONVERT> 3 "register_operand")))]
455   "TARGET_VECTOR && can_create_pseudo_p ()"
456   "#"
457   "&& 1"
458   [(const_int 0)]
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);
464   DONE;
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 ()"
477   "#"
478   "&& 1"
479   [(const_int 0)]
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);
485   DONE;
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>
495          (any_shiftrt:VWEXTI
496            (match_operand:VWEXTI 2 "register_operand")
497            (any_extend:VWEXTI
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 ()"
501   "#"
502   "&& 1"
503   [(const_int 0)]
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);
509   DONE;
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>
518          (any_shiftrt:VWEXTI
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 ()"
523   "#"
524   "&& 1"
525   [(const_int 0)]
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);
531   DONE;
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")
538     (if_then_else:VFULLI
539       (match_operand:<VM> 1 "register_operand")
540       (mulh:VFULLI
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 ()"
545    "#"
546    "&& 1"
547    [(const_int 0)]
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);
553    DONE;
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>
565       (any_shiftrt:VWEXTI
566         (match_operand:VWEXTI 1 "register_operand"                 " vr,vr")
567         (any_extend:VWEXTI
568           (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" " vr,vk")))))]
569   "TARGET_VECTOR && can_create_pseudo_p ()"
570   "#"
571   "&& 1"
572   [(const_int 0)]
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);
576   DONE;
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>
584       (any_shiftrt:VWEXTI
585         (match_operand:VWEXTI 1 "register_operand"           " vr")
586         (match_operand:<VEL> 2 "csr_operand"                 " rK"))))]
587   "TARGET_VECTOR && can_create_pseudo_p ()"
588   "#"
589   "&& 1"
590   [(const_int 0)]
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);
595   DONE;
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
606           (any_extend:VWEXTI
607             (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
608           (any_extend:VWEXTI
609             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
610   "TARGET_VECTOR && can_create_pseudo_p ()"
611   "#"
612   "&& 1"
613   [(const_int 0)]
615   insn_code icode = code_for_pred_dual_widen (<any_widen_binop:CODE>,
616                                               <any_extend:CODE>,
617                                               <MODE>mode);
618   riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
619   DONE;
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")
625         (minus:VWEXTI
626           (match_operand:VWEXTI 1 "register_operand")
627           (any_extend:VWEXTI
628             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
629   "TARGET_VECTOR && can_create_pseudo_p ()"
630   "#"
631   "&& 1"
632   [(const_int 0)]
634   insn_code icode = code_for_pred_single_widen_sub (<any_extend:CODE>,
635                                                     <MODE>mode);
636   riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
637   DONE;
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")
643         (plus:VWEXTI
644           (any_extend:VWEXTI
645             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
646           (match_operand:VWEXTI 1 "register_operand")))]
647   "TARGET_VECTOR && can_create_pseudo_p ()"
648   "#"
649   "&& 1"
650   [(const_int 0)]
652   insn_code icode = code_for_pred_single_widen_add (<any_extend:CODE>,
653                                                     <MODE>mode);
654   riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
655   DONE;
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")
665         (mult:VWEXTI
666           (any_extend:VWEXTI
667             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
668           (match_operand:VWEXTI 1 "register_operand")))]
669   "TARGET_VECTOR && can_create_pseudo_p ()"
670   "#"
671   "&& 1"
672   [(const_int 0)]
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);
682   DONE;
684 [(set_attr "type" "viwmul")])
686 (define_insn_and_split "*dual_widen_mulsu<mode>"
687   [(set (match_operand:VWEXTI 0 "register_operand")
688         (mult:VWEXTI
689           (sign_extend:VWEXTI
690             (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
691           (zero_extend:VWEXTI
692             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
693   "TARGET_VECTOR && can_create_pseudo_p ()"
694   "#"
695   "&& 1"
696   [(const_int 0)]
698   insn_code icode = code_for_pred_widen_mulsu (<MODE>mode);
699   riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
700   DONE;
702 [(set_attr "type" "vector")])
704 (define_insn_and_split "*dual_widen_mulus<mode>"
705   [(set (match_operand:VWEXTI 0 "register_operand")
706         (mult:VWEXTI
707           (zero_extend:VWEXTI
708             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
709           (sign_extend:VWEXTI
710             (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))))]
711   "TARGET_VECTOR && can_create_pseudo_p ()"
712   "#"
713   "&& 1"
714   [(const_int 0)]
716   insn_code icode = code_for_pred_widen_mulsu (<MODE>mode);
717   riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
718   DONE;
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
725           (float_extend:VWEXTF
726             (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
727           (float_extend:VWEXTF
728             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
729   "TARGET_VECTOR && can_create_pseudo_p ()"
730   "#"
731   "&& 1"
732   [(const_int 0)]
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);
736   DONE;
738 [(set_attr "type" "vector")])
740 (define_insn_and_split "*single_widen_add<mode>"
741   [(set (match_operand:VWEXTF 0 "register_operand")
742         (plus:VWEXTF
743           (float_extend:VWEXTF
744             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
745           (match_operand:VWEXTF 1 "register_operand")))]
746   "TARGET_VECTOR && can_create_pseudo_p ()"
747   "#"
748   "&& 1"
749   [(const_int 0)]
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);
753   DONE;
755 [(set_attr "type" "vfwalu")])
757 (define_insn_and_split "*single_widen_sub<mode>"
758   [(set (match_operand:VWEXTF 0 "register_operand")
759         (minus:VWEXTF
760           (match_operand:VWEXTF 1 "register_operand")
761           (float_extend:VWEXTF
762             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))))]
763   "TARGET_VECTOR && can_create_pseudo_p ()"
764   "#"
765   "&& 1"
766   [(const_int 0)]
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);
770   DONE;
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")
780         (mult:VWEXTF
781           (float_extend:VWEXTF
782             (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
783           (match_operand:VWEXTF 1 "register_operand")))]
784   "TARGET_VECTOR && can_create_pseudo_p ()"
785   "#"
786   "&& 1"
787   [(const_int 0)]
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);
797   DONE;
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 ()"
809   "#"
810   "&& 1"
811   [(const_int 0)]
813   riscv_vector::expand_reduction (<WREDUC_UNSPEC>, <WREDUC_UNSPEC_VL0_SAFE>,
814                                   riscv_vector::REDUCE_OP,
815                                   operands,
816                                   CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
817   DONE;
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 ()"
829   "#"
830   "&& 1"
831   [(const_int 0)]
833   riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
834                                   UNSPEC_WREDUC_SUM_UNORDERED_VL0_SAFE,
835                                   riscv_vector::REDUCE_OP_FRM_DYN,
836                                   operands,
837                                   CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
838   DONE;
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 ()"
851   "#"
852   "&& 1"
853   [(const_int 0)]
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]);
859   DONE;
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 ()"
875   "#"
876   "&& 1"
877   [(const_int 0)]
879   if (rtx_equal_p (operands[4], const0_rtx))
880     emit_move_insn (operands[0], operands[1]);
881   else
882     {
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,
887                                       ops, operands[1]);
888     }
889   DONE;
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")
900         (plus:VWEXTI
901           (mult:VWEXTI
902             (any_extend:VWEXTI
903               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
904             (any_extend:VWEXTI
905               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
906           (match_operand:VWEXTI 1 "register_operand")))]
907   "TARGET_VECTOR && can_create_pseudo_p ()"
908   "#"
909   "&& 1"
910   [(const_int 0)]
911   {
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);
915     DONE;
916   }
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")
922         (plus:VWEXTI
923           (mult:VWEXTI
924             (sign_extend:VWEXTI
925               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
926             (zero_extend:VWEXTI
927               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
928           (match_operand:VWEXTI 1 "register_operand")))]
929   "TARGET_VECTOR && can_create_pseudo_p ()"
930   "#"
931   "&& 1"
932   [(const_int 0)]
933   {
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);
937     DONE;
938   }
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")
944         (plus:VWEXTI
945           (mult:VWEXTI
946             (zero_extend:VWEXTI
947               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"))
948             (sign_extend:VWEXTI
949               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
950           (match_operand:VWEXTI 1 "register_operand")))]
951   "TARGET_VECTOR && can_create_pseudo_p ()"
952   "#"
953   "&& 1"
954   [(const_int 0)]
955   {
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);
959     DONE;
960   }
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")
969         (plus:VWEXTI
970           (mult:VWEXTI
971             (any_extend:VWEXTI
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 ()"
976   "#"
977   "&& 1"
978   [(const_int 0)]
979   {
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,
984                                    extend_ops);
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);
990     DONE;
991   }
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")
997         (plus:VWEXTF
998           (mult:VWEXTF
999             (float_extend:VWEXTF
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 ()"
1005   "#"
1006   "&& 1"
1007   [(const_int 0)]
1008   {
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);
1012     DONE;
1013   }
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")
1022         (plus:VWEXTF
1023           (mult:VWEXTF
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 ()"
1029   "#"
1030   "&& 1"
1031   [(const_int 0)]
1032   {
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);
1042     DONE;
1043   }
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")
1049         (minus:VWEXTF
1050           (match_operand:VWEXTF 1 "register_operand")
1051           (mult:VWEXTF
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 ()"
1057   "#"
1058   "&& 1"
1059   [(const_int 0)]
1060   {
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);
1064     DONE;
1065   }
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")
1074         (minus:VWEXTF
1075           (match_operand:VWEXTF 1 "register_operand")
1076           (mult:VWEXTF
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 ()"
1081   "#"
1082   "&& 1"
1083   [(const_int 0)]
1084   {
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);
1094     DONE;
1095   }
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")
1101         (minus:VWEXTF
1102           (mult:VWEXTF
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 ()"
1109   "#"
1110   "&& 1"
1111   [(const_int 0)]
1112   {
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);
1116     DONE;
1117   }
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")
1126         (minus:VWEXTF
1127           (mult:VWEXTF
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 ()"
1133   "#"
1134   "&& 1"
1135   [(const_int 0)]
1136   {
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);
1146     DONE;
1147   }
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")
1153         (minus:VWEXTF
1154           (mult:VWEXTF
1155             (neg:VWEXTF
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 ()"
1162   "#"
1163   "&& 1"
1164   [(const_int 0)]
1165   {
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);
1169     DONE;
1170   }
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")
1179         (minus:VWEXTF
1180           (mult:VWEXTF
1181             (neg:VWEXTF
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 ()"
1187   "#"
1188   "&& 1"
1189   [(const_int 0)]
1190   {
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);
1200     DONE;
1201   }
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>
1214               (unspec:<VM> [
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")
1220                 (reg:SI VL_REGNUM)
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 ()"
1227   "#"
1228   "&& 1"
1229   [(const_int 0)]
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));
1237   DONE;
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>
1247             (unspec:<VM> [
1248               (match_operand 2 "vector_length_operand")
1249               (const_int 0)
1250               (const_int 0)
1251               (reg:SI VL_REGNUM)
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>
1258                 (unspec:<VM> [
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")
1264                   (reg:SI VL_REGNUM)
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>
1271               (unspec:<VM> [
1272                 (match_dup 4)
1273                 (match_dup 5)
1274                 (match_dup 6)
1275                 (match_dup 7)
1276                 (match_dup 8)
1277                 (reg:SI VL_REGNUM)
1278                 (reg:SI VTYPE_REGNUM)
1279               ] UNSPEC_VPREDICATE)
1280               (match_dup 9)
1281               (match_dup 10)))
1282         ] UNSPEC_REDUC_SUM))]
1283   "TARGET_VECTOR && can_create_pseudo_p ()"
1284   "#"
1285   "&& 1"
1286   [(const_int 0)]
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));
1293   DONE;
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>
1307               (unspec:<VM> [
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")
1313                 (reg:SI VL_REGNUM)
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 ()"
1320   "#"
1321   "&& 1"
1322   [(const_int 0)]
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));
1330   DONE;
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>
1340             (unspec:<VM> [
1341               (match_operand 2 "vector_length_operand")
1342               (const_int 0)
1343               (const_int 0)
1344               (reg:SI VL_REGNUM)
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>
1351                 (unspec:<VM> [
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")
1357                   (reg:SI VL_REGNUM)
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>
1364               (unspec:<VM> [
1365                 (match_dup 4)
1366                 (match_dup 5)
1367                 (match_dup 6)
1368                 (match_dup 7)
1369                 (match_dup 8)
1370                 (reg:SI VL_REGNUM)
1371                 (reg:SI VTYPE_REGNUM)
1372               ] UNSPEC_VPREDICATE)
1373               (match_dup 9)
1374               (match_dup 10)))
1375         ] UNSPEC_REDUC_SUM_UNORDERED))]
1376   "TARGET_VECTOR && can_create_pseudo_p ()"
1377   "#"
1378   "&& 1"
1379   [(const_int 0)]
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));
1386   DONE;
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")
1397         (neg:VF
1398           (unspec:VF [
1399             (match_operand:VF 1 "register_operand")
1400             (match_operand:VF 2 "register_operand")
1401           ] UNSPEC_VCOPYSIGN)))]
1402   "TARGET_VECTOR && can_create_pseudo_p ()"
1403   "#"
1404   "&& 1"
1405   [(const_int 0)]
1407   riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (<MODE>mode),
1408                                   riscv_vector::BINARY_OP, operands);
1409   DONE;
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 ()"
1420   "#"
1421   "&& 1"
1422   [(const_int 0)]
1423   {
1424     insn_code icode = code_for_pred_not (<CODE>, <MODE>mode);
1425     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
1426     DONE;
1427   }
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")
1433         (not:VB_VLS
1434           (any_bitwise:VB_VLS
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 ()"
1438   "#"
1439   "&& 1"
1440   [(const_int 0)]
1441   {
1442     insn_code icode = code_for_pred_n (<CODE>, <MODE>mode);
1443     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
1444     DONE;
1445   }
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")
1453     (popcount:P
1454      (unspec:VB_VLS [
1455       (unspec:VB_VLS [
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")
1462       (const_int 1)
1463       (reg:SI VL_REGNUM)
1464       (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))]
1465   "TARGET_VECTOR
1466    && can_create_pseudo_p ()
1467    && riscv_vector::get_vector_mode (Pmode, GET_MODE_NUNITS (<VB_VLS:MODE>mode)).exists ()"
1468   "#"
1469   "&& 1"
1470   [(const_int 0)]
1471   {
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]);
1476     DONE;
1477   }
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 ")
1483       (ashift:VWEXTI
1484         (zero_extend:VWEXTI
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 ()"
1488   "#"
1489   "&& 1"
1490   [(const_int 0)]
1491   {
1492     insn_code icode = code_for_pred_vwsll (<MODE>mode);
1493     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1494     DONE;
1495   }
1496   [(set_attr "type" "vwsll")])
1498 (define_insn_and_split "*vwsll_zext2_<mode>"
1499   [(set (match_operand:VWEXTI 0             "register_operand"     "=vr ")
1500       (ashift:VWEXTI
1501         (zero_extend:VWEXTI
1502           (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"     " vr "))
1503         (zero_extend:VWEXTI
1504           (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" "vrvk"))))]
1505   "TARGET_ZVBB && can_create_pseudo_p ()"
1506   "#"
1507   "&& 1"
1508   [(const_int 0)]
1509   {
1510     insn_code icode = code_for_pred_vwsll (<MODE>mode);
1511     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1512     DONE;
1513   }
1514   [(set_attr "type" "vwsll")])
1517 (define_insn_and_split "*vwsll_zext1_scalar_<mode>"
1518   [(set (match_operand:VWEXTI 0             "register_operand"            "=vr")
1519       (ashift:VWEXTI
1520         (zero_extend:VWEXTI
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 ()"
1524   "#"
1525   "&& 1"
1526   [(const_int 0)]
1527   {
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);
1531     DONE;
1532   }
1533   [(set_attr "type" "vwsll")])
1535 ;; For
1536 ;;   uint16_t dst;
1537 ;;   uint8_t a, b;
1538 ;;   dst = vwsll (a, b)
1539 ;; we seem to create
1540 ;;   aa = (int) a;
1541 ;;   bb = (int) b;
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>
1548       (ashift:VQEXTI
1549         (zero_extend:VQEXTI
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 ()"
1553   "#"
1554   "&& 1"
1555   [(const_int 0)]
1556   {
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);
1563     DONE;
1564   }
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>
1570       (ashift:VQEXTI
1571         (zero_extend:VQEXTI
1572           (match_operand:<V_QUAD_TRUNC> 1   "register_operand"     " vr "))
1573         (zero_extend:VQEXTI
1574           (match_operand:<V_QUAD_TRUNC> 2   "vector_shift_operand" "vrvk")))))]
1575   "TARGET_ZVBB && can_create_pseudo_p ()"
1576   "#"
1577   "&& 1"
1578   [(const_int 0)]
1579   {
1580     insn_code icode = code_for_pred_vwsll (<V_DOUBLE_TRUNC>mode);
1581     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1582     DONE;
1583   }
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>
1589       (ashift:VQEXTI
1590         (zero_extend:VQEXTI
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 ()"
1594   "#"
1595   "&& 1"
1596   [(const_int 0)]
1597   {
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);
1601     DONE;
1602   }
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")
1608    (and:V_VLSI
1609     (not:V_VLSI
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 ()"
1613   "#"
1614   "&& 1"
1615   [(const_int 0)]
1616   {
1617     insn_code icode = code_for_pred_vandn (<MODE>mode);
1618     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1619     DONE;
1620   }
1621   [(set_attr "type" "vandn")])