;; 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 (