;; Machine description for optimization of RVV auto-vectorization. ;; Copyright (C) 2023-2024 Free Software Foundation, Inc. ;; Contributed by Juzhe Zhong (juzhe.zhong@rivai.ai), RiVAI Technologies Ltd. ;; This file is part of GCC. ;; GCC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GCC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GCC; see the file COPYING3. If not see ;; . ;; ----------------------------------------------------------------------------- ;; ---- Integer Compare Instructions Simplification ;; ----------------------------------------------------------------------------- ;; Simplify OP(V, V) Instructions to VMCLR.m Includes: ;; - 1. VMSNE ;; - 2. VMSLT ;; - 3. VMSLTU ;; - 4. VMSGT ;; - 5. VMSGTU ;; ----------------------------------------------------------------------------- ;; Simplify OP(V, V) Instructions to VMSET.m Includes: ;; - 1. VMSEQ ;; - 2. VMSLE ;; - 3. VMSLEU ;; - 4. VMSGE ;; - 5. VMSGEU ;; ----------------------------------------------------------------------------- (define_split [(set (match_operand:VB 0 "register_operand") (if_then_else:VB (unspec:VB [(match_operand:VB 1 "vector_all_trues_mask_operand") (match_operand 4 "vector_length_operand") (match_operand 5 "const_int_operand") (match_operand 6 "const_int_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (match_operand:VB 3 "vector_move_operand") (match_operand:VB 2 "vector_undef_operand")))] "TARGET_VECTOR" [(const_int 0)] { emit_insn (gen_pred_mov (mode, operands[0], CONST1_RTX (mode), RVV_VUNDEF (mode), operands[3], operands[4], operands[5])); DONE; } ) ;; ------------------------------------------------------------------------- ;; ---- Sign-extension for vmv.x.s. ;; ------------------------------------------------------------------------- (define_insn "*pred_extract_first_sextdi" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (unspec: [(vec_select: (match_operand:VI_QHS 1 "register_operand""vr") (parallel [(const_int 0)])) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))] "TARGET_VECTOR && Pmode == DImode" "vmv.x.s\t%0,%1" [(set_attr "type" "vimovvx") (set_attr "mode" "")]) (define_insn "*pred_extract_first_sextsi" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (unspec: [(vec_select: (match_operand:VI_QH 1 "register_operand" "vr") (parallel [(const_int 0)])) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)))] "TARGET_VECTOR && Pmode == SImode" "vmv.x.s\t%0,%1" [(set_attr "type" "vimovvx") (set_attr "mode" "")]) ;; ============================================================================= ;; All combine patterns for combine pass. ;; ============================================================================= ;; ============================================================================= ;; Combine op + vmerge to cond_op ;; ============================================================================= ;; Combine and vcond_mask generated by midend into cond_len_ ;; Currently supported operations: ;; abs(FP) (define_insn_and_split "*cond_abs" [(set (match_operand:V_VLSF 0 "register_operand") (if_then_else:V_VLSF (match_operand: 1 "register_operand") (abs:V_VLSF (match_operand:V_VLSF 2 "nonmemory_operand")) (match_operand:V_VLSF 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred (ABS, mode); riscv_vector::expand_cond_unop (icode, operands); DONE; } [(set_attr "type" "vector")]) ;; Combine vfsqrt.v and cond_mask (define_insn_and_split "*cond_" [(set (match_operand:V_VLSF 0 "register_operand") (if_then_else:V_VLSF (match_operand: 1 "register_operand") (any_float_unop:V_VLSF (match_operand:V_VLSF 2 "register_operand")) (match_operand:V_VLSF 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred (, mode); riscv_vector::expand_cond_unop (icode, operands); DONE; } [(set_attr "type" "vector")]) ;; Combine sign_extend/zero_extend(vf2) and vcond_mask (define_insn_and_split "*cond_" [(set (match_operand:VWEXTI 0 "register_operand") (if_then_else:VWEXTI (match_operand: 1 "register_operand") (any_extend:VWEXTI (match_operand: 2 "register_operand")) (match_operand:VWEXTI 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_vf2 (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine sign_extend/zero_extend(vf4) and vcond_mask (define_insn_and_split "*cond_" [(set (match_operand:VQEXTI 0 "register_operand") (if_then_else:VQEXTI (match_operand: 1 "register_operand") (any_extend:VQEXTI (match_operand: 2 "register_operand")) (match_operand:VQEXTI 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_vf4 (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine sign_extend/zero_extend(vf8) and vcond_mask (define_insn_and_split "*cond_" [(set (match_operand:VOEXTI 0 "register_operand") (if_then_else:VOEXTI (match_operand: 1 "register_operand") (any_extend:VOEXTI (match_operand: 2 "register_operand")) (match_operand:VOEXTI 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_vf8 (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine sign_extend/zero_extend(vf2) and vcond_mask_len (define_insn_and_split "*cond_len_" [(set (match_operand:VWEXTI 0 "register_operand") (if_then_else:VWEXTI (unspec: [(match_operand 4 "vector_length_operand") (match_operand 5 "const_int_operand") (match_operand 6 "const_int_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (vec_merge:VWEXTI (any_extend:VWEXTI (match_operand: 2 "register_operand")) (match_operand:VWEXTI 1 "vector_merge_operand") (match_operand: 3 "register_operand")) (match_dup 1)))] "TARGET_VECTOR" "#" "&& 1" [(const_int 0)] { emit_insn (gen_pred__vf2 (operands[0], operands[3], operands[1], operands[2], operands[4], operands[5], operands[6], CONST0_RTX (Pmode))); DONE; } [(set_attr "type" "vector")]) ;; Combine sign_extend/zero_extend(vf4) and vcond_mask_len (define_insn_and_split "*cond_len_" [(set (match_operand:VQEXTI 0 "register_operand") (if_then_else:VQEXTI (unspec: [(match_operand 4 "vector_length_operand") (match_operand 5 "const_int_operand") (match_operand 6 "const_int_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (vec_merge:VQEXTI (any_extend:VQEXTI (match_operand: 2 "register_operand")) (match_operand:VQEXTI 1 "vector_merge_operand") (match_operand: 3 "register_operand")) (match_dup 1)))] "TARGET_VECTOR" "#" "&& 1" [(const_int 0)] { emit_insn (gen_pred__vf4 (operands[0], operands[3], operands[1], operands[2], operands[4], operands[5], operands[6], CONST0_RTX (Pmode))); DONE; } [(set_attr "type" "vector")]) ;; Combine sign_extend/zero_extend(vf8) and vcond_mask_len (define_insn_and_split "*cond_len_" [(set (match_operand:VOEXTI 0 "register_operand") (if_then_else:VOEXTI (unspec: [(match_operand 4 "vector_length_operand") (match_operand 5 "const_int_operand") (match_operand 6 "const_int_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (vec_merge:VOEXTI (any_extend:VOEXTI (match_operand: 2 "register_operand")) (match_operand:VOEXTI 1 "vector_merge_operand") (match_operand: 3 "register_operand")) (match_dup 1)))] "TARGET_VECTOR" "#" "&& 1" [(const_int 0)] { emit_insn (gen_pred__vf8 (operands[0], operands[3], operands[1], operands[2], operands[4], operands[5], operands[6], CONST0_RTX (Pmode))); DONE; } [(set_attr "type" "vector")]) ;; Combine trunc(vf2) + vcond_mask (define_insn_and_split "*cond_trunc" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (truncate: (match_operand:VWEXTI 2 "register_operand")) (match_operand: 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_trunc (mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine FP extend(vf2) and vcond_mask (define_insn_and_split "*cond_extend" [(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand") (if_then_else:VWEXTF_ZVFHMIN (match_operand: 1 "register_operand") (float_extend:VWEXTF_ZVFHMIN (match_operand: 2 "register_operand")) (match_operand:VWEXTF_ZVFHMIN 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_extend (mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine FP extend(vf2) and vcond_mask_len (define_insn_and_split "*cond_len_extend" [(set (match_operand:VWEXTF_ZVFHMIN 0 "register_operand") (if_then_else:VWEXTF_ZVFHMIN (unspec: [(match_operand 4 "vector_length_operand") (match_operand 5 "const_int_operand") (match_operand 6 "const_int_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) (vec_merge:VWEXTF_ZVFHMIN (float_extend:VWEXTF_ZVFHMIN (match_operand: 2 "register_operand")) (match_operand:VWEXTF_ZVFHMIN 1 "vector_merge_operand") (match_operand: 3 "register_operand")) (match_dup 1)))] "TARGET_VECTOR" "#" "&& 1" [(const_int 0)] { emit_insn (gen_pred_extend (operands[0], operands[3], operands[1], operands[2], operands[4], operands[5], operands[6], CONST0_RTX (Pmode))); DONE; } [(set_attr "type" "vector")]) ;; Combine FP trunc(vf2) + vcond_mask (define_insn_and_split "*cond_trunc" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (float_truncate: (match_operand:VWEXTF_ZVFHMIN 2 "register_operand")) (match_operand: 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_trunc (mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine convert(FP->INT) + vcond_mask (define_insn_and_split "*cond_" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (any_fix: (match_operand:V_VLSF 2 "register_operand")) (match_operand: 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine convert(INT->FP) + vcond_mask (define_insn_and_split "*cond_" [(set (match_operand:V_VLSF 0 "register_operand") (if_then_else:V_VLSF (match_operand: 1 "register_operand") (any_float:V_VLSF (match_operand: 2 "register_operand")) (match_operand:V_VLSF 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine convert(FP->2xINT) + vcond_mask (define_insn_and_split "*cond_" [(set (match_operand:VWCONVERTI 0 "register_operand") (if_then_else:VWCONVERTI (match_operand: 1 "register_operand") (any_fix:VWCONVERTI (match_operand: 2 "register_operand")) (match_operand:VWCONVERTI 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_widen (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine convert(INT->2xFP) + vcond_mask (define_insn_and_split "*cond_" [(set (match_operand:V_VLSF 0 "register_operand") (if_then_else:V_VLSF (match_operand: 1 "register_operand") (any_float:V_VLSF (match_operand: 2 "register_operand")) (match_operand:V_VLSF 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_widen (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine convert(2xFP->INT) + vcond_mask (define_insn_and_split "*cond_" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (any_fix: (match_operand:V_VLSF 2 "register_operand")) (match_operand: 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_narrow (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine convert(2xINT->FP) + vcond_mask (define_insn_and_split "*cond_2" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (any_float: (match_operand:VWCONVERTI 2 "register_operand")) (match_operand: 3 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_narrow (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_unop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; Combine vnsra + vcond_mask (define_insn_and_split "*cond_vtrunc" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (truncate: (any_shiftrt:VWEXTI (match_operand:VWEXTI 2 "register_operand") (any_extend:VWEXTI (match_operand: 3 "vector_shift_operand")))) (match_operand: 4 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_narrow (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[4], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_binop (icode, ops); DONE; } [(set_attr "type" "vnshift")]) (define_insn_and_split "*cond_trunc" [(set (match_operand: 0 "register_operand") (if_then_else: (match_operand: 1 "register_operand") (truncate: (any_shiftrt:VWEXTI (match_operand:VWEXTI 2 "register_operand") (match_operand: 3 "csr_operand"))) (match_operand: 4 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_narrow_scalar (, mode); rtx ops[] = {operands[0], operands[1], operands[2], gen_lowpart (Pmode, operands[3]), operands[4], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_binop (icode, ops); DONE; } [(set_attr "type" "vnshift")]) ;; Combine vmulh.vv/vmulhu.vv + vcond_mask (define_insn_and_split "*cond_3_highpart" [(set (match_operand:VFULLI 0 "register_operand") (if_then_else:VFULLI (match_operand: 1 "register_operand") (mulh:VFULLI (match_operand:VFULLI 2 "register_operand") (match_operand:VFULLI 3 "register_operand")) (match_operand:VFULLI 4 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_mulh (, mode); rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[4], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_cond_len_binop (icode, ops); DONE; } [(set_attr "type" "vector")]) ;; ============================================================================= ;; Combine binop + trunc to narrow_binop ;; ============================================================================= ;; Combine vsr[la].vv + trunc to vnsr[la].wv (define_insn_and_split "*narrow_" [(set (match_operand: 0 "register_operand" "=vr,vr") (truncate: (any_shiftrt:VWEXTI (match_operand:VWEXTI 1 "register_operand" " vr,vr") (any_extend:VWEXTI (match_operand: 2 "vector_shift_operand" " vr,vk")))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_narrow (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "vnshift")]) ;; Combine vsr[la].w[xi] + trunc to vnsr[la].w[xi] (define_insn_and_split "*narrow__scalar" [(set (match_operand: 0 "register_operand" "=vr") (truncate: (any_shiftrt:VWEXTI (match_operand:VWEXTI 1 "register_operand" " vr") (match_operand: 2 "csr_operand" " rK"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { operands[2] = gen_lowpart (Pmode, operands[2]); insn_code icode = code_for_pred_narrow_scalar (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "vnshift")]) ;; ============================================================================= ;; Combine extend + binop to widen_binop ;; ============================================================================= (define_insn_and_split "*dual_widen_" [(set (match_operand:VWEXTI 0 "register_operand") (any_widen_binop:VWEXTI (any_extend:VWEXTI (match_operand: 1 "register_operand")) (any_extend:VWEXTI (match_operand: 2 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_dual_widen (, , mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "vector")]) (define_insn_and_split "*single_widen_sub" [(set (match_operand:VWEXTI 0 "register_operand") (minus:VWEXTI (match_operand:VWEXTI 1 "register_operand") (any_extend:VWEXTI (match_operand: 2 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_single_widen_sub (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "viwalu")]) (define_insn_and_split "*single_widen_add" [(set (match_operand:VWEXTI 0 "register_operand") (plus:VWEXTI (any_extend:VWEXTI (match_operand: 2 "register_operand")) (match_operand:VWEXTI 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_single_widen_add (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "viwalu")]) ;; This combine pattern does not correspond to an single instruction, ;; i.e. there is no vwmul.wv instruction. This is a temporary pattern ;; produced by a combine pass and if there is no further combine into ;; vwmul.vv pattern, then fall back to extend pattern and vmul.vv pattern. (define_insn_and_split "*single_widen_mul" [(set (match_operand:VWEXTI 0 "register_operand") (mult:VWEXTI (any_extend:VWEXTI (match_operand: 2 "register_operand")) (match_operand:VWEXTI 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code extend_icode = code_for_pred_vf2 (, mode); rtx tmp = gen_reg_rtx (mode); rtx extend_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops); rtx ops[] = {operands[0], operands[1], tmp}; insn_code icode = code_for_pred (MULT, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops); DONE; } [(set_attr "type" "viwmul")]) (define_insn_and_split "*dual_widen_mulsu" [(set (match_operand:VWEXTI 0 "register_operand") (mult:VWEXTI (sign_extend:VWEXTI (match_operand: 1 "register_operand")) (zero_extend:VWEXTI (match_operand: 2 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_widen_mulsu (mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "vector")]) (define_insn_and_split "*dual_widen_mulus" [(set (match_operand:VWEXTI 0 "register_operand") (mult:VWEXTI (zero_extend:VWEXTI (match_operand: 2 "register_operand")) (sign_extend:VWEXTI (match_operand: 1 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_widen_mulsu (mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "vector")]) (define_insn_and_split "*dual_widen_" [(set (match_operand:VWEXTF 0 "register_operand") (any_widen_binop:VWEXTF (float_extend:VWEXTF (match_operand: 1 "register_operand")) (float_extend:VWEXTF (match_operand: 2 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_dual_widen (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands); DONE; } [(set_attr "type" "vector")]) (define_insn_and_split "*single_widen_add" [(set (match_operand:VWEXTF 0 "register_operand") (plus:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_single_widen_add (mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands); DONE; } [(set_attr "type" "vfwalu")]) (define_insn_and_split "*single_widen_sub" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (match_operand:VWEXTF 1 "register_operand") (float_extend:VWEXTF (match_operand: 2 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_single_widen_sub (mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, operands); DONE; } [(set_attr "type" "vfwalu")]) ;; This combine pattern does not correspond to an single instruction, ;; i.e. there is no vfwmul.wv instruction. This is a temporary pattern ;; produced by a combine pass and if there is no further combine into ;; vfwmul.vv pattern, then fall back to extend pattern and vfmul.vv pattern. (define_insn_and_split "*single_widen_mul" [(set (match_operand:VWEXTF 0 "register_operand") (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code extend_icode = code_for_pred_extend (mode); rtx tmp = gen_reg_rtx (mode); rtx extend_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops); rtx ops[] = {operands[0], operands[1], tmp}; riscv_vector::emit_vlmax_insn (code_for_pred (MULT, mode), riscv_vector::BINARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmul")]) ;; Combine extend + vredsum to vwredsum[u] (define_insn_and_split "*widen_reduc_plus_scal_" [(set (match_operand: 0 "register_operand") (unspec: [ (any_extend: (match_operand:VI_QHS_NO_M8 1 "register_operand")) ] UNSPEC_REDUC_SUM))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { riscv_vector::expand_reduction (, riscv_vector::REDUCE_OP, operands, CONST0_RTX (mode)); DONE; } [(set_attr "type" "vector")]) ;; Combine extend + vfredusum to vfwredusum (define_insn_and_split "*widen_reduc_plus_scal_" [(set (match_operand: 0 "register_operand") (unspec: [ (float_extend: (match_operand:VF_HS_NO_M8 1 "register_operand")) ] UNSPEC_REDUC_SUM_UNORDERED))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED, riscv_vector::REDUCE_OP_FRM_DYN, operands, CONST0_RTX (mode)); DONE; } [(set_attr "type" "vector")]) ;; Combine extend + vfredosum to vfwredosum (define_insn_and_split "*fold_left_widen_plus_" [(set (match_operand: 0 "register_operand") (unspec: [ (float_extend: (match_operand:VF_HS_NO_M8 1 "register_operand")) (match_operand: 2 "register_operand") ] UNSPEC_REDUC_SUM_ORDERED))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_ORDERED, riscv_vector::REDUCE_OP_FRM_DYN, operands, operands[2]); DONE; } [(set_attr "type" "vector")]) ;; Combine extend + mask vfredosum to mask vfwredosum (define_insn_and_split "*mask_len_fold_left_widen_plus_" [(set (match_operand: 0 "register_operand") (unspec: [ (float_extend: (match_operand:VF_HS_NO_M8 2 "register_operand")) (match_operand: 1 "register_operand") (match_operand: 3 "vector_mask_operand") (match_operand 4 "autovec_length_operand") (match_operand 5 "const_0_operand") ] UNSPEC_REDUC_SUM_ORDERED))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { if (rtx_equal_p (operands[4], const0_rtx)) emit_move_insn (operands[0], operands[1]); else { rtx ops[] = {operands[0], operands[2], operands[3], operands[4]}; riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_ORDERED, riscv_vector::REDUCE_OP_M_FRM_DYN, ops, operands[1]); } DONE; } [(set_attr "type" "vector")]) ;; ============================================================================= ;; Combine extend + ternop to widen_ternop ;; ============================================================================= ;; Combine ext + fma(vmacc,vmadd) to widen_fma (vwmacc[u]) (define_insn_and_split "*dual_widen_fma" [(set (match_operand:VWEXTI 0 "register_operand") (plus:VWEXTI (mult:VWEXTI (any_extend:VWEXTI (match_operand: 2 "register_operand")) (any_extend:VWEXTI (match_operand: 3 "register_operand"))) (match_operand:VWEXTI 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plus (, mode), riscv_vector::WIDEN_TERNARY_OP, ops); DONE; } [(set_attr "type" "viwmuladd")]) ;; Combine sign_extend + zero_extend + fma to widen_fma (vwmaccsu) (define_insn_and_split "*dual_widen_fmasu" [(set (match_operand:VWEXTI 0 "register_operand") (plus:VWEXTI (mult:VWEXTI (sign_extend:VWEXTI (match_operand: 2 "register_operand")) (zero_extend:VWEXTI (match_operand: 3 "register_operand"))) (match_operand:VWEXTI 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (mode), riscv_vector::WIDEN_TERNARY_OP, ops); DONE; } [(set_attr "type" "viwmuladd")]) ;; Combine zero_extend + sign_extend + fma to widen_fma (vwmaccsu) (define_insn_and_split "*dual_widen_fmaus" [(set (match_operand:VWEXTI 0 "register_operand") (plus:VWEXTI (mult:VWEXTI (zero_extend:VWEXTI (match_operand: 3 "register_operand")) (sign_extend:VWEXTI (match_operand: 2 "register_operand"))) (match_operand:VWEXTI 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (mode), riscv_vector::WIDEN_TERNARY_OP, ops); DONE; } [(set_attr "type" "viwmuladd")]) ;; This combine pattern does not correspond to an single instruction. ;; This is a temporary pattern produced by a combine pass and if there ;; is no further combine into widen pattern, then fall back to extend ;; pattern and non-widen fma pattern. (define_insn_and_split "*single_widen_fma" [(set (match_operand:VWEXTI 0 "register_operand") (plus:VWEXTI (mult:VWEXTI (any_extend:VWEXTI (match_operand: 2 "register_operand")) (match_operand:VWEXTI 3 "register_operand")) (match_operand:VWEXTI 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code extend_icode = code_for_pred_vf2 (, mode); rtx tmp = gen_reg_rtx (mode); rtx extend_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops); rtx ops[] = {operands[0], tmp, operands[3], operands[1], RVV_VUNDEF(mode)}; riscv_vector::emit_vlmax_insn (code_for_pred_mul_plus (mode), riscv_vector::TERNARY_OP, ops); DONE; } [(set_attr "type" "viwmuladd")]) ;; Combine extend + fma to widen_fma (vfwmacc) (define_insn_and_split "*dual_widen_fma" [(set (match_operand:VWEXTF 0 "register_operand") (plus:VWEXTF (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (float_extend:VWEXTF (match_operand: 3 "register_operand"))) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (PLUS, mode), riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; This combine pattern does not correspond to an single instruction. ;; This is a temporary pattern produced by a combine pass and if there ;; is no further combine into widen pattern, then fall back to extend ;; pattern and non-widen fma pattern. (define_insn_and_split "*single_widen_fma" [(set (match_operand:VWEXTF 0 "register_operand") (plus:VWEXTF (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (match_operand:VWEXTF 3 "register_operand")) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_extend (mode); rtx tmp = gen_reg_rtx (mode); rtx ext_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops); rtx ops[] = {operands[0], tmp, operands[3], operands[1], RVV_VUNDEF(mode)}; riscv_vector::emit_vlmax_insn (code_for_pred_mul (PLUS, mode), riscv_vector::TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; Combine extend + fnma to widen_fnma (vfwnmsac) (define_insn_and_split "*dual_widen_fnma" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (match_operand:VWEXTF 1 "register_operand") (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (float_extend:VWEXTF (match_operand: 3 "register_operand")))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (PLUS, mode), riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; This combine pattern does not correspond to an single instruction. ;; This is a temporary pattern produced by a combine pass and if there ;; is no further combine into widen pattern, then fall back to extend ;; pattern and non-widen fnma pattern. (define_insn_and_split "*single_widen_fnma" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (match_operand:VWEXTF 1 "register_operand") (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (match_operand:VWEXTF 3 "register_operand"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_extend (mode); rtx tmp = gen_reg_rtx (mode); rtx ext_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops); rtx ops[] = {operands[0], tmp, operands[3], operands[1], RVV_VUNDEF(mode)}; riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (PLUS, mode), riscv_vector::TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; Combine extend + fms to widen_fms (vfwmsac) (define_insn_and_split "*dual_widen_fms" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (float_extend:VWEXTF (match_operand: 3 "register_operand"))) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (MINUS, mode), riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; This combine pattern does not correspond to an single instruction. ;; This is a temporary pattern produced by a combine pass and if there ;; is no further combine into widen pattern, then fall back to extend ;; pattern and non-widen fms pattern. (define_insn_and_split "*single_widen_fms" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (mult:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand")) (match_operand:VWEXTF 3 "register_operand")) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_extend (mode); rtx tmp = gen_reg_rtx (mode); rtx ext_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops); rtx ops[] = {operands[0], tmp, operands[3], operands[1], RVV_VUNDEF(mode)}; riscv_vector::emit_vlmax_insn (code_for_pred_mul (MINUS, mode), riscv_vector::TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; Combine extend + fnms to widen_fnms (vfwnmacc) (define_insn_and_split "*dual_widen_fnms" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (mult:VWEXTF (neg:VWEXTF (float_extend:VWEXTF (match_operand: 2 "register_operand"))) (float_extend:VWEXTF (match_operand: 3 "register_operand"))) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[1], operands[2], operands[3]}; riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (MINUS, mode), riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; This combine pattern does not correspond to an single instruction. ;; This is a temporary pattern produced by a combine pass and if there ;; is no further combine into widen pattern, then fall back to extend ;; pattern and non-widen fnms pattern. (define_insn_and_split "*single_widen_fnms" [(set (match_operand:VWEXTF 0 "register_operand") (minus:VWEXTF (mult:VWEXTF (neg:VWEXTF (match_operand:VWEXTF 3 "register_operand")) (float_extend:VWEXTF (match_operand: 2 "register_operand"))) (match_operand:VWEXTF 1 "register_operand")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_extend (mode); rtx tmp = gen_reg_rtx (mode); rtx ext_ops[] = {tmp, operands[2]}; riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops); rtx ops[] = {operands[0], tmp, operands[3], operands[1], RVV_VUNDEF(mode)}; riscv_vector::emit_vlmax_insn (code_for_pred_mul_neg (MINUS, mode), riscv_vector::TERNARY_OP_FRM_DYN, ops); DONE; } [(set_attr "type" "vfwmuladd")]) ;; Combine mask_extend + vredsum to mask_vwredsum[u] ;; where the mrege of mask_extend is vector const 0 (define_insn_and_split "*cond_widen_reduc_plus_scal_" [(set (match_operand: 0 "register_operand") (unspec: [ (if_then_else: (match_operand: 1 "register_operand") (any_extend: (match_operand:VI_QHS_NO_M8 2 "register_operand")) (if_then_else: (unspec: [ (match_operand: 3 "vector_all_trues_mask_operand") (match_operand 6 "vector_length_operand") (match_operand 7 "const_int_operand") (match_operand 8 "const_int_operand") (match_operand 9 "const_1_or_2_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (match_operand: 5 "vector_const_0_operand") (match_operand: 4 "vector_merge_operand"))) ] UNSPEC_REDUC_SUM))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[2], operands[1], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_reduction (, riscv_vector::REDUCE_OP_M, ops, CONST0_RTX (mode)); DONE; } [(set_attr "type" "vector")]) ;; Combine mask_len_extend + vredsum to mask_vwredsum[u] ;; where the mrege of mask_len_extend is vector const 0 (define_insn_and_split "*cond_len_widen_reduc_plus_scal_" [(set (match_operand: 0 "register_operand") (unspec: [ (if_then_else: (unspec: [ (match_operand 2 "vector_length_operand") (const_int 0) (const_int 0) (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (vec_merge: (any_extend: (match_operand:VI_QHS_NO_M8 3 "register_operand")) (if_then_else: (unspec: [ (match_operand: 4 "vector_all_trues_mask_operand") (match_operand 5 "vector_length_operand") (match_operand 6 "const_int_operand") (match_operand 7 "const_int_operand") (match_operand 8 "const_1_or_2_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (match_operand: 9 "vector_const_0_operand") (match_operand: 10 "vector_merge_operand")) (match_operand: 1 "register_operand")) (if_then_else: (unspec: [ (match_dup 4) (match_dup 5) (match_dup 6) (match_dup 7) (match_dup 8) (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (match_dup 9) (match_dup 10))) ] UNSPEC_REDUC_SUM))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[3], operands[1], operands[2]}; riscv_vector::expand_reduction (, riscv_vector::REDUCE_OP_M, ops, CONST0_RTX (mode)); DONE; } [(set_attr "type" "vector")]) ;; Combine mask_extend + vfredsum to mask_vfwredusum ;; where the mrege of mask_extend is vector const 0 (define_insn_and_split "*cond_widen_reduc_plus_scal_" [(set (match_operand: 0 "register_operand") (unspec: [ (if_then_else: (match_operand: 1 "register_operand") (float_extend: (match_operand:VF_HS_NO_M8 2 "register_operand")) (if_then_else: (unspec: [ (match_operand: 3 "vector_all_trues_mask_operand") (match_operand 6 "vector_length_operand") (match_operand 7 "const_int_operand") (match_operand 8 "const_int_operand") (match_operand 9 "const_1_or_2_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (match_operand: 5 "vector_const_0_operand") (match_operand: 4 "vector_merge_operand"))) ] UNSPEC_REDUC_SUM_UNORDERED))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[2], operands[1], gen_int_mode (GET_MODE_NUNITS (mode), Pmode)}; riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED, riscv_vector::REDUCE_OP_M_FRM_DYN, ops, CONST0_RTX (mode)); DONE; } [(set_attr "type" "vector")]) ;; Combine mask_len_extend + vredsum to mask_vwredsum[u] ;; where the mrege of mask_len_extend is vector const 0 (define_insn_and_split "*cond_len_widen_reduc_plus_scal_" [(set (match_operand: 0 "register_operand") (unspec: [ (if_then_else: (unspec: [ (match_operand 2 "vector_length_operand") (const_int 0) (const_int 0) (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (vec_merge: (float_extend: (match_operand:VF_HS_NO_M8 3 "register_operand")) (if_then_else: (unspec: [ (match_operand: 4 "vector_all_trues_mask_operand") (match_operand 5 "vector_length_operand") (match_operand 6 "const_int_operand") (match_operand 7 "const_int_operand") (match_operand 8 "const_1_or_2_operand") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (match_operand: 9 "vector_const_0_operand") (match_operand: 10 "vector_merge_operand")) (match_operand: 1 "register_operand")) (if_then_else: (unspec: [ (match_dup 4) (match_dup 5) (match_dup 6) (match_dup 7) (match_dup 8) (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM) ] UNSPEC_VPREDICATE) (match_dup 9) (match_dup 10))) ] UNSPEC_REDUC_SUM_UNORDERED))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { rtx ops[] = {operands[0], operands[3], operands[1], operands[2]}; riscv_vector::expand_reduction (UNSPEC_WREDUC_SUM_UNORDERED, riscv_vector::REDUCE_OP_M_FRM_DYN, ops, CONST0_RTX (mode)); DONE; } [(set_attr "type" "vector")]) ;; ============================================================================= ;; Misc combine patterns ;; ============================================================================= ;; Combine neg + vfsgnj to vfsgnjn (define_insn_and_split "*copysign_neg" [(set (match_operand:VF 0 "register_operand") (neg:VF (unspec:VF [ (match_operand:VF 1 "register_operand") (match_operand:VF 2 "register_operand") ] UNSPEC_VCOPYSIGN)))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (mode), riscv_vector::BINARY_OP, operands); DONE; } [(set_attr "type" "vector")]) ;; Combine vmand/vmor + vmnot to vmandnot/vmornot (define_insn_and_split "*not" [(set (match_operand:VB_VLS 0 "register_operand" "=vr") (bitmanip_bitwise:VB_VLS (not:VB_VLS (match_operand:VB_VLS 2 "register_operand" " vr")) (match_operand:VB_VLS 1 "register_operand" " vr")))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_not (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands); DONE; } [(set_attr "type" "vmalu")]) ;; Combine vmnot + vmand/vmor/vmxor to vmnand/vmnor/vmxnor (define_insn_and_split "*n" [(set (match_operand:VB_VLS 0 "register_operand" "=vr") (not:VB_VLS (any_bitwise:VB_VLS (match_operand:VB_VLS 1 "register_operand" " vr") (match_operand:VB_VLS 2 "register_operand" " vr"))))] "TARGET_VECTOR && can_create_pseudo_p ()" "#" "&& 1" [(const_int 0)] { insn_code icode = code_for_pred_n (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands); DONE; } [(set_attr "type" "vmalu")])