Add config file so b4 uses inbox.sourceware.org automatically
[official-gcc.git] / gcc / config / riscv / autovec-opt.md
blobd7a3cfd4602b61c86e6181131330dbf814da3d21
1 ;; Machine description for optimization of RVV auto-vectorization.
2 ;; Copyright (C) 2023-2024 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>, riscv_vector::REDUCE_OP,
814                                   operands,
815                                   CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
816   DONE;
818 [(set_attr "type" "vector")])
820 ;; Combine extend + vfredusum to vfwredusum
821 (define_insn_and_split "*widen_reduc_plus_scal_<mode>"
822   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
823         (unspec:<V_DOUBLE_EXTEND_VEL> [
824           (float_extend:<V_DOUBLE_EXTEND>
825             (match_operand:VF_HS_NO_M8 1 "register_operand"))
826         ] UNSPEC_REDUC_SUM_UNORDERED))]
827   "TARGET_VECTOR && can_create_pseudo_p ()"
828   "#"
829   "&& 1"
830   [(const_int 0)]
832   riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
833                                   riscv_vector::REDUCE_OP_FRM_DYN,
834                                   operands,
835                                   CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
836   DONE;
838 [(set_attr "type" "vector")])
840 ;; Combine extend + vfredosum to vfwredosum
841 (define_insn_and_split "*fold_left_widen_plus_<mode>"
842   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
843         (unspec:<V_DOUBLE_EXTEND_VEL> [
844           (float_extend:<V_DOUBLE_EXTEND>
845             (match_operand:VF_HS_NO_M8 1 "register_operand"))
846           (match_operand:<V_DOUBLE_EXTEND_VEL> 2 "register_operand")
847         ] UNSPEC_REDUC_SUM_ORDERED))]
848   "TARGET_VECTOR && can_create_pseudo_p ()"
849   "#"
850   "&& 1"
851   [(const_int 0)]
853   riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_ORDERED,
854                                   riscv_vector::REDUCE_OP_FRM_DYN,
855                                   operands, operands[2]);
856   DONE;
858 [(set_attr "type" "vector")])
860 ;; Combine extend + mask vfredosum to mask vfwredosum
861 (define_insn_and_split "*mask_len_fold_left_widen_plus_<mode>"
862   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
863         (unspec:<V_DOUBLE_EXTEND_VEL> [
864           (float_extend:<V_DOUBLE_EXTEND>
865             (match_operand:VF_HS_NO_M8 2 "register_operand"))
866           (match_operand:<V_DOUBLE_EXTEND_VEL> 1 "register_operand")
867           (match_operand:<VM> 3 "vector_mask_operand")
868           (match_operand 4 "autovec_length_operand")
869           (match_operand 5 "const_0_operand")
870         ] UNSPEC_REDUC_SUM_ORDERED))]
871   "TARGET_VECTOR && can_create_pseudo_p ()"
872   "#"
873   "&& 1"
874   [(const_int 0)]
876   if (rtx_equal_p (operands[4], const0_rtx))
877     emit_move_insn (operands[0], operands[1]);
878   else
879     {
880       rtx ops[] = {operands[0], operands[2], operands[3], operands[4]};
881       riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_ORDERED,
882                                       riscv_vector::REDUCE_OP_M_FRM_DYN,
883                                       ops, operands[1]);
884     }
885   DONE;
887 [(set_attr "type" "vector")])
889 ;; =============================================================================
890 ;; Combine extend + ternop to widen_ternop
891 ;; =============================================================================
893 ;; Combine ext + fma(vmacc,vmadd) to widen_fma (vwmacc[u])
894 (define_insn_and_split "*dual_widen_fma<su><mode>"
895   [(set (match_operand:VWEXTI 0 "register_operand")
896         (plus:VWEXTI
897           (mult:VWEXTI
898             (any_extend:VWEXTI
899               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
900             (any_extend:VWEXTI
901               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
902           (match_operand:VWEXTI 1 "register_operand")))]
903   "TARGET_VECTOR && can_create_pseudo_p ()"
904   "#"
905   "&& 1"
906   [(const_int 0)]
907   {
908     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
909     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plus (<CODE>, <MODE>mode),
910                                    riscv_vector::WIDEN_TERNARY_OP, ops);
911     DONE;
912   }
913   [(set_attr "type" "viwmuladd")])
915 ;; Combine sign_extend + zero_extend + fma to widen_fma (vwmaccsu)
916 (define_insn_and_split "*dual_widen_fmasu<mode>"
917   [(set (match_operand:VWEXTI 0 "register_operand")
918         (plus:VWEXTI
919           (mult:VWEXTI
920             (sign_extend:VWEXTI
921               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
922             (zero_extend:VWEXTI
923               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
924           (match_operand:VWEXTI 1 "register_operand")))]
925   "TARGET_VECTOR && can_create_pseudo_p ()"
926   "#"
927   "&& 1"
928   [(const_int 0)]
929   {
930     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
931     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
932                                    riscv_vector::WIDEN_TERNARY_OP, ops);
933     DONE;
934   }
935   [(set_attr "type" "viwmuladd")])
937 ;; Combine zero_extend + sign_extend + fma to widen_fma (vwmaccsu)
938 (define_insn_and_split "*dual_widen_fmaus<mode>"
939   [(set (match_operand:VWEXTI 0 "register_operand")
940         (plus:VWEXTI
941           (mult:VWEXTI
942             (zero_extend:VWEXTI
943               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"))
944             (sign_extend:VWEXTI
945               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
946           (match_operand:VWEXTI 1 "register_operand")))]
947   "TARGET_VECTOR && can_create_pseudo_p ()"
948   "#"
949   "&& 1"
950   [(const_int 0)]
951   {
952     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
953     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
954                                    riscv_vector::WIDEN_TERNARY_OP, ops);
955     DONE;
956   }
957   [(set_attr "type" "viwmuladd")])
959 ;; This combine pattern does not correspond to an single instruction.
960 ;; This is a temporary pattern produced by a combine pass and if there
961 ;; is no further combine into widen pattern, then fall back to extend
962 ;; pattern and non-widen fma pattern.
963 (define_insn_and_split "*single_widen_fma<su><mode>"
964   [(set (match_operand:VWEXTI 0 "register_operand")
965         (plus:VWEXTI
966           (mult:VWEXTI
967             (any_extend:VWEXTI
968               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
969             (match_operand:VWEXTI 3 "register_operand"))
970           (match_operand:VWEXTI 1 "register_operand")))]
971   "TARGET_VECTOR && can_create_pseudo_p ()"
972   "#"
973   "&& 1"
974   [(const_int 0)]
975   {
976     insn_code extend_icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
977     rtx tmp = gen_reg_rtx (<MODE>mode);
978     rtx extend_ops[] = {tmp, operands[2]};
979     riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP,
980                                    extend_ops);
982     rtx ops[] = {operands[0], tmp, operands[3], operands[1],
983                  RVV_VUNDEF(<MODE>mode)};
984     riscv_vector::emit_vlmax_insn (code_for_pred_mul_plus (<MODE>mode),
985                                    riscv_vector::TERNARY_OP, ops);
986     DONE;
987   }
988   [(set_attr "type" "viwmuladd")])
990 ;; Combine extend + fma to widen_fma (vfwmacc)
991 (define_insn_and_split "*dual_widen_fma<mode>"
992   [(set (match_operand:VWEXTF 0 "register_operand")
993         (plus:VWEXTF
994           (mult:VWEXTF
995             (float_extend:VWEXTF
996               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
997             (float_extend:VWEXTF
998               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
999           (match_operand:VWEXTF 1 "register_operand")))]
1000   "TARGET_VECTOR && can_create_pseudo_p ()"
1001   "#"
1002   "&& 1"
1003   [(const_int 0)]
1004   {
1005     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1006     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (PLUS, <MODE>mode),
1007                                    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1008     DONE;
1009   }
1010   [(set_attr "type" "vfwmuladd")])
1012 ;; This combine pattern does not correspond to an single instruction.
1013 ;; This is a temporary pattern produced by a combine pass and if there
1014 ;; is no further combine into widen pattern, then fall back to extend
1015 ;; pattern and non-widen fma pattern.
1016 (define_insn_and_split "*single_widen_fma<mode>"
1017   [(set (match_operand:VWEXTF 0 "register_operand")
1018         (plus:VWEXTF
1019           (mult:VWEXTF
1020             (float_extend:VWEXTF
1021               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1022             (match_operand:VWEXTF 3 "register_operand"))
1023           (match_operand:VWEXTF 1 "register_operand")))]
1024   "TARGET_VECTOR && can_create_pseudo_p ()"
1025   "#"
1026   "&& 1"
1027   [(const_int 0)]
1028   {
1029     insn_code icode = code_for_pred_extend (<MODE>mode);
1030     rtx tmp = gen_reg_rtx (<MODE>mode);
1031     rtx ext_ops[] = {tmp, operands[2]};
1032     riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1034     rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1035                  RVV_VUNDEF(<MODE>mode)};
1036     riscv_vector::emit_vlmax_insn (code_for_pred_mul (PLUS, <MODE>mode),
1037                                    riscv_vector::TERNARY_OP_FRM_DYN, ops);
1038     DONE;
1039   }
1040   [(set_attr "type" "vfwmuladd")])
1042 ;; Combine extend + fnma to widen_fnma (vfwnmsac)
1043 (define_insn_and_split "*dual_widen_fnma<mode>"
1044   [(set (match_operand:VWEXTF 0 "register_operand")
1045         (minus:VWEXTF
1046           (match_operand:VWEXTF 1 "register_operand")
1047           (mult:VWEXTF
1048             (float_extend:VWEXTF
1049               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1050             (float_extend:VWEXTF
1051               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))))]
1052   "TARGET_VECTOR && can_create_pseudo_p ()"
1053   "#"
1054   "&& 1"
1055   [(const_int 0)]
1056   {
1057     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1058     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (PLUS, <MODE>mode),
1059                                    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1060     DONE;
1061   }
1062   [(set_attr "type" "vfwmuladd")])
1064 ;; This combine pattern does not correspond to an single instruction.
1065 ;; This is a temporary pattern produced by a combine pass and if there
1066 ;; is no further combine into widen pattern, then fall back to extend
1067 ;; pattern and non-widen fnma pattern.
1068 (define_insn_and_split "*single_widen_fnma<mode>"
1069   [(set (match_operand:VWEXTF 0 "register_operand")
1070         (minus:VWEXTF
1071           (match_operand:VWEXTF 1 "register_operand")
1072           (mult:VWEXTF
1073             (float_extend:VWEXTF
1074               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1075             (match_operand:VWEXTF 3 "register_operand"))))]
1076   "TARGET_VECTOR && can_create_pseudo_p ()"
1077   "#"
1078   "&& 1"
1079   [(const_int 0)]
1080   {
1081     insn_code icode = code_for_pred_extend (<MODE>mode);
1082     rtx tmp = gen_reg_rtx (<MODE>mode);
1083     rtx ext_ops[] = {tmp, operands[2]};
1084     riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1086     rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1087                  RVV_VUNDEF(<MODE>mode)};
1088     riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (PLUS, <MODE>mode),
1089                                    riscv_vector::TERNARY_OP_FRM_DYN, ops);
1090     DONE;
1091   }
1092   [(set_attr "type" "vfwmuladd")])
1094 ;; Combine extend + fms to widen_fms (vfwmsac)
1095 (define_insn_and_split "*dual_widen_fms<mode>"
1096   [(set (match_operand:VWEXTF 0 "register_operand")
1097         (minus:VWEXTF
1098           (mult:VWEXTF
1099             (float_extend:VWEXTF
1100               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1101             (float_extend:VWEXTF
1102               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
1103           (match_operand:VWEXTF 1 "register_operand")))]
1104   "TARGET_VECTOR && can_create_pseudo_p ()"
1105   "#"
1106   "&& 1"
1107   [(const_int 0)]
1108   {
1109     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1110     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (MINUS, <MODE>mode),
1111                                    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1112     DONE;
1113   }
1114   [(set_attr "type" "vfwmuladd")])
1116 ;; This combine pattern does not correspond to an single instruction.
1117 ;; This is a temporary pattern produced by a combine pass and if there
1118 ;; is no further combine into widen pattern, then fall back to extend
1119 ;; pattern and non-widen fms pattern.
1120 (define_insn_and_split "*single_widen_fms<mode>"
1121   [(set (match_operand:VWEXTF 0 "register_operand")
1122         (minus:VWEXTF
1123           (mult:VWEXTF
1124             (float_extend:VWEXTF
1125               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand"))
1126             (match_operand:VWEXTF 3 "register_operand"))
1127           (match_operand:VWEXTF 1 "register_operand")))]
1128   "TARGET_VECTOR && can_create_pseudo_p ()"
1129   "#"
1130   "&& 1"
1131   [(const_int 0)]
1132   {
1133     insn_code icode = code_for_pred_extend (<MODE>mode);
1134     rtx tmp = gen_reg_rtx (<MODE>mode);
1135     rtx ext_ops[] = {tmp, operands[2]};
1136     riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1138     rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1139                  RVV_VUNDEF(<MODE>mode)};
1140     riscv_vector::emit_vlmax_insn (code_for_pred_mul (MINUS, <MODE>mode),
1141                                    riscv_vector::TERNARY_OP_FRM_DYN, ops);
1142     DONE;
1143   }
1144   [(set_attr "type" "vfwmuladd")])
1146 ;; Combine extend + fnms to widen_fnms (vfwnmacc)
1147 (define_insn_and_split "*dual_widen_fnms<mode>"
1148   [(set (match_operand:VWEXTF 0 "register_operand")
1149         (minus:VWEXTF
1150           (mult:VWEXTF
1151             (neg:VWEXTF
1152               (float_extend:VWEXTF
1153                 (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
1154             (float_extend:VWEXTF
1155               (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand")))
1156           (match_operand:VWEXTF 1 "register_operand")))]
1157   "TARGET_VECTOR && can_create_pseudo_p ()"
1158   "#"
1159   "&& 1"
1160   [(const_int 0)]
1161   {
1162     rtx ops[] = {operands[0], operands[1], operands[2], operands[3]};
1163     riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (MINUS, <MODE>mode),
1164                                    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops);
1165     DONE;
1166   }
1167   [(set_attr "type" "vfwmuladd")])
1169 ;; This combine pattern does not correspond to an single instruction.
1170 ;; This is a temporary pattern produced by a combine pass and if there
1171 ;; is no further combine into widen pattern, then fall back to extend
1172 ;; pattern and non-widen fnms pattern.
1173 (define_insn_and_split "*single_widen_fnms<mode>"
1174   [(set (match_operand:VWEXTF 0 "register_operand")
1175         (minus:VWEXTF
1176           (mult:VWEXTF
1177             (neg:VWEXTF
1178               (match_operand:VWEXTF 3 "register_operand"))
1179             (float_extend:VWEXTF
1180               (match_operand:<V_DOUBLE_TRUNC> 2 "register_operand")))
1181           (match_operand:VWEXTF 1 "register_operand")))]
1182   "TARGET_VECTOR && can_create_pseudo_p ()"
1183   "#"
1184   "&& 1"
1185   [(const_int 0)]
1186   {
1187     insn_code icode = code_for_pred_extend (<MODE>mode);
1188     rtx tmp = gen_reg_rtx (<MODE>mode);
1189     rtx ext_ops[] = {tmp, operands[2]};
1190     riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
1192     rtx ops[] = {operands[0], tmp, operands[3], operands[1],
1193                  RVV_VUNDEF(<MODE>mode)};
1194     riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (MINUS, <MODE>mode),
1195                                    riscv_vector::TERNARY_OP_FRM_DYN, ops);
1196     DONE;
1197   }
1198   [(set_attr "type" "vfwmuladd")])
1200 ;; Combine mask_extend + vredsum to mask_vwredsum[u]
1201 ;; where the mrege of mask_extend is vector const 0
1202 (define_insn_and_split "*cond_widen_reduc_plus_scal_<mode>"
1203   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1204         (unspec:<V_DOUBLE_EXTEND_VEL> [
1205           (if_then_else:<V_DOUBLE_EXTEND>
1206             (match_operand:<VM> 1 "register_operand")
1207             (any_extend:<V_DOUBLE_EXTEND>
1208               (match_operand:VI_QHS_NO_M8 2 "register_operand"))
1209             (if_then_else:<V_DOUBLE_EXTEND>
1210               (unspec:<VM> [
1211                 (match_operand:<VM> 3 "vector_all_trues_mask_operand")
1212                 (match_operand 6 "vector_length_operand")
1213                 (match_operand 7 "const_int_operand")
1214                 (match_operand 8 "const_int_operand")
1215                 (match_operand 9 "const_1_or_2_operand")
1216                 (reg:SI VL_REGNUM)
1217                 (reg:SI VTYPE_REGNUM)
1218               ] UNSPEC_VPREDICATE)
1219               (match_operand:<V_DOUBLE_EXTEND> 5 "vector_const_0_operand")
1220               (match_operand:<V_DOUBLE_EXTEND> 4 "vector_merge_operand")))
1221         ] UNSPEC_REDUC_SUM))]
1222   "TARGET_VECTOR && can_create_pseudo_p ()"
1223   "#"
1224   "&& 1"
1225   [(const_int 0)]
1227   rtx ops[] = {operands[0], operands[2], operands[1],
1228                gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
1229   riscv_vector::expand_reduction (<WREDUC_UNSPEC>,
1230                                   riscv_vector::REDUCE_OP_M,
1231                                   ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1232   DONE;
1234 [(set_attr "type" "vector")])
1236 ;; Combine mask_len_extend + vredsum to mask_vwredsum[u]
1237 ;; where the mrege of mask_len_extend is vector const 0
1238 (define_insn_and_split "*cond_len_widen_reduc_plus_scal_<mode>"
1239   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1240         (unspec:<V_DOUBLE_EXTEND_VEL> [
1241           (if_then_else:<V_DOUBLE_EXTEND>
1242             (unspec:<VM> [
1243               (match_operand 2 "vector_length_operand")
1244               (const_int 0)
1245               (const_int 0)
1246               (reg:SI VL_REGNUM)
1247               (reg:SI VTYPE_REGNUM)
1248             ] UNSPEC_VPREDICATE)
1249             (vec_merge:<V_DOUBLE_EXTEND>
1250               (any_extend:<V_DOUBLE_EXTEND>
1251                 (match_operand:VI_QHS_NO_M8 3 "register_operand"))
1252               (if_then_else:<V_DOUBLE_EXTEND>
1253                 (unspec:<VM> [
1254                   (match_operand:<VM> 4 "vector_all_trues_mask_operand")
1255                   (match_operand 5 "vector_length_operand")
1256                   (match_operand 6 "const_int_operand")
1257                   (match_operand 7 "const_int_operand")
1258                   (match_operand 8 "const_1_or_2_operand")
1259                   (reg:SI VL_REGNUM)
1260                   (reg:SI VTYPE_REGNUM)
1261                 ] UNSPEC_VPREDICATE)
1262                 (match_operand:<V_DOUBLE_EXTEND> 9 "vector_const_0_operand")
1263                 (match_operand:<V_DOUBLE_EXTEND> 10 "vector_merge_operand"))
1264               (match_operand:<VM> 1 "register_operand"))
1265             (if_then_else:<V_DOUBLE_EXTEND>
1266               (unspec:<VM> [
1267                 (match_dup 4)
1268                 (match_dup 5)
1269                 (match_dup 6)
1270                 (match_dup 7)
1271                 (match_dup 8)
1272                 (reg:SI VL_REGNUM)
1273                 (reg:SI VTYPE_REGNUM)
1274               ] UNSPEC_VPREDICATE)
1275               (match_dup 9)
1276               (match_dup 10)))
1277         ] UNSPEC_REDUC_SUM))]
1278   "TARGET_VECTOR && can_create_pseudo_p ()"
1279   "#"
1280   "&& 1"
1281   [(const_int 0)]
1283   rtx ops[] = {operands[0], operands[3], operands[1], operands[2]};
1284   riscv_vector::expand_reduction (<WREDUC_UNSPEC>,
1285                                   riscv_vector::REDUCE_OP_M,
1286                                   ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1287   DONE;
1289 [(set_attr "type" "vector")])
1291 ;; Combine mask_extend + vfredsum to mask_vfwredusum
1292 ;; where the mrege of mask_extend is vector const 0
1293 (define_insn_and_split "*cond_widen_reduc_plus_scal_<mode>"
1294   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1295         (unspec:<V_DOUBLE_EXTEND_VEL> [
1296           (if_then_else:<V_DOUBLE_EXTEND>
1297             (match_operand:<VM> 1 "register_operand")
1298             (float_extend:<V_DOUBLE_EXTEND>
1299               (match_operand:VF_HS_NO_M8 2 "register_operand"))
1300             (if_then_else:<V_DOUBLE_EXTEND>
1301               (unspec:<VM> [
1302                 (match_operand:<VM> 3 "vector_all_trues_mask_operand")
1303                 (match_operand 6 "vector_length_operand")
1304                 (match_operand 7 "const_int_operand")
1305                 (match_operand 8 "const_int_operand")
1306                 (match_operand 9 "const_1_or_2_operand")
1307                 (reg:SI VL_REGNUM)
1308                 (reg:SI VTYPE_REGNUM)
1309               ] UNSPEC_VPREDICATE)
1310               (match_operand:<V_DOUBLE_EXTEND> 5 "vector_const_0_operand")
1311               (match_operand:<V_DOUBLE_EXTEND> 4 "vector_merge_operand")))
1312         ] UNSPEC_REDUC_SUM_UNORDERED))]
1313   "TARGET_VECTOR && can_create_pseudo_p ()"
1314   "#"
1315   "&& 1"
1316   [(const_int 0)]
1318   rtx ops[] = {operands[0], operands[2], operands[1],
1319                gen_int_mode (GET_MODE_NUNITS (<MODE>mode), Pmode)};
1320   riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
1321                                   riscv_vector::REDUCE_OP_M_FRM_DYN,
1322                                   ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1323   DONE;
1325 [(set_attr "type" "vector")])
1327 ;; Combine mask_len_extend + vredsum to mask_vwredsum[u]
1328 ;; where the mrege of mask_len_extend is vector const 0
1329 (define_insn_and_split "*cond_len_widen_reduc_plus_scal_<mode>"
1330   [(set (match_operand:<V_DOUBLE_EXTEND_VEL> 0 "register_operand")
1331         (unspec:<V_DOUBLE_EXTEND_VEL> [
1332           (if_then_else:<V_DOUBLE_EXTEND>
1333             (unspec:<VM> [
1334               (match_operand 2 "vector_length_operand")
1335               (const_int 0)
1336               (const_int 0)
1337               (reg:SI VL_REGNUM)
1338               (reg:SI VTYPE_REGNUM)
1339             ] UNSPEC_VPREDICATE)
1340             (vec_merge:<V_DOUBLE_EXTEND>
1341               (float_extend:<V_DOUBLE_EXTEND>
1342                 (match_operand:VF_HS_NO_M8 3 "register_operand"))
1343               (if_then_else:<V_DOUBLE_EXTEND>
1344                 (unspec:<VM> [
1345                   (match_operand:<VM> 4 "vector_all_trues_mask_operand")
1346                   (match_operand 5 "vector_length_operand")
1347                   (match_operand 6 "const_int_operand")
1348                   (match_operand 7 "const_int_operand")
1349                   (match_operand 8 "const_1_or_2_operand")
1350                   (reg:SI VL_REGNUM)
1351                   (reg:SI VTYPE_REGNUM)
1352                 ] UNSPEC_VPREDICATE)
1353                 (match_operand:<V_DOUBLE_EXTEND> 9 "vector_const_0_operand")
1354                 (match_operand:<V_DOUBLE_EXTEND> 10 "vector_merge_operand"))
1355               (match_operand:<VM> 1 "register_operand"))
1356             (if_then_else:<V_DOUBLE_EXTEND>
1357               (unspec:<VM> [
1358                 (match_dup 4)
1359                 (match_dup 5)
1360                 (match_dup 6)
1361                 (match_dup 7)
1362                 (match_dup 8)
1363                 (reg:SI VL_REGNUM)
1364                 (reg:SI VTYPE_REGNUM)
1365               ] UNSPEC_VPREDICATE)
1366               (match_dup 9)
1367               (match_dup 10)))
1368         ] UNSPEC_REDUC_SUM_UNORDERED))]
1369   "TARGET_VECTOR && can_create_pseudo_p ()"
1370   "#"
1371   "&& 1"
1372   [(const_int 0)]
1374   rtx ops[] = {operands[0], operands[3], operands[1], operands[2]};
1375   riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED,
1376                                   riscv_vector::REDUCE_OP_M_FRM_DYN,
1377                                   ops, CONST0_RTX (<V_DOUBLE_EXTEND_VEL>mode));
1378   DONE;
1380 [(set_attr "type" "vector")])
1382 ;; =============================================================================
1383 ;; Misc combine patterns
1384 ;; =============================================================================
1386 ;; Combine neg + vfsgnj to vfsgnjn
1387 (define_insn_and_split "*copysign<mode>_neg"
1388   [(set (match_operand:VF 0 "register_operand")
1389         (neg:VF
1390           (unspec:VF [
1391             (match_operand:VF 1 "register_operand")
1392             (match_operand:VF 2 "register_operand")
1393           ] UNSPEC_VCOPYSIGN)))]
1394   "TARGET_VECTOR && can_create_pseudo_p ()"
1395   "#"
1396   "&& 1"
1397   [(const_int 0)]
1399   riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (<MODE>mode),
1400                                   riscv_vector::BINARY_OP, operands);
1401   DONE;
1403 [(set_attr "type" "vector")])
1405 ;; Combine vmand/vmor + vmnot to vmandnot/vmornot
1406 (define_insn_and_split "*<optab>not<mode>"
1407   [(set (match_operand:VB_VLS 0 "register_operand"           "=vr")
1408         (bitmanip_bitwise:VB_VLS
1409           (not:VB_VLS (match_operand:VB_VLS 2 "register_operand" " vr"))
1410           (match_operand:VB_VLS 1 "register_operand"         " vr")))]
1411   "TARGET_VECTOR && can_create_pseudo_p ()"
1412   "#"
1413   "&& 1"
1414   [(const_int 0)]
1415   {
1416     insn_code icode = code_for_pred_not (<CODE>, <MODE>mode);
1417     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
1418     DONE;
1419   }
1420   [(set_attr "type" "vmalu")])
1422 ;; Combine vmnot + vmand/vmor/vmxor to vmnand/vmnor/vmxnor
1423 (define_insn_and_split "*n<optab><mode>"
1424   [(set (match_operand:VB_VLS 0 "register_operand"     "=vr")
1425         (not:VB_VLS
1426           (any_bitwise:VB_VLS
1427             (match_operand:VB_VLS 1 "register_operand" " vr")
1428             (match_operand:VB_VLS 2 "register_operand" " vr"))))]
1429   "TARGET_VECTOR && can_create_pseudo_p ()"
1430   "#"
1431   "&& 1"
1432   [(const_int 0)]
1433   {
1434     insn_code icode = code_for_pred_n (<CODE>, <MODE>mode);
1435     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
1436     DONE;
1437   }
1438   [(set_attr "type" "vmalu")])
1440 ;; Optimization pattern for early break auto-vectorization
1441 ;; vcond_mask_len (mask, ones, zeros, len, bias) + vlmax popcount
1442 ;; -> non vlmax popcount (mask, len)
1443 (define_insn_and_split "*vcond_mask_len_popcount_<VB_VLS:mode><P:mode>"
1444   [(set (match_operand:P 0 "register_operand")
1445     (popcount:P
1446      (unspec:VB_VLS [
1447       (unspec:VB_VLS [
1448        (match_operand:VB_VLS 1 "register_operand")
1449        (match_operand:VB_VLS 2 "const_1_operand")
1450        (match_operand:VB_VLS 3 "const_0_operand")
1451        (match_operand 4 "autovec_length_operand")
1452        (match_operand 5 "const_0_operand")] UNSPEC_SELECT_MASK)
1453       (match_operand 6 "autovec_length_operand")
1454       (const_int 1)
1455       (reg:SI VL_REGNUM)
1456       (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))]
1457   "TARGET_VECTOR
1458    && can_create_pseudo_p ()
1459    && riscv_vector::get_vector_mode (Pmode, GET_MODE_NUNITS (<VB_VLS:MODE>mode)).exists ()"
1460   "#"
1461   "&& 1"
1462   [(const_int 0)]
1463   {
1464     riscv_vector::emit_nonvlmax_insn (
1465         code_for_pred_popcount (<VB_VLS:MODE>mode, Pmode),
1466         riscv_vector::CPOP_OP,
1467         operands, operands[4]);
1468     DONE;
1469   }
1470   [(set_attr "type" "vector")])
1472 ;; vzext.vf2 + vsll = vwsll.
1473 (define_insn_and_split "*vwsll_zext1_<mode>"
1474   [(set (match_operand:VWEXTI 0             "register_operand"     "=vr ")
1475       (ashift:VWEXTI
1476         (zero_extend:VWEXTI
1477           (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"     " vr "))
1478           (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" "vrvk")))]
1479   "TARGET_ZVBB && can_create_pseudo_p ()"
1480   "#"
1481   "&& 1"
1482   [(const_int 0)]
1483   {
1484     insn_code icode = code_for_pred_vwsll (<MODE>mode);
1485     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1486     DONE;
1487   }
1488   [(set_attr "type" "vwsll")])
1490 (define_insn_and_split "*vwsll_zext2_<mode>"
1491   [(set (match_operand:VWEXTI 0             "register_operand"     "=vr ")
1492       (ashift:VWEXTI
1493         (zero_extend:VWEXTI
1494           (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"     " vr "))
1495         (zero_extend:VWEXTI
1496           (match_operand:<V_DOUBLE_TRUNC> 2 "vector_shift_operand" "vrvk"))))]
1497   "TARGET_ZVBB && can_create_pseudo_p ()"
1498   "#"
1499   "&& 1"
1500   [(const_int 0)]
1501   {
1502     insn_code icode = code_for_pred_vwsll (<MODE>mode);
1503     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1504     DONE;
1505   }
1506   [(set_attr "type" "vwsll")])
1509 (define_insn_and_split "*vwsll_zext1_scalar_<mode>"
1510   [(set (match_operand:VWEXTI 0             "register_operand"            "=vr")
1511       (ashift:VWEXTI
1512         (zero_extend:VWEXTI
1513           (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"            " vr"))
1514           (match_operand:<VEL>            2 "vector_scalar_shift_operand" " rK")))]
1515   "TARGET_ZVBB && can_create_pseudo_p ()"
1516   "#"
1517   "&& 1"
1518   [(const_int 0)]
1519   {
1520     operands[2] = gen_lowpart (Pmode, operands[2]);
1521     insn_code icode = code_for_pred_vwsll_scalar (<MODE>mode);
1522     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1523     DONE;
1524   }
1525   [(set_attr "type" "vwsll")])
1527 ;; For
1528 ;;   uint16_t dst;
1529 ;;   uint8_t a, b;
1530 ;;   dst = vwsll (a, b)
1531 ;; we seem to create
1532 ;;   aa = (int) a;
1533 ;;   bb = (int) b;
1534 ;;   dst = (short) vwsll (aa, bb);
1535 ;; The following patterns help to combine this idiom into one vwsll.
1537 (define_insn_and_split "*vwsll_zext1_trunc_<mode>"
1538   [(set (match_operand:<V_DOUBLE_TRUNC> 0   "register_operand"     "=vr ")
1539     (truncate:<V_DOUBLE_TRUNC>
1540       (ashift:VQEXTI
1541         (zero_extend:VQEXTI
1542           (match_operand:<V_QUAD_TRUNC> 1   "register_operand"     " vr "))
1543         (match_operand:VQEXTI           2   "vector_shift_operand" "vrvk"))))]
1544   "TARGET_ZVBB && can_create_pseudo_p ()"
1545   "#"
1546   "&& 1"
1547   [(const_int 0)]
1548   {
1549     insn_code icode = code_for_pred_vwsll (<V_DOUBLE_TRUNC>mode);
1550     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1551     DONE;
1552   }
1553   [(set_attr "type" "vwsll")])
1555 (define_insn_and_split "*vwsll_zext2_trunc_<mode>"
1556   [(set (match_operand:<V_DOUBLE_TRUNC> 0   "register_operand"     "=vr ")
1557     (truncate:<V_DOUBLE_TRUNC>
1558       (ashift:VQEXTI
1559         (zero_extend:VQEXTI
1560           (match_operand:<V_QUAD_TRUNC> 1   "register_operand"     " vr "))
1561         (zero_extend:VQEXTI
1562           (match_operand:<V_QUAD_TRUNC> 2   "vector_shift_operand" "vrvk")))))]
1563   "TARGET_ZVBB && can_create_pseudo_p ()"
1564   "#"
1565   "&& 1"
1566   [(const_int 0)]
1567   {
1568     insn_code icode = code_for_pred_vwsll (<V_DOUBLE_TRUNC>mode);
1569     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1570     DONE;
1571   }
1572   [(set_attr "type" "vwsll")])
1574 (define_insn_and_split "*vwsll_zext1_trunc_scalar_<mode>"
1575   [(set (match_operand:<V_DOUBLE_TRUNC> 0   "register_operand"            "=vr ")
1576     (truncate:<V_DOUBLE_TRUNC>
1577       (ashift:VQEXTI
1578         (zero_extend:VQEXTI
1579           (match_operand:<V_QUAD_TRUNC> 1   "register_operand"            " vr "))
1580           (match_operand:<VEL>          2   "vector_scalar_shift_operand" " rK"))))]
1581   "TARGET_ZVBB && can_create_pseudo_p ()"
1582   "#"
1583   "&& 1"
1584   [(const_int 0)]
1585   {
1586     operands[2] = gen_lowpart (Pmode, operands[2]);
1587     insn_code icode = code_for_pred_vwsll_scalar (<V_DOUBLE_TRUNC>mode);
1588     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1589     DONE;
1590   }
1591   [(set_attr "type" "vwsll")])
1593 ;; vnot + vand = vandn.
1594 (define_insn_and_split "*vandn_<mode>"
1595  [(set (match_operand:V_VLSI 0 "register_operand" "=vr")
1596    (and:V_VLSI
1597     (not:V_VLSI
1598       (match_operand:V_VLSI  2 "register_operand"  "vr"))
1599     (match_operand:V_VLSI    1 "register_operand"  "vr")))]
1600   "TARGET_ZVBB && can_create_pseudo_p ()"
1601   "#"
1602   "&& 1"
1603   [(const_int 0)]
1604   {
1605     insn_code icode = code_for_pred_vandn (<MODE>mode);
1606     riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
1607     DONE;
1608   }
1609   [(set_attr "type" "vandn")])