8377 lines
262 KiB
Diff
8377 lines
262 KiB
Diff
|
|
From 2f0874e6e6f5a866e71826983dc18295c408748b Mon Sep 17 00:00:00 2001
|
|||
|
|
From: Lulu Cheng <chenglulu@loongson.cn>
|
|||
|
|
Date: Thu, 16 Mar 2023 16:34:08 +0800
|
|||
|
|
Subject: [PATCH 065/124] LoongArch: Add Loongson ASX base instruction support.
|
|||
|
|
|
|||
|
|
gcc/ChangeLog:
|
|||
|
|
|
|||
|
|
* config/loongarch/loongarch-modes.def
|
|||
|
|
(VECTOR_MODES): Add Loongson ASX instruction support.
|
|||
|
|
* config/loongarch/loongarch-protos.h (loongarch_split_256bit_move): Ditto.
|
|||
|
|
(loongarch_split_256bit_move_p): Ditto.
|
|||
|
|
(loongarch_expand_vector_group_init): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm_1): Ditto.
|
|||
|
|
* config/loongarch/loongarch.cc (loongarch_symbol_insns): Ditto.
|
|||
|
|
(loongarch_valid_offset_p): Ditto.
|
|||
|
|
(loongarch_address_insns): Ditto.
|
|||
|
|
(loongarch_const_insns): Ditto.
|
|||
|
|
(loongarch_legitimize_move): Ditto.
|
|||
|
|
(loongarch_builtin_vectorization_cost): Ditto.
|
|||
|
|
(loongarch_split_move_p): Ditto.
|
|||
|
|
(loongarch_split_move): Ditto.
|
|||
|
|
(loongarch_output_move_index_float): Ditto.
|
|||
|
|
(loongarch_split_256bit_move_p): Ditto.
|
|||
|
|
(loongarch_split_256bit_move): Ditto.
|
|||
|
|
(loongarch_output_move): Ditto.
|
|||
|
|
(loongarch_print_operand_reloc): Ditto.
|
|||
|
|
(loongarch_print_operand): Ditto.
|
|||
|
|
(loongarch_hard_regno_mode_ok_uncached): Ditto.
|
|||
|
|
(loongarch_hard_regno_nregs): Ditto.
|
|||
|
|
(loongarch_class_max_nregs): Ditto.
|
|||
|
|
(loongarch_can_change_mode_class): Ditto.
|
|||
|
|
(loongarch_mode_ok_for_mov_fmt_p): Ditto.
|
|||
|
|
(loongarch_vector_mode_supported_p): Ditto.
|
|||
|
|
(loongarch_preferred_simd_mode): Ditto.
|
|||
|
|
(loongarch_autovectorize_vector_modes): Ditto.
|
|||
|
|
(loongarch_lsx_output_division): Ditto.
|
|||
|
|
(loongarch_expand_lsx_shuffle): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm_interleave): Ditto.
|
|||
|
|
(loongarch_try_expand_lsx_vshuf_const): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm_even_odd_1): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm_even_odd): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm_1): Ditto.
|
|||
|
|
(loongarch_expand_vec_perm_const_2): Ditto.
|
|||
|
|
(loongarch_is_quad_duplicate): Ditto.
|
|||
|
|
(loongarch_is_double_duplicate): Ditto.
|
|||
|
|
(loongarch_is_odd_extraction): Ditto.
|
|||
|
|
(loongarch_is_even_extraction): Ditto.
|
|||
|
|
(loongarch_is_extraction_permutation): Ditto.
|
|||
|
|
(loongarch_is_center_extraction): Ditto.
|
|||
|
|
(loongarch_is_reversing_permutation): Ditto.
|
|||
|
|
(loongarch_is_di_misalign_extract): Ditto.
|
|||
|
|
(loongarch_is_si_misalign_extract): Ditto.
|
|||
|
|
(loongarch_is_lasx_lowpart_interleave): Ditto.
|
|||
|
|
(loongarch_is_lasx_lowpart_interleave_2): Ditto.
|
|||
|
|
(COMPARE_SELECTOR): Ditto.
|
|||
|
|
(loongarch_is_lasx_lowpart_extract): Ditto.
|
|||
|
|
(loongarch_is_lasx_highpart_interleave): Ditto.
|
|||
|
|
(loongarch_is_lasx_highpart_interleave_2): Ditto.
|
|||
|
|
(loongarch_is_elem_duplicate): Ditto.
|
|||
|
|
(loongarch_is_op_reverse_perm): Ditto.
|
|||
|
|
(loongarch_is_single_op_perm): Ditto.
|
|||
|
|
(loongarch_is_divisible_perm): Ditto.
|
|||
|
|
(loongarch_is_triple_stride_extract): Ditto.
|
|||
|
|
(loongarch_vectorize_vec_perm_const): Ditto.
|
|||
|
|
(loongarch_cpu_sched_reassociation_width): Ditto.
|
|||
|
|
(loongarch_expand_vector_extract): Ditto.
|
|||
|
|
(emit_reduc_half): Ditto.
|
|||
|
|
(loongarch_expand_vec_unpack): Ditto.
|
|||
|
|
(loongarch_expand_vector_group_init): Ditto.
|
|||
|
|
(loongarch_expand_vector_init): Ditto.
|
|||
|
|
(loongarch_expand_lsx_cmp): Ditto.
|
|||
|
|
(loongarch_builtin_support_vector_misalignment): Ditto.
|
|||
|
|
* config/loongarch/loongarch.h (UNITS_PER_LASX_REG): Ditto.
|
|||
|
|
(BITS_PER_LASX_REG): Ditto.
|
|||
|
|
(STRUCTURE_SIZE_BOUNDARY): Ditto.
|
|||
|
|
(LASX_REG_FIRST): Ditto.
|
|||
|
|
(LASX_REG_LAST): Ditto.
|
|||
|
|
(LASX_REG_NUM): Ditto.
|
|||
|
|
(LASX_REG_P): Ditto.
|
|||
|
|
(LASX_REG_RTX_P): Ditto.
|
|||
|
|
(LASX_SUPPORTED_MODE_P): Ditto.
|
|||
|
|
* config/loongarch/loongarch.md: Ditto.
|
|||
|
|
* config/loongarch/lasx.md: New file.
|
|||
|
|
|
|||
|
|
Signed-off-by: Peng Fan <fanpeng@loongson.cn>
|
|||
|
|
Signed-off-by: ticat_fp <fanpeng@loongson.cn>
|
|||
|
|
---
|
|||
|
|
gcc/config/loongarch/lasx.md | 5104 ++++++++++++++++++++++
|
|||
|
|
gcc/config/loongarch/loongarch-modes.def | 1 +
|
|||
|
|
gcc/config/loongarch/loongarch-protos.h | 4 +
|
|||
|
|
gcc/config/loongarch/loongarch.cc | 2567 ++++++++++-
|
|||
|
|
gcc/config/loongarch/loongarch.h | 60 +-
|
|||
|
|
gcc/config/loongarch/loongarch.md | 20 +-
|
|||
|
|
6 files changed, 7637 insertions(+), 119 deletions(-)
|
|||
|
|
create mode 100644 gcc/config/loongarch/lasx.md
|
|||
|
|
|
|||
|
|
diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md
|
|||
|
|
new file mode 100644
|
|||
|
|
index 000000000..8111c8bb7
|
|||
|
|
--- /dev/null
|
|||
|
|
+++ b/gcc/config/loongarch/lasx.md
|
|||
|
|
@@ -0,0 +1,5104 @@
|
|||
|
|
+;; Machine Description for LARCH Loongson ASX ASE
|
|||
|
|
+;;
|
|||
|
|
+;; Copyright (C) 2018 Free Software Foundation, Inc.
|
|||
|
|
+;;
|
|||
|
|
+;; 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
|
|||
|
|
+;; <http://www.gnu.org/licenses/>.
|
|||
|
|
+;;
|
|||
|
|
+
|
|||
|
|
+(define_c_enum "unspec" [
|
|||
|
|
+ UNSPEC_LASX_XVABSD_S
|
|||
|
|
+ UNSPEC_LASX_XVABSD_U
|
|||
|
|
+ UNSPEC_LASX_XVAVG_S
|
|||
|
|
+ UNSPEC_LASX_XVAVG_U
|
|||
|
|
+ UNSPEC_LASX_XVAVGR_S
|
|||
|
|
+ UNSPEC_LASX_XVAVGR_U
|
|||
|
|
+ UNSPEC_LASX_XVBITCLR
|
|||
|
|
+ UNSPEC_LASX_XVBITCLRI
|
|||
|
|
+ UNSPEC_LASX_XVBITREV
|
|||
|
|
+ UNSPEC_LASX_XVBITREVI
|
|||
|
|
+ UNSPEC_LASX_XVBITSET
|
|||
|
|
+ UNSPEC_LASX_XVBITSETI
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_CAF
|
|||
|
|
+ UNSPEC_LASX_XVFCLASS
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_CUNE
|
|||
|
|
+ UNSPEC_LASX_XVFCVT
|
|||
|
|
+ UNSPEC_LASX_XVFCVTH
|
|||
|
|
+ UNSPEC_LASX_XVFCVTL
|
|||
|
|
+ UNSPEC_LASX_XVFLOGB
|
|||
|
|
+ UNSPEC_LASX_XVFRECIP
|
|||
|
|
+ UNSPEC_LASX_XVFRINT
|
|||
|
|
+ UNSPEC_LASX_XVFRSQRT
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SAF
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SEQ
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SLE
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SLT
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SNE
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SOR
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SUEQ
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SULE
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SULT
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SUN
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SUNE
|
|||
|
|
+ UNSPEC_LASX_XVFTINT_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINT_U
|
|||
|
|
+ UNSPEC_LASX_XVCLO
|
|||
|
|
+ UNSPEC_LASX_XVSAT_S
|
|||
|
|
+ UNSPEC_LASX_XVSAT_U
|
|||
|
|
+ UNSPEC_LASX_XVREPLVE0
|
|||
|
|
+ UNSPEC_LASX_XVREPL128VEI
|
|||
|
|
+ UNSPEC_LASX_XVSRAR
|
|||
|
|
+ UNSPEC_LASX_XVSRARI
|
|||
|
|
+ UNSPEC_LASX_XVSRLR
|
|||
|
|
+ UNSPEC_LASX_XVSRLRI
|
|||
|
|
+ UNSPEC_LASX_XVSHUF
|
|||
|
|
+ UNSPEC_LASX_XVSHUF_B
|
|||
|
|
+ UNSPEC_LASX_BRANCH
|
|||
|
|
+ UNSPEC_LASX_BRANCH_V
|
|||
|
|
+
|
|||
|
|
+ UNSPEC_LASX_XVMUH_S
|
|||
|
|
+ UNSPEC_LASX_XVMUH_U
|
|||
|
|
+ UNSPEC_LASX_MXVEXTW_U
|
|||
|
|
+ UNSPEC_LASX_XVSLLWIL_S
|
|||
|
|
+ UNSPEC_LASX_XVSLLWIL_U
|
|||
|
|
+ UNSPEC_LASX_XVSRAN
|
|||
|
|
+ UNSPEC_LASX_XVSSRAN_S
|
|||
|
|
+ UNSPEC_LASX_XVSSRAN_U
|
|||
|
|
+ UNSPEC_LASX_XVSRARN
|
|||
|
|
+ UNSPEC_LASX_XVSSRARN_S
|
|||
|
|
+ UNSPEC_LASX_XVSSRARN_U
|
|||
|
|
+ UNSPEC_LASX_XVSRLN
|
|||
|
|
+ UNSPEC_LASX_XVSSRLN_U
|
|||
|
|
+ UNSPEC_LASX_XVSRLRN
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRN_U
|
|||
|
|
+ UNSPEC_LASX_XVFRSTPI
|
|||
|
|
+ UNSPEC_LASX_XVFRSTP
|
|||
|
|
+ UNSPEC_LASX_XVSHUF4I
|
|||
|
|
+ UNSPEC_LASX_XVBSRL_V
|
|||
|
|
+ UNSPEC_LASX_XVBSLL_V
|
|||
|
|
+ UNSPEC_LASX_XVEXTRINS
|
|||
|
|
+ UNSPEC_LASX_XVMSKLTZ
|
|||
|
|
+ UNSPEC_LASX_XVSIGNCOV
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNE_W_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNE_L_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRP_W_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRP_L_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRM_W_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRM_L_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINT_W_D
|
|||
|
|
+ UNSPEC_LASX_XVFFINT_S_L
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRZ_W_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRP_W_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRM_W_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNE_W_D
|
|||
|
|
+ UNSPEC_LASX_XVFTINTH_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTL_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFFINTH_D_W
|
|||
|
|
+ UNSPEC_LASX_XVFFINTL_D_W
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRZH_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRZL_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRPH_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRPL_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRMH_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRML_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNEL_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNEH_L_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRNE_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRNE_D
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRZ_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRZ_D
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRP_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRP_D
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRM_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRM_D
|
|||
|
|
+ UNSPEC_LASX_XVREPLVE0_Q
|
|||
|
|
+ UNSPEC_LASX_XVPERM_W
|
|||
|
|
+ UNSPEC_LASX_XVPERMI_Q
|
|||
|
|
+ UNSPEC_LASX_XVPERMI_D
|
|||
|
|
+
|
|||
|
|
+ UNSPEC_LASX_XVADDWEV
|
|||
|
|
+ UNSPEC_LASX_XVADDWEV2
|
|||
|
|
+ UNSPEC_LASX_XVADDWEV3
|
|||
|
|
+ UNSPEC_LASX_XVSUBWEV
|
|||
|
|
+ UNSPEC_LASX_XVSUBWEV2
|
|||
|
|
+ UNSPEC_LASX_XVMULWEV
|
|||
|
|
+ UNSPEC_LASX_XVMULWEV2
|
|||
|
|
+ UNSPEC_LASX_XVMULWEV3
|
|||
|
|
+ UNSPEC_LASX_XVADDWOD
|
|||
|
|
+ UNSPEC_LASX_XVADDWOD2
|
|||
|
|
+ UNSPEC_LASX_XVADDWOD3
|
|||
|
|
+ UNSPEC_LASX_XVSUBWOD
|
|||
|
|
+ UNSPEC_LASX_XVSUBWOD2
|
|||
|
|
+ UNSPEC_LASX_XVMULWOD
|
|||
|
|
+ UNSPEC_LASX_XVMULWOD2
|
|||
|
|
+ UNSPEC_LASX_XVMULWOD3
|
|||
|
|
+ UNSPEC_LASX_XVMADDWEV
|
|||
|
|
+ UNSPEC_LASX_XVMADDWEV2
|
|||
|
|
+ UNSPEC_LASX_XVMADDWEV3
|
|||
|
|
+ UNSPEC_LASX_XVMADDWOD
|
|||
|
|
+ UNSPEC_LASX_XVMADDWOD2
|
|||
|
|
+ UNSPEC_LASX_XVMADDWOD3
|
|||
|
|
+ UNSPEC_LASX_XVHADDW_Q_D
|
|||
|
|
+ UNSPEC_LASX_XVHSUBW_Q_D
|
|||
|
|
+ UNSPEC_LASX_XVHADDW_QU_DU
|
|||
|
|
+ UNSPEC_LASX_XVHSUBW_QU_DU
|
|||
|
|
+ UNSPEC_LASX_XVROTR
|
|||
|
|
+ UNSPEC_LASX_XVADD_Q
|
|||
|
|
+ UNSPEC_LASX_XVSUB_Q
|
|||
|
|
+ UNSPEC_LASX_XVREPLVE
|
|||
|
|
+ UNSPEC_LASX_XVSHUF4
|
|||
|
|
+ UNSPEC_LASX_XVMSKGEZ
|
|||
|
|
+ UNSPEC_LASX_XVMSKNZ
|
|||
|
|
+ UNSPEC_LASX_XVEXTH_Q_D
|
|||
|
|
+ UNSPEC_LASX_XVEXTH_QU_DU
|
|||
|
|
+ UNSPEC_LASX_XVEXTL_Q_D
|
|||
|
|
+ UNSPEC_LASX_XVSRLNI
|
|||
|
|
+ UNSPEC_LASX_XVSRLRNI
|
|||
|
|
+ UNSPEC_LASX_XVSSRLNI
|
|||
|
|
+ UNSPEC_LASX_XVSSRLNI2
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRNI
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRNI2
|
|||
|
|
+ UNSPEC_LASX_XVSRANI
|
|||
|
|
+ UNSPEC_LASX_XVSRARNI
|
|||
|
|
+ UNSPEC_LASX_XVSSRANI
|
|||
|
|
+ UNSPEC_LASX_XVSSRANI2
|
|||
|
|
+ UNSPEC_LASX_XVSSRARNI
|
|||
|
|
+ UNSPEC_LASX_XVSSRARNI2
|
|||
|
|
+ UNSPEC_LASX_XVPERMI
|
|||
|
|
+ UNSPEC_LASX_XVINSVE0
|
|||
|
|
+ UNSPEC_LASX_XVPICKVE
|
|||
|
|
+ UNSPEC_LASX_XVSSRLN
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRN
|
|||
|
|
+ UNSPEC_LASX_XVEXTL_QU_DU
|
|||
|
|
+ UNSPEC_LASX_XVLDI
|
|||
|
|
+ UNSPEC_LASX_XVLDX
|
|||
|
|
+ UNSPEC_LASX_XVSTX
|
|||
|
|
+])
|
|||
|
|
+
|
|||
|
|
+;; All vector modes with 256 bits.
|
|||
|
|
+(define_mode_iterator LASX [V4DF V8SF V4DI V8SI V16HI V32QI])
|
|||
|
|
+
|
|||
|
|
+;; Same as LASX. Used by vcond to iterate two modes.
|
|||
|
|
+(define_mode_iterator LASX_2 [V4DF V8SF V4DI V8SI V16HI V32QI])
|
|||
|
|
+
|
|||
|
|
+;; Only used for splitting insert_d and copy_{u,s}.d.
|
|||
|
|
+(define_mode_iterator LASX_D [V4DI V4DF])
|
|||
|
|
+
|
|||
|
|
+;; Only used for splitting insert_d and copy_{u,s}.d.
|
|||
|
|
+(define_mode_iterator LASX_WD [V4DI V4DF V8SI V8SF])
|
|||
|
|
+
|
|||
|
|
+;; Only used for copy256_{u,s}.w.
|
|||
|
|
+(define_mode_iterator LASX_W [V8SI V8SF])
|
|||
|
|
+
|
|||
|
|
+;; Only integer modes in LASX.
|
|||
|
|
+(define_mode_iterator ILASX [V4DI V8SI V16HI V32QI])
|
|||
|
|
+
|
|||
|
|
+;; As ILASX but excludes V32QI.
|
|||
|
|
+(define_mode_iterator ILASX_DWH [V4DI V8SI V16HI])
|
|||
|
|
+
|
|||
|
|
+;; As LASX but excludes V32QI.
|
|||
|
|
+(define_mode_iterator LASX_DWH [V4DF V8SF V4DI V8SI V16HI])
|
|||
|
|
+
|
|||
|
|
+;; As ILASX but excludes V4DI.
|
|||
|
|
+(define_mode_iterator ILASX_WHB [V8SI V16HI V32QI])
|
|||
|
|
+
|
|||
|
|
+;; Only integer modes equal or larger than a word.
|
|||
|
|
+(define_mode_iterator ILASX_DW [V4DI V8SI])
|
|||
|
|
+
|
|||
|
|
+;; Only integer modes smaller than a word.
|
|||
|
|
+(define_mode_iterator ILASX_HB [V16HI V32QI])
|
|||
|
|
+
|
|||
|
|
+;; Only floating-point modes in LASX.
|
|||
|
|
+(define_mode_iterator FLASX [V4DF V8SF])
|
|||
|
|
+
|
|||
|
|
+;; Only used for immediate set shuffle elements instruction.
|
|||
|
|
+(define_mode_iterator LASX_WHB_W [V8SI V16HI V32QI V8SF])
|
|||
|
|
+
|
|||
|
|
+;; The attribute gives the integer vector mode with same size in Loongson ASX.
|
|||
|
|
+(define_mode_attr VIMODE256
|
|||
|
|
+ [(V4DF "V4DI")
|
|||
|
|
+ (V8SF "V8SI")
|
|||
|
|
+ (V4DI "V4DI")
|
|||
|
|
+ (V8SI "V8SI")
|
|||
|
|
+ (V16HI "V16HI")
|
|||
|
|
+ (V32QI "V32QI")])
|
|||
|
|
+
|
|||
|
|
+;;attribute gives half modes for vector modes.
|
|||
|
|
+;;attribute gives half modes (Same Size) for vector modes.
|
|||
|
|
+(define_mode_attr VHSMODE256
|
|||
|
|
+ [(V16HI "V32QI")
|
|||
|
|
+ (V8SI "V16HI")
|
|||
|
|
+ (V4DI "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;attribute gives half modes for vector modes.
|
|||
|
|
+(define_mode_attr VHMODE256
|
|||
|
|
+ [(V32QI "V16QI")
|
|||
|
|
+ (V16HI "V8HI")
|
|||
|
|
+ (V8SI "V4SI")
|
|||
|
|
+ (V4DI "V2DI")])
|
|||
|
|
+
|
|||
|
|
+;;attribute gives half float modes for vector modes.
|
|||
|
|
+(define_mode_attr VFHMODE256
|
|||
|
|
+ [(V8SF "V4SF")
|
|||
|
|
+ (V4DF "V2DF")])
|
|||
|
|
+
|
|||
|
|
+;; The attribute gives double modes for vector modes in LASX.
|
|||
|
|
+(define_mode_attr VDMODE256
|
|||
|
|
+ [(V8SI "V4DI")
|
|||
|
|
+ (V16HI "V8SI")
|
|||
|
|
+ (V32QI "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;; extended from VDMODE256
|
|||
|
|
+(define_mode_attr VDMODEEXD256
|
|||
|
|
+ [(V4DI "V4DI")
|
|||
|
|
+ (V8SI "V4DI")
|
|||
|
|
+ (V16HI "V8SI")
|
|||
|
|
+ (V32QI "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;; The attribute gives half modes with same number of elements for vector modes.
|
|||
|
|
+(define_mode_attr VTRUNCMODE256
|
|||
|
|
+ [(V16HI "V16QI")
|
|||
|
|
+ (V8SI "V8HI")
|
|||
|
|
+ (V4DI "V4SI")])
|
|||
|
|
+
|
|||
|
|
+;; Double-sized Vector MODE with same elemet type. "Vector, Enlarged-MODE"
|
|||
|
|
+(define_mode_attr VEMODE256
|
|||
|
|
+ [(V8SF "V16SF")
|
|||
|
|
+ (V8SI "V16SI")
|
|||
|
|
+ (V4DF "V8DF")
|
|||
|
|
+ (V4DI "V8DI")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives the mode of the result for "copy_s_b, copy_u_b" etc.
|
|||
|
|
+(define_mode_attr VRES256
|
|||
|
|
+ [(V4DF "DF")
|
|||
|
|
+ (V8SF "SF")
|
|||
|
|
+ (V4DI "DI")
|
|||
|
|
+ (V8SI "SI")
|
|||
|
|
+ (V16HI "SI")
|
|||
|
|
+ (V32QI "SI")])
|
|||
|
|
+
|
|||
|
|
+;; Only used with LASX_D iterator.
|
|||
|
|
+(define_mode_attr lasx_d
|
|||
|
|
+ [(V4DI "reg_or_0")
|
|||
|
|
+ (V4DF "register")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives the 256 bit integer vector mode with same size.
|
|||
|
|
+(define_mode_attr mode256_i
|
|||
|
|
+ [(V4DF "v4di")
|
|||
|
|
+ (V8SF "v8si")
|
|||
|
|
+ (V4DI "v4di")
|
|||
|
|
+ (V8SI "v8si")
|
|||
|
|
+ (V16HI "v16hi")
|
|||
|
|
+ (V32QI "v32qi")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives the 256 bit float vector mode with same size.
|
|||
|
|
+(define_mode_attr mode256_f
|
|||
|
|
+ [(V4DF "v4df")
|
|||
|
|
+ (V8SF "v8sf")
|
|||
|
|
+ (V4DI "v4df")
|
|||
|
|
+ (V8SI "v8sf")])
|
|||
|
|
+
|
|||
|
|
+ ;; This attribute gives suffix for LASX instructions. HOW?
|
|||
|
|
+(define_mode_attr lasxfmt
|
|||
|
|
+ [(V4DF "d")
|
|||
|
|
+ (V8SF "w")
|
|||
|
|
+ (V4DI "d")
|
|||
|
|
+ (V8SI "w")
|
|||
|
|
+ (V16HI "h")
|
|||
|
|
+ (V32QI "b")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr flasxfmt
|
|||
|
|
+ [(V4DF "d")
|
|||
|
|
+ (V8SF "s")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr lasxfmt_u
|
|||
|
|
+ [(V4DF "du")
|
|||
|
|
+ (V8SF "wu")
|
|||
|
|
+ (V4DI "du")
|
|||
|
|
+ (V8SI "wu")
|
|||
|
|
+ (V16HI "hu")
|
|||
|
|
+ (V32QI "bu")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr ilasxfmt
|
|||
|
|
+ [(V4DF "l")
|
|||
|
|
+ (V8SF "w")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr ilasxfmt_u
|
|||
|
|
+ [(V4DF "lu")
|
|||
|
|
+ (V8SF "wu")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives suffix for integers in VHMODE256.
|
|||
|
|
+(define_mode_attr hlasxfmt
|
|||
|
|
+ [(V4DI "w")
|
|||
|
|
+ (V8SI "h")
|
|||
|
|
+ (V16HI "b")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr hlasxfmt_u
|
|||
|
|
+ [(V4DI "wu")
|
|||
|
|
+ (V8SI "hu")
|
|||
|
|
+ (V16HI "bu")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives suffix for integers in VHSMODE256.
|
|||
|
|
+(define_mode_attr hslasxfmt
|
|||
|
|
+ [(V4DI "w")
|
|||
|
|
+ (V8SI "h")
|
|||
|
|
+ (V16HI "b")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives define_insn suffix for LASX instructions that need
|
|||
|
|
+;; distinction between integer and floating point.
|
|||
|
|
+(define_mode_attr lasxfmt_f
|
|||
|
|
+ [(V4DF "d_f")
|
|||
|
|
+ (V8SF "w_f")
|
|||
|
|
+ (V4DI "d")
|
|||
|
|
+ (V8SI "w")
|
|||
|
|
+ (V16HI "h")
|
|||
|
|
+ (V32QI "b")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr flasxfmt_f
|
|||
|
|
+ [(V4DF "d_f")
|
|||
|
|
+ (V8SF "s_f")
|
|||
|
|
+ (V4DI "d")
|
|||
|
|
+ (V8SI "w")
|
|||
|
|
+ (V16HI "h")
|
|||
|
|
+ (V32QI "b")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives define_insn suffix for LASX instructions that need
|
|||
|
|
+;; distinction between integer and floating point.
|
|||
|
|
+(define_mode_attr lasxfmt_f_wd
|
|||
|
|
+ [(V4DF "d_f")
|
|||
|
|
+ (V8SF "w_f")
|
|||
|
|
+ (V4DI "d")
|
|||
|
|
+ (V8SI "w")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute gives suffix for integers in VHMODE256.
|
|||
|
|
+(define_mode_attr dlasxfmt
|
|||
|
|
+ [(V8SI "d")
|
|||
|
|
+ (V16HI "w")
|
|||
|
|
+ (V32QI "h")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr dlasxfmt_u
|
|||
|
|
+ [(V8SI "du")
|
|||
|
|
+ (V16HI "wu")
|
|||
|
|
+ (V32QI "hu")])
|
|||
|
|
+
|
|||
|
|
+;; for VDMODEEXD256
|
|||
|
|
+(define_mode_attr dlasxqfmt
|
|||
|
|
+ [(V4DI "q")
|
|||
|
|
+ (V8SI "d")
|
|||
|
|
+ (V16HI "w")
|
|||
|
|
+ (V32QI "h")])
|
|||
|
|
+
|
|||
|
|
+;; This is used to form an immediate operand constraint using
|
|||
|
|
+;; "const_<indeximm256>_operand".
|
|||
|
|
+(define_mode_attr indeximm256
|
|||
|
|
+ [(V4DF "0_to_3")
|
|||
|
|
+ (V8SF "0_to_7")
|
|||
|
|
+ (V4DI "0_to_3")
|
|||
|
|
+ (V8SI "0_to_7")
|
|||
|
|
+ (V16HI "uimm4")
|
|||
|
|
+ (V32QI "uimm5")])
|
|||
|
|
+
|
|||
|
|
+;; This is used to form an immediate operand constraint using to ref high half
|
|||
|
|
+;; "const_<indeximm_hi>_operand".
|
|||
|
|
+(define_mode_attr indeximm_hi
|
|||
|
|
+ [(V4DF "2_or_3")
|
|||
|
|
+ (V8SF "4_to_7")
|
|||
|
|
+ (V4DI "2_or_3")
|
|||
|
|
+ (V8SI "4_to_7")
|
|||
|
|
+ (V16HI "8_to_15")
|
|||
|
|
+ (V32QI "16_to_31")])
|
|||
|
|
+
|
|||
|
|
+;; This is used to form an immediate operand constraint using to ref low half
|
|||
|
|
+;; "const_<indeximm_lo>_operand".
|
|||
|
|
+(define_mode_attr indeximm_lo
|
|||
|
|
+ [(V4DF "0_or_1")
|
|||
|
|
+ (V8SF "0_to_3")
|
|||
|
|
+ (V4DI "0_or_1")
|
|||
|
|
+ (V8SI "0_to_3")
|
|||
|
|
+ (V16HI "uimm3")
|
|||
|
|
+ (V32QI "uimm4")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute represents bitmask needed for vec_merge using in lasx
|
|||
|
|
+;; "const_<bitmask256>_operand".
|
|||
|
|
+(define_mode_attr bitmask256
|
|||
|
|
+ [(V4DF "exp_4")
|
|||
|
|
+ (V8SF "exp_8")
|
|||
|
|
+ (V4DI "exp_4")
|
|||
|
|
+ (V8SI "exp_8")
|
|||
|
|
+ (V16HI "exp_16")
|
|||
|
|
+ (V32QI "exp_32")])
|
|||
|
|
+
|
|||
|
|
+;; This attribute represents bitmask needed for vec_merge using to ref low half
|
|||
|
|
+;; "const_<bitmask_lo>_operand".
|
|||
|
|
+(define_mode_attr bitmask_lo
|
|||
|
|
+ [(V4DF "exp_2")
|
|||
|
|
+ (V8SF "exp_4")
|
|||
|
|
+ (V4DI "exp_2")
|
|||
|
|
+ (V8SI "exp_4")
|
|||
|
|
+ (V16HI "exp_8")
|
|||
|
|
+ (V32QI "exp_16")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+;; This attribute is used to form an immediate operand constraint using
|
|||
|
|
+;; "const_<bitimm256>_operand".
|
|||
|
|
+(define_mode_attr bitimm256
|
|||
|
|
+ [(V32QI "uimm3")
|
|||
|
|
+ (V16HI "uimm4")
|
|||
|
|
+ (V8SI "uimm5")
|
|||
|
|
+ (V4DI "uimm6")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr d2lasxfmt
|
|||
|
|
+ [(V8SI "q")
|
|||
|
|
+ (V16HI "d")
|
|||
|
|
+ (V32QI "w")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr d2lasxfmt_u
|
|||
|
|
+ [(V8SI "qu")
|
|||
|
|
+ (V16HI "du")
|
|||
|
|
+ (V32QI "wu")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr VD2MODE256
|
|||
|
|
+ [(V8SI "V4DI")
|
|||
|
|
+ (V16HI "V4DI")
|
|||
|
|
+ (V32QI "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr lasxfmt_wd
|
|||
|
|
+ [(V4DI "d")
|
|||
|
|
+ (V8SI "w")
|
|||
|
|
+ (V16HI "w")
|
|||
|
|
+ (V32QI "w")])
|
|||
|
|
+
|
|||
|
|
+(define_int_iterator FRINT256_S [UNSPEC_LASX_XVFRINTRP_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRZ_S
|
|||
|
|
+ UNSPEC_LASX_XVFRINT
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRM_S])
|
|||
|
|
+
|
|||
|
|
+(define_int_iterator FRINT256_D [UNSPEC_LASX_XVFRINTRP_D
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRZ_D
|
|||
|
|
+ UNSPEC_LASX_XVFRINT
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRM_D])
|
|||
|
|
+
|
|||
|
|
+(define_int_attr frint256_pattern_s
|
|||
|
|
+ [(UNSPEC_LASX_XVFRINTRP_S "ceil")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRZ_S "btrunc")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINT "rint")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRM_S "floor")])
|
|||
|
|
+
|
|||
|
|
+(define_int_attr frint256_pattern_d
|
|||
|
|
+ [(UNSPEC_LASX_XVFRINTRP_D "ceil")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRZ_D "btrunc")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINT "rint")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRM_D "floor")])
|
|||
|
|
+
|
|||
|
|
+(define_int_attr frint256_suffix
|
|||
|
|
+ [(UNSPEC_LASX_XVFRINTRP_S "rp")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRP_D "rp")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRZ_S "rz")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRZ_D "rz")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINT "")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRM_S "rm")
|
|||
|
|
+ (UNSPEC_LASX_XVFRINTRM_D "rm")])
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_init<mode><unitmode>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vector_init (operands[0], operands[1]);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_initv32qiv16qi"
|
|||
|
|
+ [(match_operand:V32QI 0 "register_operand")
|
|||
|
|
+ (match_operand:V16QI 1 "")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vector_group_init (operands[0], operands[1]);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; FIXME: Delete.
|
|||
|
|
+(define_insn "vec_pack_trunc_<mode>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:<VHSMODE256>
|
|||
|
|
+ (truncate:<VTRUNCMODE256>
|
|||
|
|
+ (match_operand:ILASX_DWH 1 "register_operand" "f"))
|
|||
|
|
+ (truncate:<VTRUNCMODE256>
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickev.<hslasxfmt>\t%u0,%u2,%u1\n\txvpermi.d\t%u0,%u0,0xd8"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "8")])
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_unpacks_hi_v8sf"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (float_extend:V4DF
|
|||
|
|
+ (vec_select:V4SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_dup 2))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ operands[2] = loongarch_lsx_vec_parallel_const_half (V8SFmode,
|
|||
|
|
+ true/*high_p*/);
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_unpacks_lo_v8sf"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (float_extend:V4DF
|
|||
|
|
+ (vec_select:V4SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_dup 2))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ operands[2] = loongarch_lsx_vec_parallel_const_half (V8SFmode,
|
|||
|
|
+ false/*high_p*/);
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_unpacks_hi_<mode>"
|
|||
|
|
+ [(match_operand:<VDMODE256> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX_WHB 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_unpack (operands, false/*unsigned_p*/,
|
|||
|
|
+ true/*high_p*/);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_unpacks_lo_<mode>"
|
|||
|
|
+ [(match_operand:<VDMODE256> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX_WHB 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_unpack (operands, false/*unsigned_p*/, false/*high_p*/);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_unpacku_hi_<mode>"
|
|||
|
|
+ [(match_operand:<VDMODE256> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX_WHB 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_unpack (operands, true/*unsigned_p*/, true/*high_p*/);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_unpacku_lo_<mode>"
|
|||
|
|
+ [(match_operand:<VDMODE256> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX_WHB 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_unpack (operands, true/*unsigned_p*/, false/*high_p*/);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvinsgr2vr_<lasxfmt_f_wd>"
|
|||
|
|
+ [(set (match_operand:ILASX_DW 0 "register_operand" "=f")
|
|||
|
|
+ (vec_merge:ILASX_DW
|
|||
|
|
+ (vec_duplicate:ILASX_DW
|
|||
|
|
+ (match_operand:<UNITMODE> 1 "reg_or_0_operand" "rJ"))
|
|||
|
|
+ (match_operand:ILASX_DW 2 "register_operand" "0")
|
|||
|
|
+ (match_operand 3 "const_<bitmask256>_operand" "")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+#if 0
|
|||
|
|
+ if (!TARGET_64BIT && (<MODE>mode == V4DImode || <MODE>mode == V4DFmode))
|
|||
|
|
+ return "#";
|
|||
|
|
+ else
|
|||
|
|
+#endif
|
|||
|
|
+ return "xvinsgr2vr.<lasxfmt>\t%u0,%z1,%y3";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_insert")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_concatv4di"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V4DI
|
|||
|
|
+ (match_operand:V2DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V2DI 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvpermi.q\t%u0,%u2,0x20";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_concatv8si"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V8SI
|
|||
|
|
+ (match_operand:V4SI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4SI 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvpermi.q\t%u0,%u2,0x20";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_concatv16hi"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V16HI
|
|||
|
|
+ (match_operand:V8HI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V8HI 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvpermi.q\t%u0,%u2,0x20";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_concatv32qi"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V32QI
|
|||
|
|
+ (match_operand:V16QI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V16QI 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvpermi.q\t%u0,%u2,0x20";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_concatv4df"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V4DF
|
|||
|
|
+ (match_operand:V2DF 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V2DF 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvpermi.q\t%u0,%u2,0x20";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_concatv8sf"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V8SF
|
|||
|
|
+ (match_operand:V4SF 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4SF 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvpermi.q\t%u0,%u2,0x20";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;; xshuf.w
|
|||
|
|
+(define_insn "lasx_xvperm_<lasxfmt_f_wd>"
|
|||
|
|
+ [(set (match_operand:LASX_W 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX_W
|
|||
|
|
+ [(match_operand:LASX_W 1 "nonimmediate_operand" "f")
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVPERM_W))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvperm.w\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;; xvpermi.d
|
|||
|
|
+(define_insn "lasx_xvpermi_d_<LASX:mode>"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX
|
|||
|
|
+ [(match_operand:LASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:SI 2 "const_uimm8_operand")]
|
|||
|
|
+ UNSPEC_LASX_XVPERMI_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpermi.d\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpermi_d_<mode>_1"
|
|||
|
|
+ [(set (match_operand:LASX_D 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:LASX_D
|
|||
|
|
+ (match_operand:LASX_D 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 3 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 4 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 5 "const_0_to_3_operand")])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ int mask = 0;
|
|||
|
|
+ mask |= INTVAL (operands[2]) << 0;
|
|||
|
|
+ mask |= INTVAL (operands[3]) << 2;
|
|||
|
|
+ mask |= INTVAL (operands[4]) << 4;
|
|||
|
|
+ mask |= INTVAL (operands[5]) << 6;
|
|||
|
|
+ operands[2] = GEN_INT (mask);
|
|||
|
|
+ return "xvpermi.d\t%u0,%u1,%2";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;; xvpermi.q
|
|||
|
|
+(define_insn "lasx_xvpermi_q_<LASX:mode>"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX
|
|||
|
|
+ [(match_operand:LASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:LASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand")]
|
|||
|
|
+ UNSPEC_LASX_XVPERMI_Q))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpermi.q\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickve2gr_d<u>"
|
|||
|
|
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
|||
|
|
+ (any_extend:DI
|
|||
|
|
+ (vec_select:DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickve2gr.d<u>\t%0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_copy")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_set<mode>"
|
|||
|
|
+ [(match_operand:ILASX_DW 0 "register_operand")
|
|||
|
|
+ (match_operand:<UNITMODE> 1 "reg_or_0_operand")
|
|||
|
|
+ (match_operand 2 "const_<indeximm256>_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx index = GEN_INT (1 << INTVAL (operands[2]));
|
|||
|
|
+ emit_insn (gen_lasx_xvinsgr2vr_<lasxfmt_f_wd> (operands[0], operands[1],
|
|||
|
|
+ operands[0], index));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_set<mode>"
|
|||
|
|
+ [(match_operand:FLASX 0 "register_operand")
|
|||
|
|
+ (match_operand:<UNITMODE> 1 "reg_or_0_operand")
|
|||
|
|
+ (match_operand 2 "const_<indeximm256>_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx index = GEN_INT (1 << INTVAL (operands[2]));
|
|||
|
|
+ emit_insn (gen_lasx_xvinsve0_<lasxfmt_f>_scalar (operands[0], operands[1],
|
|||
|
|
+ operands[0], index));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_extract<mode><unitmode>"
|
|||
|
|
+ [(match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "register_operand")
|
|||
|
|
+ (match_operand 2 "const_<indeximm256>_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vector_extract (operands[0], operands[1],
|
|||
|
|
+ INTVAL (operands[2]));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_perm<mode>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "register_operand")
|
|||
|
|
+ (match_operand:LASX 2 "register_operand")
|
|||
|
|
+ (match_operand:<VIMODE256> 3 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_perm_1 (operands);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; FIXME: 256??
|
|||
|
|
+(define_expand "vcondu<LASX:mode><ILASX:mode>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "reg_or_m1_operand")
|
|||
|
|
+ (match_operand:LASX 2 "reg_or_0_operand")
|
|||
|
|
+ (match_operator 3 ""
|
|||
|
|
+ [(match_operand:ILASX 4 "register_operand")
|
|||
|
|
+ (match_operand:ILASX 5 "register_operand")])]
|
|||
|
|
+ "ISA_HAS_LASX
|
|||
|
|
+ && (GET_MODE_NUNITS (<LASX:MODE>mode)
|
|||
|
|
+ == GET_MODE_NUNITS (<ILASX:MODE>mode))"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_cond_expr (<LASX:MODE>mode, <LASX:VIMODE256>mode,
|
|||
|
|
+ operands);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; FIXME: 256??
|
|||
|
|
+(define_expand "vcond<LASX:mode><LASX_2:mode>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "reg_or_m1_operand")
|
|||
|
|
+ (match_operand:LASX 2 "reg_or_0_operand")
|
|||
|
|
+ (match_operator 3 ""
|
|||
|
|
+ [(match_operand:LASX_2 4 "register_operand")
|
|||
|
|
+ (match_operand:LASX_2 5 "register_operand")])]
|
|||
|
|
+ "ISA_HAS_LASX
|
|||
|
|
+ && (GET_MODE_NUNITS (<LASX:MODE>mode)
|
|||
|
|
+ == GET_MODE_NUNITS (<LASX_2:MODE>mode))"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_cond_expr (<LASX:MODE>mode, <LASX:VIMODE256>mode,
|
|||
|
|
+ operands);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; Same as vcond_
|
|||
|
|
+(define_expand "vcond_mask_<ILASX:mode><ILASX:mode>"
|
|||
|
|
+ [(match_operand:ILASX 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX 1 "reg_or_m1_operand")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_0_operand")
|
|||
|
|
+ (match_operand:ILASX 3 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ loongarch_expand_vec_cond_mask_expr (<ILASX:MODE>mode,
|
|||
|
|
+ <ILASX:VIMODE256>mode, operands);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "lasx_xvrepli<mode>"
|
|||
|
|
+ [(match_operand:ILASX 0 "register_operand")
|
|||
|
|
+ (match_operand 1 "const_imm10_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ if (<MODE>mode == V32QImode)
|
|||
|
|
+ operands[1] = GEN_INT (trunc_int_for_mode (INTVAL (operands[1]),
|
|||
|
|
+ <UNITMODE>mode));
|
|||
|
|
+ emit_move_insn (operands[0],
|
|||
|
|
+ loongarch_gen_const_int_vector (<MODE>mode, INTVAL (operands[1])));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "mov<mode>"
|
|||
|
|
+ [(set (match_operand:LASX 0)
|
|||
|
|
+ (match_operand:LASX 1))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ if (loongarch_legitimize_move (<MODE>mode, operands[0], operands[1]))
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_expand "movmisalign<mode>"
|
|||
|
|
+ [(set (match_operand:LASX 0)
|
|||
|
|
+ (match_operand:LASX 1))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ if (loongarch_legitimize_move (<MODE>mode, operands[0], operands[1]))
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; 256-bit LASX modes can only exist in LASX registers or memory.
|
|||
|
|
+(define_insn "mov<mode>_lasx"
|
|||
|
|
+ [(set (match_operand:LASX 0 "nonimmediate_operand" "=f,f,R,*r,*f")
|
|||
|
|
+ (match_operand:LASX 1 "move_operand" "fYGYI,R,f,*f,*r"))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ { return loongarch_output_move (operands[0], operands[1]); }
|
|||
|
|
+ [(set_attr "type" "simd_move,simd_load,simd_store,simd_copy,simd_insert")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "8,4,4,4,4")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_split
|
|||
|
|
+ [(set (match_operand:LASX 0 "nonimmediate_operand")
|
|||
|
|
+ (match_operand:LASX 1 "move_operand"))]
|
|||
|
|
+ "reload_completed && ISA_HAS_LASX
|
|||
|
|
+ && loongarch_split_move_insn_p (operands[0], operands[1])"
|
|||
|
|
+ [(const_int 0)]
|
|||
|
|
+{
|
|||
|
|
+ loongarch_split_move_insn (operands[0], operands[1], curr_insn);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; Offset load
|
|||
|
|
+(define_expand "lasx_mxld_<lasxfmt_f>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand 1 "pmode_register_operand")
|
|||
|
|
+ (match_operand 2 "aq10<lasxfmt>_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
|||
|
|
+ INTVAL (operands[2]));
|
|||
|
|
+ loongarch_emit_move (operands[0], gen_rtx_MEM (<MODE>mode, addr));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; Offset store
|
|||
|
|
+(define_expand "lasx_mxst_<lasxfmt_f>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand 1 "pmode_register_operand")
|
|||
|
|
+ (match_operand 2 "aq10<lasxfmt>_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
|||
|
|
+ INTVAL (operands[2]));
|
|||
|
|
+ loongarch_emit_move (gen_rtx_MEM (<MODE>mode, addr), operands[0]);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+;; LASX
|
|||
|
|
+(define_insn "add<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f,f")
|
|||
|
|
+ (plus:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_ximm5_operand" "f,Unv5,Uuv5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ switch (which_alternative)
|
|||
|
|
+ {
|
|||
|
|
+ case 0:
|
|||
|
|
+ return "xvadd.<lasxfmt>\t%u0,%u1,%u2";
|
|||
|
|
+ case 1:
|
|||
|
|
+ {
|
|||
|
|
+ HOST_WIDE_INT val = INTVAL (CONST_VECTOR_ELT (operands[2], 0));
|
|||
|
|
+
|
|||
|
|
+ operands[2] = GEN_INT (-val);
|
|||
|
|
+ return "xvsubi.<lasxfmt_u>\t%u0,%u1,%d2";
|
|||
|
|
+ }
|
|||
|
|
+ case 2:
|
|||
|
|
+ return "xvaddi.<lasxfmt_u>\t%u0,%u1,%E2";
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "alu_type" "simd_add")
|
|||
|
|
+ (set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "sub<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (minus:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvsub.<lasxfmt>\t%u0,%u1,%u2
|
|||
|
|
+ xvsubi.<lasxfmt_u>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "alu_type" "simd_add")
|
|||
|
|
+ (set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "mul<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (mult:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmul.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_mul")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmadd_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (plus:ILASX (mult:ILASX (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 3 "register_operand" "f"))
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "0")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmadd.<lasxfmt>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_mul")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmsub_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (minus:ILASX (match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (mult:ILASX (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 3 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmsub.<lasxfmt>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_mul")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "div<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (div:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return loongarch_lsx_output_division ("xvdiv.<lasxfmt>\t%u0,%u1,%u2",
|
|||
|
|
+ operands);
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_div")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "udiv<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (udiv:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return loongarch_lsx_output_division ("xvdiv.<lasxfmt_u>\t%u0,%u1,%u2",
|
|||
|
|
+ operands);
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_div")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "mod<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (mod:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return loongarch_lsx_output_division ("xvmod.<lasxfmt>\t%u0,%u1,%u2",
|
|||
|
|
+ operands);
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_div")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "umod<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (umod:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return loongarch_lsx_output_division ("xvmod.<lasxfmt_u>\t%u0,%u1,%u2",
|
|||
|
|
+ operands);
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_div")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "xor<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f,f")
|
|||
|
|
+ (xor:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvxor.v\t%u0,%u1,%u2
|
|||
|
|
+ xvbitrevi.%v0\t%u0,%u1,%V2
|
|||
|
|
+ xvxori.b\t%u0,%u1,%B2"
|
|||
|
|
+ [(set_attr "type" "simd_logic,simd_bit,simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "ior<mode>3"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f,f,f")
|
|||
|
|
+ (ior:LASX
|
|||
|
|
+ (match_operand:LASX 1 "register_operand" "f,f,f")
|
|||
|
|
+ (match_operand:LASX 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvor.v\t%u0,%u1,%u2
|
|||
|
|
+ xvbitseti.%v0\t%u0,%u1,%V2
|
|||
|
|
+ xvori.b\t%u0,%u1,%B2"
|
|||
|
|
+ [(set_attr "type" "simd_logic,simd_bit,simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "and<mode>3"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f,f,f")
|
|||
|
|
+ (and:LASX
|
|||
|
|
+ (match_operand:LASX 1 "register_operand" "f,f,f")
|
|||
|
|
+ (match_operand:LASX 2 "reg_or_vector_same_val_operand" "f,YZ,Urv8")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ switch (which_alternative)
|
|||
|
|
+ {
|
|||
|
|
+ case 0:
|
|||
|
|
+ return "xvand.v\t%u0,%u1,%u2";
|
|||
|
|
+ case 1:
|
|||
|
|
+ {
|
|||
|
|
+ rtx elt0 = CONST_VECTOR_ELT (operands[2], 0);
|
|||
|
|
+ unsigned HOST_WIDE_INT val = ~UINTVAL (elt0);
|
|||
|
|
+ operands[2] = loongarch_gen_const_int_vector (<MODE>mode, val & (-val));
|
|||
|
|
+ return "xvbitclri.%v0\t%u0,%u1,%V2";
|
|||
|
|
+ }
|
|||
|
|
+ case 2:
|
|||
|
|
+ return "xvandi.b\t%u0,%u1,%B2";
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_logic,simd_bit,simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "one_cmpl<mode>2"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (not:ILASX (match_operand:ILASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvnor.v\t%u0,%u1,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+;; LASX
|
|||
|
|
+(define_insn "vlshr<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (lshiftrt:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvsrl.<lasxfmt>\t%u0,%u1,%u2
|
|||
|
|
+ xvsrli.<lasxfmt>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;; LASX ">>"
|
|||
|
|
+(define_insn "vashr<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (ashiftrt:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvsra.<lasxfmt>\t%u0,%u1,%u2
|
|||
|
|
+ xvsrai.<lasxfmt>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;; LASX "<<"
|
|||
|
|
+(define_insn "vashl<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (ashift:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvsll.<lasxfmt>\t%u0,%u1,%u2
|
|||
|
|
+ xvslli.<lasxfmt>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "add<mode>3"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (plus:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfadd.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "sub<mode>3"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (minus:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfsub.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "mul<mode>3"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (mult:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmul.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fmul")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "div<mode>3"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (div:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfdiv.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fdiv")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "fma<mode>4"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (fma:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 3 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmadd.<flasxfmt>\t%u0,%u1,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "fnma<mode>4"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (fma:FLASX (neg:FLASX (match_operand:FLASX 1 "register_operand" "f"))
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 3 "register_operand" "0")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfnmsub.<flasxfmt>\t%u0,%u1,%u2,%u0"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "sqrt<mode>2"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (sqrt:FLASX (match_operand:FLASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfsqrt.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fdiv")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvadda_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (plus:ILASX (abs:ILASX (match_operand:ILASX 1 "register_operand" "f"))
|
|||
|
|
+ (abs:ILASX (match_operand:ILASX 2 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvadda.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "ssadd<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (ss_plus:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsadd.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "usadd<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (us_plus:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsadd.<lasxfmt_u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvabsd_s_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVABSD_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvabsd.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvabsd_u_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVABSD_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvabsd.<lasxfmt_u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvavg_s_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVAVG_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvavg.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvavg_u_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVAVG_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvavg.<lasxfmt_u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvavgr_s_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVAVGR_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvavgr.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvavgr_u_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVAVGR_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvavgr.<lasxfmt_u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitclr_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVBITCLR))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitclr.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitclri_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVBITCLRI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitclri.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitrev_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVBITREV))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitrev.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitrevi_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVBITREVI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitrevi.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitsel_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (ior:LASX (and:LASX (not:LASX
|
|||
|
|
+ (match_operand:LASX 3 "register_operand" "f"))
|
|||
|
|
+ (match_operand:LASX 1 "register_operand" "f"))
|
|||
|
|
+ (and:LASX (match_dup 3)
|
|||
|
|
+ (match_operand:LASX 2 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitsel.v\t%u0,%u1,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_bitmov")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitseli_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (ior:V32QI (and:V32QI (not:V32QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "0"))
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (and:V32QI (match_dup 1)
|
|||
|
|
+ (match_operand:V32QI 3 "const_vector_same_val_operand" "Urv8"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitseli.b\t%u0,%u2,%B3"
|
|||
|
|
+ [(set_attr "type" "simd_bitmov")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitset_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVBITSET))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitset.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbitseti_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVBITSETI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitseti.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvs<ICC:icc>_<ILASX:lasxfmt><cmpi_1>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (ICC:ILASX
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_<ICC:cmpi>imm5_operand" "f,U<ICC:cmpi>v5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvs<ICC:icc>.<ILASX:lasxfmt><cmpi_1>\t%u0,%u1,%u2
|
|||
|
|
+ xvs<ICC:icci>.<ILASX:lasxfmt><cmpi_1>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_cmp<mode><mode256_i>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand")
|
|||
|
|
+ (match_operator 1 ""
|
|||
|
|
+ [(match_operand:LASX 2 "register_operand")
|
|||
|
|
+ (match_operand:LASX 3 "register_operand")]))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ bool ok = loongarch_expand_vec_cmp (operands);
|
|||
|
|
+ gcc_assert (ok);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "vec_cmpu<ILASX:mode><mode256_i>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand")
|
|||
|
|
+ (match_operator 1 ""
|
|||
|
|
+ [(match_operand:ILASX 2 "register_operand")
|
|||
|
|
+ (match_operand:ILASX 3 "register_operand")]))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ bool ok = loongarch_expand_vec_cmp (operands);
|
|||
|
|
+ gcc_assert (ok);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfclass_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VIMODE256> [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCLASS))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfclass.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fclass")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfcmp_caf_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VIMODE256> [(match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_CAF))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcmp.caf.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fcmp")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfcmp_cune_<FLASX:flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VIMODE256> [(match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_CUNE))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcmp.cune.<FLASX:flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fcmp")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_int_iterator FSC256_UNS [UNSPEC_LASX_XVFCMP_SAF UNSPEC_LASX_XVFCMP_SUN
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SOR UNSPEC_LASX_XVFCMP_SEQ
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SNE UNSPEC_LASX_XVFCMP_SUEQ
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SUNE UNSPEC_LASX_XVFCMP_SULE
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SULT UNSPEC_LASX_XVFCMP_SLE
|
|||
|
|
+ UNSPEC_LASX_XVFCMP_SLT])
|
|||
|
|
+
|
|||
|
|
+(define_int_attr fsc256
|
|||
|
|
+ [(UNSPEC_LASX_XVFCMP_SAF "saf")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SUN "sun")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SOR "sor")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SEQ "seq")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SNE "sne")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SUEQ "sueq")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SUNE "sune")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SULE "sule")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SULT "sult")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SLE "sle")
|
|||
|
|
+ (UNSPEC_LASX_XVFCMP_SLT "slt")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfcmp_<vfcond:fcc>_<FLASX:flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (vfcond:<VIMODE256> (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcmp.<vfcond:fcc>.<FLASX:flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fcmp")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfcmp_<fsc256>_<FLASX:flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VIMODE256> [(match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")]
|
|||
|
|
+ FSC256_UNS))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcmp.<fsc256>.<FLASX:flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fcmp")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr fint256
|
|||
|
|
+ [(V8SF "v8si")
|
|||
|
|
+ (V4DF "v4di")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr FINTCNV256
|
|||
|
|
+ [(V8SF "I2S")
|
|||
|
|
+ (V4DF "I2D")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr FINTCNV256_2
|
|||
|
|
+ [(V8SF "S2I")
|
|||
|
|
+ (V4DF "D2I")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "float<fint256><FLASX:mode>2"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (float:FLASX (match_operand:<VIMODE256> 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvffint.<flasxfmt>.<ilasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "cnv_mode" "<FINTCNV256>")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "floatuns<fint256><FLASX:mode>2"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (unsigned_float:FLASX
|
|||
|
|
+ (match_operand:<VIMODE256> 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvffint.<flasxfmt>.<ilasxfmt_u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "cnv_mode" "<FINTCNV256>")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr FFQ256
|
|||
|
|
+ [(V4SF "V16HI")
|
|||
|
|
+ (V2DF "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvreplgr2vr_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (vec_duplicate:ILASX
|
|||
|
|
+ (match_operand:<UNITMODE> 1 "reg_or_0_operand" "r,J")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ if (which_alternative == 1)
|
|||
|
|
+ return "xvldi.b\t%u0,0" ;
|
|||
|
|
+
|
|||
|
|
+ if (!TARGET_64BIT && (<MODE>mode == V2DImode || <MODE>mode == V2DFmode))
|
|||
|
|
+ return "#";
|
|||
|
|
+ else
|
|||
|
|
+ return "xvreplgr2vr.<lasxfmt>\t%u0,%z1";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_fill")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "8")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "logb<mode>2"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:FLASX [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFLOGB))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvflogb.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_flog2")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "smax<mode>3"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (smax:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmax.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fminmax")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfmaxa_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (if_then_else:FLASX
|
|||
|
|
+ (gt (abs:FLASX (match_operand:FLASX 1 "register_operand" "f"))
|
|||
|
|
+ (abs:FLASX (match_operand:FLASX 2 "register_operand" "f")))
|
|||
|
|
+ (match_dup 1)
|
|||
|
|
+ (match_dup 2)))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmaxa.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fminmax")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "smin<mode>3"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (smin:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmin.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fminmax")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfmina_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (if_then_else:FLASX
|
|||
|
|
+ (lt (abs:FLASX (match_operand:FLASX 1 "register_operand" "f"))
|
|||
|
|
+ (abs:FLASX (match_operand:FLASX 2 "register_operand" "f")))
|
|||
|
|
+ (match_dup 1)
|
|||
|
|
+ (match_dup 2)))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmina.<flasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fminmax")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrecip_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:FLASX [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRECIP))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrecip.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fdiv")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrint_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:FLASX [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINT))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrint.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrsqrt_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:FLASX [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRSQRT))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrsqrt.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fdiv")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftint_s_<ilasxfmt>_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VIMODE256> [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINT_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftint.<ilasxfmt>.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "cnv_mode" "<FINTCNV256_2>")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftint_u_<ilasxfmt_u>_<flasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VIMODE256> [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINT_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftint.<ilasxfmt_u>.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "cnv_mode" "<FINTCNV256_2>")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "fix_trunc<FLASX:mode><mode256_i>2"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (fix:<VIMODE256> (match_operand:FLASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrz.<ilasxfmt>.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "cnv_mode" "<FINTCNV256_2>")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "fixuns_trunc<FLASX:mode><mode256_i>2"
|
|||
|
|
+ [(set (match_operand:<VIMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unsigned_fix:<VIMODE256> (match_operand:FLASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrz.<ilasxfmt_u>.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "cnv_mode" "<FINTCNV256_2>")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvh<optab>w_h<u>_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (addsub:V16HI
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvh<optab>w.h<u>.b<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvh<optab>w_w<u>_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (addsub:V8SI
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvh<optab>w.w<u>.h<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvh<optab>w_d<u>_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (addsub:V4DI
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvh<optab>w.d<u>.w<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackev_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (vec_concat:V64QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 32)
|
|||
|
|
+ (const_int 2) (const_int 34)
|
|||
|
|
+ (const_int 4) (const_int 36)
|
|||
|
|
+ (const_int 6) (const_int 38)
|
|||
|
|
+ (const_int 8) (const_int 40)
|
|||
|
|
+ (const_int 10) (const_int 42)
|
|||
|
|
+ (const_int 12) (const_int 44)
|
|||
|
|
+ (const_int 14) (const_int 46)
|
|||
|
|
+ (const_int 16) (const_int 48)
|
|||
|
|
+ (const_int 18) (const_int 50)
|
|||
|
|
+ (const_int 20) (const_int 52)
|
|||
|
|
+ (const_int 22) (const_int 54)
|
|||
|
|
+ (const_int 24) (const_int 56)
|
|||
|
|
+ (const_int 26) (const_int 58)
|
|||
|
|
+ (const_int 28) (const_int 60)
|
|||
|
|
+ (const_int 30) (const_int 62)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackev.b\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackev_h"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (vec_concat:V32HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 16)
|
|||
|
|
+ (const_int 2) (const_int 18)
|
|||
|
|
+ (const_int 4) (const_int 20)
|
|||
|
|
+ (const_int 6) (const_int 22)
|
|||
|
|
+ (const_int 8) (const_int 24)
|
|||
|
|
+ (const_int 10) (const_int 26)
|
|||
|
|
+ (const_int 12) (const_int 28)
|
|||
|
|
+ (const_int 14) (const_int 30)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackev.h\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackev_w"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SI
|
|||
|
|
+ (vec_concat:V16SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 8)
|
|||
|
|
+ (const_int 2) (const_int 10)
|
|||
|
|
+ (const_int 4) (const_int 12)
|
|||
|
|
+ (const_int 6) (const_int 14)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackev.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackev_w_f"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SF
|
|||
|
|
+ (vec_concat:V16SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SF 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 8)
|
|||
|
|
+ (const_int 2) (const_int 10)
|
|||
|
|
+ (const_int 4) (const_int 12)
|
|||
|
|
+ (const_int 6) (const_int 14)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackev.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvh_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (vec_concat:V64QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 8) (const_int 40)
|
|||
|
|
+ (const_int 9) (const_int 41)
|
|||
|
|
+ (const_int 10) (const_int 42)
|
|||
|
|
+ (const_int 11) (const_int 43)
|
|||
|
|
+ (const_int 12) (const_int 44)
|
|||
|
|
+ (const_int 13) (const_int 45)
|
|||
|
|
+ (const_int 14) (const_int 46)
|
|||
|
|
+ (const_int 15) (const_int 47)
|
|||
|
|
+ (const_int 24) (const_int 56)
|
|||
|
|
+ (const_int 25) (const_int 57)
|
|||
|
|
+ (const_int 26) (const_int 58)
|
|||
|
|
+ (const_int 27) (const_int 59)
|
|||
|
|
+ (const_int 28) (const_int 60)
|
|||
|
|
+ (const_int 29) (const_int 61)
|
|||
|
|
+ (const_int 30) (const_int 62)
|
|||
|
|
+ (const_int 31) (const_int 63)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvh.b\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvh_h"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (vec_concat:V32HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 4) (const_int 20)
|
|||
|
|
+ (const_int 5) (const_int 21)
|
|||
|
|
+ (const_int 6) (const_int 22)
|
|||
|
|
+ (const_int 7) (const_int 23)
|
|||
|
|
+ (const_int 12) (const_int 28)
|
|||
|
|
+ (const_int 13) (const_int 29)
|
|||
|
|
+ (const_int 14) (const_int 30)
|
|||
|
|
+ (const_int 15) (const_int 31)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvh.h\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr xvilvh_suffix
|
|||
|
|
+ [(V8SI "") (V8SF "_f")
|
|||
|
|
+ (V4DI "") (V4DF "_f")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvh_w<xvilvh_suffix>"
|
|||
|
|
+ [(set (match_operand:LASX_W 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:LASX_W
|
|||
|
|
+ (vec_concat:<VEMODE256>
|
|||
|
|
+ (match_operand:LASX_W 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:LASX_W 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 2) (const_int 10)
|
|||
|
|
+ (const_int 3) (const_int 11)
|
|||
|
|
+ (const_int 6) (const_int 14)
|
|||
|
|
+ (const_int 7) (const_int 15)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvh.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvh_d<xvilvh_suffix>"
|
|||
|
|
+ [(set (match_operand:LASX_D 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:LASX_D
|
|||
|
|
+ (vec_concat:<VEMODE256>
|
|||
|
|
+ (match_operand:LASX_D 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:LASX_D 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 5)
|
|||
|
|
+ (const_int 3) (const_int 7)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvh.d\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackod_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (vec_concat:V64QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 33)
|
|||
|
|
+ (const_int 3) (const_int 35)
|
|||
|
|
+ (const_int 5) (const_int 37)
|
|||
|
|
+ (const_int 7) (const_int 39)
|
|||
|
|
+ (const_int 9) (const_int 41)
|
|||
|
|
+ (const_int 11) (const_int 43)
|
|||
|
|
+ (const_int 13) (const_int 45)
|
|||
|
|
+ (const_int 15) (const_int 47)
|
|||
|
|
+ (const_int 17) (const_int 49)
|
|||
|
|
+ (const_int 19) (const_int 51)
|
|||
|
|
+ (const_int 21) (const_int 53)
|
|||
|
|
+ (const_int 23) (const_int 55)
|
|||
|
|
+ (const_int 25) (const_int 57)
|
|||
|
|
+ (const_int 27) (const_int 59)
|
|||
|
|
+ (const_int 29) (const_int 61)
|
|||
|
|
+ (const_int 31) (const_int 63)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackod.b\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackod_h"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (vec_concat:V32HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 17)
|
|||
|
|
+ (const_int 3) (const_int 19)
|
|||
|
|
+ (const_int 5) (const_int 21)
|
|||
|
|
+ (const_int 7) (const_int 23)
|
|||
|
|
+ (const_int 9) (const_int 25)
|
|||
|
|
+ (const_int 11) (const_int 27)
|
|||
|
|
+ (const_int 13) (const_int 29)
|
|||
|
|
+ (const_int 15) (const_int 31)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackod.h\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackod_w"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SI
|
|||
|
|
+ (vec_concat:V16SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 9)
|
|||
|
|
+ (const_int 3) (const_int 11)
|
|||
|
|
+ (const_int 5) (const_int 13)
|
|||
|
|
+ (const_int 7) (const_int 15)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackod.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpackod_w_f"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SF
|
|||
|
|
+ (vec_concat:V16SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SF 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 9)
|
|||
|
|
+ (const_int 3) (const_int 11)
|
|||
|
|
+ (const_int 5) (const_int 13)
|
|||
|
|
+ (const_int 7) (const_int 15)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpackod.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvl_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (vec_concat:V64QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 32)
|
|||
|
|
+ (const_int 1) (const_int 33)
|
|||
|
|
+ (const_int 2) (const_int 34)
|
|||
|
|
+ (const_int 3) (const_int 35)
|
|||
|
|
+ (const_int 4) (const_int 36)
|
|||
|
|
+ (const_int 5) (const_int 37)
|
|||
|
|
+ (const_int 6) (const_int 38)
|
|||
|
|
+ (const_int 7) (const_int 39)
|
|||
|
|
+ (const_int 16) (const_int 48)
|
|||
|
|
+ (const_int 17) (const_int 49)
|
|||
|
|
+ (const_int 18) (const_int 50)
|
|||
|
|
+ (const_int 19) (const_int 51)
|
|||
|
|
+ (const_int 20) (const_int 52)
|
|||
|
|
+ (const_int 21) (const_int 53)
|
|||
|
|
+ (const_int 22) (const_int 54)
|
|||
|
|
+ (const_int 23) (const_int 55)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvl.b\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvl_h"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (vec_concat:V32HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 16)
|
|||
|
|
+ (const_int 1) (const_int 17)
|
|||
|
|
+ (const_int 2) (const_int 18)
|
|||
|
|
+ (const_int 3) (const_int 19)
|
|||
|
|
+ (const_int 8) (const_int 24)
|
|||
|
|
+ (const_int 9) (const_int 25)
|
|||
|
|
+ (const_int 10) (const_int 26)
|
|||
|
|
+ (const_int 11) (const_int 27)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvl.h\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvl_w"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SI
|
|||
|
|
+ (vec_concat:V16SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 8)
|
|||
|
|
+ (const_int 1) (const_int 9)
|
|||
|
|
+ (const_int 4) (const_int 12)
|
|||
|
|
+ (const_int 5) (const_int 13)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvl.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvl_w_f"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SF
|
|||
|
|
+ (vec_concat:V16SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SF 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 8)
|
|||
|
|
+ (const_int 1) (const_int 9)
|
|||
|
|
+ (const_int 4) (const_int 12)
|
|||
|
|
+ (const_int 5) (const_int 13)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvl.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvl_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V4DI
|
|||
|
|
+ (vec_concat:V8DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 4)
|
|||
|
|
+ (const_int 2) (const_int 6)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvl.d\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvilvl_d_f"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V4DF
|
|||
|
|
+ (vec_concat:V8DF
|
|||
|
|
+ (match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 4)
|
|||
|
|
+ (const_int 2) (const_int 6)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvilvl.d\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "smax<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (smax:ILASX (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_simm5_operand" "f,Usv5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvmax.<lasxfmt>\t%u0,%u1,%u2
|
|||
|
|
+ xvmaxi.<lasxfmt>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "umax<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (umax:ILASX (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvmax.<lasxfmt_u>\t%u0,%u1,%u2
|
|||
|
|
+ xvmaxi.<lasxfmt_u>\t%u0,%u1,%B2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "smin<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (smin:ILASX (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_simm5_operand" "f,Usv5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvmin.<lasxfmt>\t%u0,%u1,%u2
|
|||
|
|
+ xvmini.<lasxfmt>\t%u0,%u1,%E2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "umin<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (umin:ILASX (match_operand:ILASX 1 "register_operand" "f,f")
|
|||
|
|
+ (match_operand:ILASX 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvmin.<lasxfmt_u>\t%u0,%u1,%u2
|
|||
|
|
+ xvmini.<lasxfmt_u>\t%u0,%u1,%B2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvclo_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (clz:ILASX (not:ILASX (match_operand:ILASX 1 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvclo.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "clz<mode>2"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (clz:ILASX (match_operand:ILASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvclz.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvnor_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f,f")
|
|||
|
|
+ (and:ILASX (not:ILASX (match_operand:ILASX 1 "register_operand" "f,f"))
|
|||
|
|
+ (not:ILASX (match_operand:ILASX 2 "reg_or_vector_same_val_operand" "f,Urv8"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "@
|
|||
|
|
+ xvnor.v\t%u0,%u1,%u2
|
|||
|
|
+ xvnori.b\t%u0,%u1,%B2"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickev_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (vec_concat:V64QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 32) (const_int 34)
|
|||
|
|
+ (const_int 36) (const_int 38)
|
|||
|
|
+ (const_int 40) (const_int 42)
|
|||
|
|
+ (const_int 44) (const_int 46)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)
|
|||
|
|
+ (const_int 48) (const_int 50)
|
|||
|
|
+ (const_int 52) (const_int 54)
|
|||
|
|
+ (const_int 56) (const_int 58)
|
|||
|
|
+ (const_int 60) (const_int 62)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickev.b\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickev_h"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (vec_concat:V32HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickev.h\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickev_w"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SI
|
|||
|
|
+ (vec_concat:V16SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 12) (const_int 14)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickev.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickev_w_f"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SF
|
|||
|
|
+ (vec_concat:V16SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SF 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 12) (const_int 14)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickev.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickod_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (vec_concat:V64QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 33) (const_int 35)
|
|||
|
|
+ (const_int 37) (const_int 39)
|
|||
|
|
+ (const_int 41) (const_int 43)
|
|||
|
|
+ (const_int 45) (const_int 47)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)
|
|||
|
|
+ (const_int 49) (const_int 51)
|
|||
|
|
+ (const_int 53) (const_int 55)
|
|||
|
|
+ (const_int 57) (const_int 59)
|
|||
|
|
+ (const_int 61) (const_int 63)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickod.b\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickod_h"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (vec_concat:V32HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickod.h\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickod_w"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SI
|
|||
|
|
+ (vec_concat:V16SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 13) (const_int 15)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickod.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickod_w_f"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:V8SF
|
|||
|
|
+ (vec_concat:V16SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SF 2 "register_operand" "f"))
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 13) (const_int 15)])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickod.w\t%u0,%u2,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_permute")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "popcount<mode>2"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (popcount:ILASX (match_operand:ILASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpcnt.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_pcnt")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsat_s_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSAT_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsat.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_sat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsat_u_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSAT_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsat.<lasxfmt_u>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_sat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvshuf4i_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX_WHB_W 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX_WHB_W [(match_operand:LASX_WHB_W 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_uimm8_operand")]
|
|||
|
|
+ UNSPEC_LASX_XVSHUF4I))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvshuf4i.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shf")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvshuf4i_<lasxfmt_f>_1"
|
|||
|
|
+ [(set (match_operand:LASX_W 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:LASX_W
|
|||
|
|
+ (match_operand:LASX_W 1 "nonimmediate_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 3 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 4 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 5 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 6 "const_4_to_7_operand")
|
|||
|
|
+ (match_operand 7 "const_4_to_7_operand")
|
|||
|
|
+ (match_operand 8 "const_4_to_7_operand")
|
|||
|
|
+ (match_operand 9 "const_4_to_7_operand")])))]
|
|||
|
|
+ "ISA_HAS_LASX
|
|||
|
|
+ && INTVAL (operands[2]) + 4 == INTVAL (operands[6])
|
|||
|
|
+ && INTVAL (operands[3]) + 4 == INTVAL (operands[7])
|
|||
|
|
+ && INTVAL (operands[4]) + 4 == INTVAL (operands[8])
|
|||
|
|
+ && INTVAL (operands[5]) + 4 == INTVAL (operands[9])"
|
|||
|
|
+{
|
|||
|
|
+ int mask = 0;
|
|||
|
|
+ mask |= INTVAL (operands[2]) << 0;
|
|||
|
|
+ mask |= INTVAL (operands[3]) << 2;
|
|||
|
|
+ mask |= INTVAL (operands[4]) << 4;
|
|||
|
|
+ mask |= INTVAL (operands[5]) << 6;
|
|||
|
|
+ operands[2] = GEN_INT (mask);
|
|||
|
|
+
|
|||
|
|
+ return "xvshuf4i.w\t%u0,%u1,%2";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_shf")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrar_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSRAR))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrar.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrari_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSRARI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrari.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrlr_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSRLR))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrlr.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrlri_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSRLRI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrlri.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssub_s_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (ss_minus:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssub.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssub_u_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (us_minus:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssub.<lasxfmt_u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvshuf_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX_DWH 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX_DWH [(match_operand:LASX_DWH 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:LASX_DWH 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:LASX_DWH 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSHUF))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvshuf.<lasxfmt>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_sld")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvshuf_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V32QI [(match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V32QI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSHUF_B))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvshuf.b\t%u0,%u1,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_sld")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvreplve0_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:LASX
|
|||
|
|
+ (vec_select:<UNITMODE>
|
|||
|
|
+ (match_operand:LASX 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvreplve0.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvrepl128vei_b_internal"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:V32QI
|
|||
|
|
+ (vec_select:V32QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_uimm4_operand" "")
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_operand 3 "const_16_to_31_operand" "")
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX && ((INTVAL (operands[3]) - INTVAL (operands[2])) == 16)"
|
|||
|
|
+ "xvrepl128vei.b\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvrepl128vei_h_internal"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:V16HI
|
|||
|
|
+ (vec_select:V16HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_uimm3_operand" "")
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_dup 2)
|
|||
|
|
+ (match_operand 3 "const_8_to_15_operand" "")
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)
|
|||
|
|
+ (match_dup 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX && ((INTVAL (operands[3]) - INTVAL (operands[2])) == 8)"
|
|||
|
|
+ "xvrepl128vei.h\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvrepl128vei_w_internal"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:V8SI
|
|||
|
|
+ (vec_select:V8SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")
|
|||
|
|
+ (match_dup 2) (match_dup 2) (match_dup 2)
|
|||
|
|
+ (match_operand 3 "const_4_to_7_operand" "")
|
|||
|
|
+ (match_dup 3) (match_dup 3) (match_dup 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX && ((INTVAL (operands[3]) - INTVAL (operands[2])) == 4)"
|
|||
|
|
+ "xvrepl128vei.w\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvrepl128vei_d_internal"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:V4DI
|
|||
|
|
+ (vec_select:V4DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_0_or_1_operand" "")
|
|||
|
|
+ (match_dup 2)
|
|||
|
|
+ (match_operand 3 "const_2_or_3_operand" "")
|
|||
|
|
+ (match_dup 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX && ((INTVAL (operands[3]) - INTVAL (operands[2])) == 2)"
|
|||
|
|
+ "xvrepl128vei.d\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvrepl128vei_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX [(match_operand:LASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<indeximm_lo>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVREPL128VEI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvrepl128vei.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvreplve0_<lasxfmt_f>_scalar"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:FLASX
|
|||
|
|
+ (match_operand:<UNITMODE> 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvreplve0.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvreplve0_q"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V32QI [(match_operand:V32QI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVREPLVE0_Q))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvreplve0.q\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfcvt_h_s"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V16HI [(match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V8SF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCVT))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvt.h.s\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfcvt_s_d"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCVT))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvt.s.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_pack_trunc_v4df"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (vec_concat:V8SF
|
|||
|
|
+ (float_truncate:V4SF (match_operand:V4DF 1 "register_operand" "f"))
|
|||
|
|
+ (float_truncate:V4SF (match_operand:V4DF 2 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvt.s.d\t%u0,%u2,%u1\n\txvpermi.d\t%u0,%u0,0xd8"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V8SF")
|
|||
|
|
+ (set_attr "length" "8")])
|
|||
|
|
+
|
|||
|
|
+;; Define for builtin function.
|
|||
|
|
+(define_insn "lasx_xvfcvth_s_h"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V16HI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCVTH))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvth.s.h\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+;; Define for builtin function.
|
|||
|
|
+(define_insn "lasx_xvfcvth_d_s"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (float_extend:V4DF
|
|||
|
|
+ (vec_select:V4SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 2) (const_int 3)
|
|||
|
|
+ (const_int 6) (const_int 7)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvth.d.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DF")
|
|||
|
|
+ (set_attr "length" "12")])
|
|||
|
|
+
|
|||
|
|
+;; Define for gen insn.
|
|||
|
|
+(define_insn "lasx_xvfcvth_d_insn"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (float_extend:V4DF
|
|||
|
|
+ (vec_select:V4SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 4) (const_int 5)
|
|||
|
|
+ (const_int 6) (const_int 7)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpermi.d\t%u0,%u1,0xfa\n\txvfcvtl.d.s\t%u0,%u0"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DF")
|
|||
|
|
+ (set_attr "length" "12")])
|
|||
|
|
+
|
|||
|
|
+;; Define for builtin function.
|
|||
|
|
+(define_insn "lasx_xvfcvtl_s_h"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V16HI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFCVTL))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvtl.s.h\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+;; Define for builtin function.
|
|||
|
|
+(define_insn "lasx_xvfcvtl_d_s"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (float_extend:V4DF
|
|||
|
|
+ (vec_select:V4SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 4) (const_int 5)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfcvtl.d.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DF")
|
|||
|
|
+ (set_attr "length" "8")])
|
|||
|
|
+
|
|||
|
|
+;; Define for gen insn.
|
|||
|
|
+(define_insn "lasx_xvfcvtl_d_insn"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (float_extend:V4DF
|
|||
|
|
+ (vec_select:V4SF
|
|||
|
|
+ (match_operand:V8SF 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpermi.d\t%u0,%u1,0x50\n\txvfcvtl.d.s\t%u0,%u0"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DF")
|
|||
|
|
+ (set_attr "length" "8")])
|
|||
|
|
+
|
|||
|
|
+(define_code_attr lasxbr
|
|||
|
|
+ [(eq "xbz")
|
|||
|
|
+ (ne "xbnz")])
|
|||
|
|
+
|
|||
|
|
+(define_code_attr lasxeq_v
|
|||
|
|
+ [(eq "eqz")
|
|||
|
|
+ (ne "nez")])
|
|||
|
|
+
|
|||
|
|
+(define_code_attr lasxne_v
|
|||
|
|
+ [(eq "nez")
|
|||
|
|
+ (ne "eqz")])
|
|||
|
|
+
|
|||
|
|
+(define_code_attr lasxeq
|
|||
|
|
+ [(eq "anyeqz")
|
|||
|
|
+ (ne "allnez")])
|
|||
|
|
+
|
|||
|
|
+(define_code_attr lasxne
|
|||
|
|
+ [(eq "allnez")
|
|||
|
|
+ (ne "anyeqz")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_<lasxbr>_<lasxfmt_f>"
|
|||
|
|
+ [(set (pc)
|
|||
|
|
+ (if_then_else
|
|||
|
|
+ (equality_op
|
|||
|
|
+ (unspec:SI [(match_operand:LASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_BRANCH)
|
|||
|
|
+ (match_operand:SI 2 "const_0_operand"))
|
|||
|
|
+ (label_ref (match_operand 0))
|
|||
|
|
+ (pc)))
|
|||
|
|
+ (clobber (match_scratch:FCC 3 "=z"))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return loongarch_output_conditional_branch (insn, operands,
|
|||
|
|
+ "xvset<lasxeq>.<lasxfmt>\t%Z3%u1\n\tbcnez\t%Z3%0",
|
|||
|
|
+ "xvset<lasxne>.<lasxfmt>\t%z3%u1\n\tbcnez\t%Z3%0");
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_branch")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_<lasxbr>_v_<lasxfmt_f>"
|
|||
|
|
+ [(set (pc)
|
|||
|
|
+ (if_then_else
|
|||
|
|
+ (equality_op
|
|||
|
|
+ (unspec:SI [(match_operand:LASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_BRANCH_V)
|
|||
|
|
+ (match_operand:SI 2 "const_0_operand"))
|
|||
|
|
+ (label_ref (match_operand 0))
|
|||
|
|
+ (pc)))
|
|||
|
|
+ (clobber (match_scratch:FCC 3 "=z"))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return loongarch_output_conditional_branch (insn, operands,
|
|||
|
|
+ "xvset<lasxeq_v>.v\t%Z3%u1\n\tbcnez\t%Z3%0",
|
|||
|
|
+ "xvset<lasxne_v>.v\t%Z3%u1\n\tbcnez\t%Z3%0");
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_branch")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;; loongson-asx.
|
|||
|
|
+(define_insn "lasx_vext2xv_h<u>_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)
|
|||
|
|
+ (const_int 4) (const_int 5)
|
|||
|
|
+ (const_int 6) (const_int 7)
|
|||
|
|
+ (const_int 8) (const_int 9)
|
|||
|
|
+ (const_int 10) (const_int 11)
|
|||
|
|
+ (const_int 12) (const_int 13)
|
|||
|
|
+ (const_int 14) (const_int 15)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "vext2xv.h<u>.b<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_vext2xv_w<u>_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)
|
|||
|
|
+ (const_int 4) (const_int 5)
|
|||
|
|
+ (const_int 6) (const_int 7)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "vext2xv.w<u>.h<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_vext2xv_d<u>_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "vext2xv.d<u>.w<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_vext2xv_w<u>_b<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)
|
|||
|
|
+ (const_int 4) (const_int 5)
|
|||
|
|
+ (const_int 6) (const_int 7)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "vext2xv.w<u>.b<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_vext2xv_d<u>_h<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "vext2xv.d<u>.h<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_vext2xv_d<u>_b<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 1)
|
|||
|
|
+ (const_int 2) (const_int 3)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "vext2xv.d<u>.b<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;; Extend loongson-sx to loongson-asx.
|
|||
|
|
+(define_insn "xvandn<mode>3"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (and:LASX (not:LASX (match_operand:LASX 1 "register_operand" "f"))
|
|||
|
|
+ (match_operand:LASX 2 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvandn.v\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "abs<mode>2"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (abs:ILASX (match_operand:ILASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsigncov.<lasxfmt>\t%u0,%u1,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "neg<mode>2"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (neg:ILASX (match_operand:ILASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvneg.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmuh_s_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMUH_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmuh.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmuh_u_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMUH_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmuh.<lasxfmt_u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsllwil_s_<dlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VDMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VDMODE256> [(match_operand:ILASX_WHB 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSLLWIL_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsllwil.<dlasxfmt>.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsllwil_u_<dlasxfmt_u>_<lasxfmt_u>"
|
|||
|
|
+ [(set (match_operand:<VDMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VDMODE256> [(match_operand:ILASX_WHB 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSLLWIL_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsllwil.<dlasxfmt_u>.<lasxfmt_u>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsran_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSRAN))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsran.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssran_s_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRAN_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssran.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssran_u_<hlasxfmt_u>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRAN_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssran.<hlasxfmt_u>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrarn_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSRARN))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrarn.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrarn_s_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRARN_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrarn.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrarn_u_<hlasxfmt_u>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRARN_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrarn.<hlasxfmt_u>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrln_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSRLN))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrln.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrln_u_<hlasxfmt_u>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLN_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrln.<hlasxfmt_u>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrlrn_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSRLRN))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrlrn.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrlrn_u_<hlasxfmt_u>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRN_U))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrlrn.<hlasxfmt_u>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrstpi_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX_HB 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX_HB [(match_operand:ILASX_HB 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX_HB 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm5_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVFRSTPI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrstpi.<lasxfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrstp_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX_HB 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX_HB [(match_operand:ILASX_HB 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX_HB 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_HB 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRSTP))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrstp.<lasxfmt>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvshuf4i_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand")]
|
|||
|
|
+ UNSPEC_LASX_XVSHUF4I))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvshuf4i.d\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_sld")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbsrl_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_uimm5_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVBSRL_V))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbsrl.v\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvbsll_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_uimm5_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVBSLL_V))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbsll.v\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvextrins_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVEXTRINS))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvextrins.<lasxfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmskltz_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMSKLTZ))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmskltz.<lasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsigncov_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSIGNCOV))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsigncov.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_expand "copysign<mode>3"
|
|||
|
|
+ [(set (match_dup 4)
|
|||
|
|
+ (and:FLASX
|
|||
|
|
+ (not:FLASX (match_dup 3))
|
|||
|
|
+ (match_operand:FLASX 1 "register_operand")))
|
|||
|
|
+ (set (match_dup 5)
|
|||
|
|
+ (and:FLASX (match_dup 3)
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand")))
|
|||
|
|
+ (set (match_operand:FLASX 0 "register_operand")
|
|||
|
|
+ (ior:FLASX (match_dup 4) (match_dup 5)))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
|
|||
|
|
+
|
|||
|
|
+ operands[4] = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ operands[5] = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "absv4df2"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (abs:V4DF (match_operand:V4DF 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitclri.d\t%u0,%u1,63"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "absv8sf2"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (abs:V8SF (match_operand:V8SF 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitclri.w\t%u0,%u1,31"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "negv4df2"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (neg:V4DF (match_operand:V4DF 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitrevi.d\t%u0,%u1,63"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "negv8sf2"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (neg:V8SF (match_operand:V8SF 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvbitrevi.w\t%u0,%u1,31"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "xvfmadd<mode>4"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (fma:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 3 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmadd.<flasxfmt>\t%u0,%u1,$u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "fms<mode>4"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (fma:FLASX (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")
|
|||
|
|
+ (neg:FLASX (match_operand:FLASX 3 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfmsub.<flasxfmt>\t%u0,%u1,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "xvfnmsub<mode>4_nmsub4"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (neg:FLASX
|
|||
|
|
+ (fma:FLASX
|
|||
|
|
+ (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")
|
|||
|
|
+ (neg:FLASX (match_operand:FLASX 3 "register_operand" "f")))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfnmsub.<flasxfmt>\t%u0,%u1,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "xvfnmadd<mode>4_nmadd4"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (neg:FLASX
|
|||
|
|
+ (fma:FLASX
|
|||
|
|
+ (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:FLASX 3 "register_operand" "f"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfnmadd.<flasxfmt>\t%u0,%u1,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrne_w_s"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNE_W_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrne.w.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrne_l_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNE_L_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrne.l.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrp_w_s"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRP_W_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrp.w.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrp_l_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRP_L_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrp.l.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrm_w_s"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRM_W_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrm.w.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrm_l_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRM_L_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrm.l.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftint_w_d"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINT_W_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftint.w.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvffint_s_l"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFFINT_S_L))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvffint.s.l\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrz_w_d"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRZ_W_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrz.w.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrp_w_d"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRP_W_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrp.w.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrm_w_d"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRM_W_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrm.w.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrne_w_d"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SI [(match_operand:V4DF 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DF 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNE_W_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrne.w.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftinth_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTH_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftinth.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintl_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTL_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintl.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvffinth_d_w"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V8SI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFFINTH_D_W))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvffinth.d.w\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvffintl_d_w"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V8SI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFFINTL_D_W))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvffintl.d.w\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrzh_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRZH_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrzh.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrzl_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRZL_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrzl.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrph_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRPH_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrph.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrpl_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRPL_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrpl.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrmh_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRMH_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrmh.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrml_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRML_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrml.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrneh_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNEH_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrneh.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvftintrnel_l_s"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFTINTRNEL_L_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvftintrnel.l.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrne_s"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRNE_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrne.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrne_d"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRNE_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrne.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrz_s"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRZ_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrz.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrz_d"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRZ_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrz.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrp_s"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRP_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrp.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrp_d"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRP_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrp.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrm_s"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRM_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrm.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvfrintrm_d"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINTRM_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrintrm.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+;; Vector versions of the floating-point frint patterns.
|
|||
|
|
+;; Expands to btrunc, ceil, floor, rint.
|
|||
|
|
+(define_insn "<FRINT256_S:frint256_pattern_s>v8sf2"
|
|||
|
|
+ [(set (match_operand:V8SF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V8SF [(match_operand:V8SF 1 "register_operand" "f")]
|
|||
|
|
+ FRINT256_S))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrint<FRINT256_S:frint256_suffix>.s\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V8SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "<FRINT256_D:frint256_pattern_d>v4df2"
|
|||
|
|
+ [(set (match_operand:V4DF 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DF [(match_operand:V4DF 1 "register_operand" "f")]
|
|||
|
|
+ FRINT256_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrint<FRINT256_D:frint256_suffix>.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "V4DF")])
|
|||
|
|
+
|
|||
|
|
+;; Expands to round.
|
|||
|
|
+(define_insn "round<mode>2"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:FLASX [(match_operand:FLASX 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVFRINT))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvfrint.<flasxfmt>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;; Offset load and broadcast
|
|||
|
|
+(define_expand "lasx_xvldrepl_<lasxfmt_f>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand 2 "aq12<lasxfmt>_operand")
|
|||
|
|
+ (match_operand 1 "pmode_register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ emit_insn (gen_lasx_xvldrepl_<lasxfmt_f>_insn
|
|||
|
|
+ (operands[0], operands[1], operands[2]));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvldrepl_<lasxfmt_f>_insn"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:LASX
|
|||
|
|
+ (mem:<UNITMODE> (plus:DI (match_operand:DI 1 "register_operand" "r")
|
|||
|
|
+ (match_operand 2 "aq12<lasxfmt>_operand")))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvldrepl.<lasxfmt>\t%u0,%1,%2";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_load")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "4")])
|
|||
|
|
+
|
|||
|
|
+;; Offset is "0"
|
|||
|
|
+(define_insn "lasx_xvldrepl_<lasxfmt_f>_insn_0"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (vec_duplicate:LASX
|
|||
|
|
+ (mem:<UNITMODE> (match_operand:DI 1 "register_operand" "r"))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvldrepl.<lasxfmt>\t%u0,%1,0";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_load")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "4")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.H.B XVSUBWEV.H.B XVMULWEV.H.B
|
|||
|
|
+;;XVADDWEV.H.BU XVSUBWEV.H.BU XVMULWEV.H.BU
|
|||
|
|
+(define_insn "lasx_xv<optab>wev_h_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (addsubmul:V16HI
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wev.h.b<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.W.H XVSUBWEV.W.H XVMULWEV.W.H
|
|||
|
|
+;;XVADDWEV.W.HU XVSUBWEV.W.HU XVMULWEV.W.HU
|
|||
|
|
+(define_insn "lasx_xv<optab>wev_w_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (addsubmul:V8SI
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wev.w.h<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.D.W XVSUBWEV.D.W XVMULWEV.D.W
|
|||
|
|
+;;XVADDWEV.D.WU XVSUBWEV.D.WU XVMULWEV.D.WU
|
|||
|
|
+(define_insn "lasx_xv<optab>wev_d_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (addsubmul:V4DI
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wev.d.w<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvaddwev_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADDWEV))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvaddwev.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVSUBWEV.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvsubwev_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSUBWEV))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsubwev.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMULWEV.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmulwev_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMULWEV))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwev.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.H.B XVSUBWOD.H.B XVMULWOD.H.B
|
|||
|
|
+;;XVADDWOD.H.BU XVSUBWOD.H.BU XVMULWOD.H.BU
|
|||
|
|
+(define_insn "lasx_xv<optab>wod_h_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (addsubmul:V16HI
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wod.h.b<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.W.H XVSUBWOD.W.H XVMULWOD.W.H
|
|||
|
|
+;;XVADDWOD.W.HU XVSUBWOD.W.HU XVMULWOD.W.HU
|
|||
|
|
+(define_insn "lasx_xv<optab>wod_w_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (addsubmul:V8SI
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wod.w.h<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.D.W XVSUBWOD.D.W XVMULWOD.D.W
|
|||
|
|
+;;XVADDWOD.D.WU XVSUBWOD.D.WU XVMULWOD.D.WU
|
|||
|
|
+(define_insn "lasx_xv<optab>wod_d_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (addsubmul:V4DI
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wod.d.w<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvaddwod_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADDWOD))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvaddwod.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVSUBWOD.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvsubwod_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSUBWOD))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsubwod.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMULWOD.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmulwod_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMULWOD))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwod.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvaddwev_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADDWEV2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvaddwev.q.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVSUBWEV.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvsubwev_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSUBWEV2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsubwev.q.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMULWEV.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmulwev_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMULWEV2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwev.q.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvaddwod_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADDWOD2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvaddwod.q.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVSUBWOD.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvsubwod_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSUBWOD2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsubwod.q.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMULWOD.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmulwod_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMULWOD2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwod.q.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.H.BU.B XVMULWEV.H.BU.B
|
|||
|
|
+(define_insn "lasx_xv<optab>wev_h_bu_b"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (addmul:V16HI
|
|||
|
|
+ (zero_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))
|
|||
|
|
+ (sign_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wev.h.bu.b\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.W.HU.H XVMULWEV.W.HU.H
|
|||
|
|
+(define_insn "lasx_xv<optab>wev_w_hu_h"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (addmul:V8SI
|
|||
|
|
+ (zero_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))
|
|||
|
|
+ (sign_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wev.w.hu.h\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.D.WU.W XVMULWEV.D.WU.W
|
|||
|
|
+(define_insn "lasx_xv<optab>wev_d_wu_w"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (addmul:V4DI
|
|||
|
|
+ (zero_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))
|
|||
|
|
+ (sign_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wev.d.wu.w\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.H.BU.B XVMULWOD.H.BU.B
|
|||
|
|
+(define_insn "lasx_xv<optab>wod_h_bu_b"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (addmul:V16HI
|
|||
|
|
+ (zero_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))
|
|||
|
|
+ (sign_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wod.h.bu.b\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.W.HU.H XVMULWOD.W.HU.H
|
|||
|
|
+(define_insn "lasx_xv<optab>wod_w_hu_h"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (addmul:V8SI
|
|||
|
|
+ (zero_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))
|
|||
|
|
+ (sign_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wod.w.hu.h\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.D.WU.W XVMULWOD.D.WU.W
|
|||
|
|
+(define_insn "lasx_xv<optab>wod_d_wu_w"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (addmul:V4DI
|
|||
|
|
+ (zero_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))
|
|||
|
|
+ (sign_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xv<optab>wod.d.wu.w\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.H.B XVMADDWEV.H.BU
|
|||
|
|
+(define_insn "lasx_xvmaddwev_h_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V16HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V16HI
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.h.b<u>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.W.H XVMADDWEV.W.HU
|
|||
|
|
+(define_insn "lasx_xvmaddwev_w_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V8SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V8SI
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.w.h<u>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.D.W XVMADDWEV.D.WU
|
|||
|
|
+(define_insn "lasx_xvmaddwev_d_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V4DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V4DI
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.d.w<u>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmaddwev_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMADDWEV))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.q.d\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.H.B XVMADDWOD.H.BU
|
|||
|
|
+(define_insn "lasx_xvmaddwod_h_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V16HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V16HI
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.h.b<u>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.W.H XVMADDWOD.W.HU
|
|||
|
|
+(define_insn "lasx_xvmaddwod_w_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V8SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V8SI
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.w.h<u>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.D.W XVMADDWOD.D.WU
|
|||
|
|
+(define_insn "lasx_xvmaddwod_d_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V4DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V4DI
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.d.w<u>\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmaddwod_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMADDWOD))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.q.d\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmaddwev_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMADDWEV2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.q.du\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.Q.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmaddwod_q_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMADDWOD2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.q.du\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.H.BU.B
|
|||
|
|
+(define_insn "lasx_xvmaddwev_h_bu_b"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V16HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V16HI
|
|||
|
|
+ (zero_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)])))
|
|||
|
|
+ (sign_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)
|
|||
|
|
+ (const_int 16) (const_int 18)
|
|||
|
|
+ (const_int 20) (const_int 22)
|
|||
|
|
+ (const_int 24) (const_int 26)
|
|||
|
|
+ (const_int 28) (const_int 30)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.h.bu.b\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.W.HU.H
|
|||
|
|
+(define_insn "lasx_xvmaddwev_w_hu_h"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V8SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V8SI
|
|||
|
|
+ (zero_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)])))
|
|||
|
|
+ (sign_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)
|
|||
|
|
+ (const_int 8) (const_int 10)
|
|||
|
|
+ (const_int 12) (const_int 14)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.w.hu.h\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.D.WU.W
|
|||
|
|
+(define_insn "lasx_xvmaddwev_d_wu_w"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V4DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V4DI
|
|||
|
|
+ (zero_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))
|
|||
|
|
+ (sign_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.d.wu.w\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWEV.Q.DU.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmaddwev_q_du_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMADDWEV3))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwev.q.du.d\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.H.BU.B
|
|||
|
|
+(define_insn "lasx_xvmaddwod_h_bu_b"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V16HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V16HI
|
|||
|
|
+ (zero_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)])))
|
|||
|
|
+ (sign_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)
|
|||
|
|
+ (const_int 17) (const_int 19)
|
|||
|
|
+ (const_int 21) (const_int 23)
|
|||
|
|
+ (const_int 25) (const_int 27)
|
|||
|
|
+ (const_int 29) (const_int 31)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.h.bu.b\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.W.HU.H
|
|||
|
|
+(define_insn "lasx_xvmaddwod_w_hu_h"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V8SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V8SI
|
|||
|
|
+ (zero_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)])))
|
|||
|
|
+ (sign_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)
|
|||
|
|
+ (const_int 9) (const_int 11)
|
|||
|
|
+ (const_int 13) (const_int 15)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.w.hu.h\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.D.WU.W
|
|||
|
|
+(define_insn "lasx_xvmaddwod_d_wu_w"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (plus:V4DI
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (mult:V4DI
|
|||
|
|
+ (zero_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)])))
|
|||
|
|
+ (sign_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 3 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 1) (const_int 3)
|
|||
|
|
+ (const_int 5) (const_int 7)]))))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.d.wu.w\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_fmadd")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMADDWOD.Q.DU.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvmaddwod_q_du_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 3 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMADDWOD3))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmaddwod.q.du.d\t%u0,%u2,%u3"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVHADDW.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvhaddw_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVHADDW_Q_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvhaddw.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVHSUBW.Q.D
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvhsubw_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVHSUBW_Q_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvhsubw.q.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVHADDW.QU.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvhaddw_qu_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVHADDW_QU_DU))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvhaddw.qu.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVHSUBW.QU.DU
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvhsubw_qu_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVHSUBW_QU_DU))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvhsubw.qu.du\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVROTR.B XVROTR.H XVROTR.W XVROTR.D
|
|||
|
|
+;;TODO-478
|
|||
|
|
+(define_insn "lasx_xvrotr_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVROTR))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvrotr.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;;XVADD.Q
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvadd_q"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADD_Q))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvadd.q\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVSUB.Q
|
|||
|
|
+;;TODO2
|
|||
|
|
+(define_insn "lasx_xvsub_q"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSUB_Q))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsub.q\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVSSRLN.B.H XVSSRLN.H.W XVSSRLN.W.D
|
|||
|
|
+(define_insn "lasx_xvssrln_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLN))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrln.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;;XVREPLVE.B XVREPLVE.H XVREPLVE.W XVREPLVE.D
|
|||
|
|
+(define_insn "lasx_xvreplve_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX [(match_operand:LASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:SI 2 "register_operand" "r")]
|
|||
|
|
+ UNSPEC_LASX_XVREPLVE))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvreplve.<lasxfmt>\t%u0,%u1,%z2"
|
|||
|
|
+ [(set_attr "type" "simd_splat")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWEV.Q.DU.D
|
|||
|
|
+(define_insn "lasx_xvaddwev_q_du_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADDWEV3))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvaddwev.q.du.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVADDWOD.Q.DU.D
|
|||
|
|
+(define_insn "lasx_xvaddwod_q_du_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVADDWOD3))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvaddwod.q.du.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMULWEV.Q.DU.D
|
|||
|
|
+(define_insn "lasx_xvmulwev_q_du_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMULWEV3))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwev.q.du.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;;XVMULWOD.Q.DU.D
|
|||
|
|
+(define_insn "lasx_xvmulwod_q_du_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:V4DI 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMULWOD3))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwod.q.du.d\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickve2gr_w<u>"
|
|||
|
|
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
|||
|
|
+ (any_extend:SI
|
|||
|
|
+ (vec_select:SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_0_to_7_operand" "")]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickve2gr.w<u>\t%0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_copy")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmskgez_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V32QI [(match_operand:V32QI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMSKGEZ))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmskgez.b\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvmsknz_b"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V32QI [(match_operand:V32QI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVMSKNZ))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmsknz.b\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvexth_h<u>_b<u>"
|
|||
|
|
+ [(set (match_operand:V16HI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V16HI
|
|||
|
|
+ (vec_select:V16QI
|
|||
|
|
+ (match_operand:V32QI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 16) (const_int 17)
|
|||
|
|
+ (const_int 18) (const_int 19)
|
|||
|
|
+ (const_int 20) (const_int 21)
|
|||
|
|
+ (const_int 22) (const_int 23)
|
|||
|
|
+ (const_int 24) (const_int 25)
|
|||
|
|
+ (const_int 26) (const_int 27)
|
|||
|
|
+ (const_int 28) (const_int 29)
|
|||
|
|
+ (const_int 30) (const_int 31)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvexth.h<u>.b<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V16HI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvexth_w<u>_h<u>"
|
|||
|
|
+ [(set (match_operand:V8SI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V8SI
|
|||
|
|
+ (vec_select:V8HI
|
|||
|
|
+ (match_operand:V16HI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 8) (const_int 9)
|
|||
|
|
+ (const_int 10) (const_int 11)
|
|||
|
|
+ (const_int 12) (const_int 13)
|
|||
|
|
+ (const_int 14) (const_int 15)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvexth.w<u>.h<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V8SI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvexth_d<u>_w<u>"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 4) (const_int 5)
|
|||
|
|
+ (const_int 6) (const_int 7)]))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvexth.d<u>.w<u>\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvexth_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVEXTH_Q_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvexth.q.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvexth_qu_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVEXTH_QU_DU))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvexth.qu.du\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvrotri_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (rotatert:ILASX (match_operand:ILASX 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<bitimm256>_operand" "")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvrotri.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shf")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvextl_q_d"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVEXTL_Q_D))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvextl.q.d\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_fcvt")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrlni_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSRLNI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrlni.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrlrni_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSRLRNI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrlrni.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrlni_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLNI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrlni.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrlni_<lasxfmt_u>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLNI2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrlni.<lasxfmt_u>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrlrni_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRNI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrlrni.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrlrni_<lasxfmt_u>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRNI2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrlrni.<lasxfmt_u>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrani_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSRANI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrani.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvsrarni_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSRARNI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvsrarni.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrani_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRANI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrani.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrani_<lasxfmt_u>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRANI2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrani.<lasxfmt_u>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrarni_<lasxfmt>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRARNI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrarni.<lasxfmt>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrarni_<lasxfmt_u>_<dlasxqfmt>"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:ILASX [(match_operand:ILASX 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:ILASX 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRARNI2))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrarni.<lasxfmt_u>.<dlasxqfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shift")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_mode_attr VDOUBLEMODEW256
|
|||
|
|
+ [(V8SI "V16SI")
|
|||
|
|
+ (V8SF "V16SF")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpermi_<lasxfmt_f_wd>"
|
|||
|
|
+ [(set (match_operand:LASX_W 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX_W [(match_operand:LASX_W 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:LASX_W 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_uimm8_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVPERMI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpermi.w\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpermi_<lasxfmt_f_wd>_1"
|
|||
|
|
+ [(set (match_operand:LASX_W 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:LASX_W
|
|||
|
|
+ (vec_concat:<VDOUBLEMODEW256>
|
|||
|
|
+ (match_operand:LASX_W 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:LASX_W 2 "register_operand" "0"))
|
|||
|
|
+ (parallel [(match_operand 3 "const_0_to_3_operand")
|
|||
|
|
+ (match_operand 4 "const_0_to_3_operand" )
|
|||
|
|
+ (match_operand 5 "const_8_to_11_operand" )
|
|||
|
|
+ (match_operand 6 "const_8_to_11_operand" )
|
|||
|
|
+ (match_operand 7 "const_4_to_7_operand" )
|
|||
|
|
+ (match_operand 8 "const_4_to_7_operand" )
|
|||
|
|
+ (match_operand 9 "const_12_to_15_operand")
|
|||
|
|
+ (match_operand 10 "const_12_to_15_operand")])))]
|
|||
|
|
+ "ISA_HAS_LASX
|
|||
|
|
+ && INTVAL (operands[3]) + 4 == INTVAL (operands[7])
|
|||
|
|
+ && INTVAL (operands[4]) + 4 == INTVAL (operands[8])
|
|||
|
|
+ && INTVAL (operands[5]) + 4 == INTVAL (operands[9])
|
|||
|
|
+ && INTVAL (operands[6]) + 4 == INTVAL (operands[10])"
|
|||
|
|
+{
|
|||
|
|
+ int mask = 0;
|
|||
|
|
+ mask |= INTVAL (operands[3]) << 0;
|
|||
|
|
+ mask |= INTVAL (operands[4]) << 2;
|
|||
|
|
+ mask |= (INTVAL (operands[5]) - 8) << 4;
|
|||
|
|
+ mask |= (INTVAL (operands[6]) - 8) << 6;
|
|||
|
|
+ operands[3] = GEN_INT (mask);
|
|||
|
|
+
|
|||
|
|
+ return "xvpermi.w\t%u0,%u1,%3";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_expand "lasx_xvld"
|
|||
|
|
+ [(match_operand:V32QI 0 "register_operand")
|
|||
|
|
+ (match_operand 1 "pmode_register_operand")
|
|||
|
|
+ (match_operand 2 "aq12b_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
|||
|
|
+ INTVAL (operands[2]));
|
|||
|
|
+ loongarch_emit_move (operands[0], gen_rtx_MEM (V32QImode, addr));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "lasx_xvst"
|
|||
|
|
+ [(match_operand:V32QI 0 "register_operand")
|
|||
|
|
+ (match_operand 1 "pmode_register_operand")
|
|||
|
|
+ (match_operand 2 "aq12b_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx addr = plus_constant (GET_MODE (operands[1]), operands[1],
|
|||
|
|
+ INTVAL (operands[2]));
|
|||
|
|
+ loongarch_emit_move (gen_rtx_MEM (V32QImode, addr), operands[0]);
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "lasx_xvstelm_<lasxfmt_f>"
|
|||
|
|
+ [(match_operand:LASX 0 "register_operand")
|
|||
|
|
+ (match_operand 3 "const_<indeximm256>_operand")
|
|||
|
|
+ (match_operand 2 "aq8<lasxfmt>_operand")
|
|||
|
|
+ (match_operand 1 "pmode_register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ emit_insn (gen_lasx_xvstelm_<lasxfmt_f>_insn
|
|||
|
|
+ (operands[1], operands[2], operands[0], operands[3]));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvstelm_<lasxfmt_f>_insn"
|
|||
|
|
+ [(set (mem:<UNITMODE> (plus:DI (match_operand:DI 0 "register_operand" "r")
|
|||
|
|
+ (match_operand 1 "aq8<lasxfmt>_operand")))
|
|||
|
|
+ (vec_select:<UNITMODE>
|
|||
|
|
+ (match_operand:LASX 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 3 "const_<indeximm256>_operand" "")])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvstelm.<lasxfmt>\t%u2,%0,%1,%3";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_store")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "4")])
|
|||
|
|
+
|
|||
|
|
+;; Offset is "0"
|
|||
|
|
+(define_insn "lasx_xvstelm_<lasxfmt_f>_insn_0"
|
|||
|
|
+ [(set (mem:<UNITMODE> (match_operand:DI 0 "register_operand" "r"))
|
|||
|
|
+ (vec_select:<UNITMODE>
|
|||
|
|
+ (match_operand:LASX_WD 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand:SI 2 "const_<indeximm256>_operand")])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvstelm.<lasxfmt>\t%u1,%0,0,%2";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_store")
|
|||
|
|
+ (set_attr "mode" "<MODE>")
|
|||
|
|
+ (set_attr "length" "4")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvinsve0_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX_WD 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX_WD [(match_operand:LASX_WD 1 "register_operand" "0")
|
|||
|
|
+ (match_operand:LASX_WD 2 "register_operand" "f")
|
|||
|
|
+ (match_operand 3 "const_<indeximm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVINSVE0))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvinsve0.<lasxfmt>\t%u0,%u2,%3"
|
|||
|
|
+ [(set_attr "type" "simd_shf")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvinsve0_<lasxfmt_f>_scalar"
|
|||
|
|
+ [(set (match_operand:FLASX 0 "register_operand" "=f")
|
|||
|
|
+ (vec_merge:FLASX
|
|||
|
|
+ (vec_duplicate:FLASX
|
|||
|
|
+ (match_operand:<UNITMODE> 1 "register_operand" "f"))
|
|||
|
|
+ (match_operand:FLASX 2 "register_operand" "0")
|
|||
|
|
+ (match_operand 3 "const_<bitmask256>_operand" "")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvinsve0.<lasxfmt>\t%u0,%u1,%y3"
|
|||
|
|
+ [(set_attr "type" "simd_insert")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickve_<lasxfmt_f>"
|
|||
|
|
+ [(set (match_operand:LASX_WD 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:LASX_WD [(match_operand:LASX_WD 1 "register_operand" "f")
|
|||
|
|
+ (match_operand 2 "const_<indeximm256>_operand" "")]
|
|||
|
|
+ UNSPEC_LASX_XVPICKVE))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickve.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shf")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvpickve_<lasxfmt_f>_scalar"
|
|||
|
|
+ [(set (match_operand:<UNITMODE> 0 "register_operand" "=f")
|
|||
|
|
+ (vec_select:<UNITMODE>
|
|||
|
|
+ (match_operand:FLASX 1 "register_operand" "f")
|
|||
|
|
+ (parallel [(match_operand 2 "const_<indeximm256>_operand" "")])))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvpickve.<lasxfmt>\t%u0,%u1,%2"
|
|||
|
|
+ [(set_attr "type" "simd_shf")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvssrlrn_<hlasxfmt>_<lasxfmt>"
|
|||
|
|
+ [(set (match_operand:<VHSMODE256> 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:<VHSMODE256> [(match_operand:ILASX_DWH 1 "register_operand" "f")
|
|||
|
|
+ (match_operand:ILASX_DWH 2 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSSRLRN))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvssrlrn.<hlasxfmt>.<lasxfmt>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "xvorn<mode>3"
|
|||
|
|
+ [(set (match_operand:ILASX 0 "register_operand" "=f")
|
|||
|
|
+ (ior:ILASX (not:ILASX (match_operand:ILASX 2 "register_operand" "f"))
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand" "f")))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvorn.v\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_logic")
|
|||
|
|
+ (set_attr "mode" "<MODE>")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvextl_qu_du"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI [(match_operand:V4DI 1 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVEXTL_QU_DU))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvextl.qu.du\t%u0,%u1"
|
|||
|
|
+ [(set_attr "type" "simd_bit")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvldi"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V4DI[(match_operand 1 "const_imm13_operand")]
|
|||
|
|
+ UNSPEC_LASX_XVLDI))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ HOST_WIDE_INT val = INTVAL (operands[1]);
|
|||
|
|
+ if (val < 0)
|
|||
|
|
+ {
|
|||
|
|
+ HOST_WIDE_INT modeVal = (val & 0xf00) >> 8;
|
|||
|
|
+ if (modeVal < 13)
|
|||
|
|
+ return "xvldi\t%u0,%1";
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ sorry ("imm13 only support 0000 ~ 1100 in bits '12 ~ 9' when bit '13' is 1");
|
|||
|
|
+ return "#";
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ return "xvldi\t%u0,%1";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_load")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvldx"
|
|||
|
|
+ [(set (match_operand:V32QI 0 "register_operand" "=f")
|
|||
|
|
+ (unspec:V32QI [(match_operand:DI 1 "register_operand" "r")
|
|||
|
|
+ (match_operand:DI 2 "reg_or_0_operand" "rJ")]
|
|||
|
|
+ UNSPEC_LASX_XVLDX))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvldx\t%u0,%1,%z2";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_load")
|
|||
|
|
+ (set_attr "mode" "V32QI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "lasx_xvstx"
|
|||
|
|
+ [(set (mem:V32QI (plus:DI (match_operand:DI 1 "register_operand" "r")
|
|||
|
|
+ (match_operand:DI 2 "reg_or_0_operand" "rJ")))
|
|||
|
|
+ (unspec: V32QI[(match_operand:V32QI 0 "register_operand" "f")]
|
|||
|
|
+ UNSPEC_LASX_XVSTX))]
|
|||
|
|
+
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ return "xvstx\t%u0,%1,%z2";
|
|||
|
|
+}
|
|||
|
|
+ [(set_attr "type" "simd_store")
|
|||
|
|
+ (set_attr "mode" "DI")])
|
|||
|
|
+
|
|||
|
|
+(define_insn "vec_widen_<su>mult_even_v8si"
|
|||
|
|
+ [(set (match_operand:V4DI 0 "register_operand" "=f")
|
|||
|
|
+ (mult:V4DI
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand" "%f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))
|
|||
|
|
+ (any_extend:V4DI
|
|||
|
|
+ (vec_select:V4SI
|
|||
|
|
+ (match_operand:V8SI 2 "register_operand" "f")
|
|||
|
|
+ (parallel [(const_int 0) (const_int 2)
|
|||
|
|
+ (const_int 4) (const_int 6)])))))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+ "xvmulwev.d.w<u>\t%u0,%u1,%u2"
|
|||
|
|
+ [(set_attr "type" "simd_int_arith")
|
|||
|
|
+ (set_attr "mode" "V4DI")])
|
|||
|
|
+
|
|||
|
|
+;; Vector reduction operation
|
|||
|
|
+(define_expand "reduc_plus_scal_v4di"
|
|||
|
|
+ [(match_operand:DI 0 "register_operand")
|
|||
|
|
+ (match_operand:V4DI 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (V4DImode);
|
|||
|
|
+ rtx tmp1 = gen_reg_rtx (V4DImode);
|
|||
|
|
+ rtx vec_res = gen_reg_rtx (V4DImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvhaddw_q_d (tmp, operands[1], operands[1]));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v4di (tmp1, tmp, GEN_INT (2)));
|
|||
|
|
+ emit_insn (gen_addv4di3 (vec_res, tmp, tmp1));
|
|||
|
|
+ emit_insn (gen_vec_extractv4didi (operands[0], vec_res, const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_plus_scal_v8si"
|
|||
|
|
+ [(match_operand:SI 0 "register_operand")
|
|||
|
|
+ (match_operand:V8SI 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (V4DImode);
|
|||
|
|
+ rtx tmp1 = gen_reg_rtx (V4DImode);
|
|||
|
|
+ rtx vec_res = gen_reg_rtx (V4DImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvhaddw_d_w (tmp, operands[1], operands[1]));
|
|||
|
|
+ emit_insn (gen_lasx_xvhaddw_q_d (tmp1, tmp, tmp));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v4di (tmp, tmp1, GEN_INT (2)));
|
|||
|
|
+ emit_insn (gen_addv4di3 (vec_res, tmp, tmp1));
|
|||
|
|
+ emit_insn (gen_vec_extractv8sisi (operands[0], gen_lowpart (V8SImode,vec_res),
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_plus_scal_<mode>"
|
|||
|
|
+ [(match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:FLASX 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ loongarch_expand_vector_reduc (gen_add<mode>3, tmp, operands[1]);
|
|||
|
|
+ emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_<optab>_scal_<mode>"
|
|||
|
|
+ [(any_bitwise:<UNITMODE>
|
|||
|
|
+ (match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand"))]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ loongarch_expand_vector_reduc (gen_<optab><mode>3, tmp, operands[1]);
|
|||
|
|
+ emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_smax_scal_<mode>"
|
|||
|
|
+ [(match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ loongarch_expand_vector_reduc (gen_smax<mode>3, tmp, operands[1]);
|
|||
|
|
+ emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_smin_scal_<mode>"
|
|||
|
|
+ [(match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:LASX 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ loongarch_expand_vector_reduc (gen_smin<mode>3, tmp, operands[1]);
|
|||
|
|
+ emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_umax_scal_<mode>"
|
|||
|
|
+ [(match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ loongarch_expand_vector_reduc (gen_umax<mode>3, tmp, operands[1]);
|
|||
|
|
+ emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
+
|
|||
|
|
+(define_expand "reduc_umin_scal_<mode>"
|
|||
|
|
+ [(match_operand:<UNITMODE> 0 "register_operand")
|
|||
|
|
+ (match_operand:ILASX 1 "register_operand")]
|
|||
|
|
+ "ISA_HAS_LASX"
|
|||
|
|
+{
|
|||
|
|
+ rtx tmp = gen_reg_rtx (<MODE>mode);
|
|||
|
|
+ loongarch_expand_vector_reduc (gen_umin<mode>3, tmp, operands[1]);
|
|||
|
|
+ emit_insn (gen_vec_extract<mode><unitmode> (operands[0], tmp,
|
|||
|
|
+ const0_rtx));
|
|||
|
|
+ DONE;
|
|||
|
|
+})
|
|||
|
|
diff --git a/gcc/config/loongarch/loongarch-modes.def b/gcc/config/loongarch/loongarch-modes.def
|
|||
|
|
index b69ad3d83..ac9ea3142 100644
|
|||
|
|
--- a/gcc/config/loongarch/loongarch-modes.def
|
|||
|
|
+++ b/gcc/config/loongarch/loongarch-modes.def
|
|||
|
|
@@ -33,6 +33,7 @@ VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
|
|||
|
|
VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
|
|||
|
|
VECTOR_MODES (FLOAT, 16); /* V4SF V2DF */
|
|||
|
|
|
|||
|
|
+/* For LARCH LASX 256 bits. */
|
|||
|
|
VECTOR_MODES (INT, 32); /* V32QI V16HI V8SI V4DI */
|
|||
|
|
VECTOR_MODES (FLOAT, 32); /* V8SF V4DF */
|
|||
|
|
|
|||
|
|
diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h
|
|||
|
|
index 24e42fa99..133ec9fa8 100644
|
|||
|
|
--- a/gcc/config/loongarch/loongarch-protos.h
|
|||
|
|
+++ b/gcc/config/loongarch/loongarch-protos.h
|
|||
|
|
@@ -89,6 +89,8 @@ extern bool loongarch_split_move_insn_p (rtx, rtx);
|
|||
|
|
extern void loongarch_split_move_insn (rtx, rtx, rtx);
|
|||
|
|
extern void loongarch_split_128bit_move (rtx, rtx);
|
|||
|
|
extern bool loongarch_split_128bit_move_p (rtx, rtx);
|
|||
|
|
+extern void loongarch_split_256bit_move (rtx, rtx);
|
|||
|
|
+extern bool loongarch_split_256bit_move_p (rtx, rtx);
|
|||
|
|
extern void loongarch_split_lsx_copy_d (rtx, rtx, rtx, rtx (*)(rtx, rtx, rtx));
|
|||
|
|
extern void loongarch_split_lsx_insert_d (rtx, rtx, rtx, rtx);
|
|||
|
|
extern void loongarch_split_lsx_fill_d (rtx, rtx);
|
|||
|
|
@@ -174,9 +176,11 @@ union loongarch_gen_fn_ptrs
|
|||
|
|
extern void loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs,
|
|||
|
|
rtx, rtx, rtx, rtx, rtx);
|
|||
|
|
|
|||
|
|
+extern void loongarch_expand_vector_group_init (rtx, rtx);
|
|||
|
|
extern void loongarch_expand_vector_init (rtx, rtx);
|
|||
|
|
extern void loongarch_expand_vec_unpack (rtx op[2], bool, bool);
|
|||
|
|
extern void loongarch_expand_vec_perm (rtx, rtx, rtx, rtx);
|
|||
|
|
+extern void loongarch_expand_vec_perm_1 (rtx[]);
|
|||
|
|
extern void loongarch_expand_vector_extract (rtx, rtx, int);
|
|||
|
|
extern void loongarch_expand_vector_reduc (rtx (*)(rtx, rtx, rtx), rtx, rtx);
|
|||
|
|
|
|||
|
|
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
|
|||
|
|
index 40b83d72b..dae35a479 100644
|
|||
|
|
--- a/gcc/config/loongarch/loongarch.cc
|
|||
|
|
+++ b/gcc/config/loongarch/loongarch.cc
|
|||
|
|
@@ -1927,7 +1927,7 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
|
|||
|
|
{
|
|||
|
|
/* LSX LD.* and ST.* cannot support loading symbols via an immediate
|
|||
|
|
operand. */
|
|||
|
|
- if (LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ if (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))
|
|||
|
|
return 0;
|
|||
|
|
|
|||
|
|
switch (type)
|
|||
|
|
@@ -2060,6 +2060,11 @@ loongarch_valid_offset_p (rtx x, machine_mode mode)
|
|||
|
|
loongarch_ldst_scaled_shift (mode)))
|
|||
|
|
return false;
|
|||
|
|
|
|||
|
|
+ /* LASX XVLD.B and XVST.B supports 10-bit signed offsets without shift. */
|
|||
|
|
+ if (LASX_SUPPORTED_MODE_P (mode)
|
|||
|
|
+ && !loongarch_signed_immediate_p (INTVAL (x), 10, 0))
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@@ -2272,7 +2277,9 @@ loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p)
|
|||
|
|
{
|
|||
|
|
struct loongarch_address_info addr;
|
|||
|
|
int factor;
|
|||
|
|
- bool lsx_p = !might_split_p && LSX_SUPPORTED_MODE_P (mode);
|
|||
|
|
+ bool lsx_p = (!might_split_p
|
|||
|
|
+ && (LSX_SUPPORTED_MODE_P (mode)
|
|||
|
|
+ || LASX_SUPPORTED_MODE_P (mode)));
|
|||
|
|
|
|||
|
|
if (!loongarch_classify_address (&addr, x, mode, false))
|
|||
|
|
return 0;
|
|||
|
|
@@ -2418,7 +2425,8 @@ loongarch_const_insns (rtx x)
|
|||
|
|
return loongarch_integer_cost (INTVAL (x));
|
|||
|
|
|
|||
|
|
case CONST_VECTOR:
|
|||
|
|
- if (LSX_SUPPORTED_MODE_P (GET_MODE (x))
|
|||
|
|
+ if ((LSX_SUPPORTED_MODE_P (GET_MODE (x))
|
|||
|
|
+ || LASX_SUPPORTED_MODE_P (GET_MODE (x)))
|
|||
|
|
&& loongarch_const_vector_same_int_p (x, GET_MODE (x), -512, 511))
|
|||
|
|
return 1;
|
|||
|
|
/* Fall through. */
|
|||
|
|
@@ -3257,10 +3265,11 @@ loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src)
|
|||
|
|
|
|||
|
|
/* Both src and dest are non-registers; one special case is supported where
|
|||
|
|
the source is (const_int 0) and the store can source the zero register.
|
|||
|
|
- LSX is never able to source the zero register directly in
|
|||
|
|
+ LSX and LASX are never able to source the zero register directly in
|
|||
|
|
memory operations. */
|
|||
|
|
if (!register_operand (dest, mode) && !register_operand (src, mode)
|
|||
|
|
- && (!const_0_operand (src, mode) || LSX_SUPPORTED_MODE_P (mode)))
|
|||
|
|
+ && (!const_0_operand (src, mode)
|
|||
|
|
+ || LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode)))
|
|||
|
|
{
|
|||
|
|
loongarch_emit_move (dest, force_reg (mode, src));
|
|||
|
|
return true;
|
|||
|
|
@@ -3842,6 +3851,7 @@ loongarch_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
|
|||
|
|
int misalign ATTRIBUTE_UNUSED)
|
|||
|
|
{
|
|||
|
|
unsigned elements;
|
|||
|
|
+ machine_mode mode = vectype != NULL ? TYPE_MODE (vectype) : DImode;
|
|||
|
|
|
|||
|
|
switch (type_of_cost)
|
|||
|
|
{
|
|||
|
|
@@ -3858,7 +3868,8 @@ loongarch_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
|
|||
|
|
return 1;
|
|||
|
|
|
|||
|
|
case vec_perm:
|
|||
|
|
- return 1;
|
|||
|
|
+ return LASX_SUPPORTED_MODE_P (mode)
|
|||
|
|
+ && !LSX_SUPPORTED_MODE_P (mode) ? 2 : 1;
|
|||
|
|
|
|||
|
|
case unaligned_load:
|
|||
|
|
case vector_gather_load:
|
|||
|
|
@@ -3939,6 +3950,10 @@ loongarch_split_move_p (rtx dest, rtx src)
|
|||
|
|
if (LSX_SUPPORTED_MODE_P (GET_MODE (dest)))
|
|||
|
|
return loongarch_split_128bit_move_p (dest, src);
|
|||
|
|
|
|||
|
|
+ /* Check if LASX moves need splitting. */
|
|||
|
|
+ if (LASX_SUPPORTED_MODE_P (GET_MODE (dest)))
|
|||
|
|
+ return loongarch_split_256bit_move_p (dest, src);
|
|||
|
|
+
|
|||
|
|
/* Otherwise split all multiword moves. */
|
|||
|
|
return size > UNITS_PER_WORD;
|
|||
|
|
}
|
|||
|
|
@@ -3954,6 +3969,8 @@ loongarch_split_move (rtx dest, rtx src, rtx insn_)
|
|||
|
|
gcc_checking_assert (loongarch_split_move_p (dest, src));
|
|||
|
|
if (LSX_SUPPORTED_MODE_P (GET_MODE (dest)))
|
|||
|
|
loongarch_split_128bit_move (dest, src);
|
|||
|
|
+ else if (LASX_SUPPORTED_MODE_P (GET_MODE (dest)))
|
|||
|
|
+ loongarch_split_256bit_move (dest, src);
|
|||
|
|
else if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src))
|
|||
|
|
{
|
|||
|
|
if (!TARGET_64BIT && GET_MODE (dest) == DImode)
|
|||
|
|
@@ -4119,7 +4136,7 @@ const char *
|
|||
|
|
loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr)
|
|||
|
|
{
|
|||
|
|
int index = exact_log2 (GET_MODE_SIZE (mode));
|
|||
|
|
- if (!IN_RANGE (index, 2, 4))
|
|||
|
|
+ if (!IN_RANGE (index, 2, 5))
|
|||
|
|
return NULL;
|
|||
|
|
|
|||
|
|
struct loongarch_address_info info;
|
|||
|
|
@@ -4128,17 +4145,19 @@ loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr)
|
|||
|
|
|| !loongarch_legitimate_address_p (mode, x, false))
|
|||
|
|
return NULL;
|
|||
|
|
|
|||
|
|
- const char *const insn[][3] =
|
|||
|
|
+ const char *const insn[][4] =
|
|||
|
|
{
|
|||
|
|
{
|
|||
|
|
"fstx.s\t%1,%0",
|
|||
|
|
"fstx.d\t%1,%0",
|
|||
|
|
- "vstx\t%w1,%0"
|
|||
|
|
+ "vstx\t%w1,%0",
|
|||
|
|
+ "xvstx\t%u1,%0"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"fldx.s\t%0,%1",
|
|||
|
|
"fldx.d\t%0,%1",
|
|||
|
|
- "vldx\t%w0,%1"
|
|||
|
|
+ "vldx\t%w0,%1",
|
|||
|
|
+ "xvldx\t%u0,%1"
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
@@ -4172,6 +4191,34 @@ loongarch_split_128bit_move_p (rtx dest, rtx src)
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+/* Return true if a 256-bit move from SRC to DEST should be split. */
|
|||
|
|
+
|
|||
|
|
+bool
|
|||
|
|
+loongarch_split_256bit_move_p (rtx dest, rtx src)
|
|||
|
|
+{
|
|||
|
|
+ /* LSX-to-LSX moves can be done in a single instruction. */
|
|||
|
|
+ if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ /* Check for LSX loads and stores. */
|
|||
|
|
+ if (FP_REG_RTX_P (dest) && MEM_P (src))
|
|||
|
|
+ return false;
|
|||
|
|
+ if (FP_REG_RTX_P (src) && MEM_P (dest))
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ /* Check for LSX set to an immediate const vector with valid replicated
|
|||
|
|
+ element. */
|
|||
|
|
+ if (FP_REG_RTX_P (dest)
|
|||
|
|
+ && loongarch_const_vector_same_int_p (src, GET_MODE (src), -512, 511))
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ /* Check for LSX load zero immediate. */
|
|||
|
|
+ if (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src)))
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ return true;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
/* Split a 128-bit move from SRC to DEST. */
|
|||
|
|
|
|||
|
|
void
|
|||
|
|
@@ -4263,6 +4310,97 @@ loongarch_split_128bit_move (rtx dest, rtx src)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+/* Split a 256-bit move from SRC to DEST. */
|
|||
|
|
+
|
|||
|
|
+void
|
|||
|
|
+loongarch_split_256bit_move (rtx dest, rtx src)
|
|||
|
|
+{
|
|||
|
|
+ int byte, index;
|
|||
|
|
+ rtx low_dest, low_src, d, s;
|
|||
|
|
+
|
|||
|
|
+ if (FP_REG_RTX_P (dest))
|
|||
|
|
+ {
|
|||
|
|
+ gcc_assert (!MEM_P (src));
|
|||
|
|
+
|
|||
|
|
+ rtx new_dest = dest;
|
|||
|
|
+ if (!TARGET_64BIT)
|
|||
|
|
+ {
|
|||
|
|
+ if (GET_MODE (dest) != V8SImode)
|
|||
|
|
+ new_dest = simplify_gen_subreg (V8SImode, dest, GET_MODE (dest), 0);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ if (GET_MODE (dest) != V4DImode)
|
|||
|
|
+ new_dest = simplify_gen_subreg (V4DImode, dest, GET_MODE (dest), 0);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ for (byte = 0, index = 0; byte < GET_MODE_SIZE (GET_MODE (dest));
|
|||
|
|
+ byte += UNITS_PER_WORD, index++)
|
|||
|
|
+ {
|
|||
|
|
+ s = loongarch_subword_at_byte (src, byte);
|
|||
|
|
+ if (!TARGET_64BIT)
|
|||
|
|
+ emit_insn (gen_lasx_xvinsgr2vr_w (new_dest, s, new_dest,
|
|||
|
|
+ GEN_INT (1 << index)));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvinsgr2vr_d (new_dest, s, new_dest,
|
|||
|
|
+ GEN_INT (1 << index)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (FP_REG_RTX_P (src))
|
|||
|
|
+ {
|
|||
|
|
+ gcc_assert (!MEM_P (dest));
|
|||
|
|
+
|
|||
|
|
+ rtx new_src = src;
|
|||
|
|
+ if (!TARGET_64BIT)
|
|||
|
|
+ {
|
|||
|
|
+ if (GET_MODE (src) != V8SImode)
|
|||
|
|
+ new_src = simplify_gen_subreg (V8SImode, src, GET_MODE (src), 0);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ if (GET_MODE (src) != V4DImode)
|
|||
|
|
+ new_src = simplify_gen_subreg (V4DImode, src, GET_MODE (src), 0);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ for (byte = 0, index = 0; byte < GET_MODE_SIZE (GET_MODE (src));
|
|||
|
|
+ byte += UNITS_PER_WORD, index++)
|
|||
|
|
+ {
|
|||
|
|
+ d = loongarch_subword_at_byte (dest, byte);
|
|||
|
|
+ if (!TARGET_64BIT)
|
|||
|
|
+ emit_insn (gen_lsx_vpickve2gr_w (d, new_src, GEN_INT (index)));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lsx_vpickve2gr_d (d, new_src, GEN_INT (index)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ low_dest = loongarch_subword_at_byte (dest, 0);
|
|||
|
|
+ low_src = loongarch_subword_at_byte (src, 0);
|
|||
|
|
+ gcc_assert (REG_P (low_dest) && REG_P (low_src));
|
|||
|
|
+ /* Make sure the source register is not written before reading. */
|
|||
|
|
+ if (REGNO (low_dest) <= REGNO (low_src))
|
|||
|
|
+ {
|
|||
|
|
+ for (byte = 0; byte < GET_MODE_SIZE (TImode);
|
|||
|
|
+ byte += UNITS_PER_WORD)
|
|||
|
|
+ {
|
|||
|
|
+ d = loongarch_subword_at_byte (dest, byte);
|
|||
|
|
+ s = loongarch_subword_at_byte (src, byte);
|
|||
|
|
+ loongarch_emit_move (d, s);
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ for (byte = GET_MODE_SIZE (TImode) - UNITS_PER_WORD; byte >= 0;
|
|||
|
|
+ byte -= UNITS_PER_WORD)
|
|||
|
|
+ {
|
|||
|
|
+ d = loongarch_subword_at_byte (dest, byte);
|
|||
|
|
+ s = loongarch_subword_at_byte (src, byte);
|
|||
|
|
+ loongarch_emit_move (d, s);
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
|
|||
|
|
/* Split a COPY_S.D with operands DEST, SRC and INDEX. GEN is a function
|
|||
|
|
used to generate subregs. */
|
|||
|
|
@@ -4350,11 +4488,12 @@ loongarch_output_move (rtx dest, rtx src)
|
|||
|
|
machine_mode mode = GET_MODE (dest);
|
|||
|
|
bool dbl_p = (GET_MODE_SIZE (mode) == 8);
|
|||
|
|
bool lsx_p = LSX_SUPPORTED_MODE_P (mode);
|
|||
|
|
+ bool lasx_p = LASX_SUPPORTED_MODE_P (mode);
|
|||
|
|
|
|||
|
|
if (loongarch_split_move_p (dest, src))
|
|||
|
|
return "#";
|
|||
|
|
|
|||
|
|
- if ((lsx_p)
|
|||
|
|
+ if ((lsx_p || lasx_p)
|
|||
|
|
&& dest_code == REG && FP_REG_P (REGNO (dest))
|
|||
|
|
&& src_code == CONST_VECTOR
|
|||
|
|
&& CONST_INT_P (CONST_VECTOR_ELT (src, 0)))
|
|||
|
|
@@ -4364,6 +4503,8 @@ loongarch_output_move (rtx dest, rtx src)
|
|||
|
|
{
|
|||
|
|
case 16:
|
|||
|
|
return "vrepli.%v0\t%w0,%E1";
|
|||
|
|
+ case 32:
|
|||
|
|
+ return "xvrepli.%v0\t%u0,%E1";
|
|||
|
|
default: gcc_unreachable ();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
@@ -4378,13 +4519,15 @@ loongarch_output_move (rtx dest, rtx src)
|
|||
|
|
|
|||
|
|
if (FP_REG_P (REGNO (dest)))
|
|||
|
|
{
|
|||
|
|
- if (lsx_p)
|
|||
|
|
+ if (lsx_p || lasx_p)
|
|||
|
|
{
|
|||
|
|
gcc_assert (src == CONST0_RTX (GET_MODE (src)));
|
|||
|
|
switch (GET_MODE_SIZE (mode))
|
|||
|
|
{
|
|||
|
|
case 16:
|
|||
|
|
return "vrepli.b\t%w0,0";
|
|||
|
|
+ case 32:
|
|||
|
|
+ return "xvrepli.b\t%u0,0";
|
|||
|
|
default:
|
|||
|
|
gcc_unreachable ();
|
|||
|
|
}
|
|||
|
|
@@ -4517,12 +4660,14 @@ loongarch_output_move (rtx dest, rtx src)
|
|||
|
|
{
|
|||
|
|
if (dest_code == REG && FP_REG_P (REGNO (dest)))
|
|||
|
|
{
|
|||
|
|
- if (lsx_p)
|
|||
|
|
+ if (lsx_p || lasx_p)
|
|||
|
|
{
|
|||
|
|
switch (GET_MODE_SIZE (mode))
|
|||
|
|
{
|
|||
|
|
case 16:
|
|||
|
|
return "vori.b\t%w0,%w1,0";
|
|||
|
|
+ case 32:
|
|||
|
|
+ return "xvori.b\t%u0,%u1,0";
|
|||
|
|
default:
|
|||
|
|
gcc_unreachable ();
|
|||
|
|
}
|
|||
|
|
@@ -4540,12 +4685,14 @@ loongarch_output_move (rtx dest, rtx src)
|
|||
|
|
if (insn)
|
|||
|
|
return insn;
|
|||
|
|
|
|||
|
|
- if (lsx_p)
|
|||
|
|
+ if (lsx_p || lasx_p)
|
|||
|
|
{
|
|||
|
|
switch (GET_MODE_SIZE (mode))
|
|||
|
|
{
|
|||
|
|
case 16:
|
|||
|
|
return "vst\t%w1,%0";
|
|||
|
|
+ case 32:
|
|||
|
|
+ return "xvst\t%u1,%0";
|
|||
|
|
default:
|
|||
|
|
gcc_unreachable ();
|
|||
|
|
}
|
|||
|
|
@@ -4566,12 +4713,14 @@ loongarch_output_move (rtx dest, rtx src)
|
|||
|
|
if (insn)
|
|||
|
|
return insn;
|
|||
|
|
|
|||
|
|
- if (lsx_p)
|
|||
|
|
+ if (lsx_p || lasx_p)
|
|||
|
|
{
|
|||
|
|
switch (GET_MODE_SIZE (mode))
|
|||
|
|
{
|
|||
|
|
case 16:
|
|||
|
|
return "vld\t%w0,%1";
|
|||
|
|
+ case 32:
|
|||
|
|
+ return "xvld\t%u0,%1";
|
|||
|
|
default:
|
|||
|
|
gcc_unreachable ();
|
|||
|
|
}
|
|||
|
|
@@ -5599,18 +5748,27 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part,
|
|||
|
|
'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
|
|||
|
|
'z' for (eq:?I ...), 'n' for (ne:?I ...).
|
|||
|
|
't' Like 'T', but with the EQ/NE cases reversed
|
|||
|
|
- 'V' Print exact log2 of CONST_INT OP element 0 of a replicated
|
|||
|
|
- CONST_VECTOR in decimal.
|
|||
|
|
+ 'F' Print the FPU branch condition for comparison OP.
|
|||
|
|
+ 'W' Print the inverse of the FPU branch condition for comparison OP.
|
|||
|
|
+ 'w' Print a LSX register.
|
|||
|
|
+ 'u' Print a LASX register.
|
|||
|
|
+ 'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...),
|
|||
|
|
+ 'z' for (eq:?I ...), 'n' for (ne:?I ...).
|
|||
|
|
+ 't' Like 'T', but with the EQ/NE cases reversed
|
|||
|
|
+ 'Y' Print loongarch_fp_conditions[INTVAL (OP)]
|
|||
|
|
+ 'Z' Print OP and a comma for 8CC, otherwise print nothing.
|
|||
|
|
+ 'z' Print $0 if OP is zero, otherwise print OP normally.
|
|||
|
|
'v' Print the insn size suffix b, h, w or d for vector modes V16QI, V8HI,
|
|||
|
|
V4SI, V2SI, and w, d for vector modes V4SF, V2DF respectively.
|
|||
|
|
+ 'V' Print exact log2 of CONST_INT OP element 0 of a replicated
|
|||
|
|
+ CONST_VECTOR in decimal.
|
|||
|
|
'W' Print the inverse of the FPU branch condition for comparison OP.
|
|||
|
|
- 'w' Print a LSX register.
|
|||
|
|
'X' Print CONST_INT OP in hexadecimal format.
|
|||
|
|
'x' Print the low 16 bits of CONST_INT OP in hexadecimal format.
|
|||
|
|
'Y' Print loongarch_fp_conditions[INTVAL (OP)]
|
|||
|
|
'y' Print exact log2 of CONST_INT OP in decimal.
|
|||
|
|
'Z' Print OP and a comma for 8CC, otherwise print nothing.
|
|||
|
|
- 'z' Print $r0 if OP is zero, otherwise print OP normally. */
|
|||
|
|
+ 'z' Print $0 if OP is zero, otherwise print OP normally. */
|
|||
|
|
|
|||
|
|
static void
|
|||
|
|
loongarch_print_operand (FILE *file, rtx op, int letter)
|
|||
|
|
@@ -5752,46 +5910,11 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
|
|||
|
|
output_operand_lossage ("invalid use of '%%%c'", letter);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
- case 'v':
|
|||
|
|
- switch (GET_MODE (op))
|
|||
|
|
- {
|
|||
|
|
- case E_V16QImode:
|
|||
|
|
- case E_V32QImode:
|
|||
|
|
- fprintf (file, "b");
|
|||
|
|
- break;
|
|||
|
|
- case E_V8HImode:
|
|||
|
|
- case E_V16HImode:
|
|||
|
|
- fprintf (file, "h");
|
|||
|
|
- break;
|
|||
|
|
- case E_V4SImode:
|
|||
|
|
- case E_V4SFmode:
|
|||
|
|
- case E_V8SImode:
|
|||
|
|
- case E_V8SFmode:
|
|||
|
|
- fprintf (file, "w");
|
|||
|
|
- break;
|
|||
|
|
- case E_V2DImode:
|
|||
|
|
- case E_V2DFmode:
|
|||
|
|
- case E_V4DImode:
|
|||
|
|
- case E_V4DFmode:
|
|||
|
|
- fprintf (file, "d");
|
|||
|
|
- break;
|
|||
|
|
- default:
|
|||
|
|
- output_operand_lossage ("invalid use of '%%%c'", letter);
|
|||
|
|
- }
|
|||
|
|
- break;
|
|||
|
|
-
|
|||
|
|
case 'W':
|
|||
|
|
loongarch_print_float_branch_condition (file, reverse_condition (code),
|
|||
|
|
letter);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
- case 'w':
|
|||
|
|
- if (code == REG && LSX_REG_P (REGNO (op)))
|
|||
|
|
- fprintf (file, "$vr%s", ®_names[REGNO (op)][2]);
|
|||
|
|
- else
|
|||
|
|
- output_operand_lossage ("invalid use of '%%%c'", letter);
|
|||
|
|
- break;
|
|||
|
|
-
|
|||
|
|
case 'x':
|
|||
|
|
if (CONST_INT_P (op))
|
|||
|
|
fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff);
|
|||
|
|
@@ -5833,6 +5956,48 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
|
|||
|
|
fputc (',', file);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
+ case 'w':
|
|||
|
|
+ if (code == REG && LSX_REG_P (REGNO (op)))
|
|||
|
|
+ fprintf (file, "$vr%s", ®_names[REGNO (op)][2]);
|
|||
|
|
+ else
|
|||
|
|
+ output_operand_lossage ("invalid use of '%%%c'", letter);
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case 'u':
|
|||
|
|
+ if (code == REG && LASX_REG_P (REGNO (op)))
|
|||
|
|
+ fprintf (file, "$xr%s", ®_names[REGNO (op)][2]);
|
|||
|
|
+ else
|
|||
|
|
+ output_operand_lossage ("invalid use of '%%%c'", letter);
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case 'v':
|
|||
|
|
+ switch (GET_MODE (op))
|
|||
|
|
+ {
|
|||
|
|
+ case E_V16QImode:
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ fprintf (file, "b");
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8HImode:
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ fprintf (file, "h");
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4SImode:
|
|||
|
|
+ case E_V4SFmode:
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ fprintf (file, "w");
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V2DImode:
|
|||
|
|
+ case E_V2DFmode:
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ fprintf (file, "d");
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ output_operand_lossage ("invalid use of '%%%c'", letter);
|
|||
|
|
+ }
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
default:
|
|||
|
|
switch (code)
|
|||
|
|
{
|
|||
|
|
@@ -6163,13 +6328,18 @@ loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode)
|
|||
|
|
size = GET_MODE_SIZE (mode);
|
|||
|
|
mclass = GET_MODE_CLASS (mode);
|
|||
|
|
|
|||
|
|
- if (GP_REG_P (regno) && !LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ if (GP_REG_P (regno) && !LSX_SUPPORTED_MODE_P (mode)
|
|||
|
|
+ && !LASX_SUPPORTED_MODE_P (mode))
|
|||
|
|
return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD;
|
|||
|
|
|
|||
|
|
/* For LSX, allow TImode and 128-bit vector modes in all FPR. */
|
|||
|
|
if (FP_REG_P (regno) && LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
return true;
|
|||
|
|
|
|||
|
|
+ /* FIXED ME: For LASX, allow TImode and 256-bit vector modes in all FPR. */
|
|||
|
|
+ if (FP_REG_P (regno) && LASX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ return true;
|
|||
|
|
+
|
|||
|
|
if (FP_REG_P (regno))
|
|||
|
|
{
|
|||
|
|
if (mclass == MODE_FLOAT
|
|||
|
|
@@ -6222,6 +6392,9 @@ loongarch_hard_regno_nregs (unsigned int regno, machine_mode mode)
|
|||
|
|
if (LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
return 1;
|
|||
|
|
|
|||
|
|
+ if (LASX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ return 1;
|
|||
|
|
+
|
|||
|
|
return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@@ -6251,7 +6424,10 @@ loongarch_class_max_nregs (enum reg_class rclass, machine_mode mode)
|
|||
|
|
{
|
|||
|
|
if (loongarch_hard_regno_mode_ok (FP_REG_FIRST, mode))
|
|||
|
|
{
|
|||
|
|
- if (LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ /* Fixed me. */
|
|||
|
|
+ if (LASX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ size = MIN (size, UNITS_PER_LASX_REG);
|
|||
|
|
+ else if (LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
size = MIN (size, UNITS_PER_LSX_REG);
|
|||
|
|
else
|
|||
|
|
size = MIN (size, UNITS_PER_FPREG);
|
|||
|
|
@@ -6269,6 +6445,10 @@ static bool
|
|||
|
|
loongarch_can_change_mode_class (machine_mode from, machine_mode to,
|
|||
|
|
reg_class_t rclass)
|
|||
|
|
{
|
|||
|
|
+ /* Allow conversions between different LSX/LASX vector modes. */
|
|||
|
|
+ if (LASX_SUPPORTED_MODE_P (from) && LASX_SUPPORTED_MODE_P (to))
|
|||
|
|
+ return true;
|
|||
|
|
+
|
|||
|
|
/* Allow conversions between different LSX vector modes. */
|
|||
|
|
if (LSX_SUPPORTED_MODE_P (from) && LSX_SUPPORTED_MODE_P (to))
|
|||
|
|
return true;
|
|||
|
|
@@ -6292,7 +6472,8 @@ loongarch_mode_ok_for_mov_fmt_p (machine_mode mode)
|
|||
|
|
return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
- return LSX_SUPPORTED_MODE_P (mode);
|
|||
|
|
+ return ISA_HAS_LASX ? LASX_SUPPORTED_MODE_P (mode)
|
|||
|
|
+ : LSX_SUPPORTED_MODE_P (mode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@@ -6494,7 +6675,8 @@ loongarch_valid_pointer_mode (scalar_int_mode mode)
|
|||
|
|
static bool
|
|||
|
|
loongarch_vector_mode_supported_p (machine_mode mode)
|
|||
|
|
{
|
|||
|
|
- return LSX_SUPPORTED_MODE_P (mode);
|
|||
|
|
+ return ISA_HAS_LASX ? LASX_SUPPORTED_MODE_P (mode)
|
|||
|
|
+ : LSX_SUPPORTED_MODE_P (mode);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
|
|||
|
|
@@ -6520,19 +6702,19 @@ loongarch_preferred_simd_mode (scalar_mode mode)
|
|||
|
|
switch (mode)
|
|||
|
|
{
|
|||
|
|
case E_QImode:
|
|||
|
|
- return E_V16QImode;
|
|||
|
|
+ return ISA_HAS_LASX ? E_V32QImode : E_V16QImode;
|
|||
|
|
case E_HImode:
|
|||
|
|
- return E_V8HImode;
|
|||
|
|
+ return ISA_HAS_LASX ? E_V16HImode : E_V8HImode;
|
|||
|
|
case E_SImode:
|
|||
|
|
- return E_V4SImode;
|
|||
|
|
+ return ISA_HAS_LASX ? E_V8SImode : E_V4SImode;
|
|||
|
|
case E_DImode:
|
|||
|
|
- return E_V2DImode;
|
|||
|
|
+ return ISA_HAS_LASX ? E_V4DImode : E_V2DImode;
|
|||
|
|
|
|||
|
|
case E_SFmode:
|
|||
|
|
- return E_V4SFmode;
|
|||
|
|
+ return ISA_HAS_LASX ? E_V8SFmode : E_V4SFmode;
|
|||
|
|
|
|||
|
|
case E_DFmode:
|
|||
|
|
- return E_V2DFmode;
|
|||
|
|
+ return ISA_HAS_LASX ? E_V4DFmode : E_V2DFmode;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
@@ -6543,7 +6725,12 @@ loongarch_preferred_simd_mode (scalar_mode mode)
|
|||
|
|
static unsigned int
|
|||
|
|
loongarch_autovectorize_vector_modes (vector_modes *modes, bool)
|
|||
|
|
{
|
|||
|
|
- if (ISA_HAS_LSX)
|
|||
|
|
+ if (ISA_HAS_LASX)
|
|||
|
|
+ {
|
|||
|
|
+ modes->safe_push (V32QImode);
|
|||
|
|
+ modes->safe_push (V16QImode);
|
|||
|
|
+ }
|
|||
|
|
+ else if (ISA_HAS_LSX)
|
|||
|
|
{
|
|||
|
|
modes->safe_push (V16QImode);
|
|||
|
|
}
|
|||
|
|
@@ -6723,11 +6910,18 @@ const char *
|
|||
|
|
loongarch_lsx_output_division (const char *division, rtx *operands)
|
|||
|
|
{
|
|||
|
|
const char *s;
|
|||
|
|
+ machine_mode mode = GET_MODE (*operands);
|
|||
|
|
|
|||
|
|
s = division;
|
|||
|
|
if (TARGET_CHECK_ZERO_DIV)
|
|||
|
|
{
|
|||
|
|
- if (ISA_HAS_LSX)
|
|||
|
|
+ if (ISA_HAS_LASX && GET_MODE_SIZE (mode) == 32)
|
|||
|
|
+ {
|
|||
|
|
+ output_asm_insn ("xvsetallnez.%v0\t$fcc7,%u2",operands);
|
|||
|
|
+ output_asm_insn (s, operands);
|
|||
|
|
+ output_asm_insn ("bcnez\t$fcc7,1f", operands);
|
|||
|
|
+ }
|
|||
|
|
+ else if (ISA_HAS_LSX)
|
|||
|
|
{
|
|||
|
|
output_asm_insn ("vsetallnez.%v0\t$fcc7,%w2",operands);
|
|||
|
|
output_asm_insn (s, operands);
|
|||
|
|
@@ -7566,7 +7760,7 @@ loongarch_expand_lsx_shuffle (struct expand_vec_perm_d *d)
|
|||
|
|
rtx_insn *insn;
|
|||
|
|
unsigned i;
|
|||
|
|
|
|||
|
|
- if (!ISA_HAS_LSX)
|
|||
|
|
+ if (!ISA_HAS_LSX && !ISA_HAS_LASX)
|
|||
|
|
return false;
|
|||
|
|
|
|||
|
|
for (i = 0; i < d->nelt; i++)
|
|||
|
|
@@ -7590,40 +7784,484 @@ loongarch_expand_lsx_shuffle (struct expand_vec_perm_d *d)
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
-void
|
|||
|
|
-loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel)
|
|||
|
|
+/* Try to simplify a two vector permutation using 2 intra-lane interleave
|
|||
|
|
+ insns and cross-lane shuffle for 32-byte vectors. */
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_expand_vec_perm_interleave (struct expand_vec_perm_d *d)
|
|||
|
|
{
|
|||
|
|
- machine_mode vmode = GET_MODE (target);
|
|||
|
|
+ unsigned i, nelt;
|
|||
|
|
+ rtx t1,t2,t3;
|
|||
|
|
+ rtx (*gen_high) (rtx, rtx, rtx);
|
|||
|
|
+ rtx (*gen_low) (rtx, rtx, rtx);
|
|||
|
|
+ machine_mode mode = GET_MODE (d->target);
|
|||
|
|
|
|||
|
|
- switch (vmode)
|
|||
|
|
+ if (d->one_vector_p)
|
|||
|
|
+ return false;
|
|||
|
|
+ if (ISA_HAS_LASX && GET_MODE_SIZE (d->vmode) == 32)
|
|||
|
|
+ ;
|
|||
|
|
+ else
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ nelt = d->nelt;
|
|||
|
|
+ if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
|
|||
|
|
+ return false;
|
|||
|
|
+ for (i = 0; i < nelt; i += 2)
|
|||
|
|
+ if (d->perm[i] != d->perm[0] + i / 2
|
|||
|
|
+ || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ if (d->testing_p)
|
|||
|
|
+ return true;
|
|||
|
|
+
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
{
|
|||
|
|
- case E_V16QImode:
|
|||
|
|
- emit_insn (gen_lsx_vshuf_b (target, op1, op0, sel));
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ gen_high = gen_lasx_xvilvh_b;
|
|||
|
|
+ gen_low = gen_lasx_xvilvl_b;
|
|||
|
|
break;
|
|||
|
|
- case E_V2DFmode:
|
|||
|
|
- emit_insn (gen_lsx_vshuf_d_f (target, sel, op1, op0));
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ gen_high = gen_lasx_xvilvh_h;
|
|||
|
|
+ gen_low = gen_lasx_xvilvl_h;
|
|||
|
|
break;
|
|||
|
|
- case E_V2DImode:
|
|||
|
|
- emit_insn (gen_lsx_vshuf_d (target, sel, op1, op0));
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ gen_high = gen_lasx_xvilvh_w;
|
|||
|
|
+ gen_low = gen_lasx_xvilvl_w;
|
|||
|
|
break;
|
|||
|
|
- case E_V4SFmode:
|
|||
|
|
- emit_insn (gen_lsx_vshuf_w_f (target, sel, op1, op0));
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ gen_high = gen_lasx_xvilvh_d;
|
|||
|
|
+ gen_low = gen_lasx_xvilvl_d;
|
|||
|
|
break;
|
|||
|
|
- case E_V4SImode:
|
|||
|
|
- emit_insn (gen_lsx_vshuf_w (target, sel, op1, op0));
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ gen_high = gen_lasx_xvilvh_w_f;
|
|||
|
|
+ gen_low = gen_lasx_xvilvl_w_f;
|
|||
|
|
break;
|
|||
|
|
- case E_V8HImode:
|
|||
|
|
- emit_insn (gen_lsx_vshuf_h (target, sel, op1, op0));
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ gen_high = gen_lasx_xvilvh_d_f;
|
|||
|
|
+ gen_low = gen_lasx_xvilvl_d_f;
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
- break;
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ t1 = gen_reg_rtx (mode);
|
|||
|
|
+ t2 = gen_reg_rtx (mode);
|
|||
|
|
+ emit_insn (gen_high (t1, d->op0, d->op1));
|
|||
|
|
+ emit_insn (gen_low (t2, d->op0, d->op1));
|
|||
|
|
+ if (mode == V4DFmode || mode == V8SFmode)
|
|||
|
|
+ {
|
|||
|
|
+ t3 = gen_reg_rtx (V4DFmode);
|
|||
|
|
+ if (d->perm[0])
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4df (t3, gen_lowpart (V4DFmode, t1),
|
|||
|
|
+ gen_lowpart (V4DFmode, t2),
|
|||
|
|
+ GEN_INT (0x31)));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4df (t3, gen_lowpart (V4DFmode, t1),
|
|||
|
|
+ gen_lowpart (V4DFmode, t2),
|
|||
|
|
+ GEN_INT (0x20)));
|
|||
|
|
}
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ t3 = gen_reg_rtx (V4DImode);
|
|||
|
|
+ if (d->perm[0])
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (t3, gen_lowpart (V4DImode, t1),
|
|||
|
|
+ gen_lowpart (V4DImode, t2),
|
|||
|
|
+ GEN_INT (0x31)));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (t3, gen_lowpart (V4DImode, t1),
|
|||
|
|
+ gen_lowpart (V4DImode, t2),
|
|||
|
|
+ GEN_INT (0x20)));
|
|||
|
|
+ }
|
|||
|
|
+ emit_move_insn (d->target, gen_lowpart (mode, t3));
|
|||
|
|
+ return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+/* Implement extract-even and extract-odd permutations. */
|
|||
|
|
+
|
|||
|
|
static bool
|
|||
|
|
-loongarch_try_expand_lsx_vshuf_const (struct expand_vec_perm_d *d)
|
|||
|
|
+loongarch_expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
|
|||
|
|
{
|
|||
|
|
- int i;
|
|||
|
|
+ rtx t1;
|
|||
|
|
+ machine_mode mode = GET_MODE (d->target);
|
|||
|
|
+
|
|||
|
|
+ if (d->testing_p)
|
|||
|
|
+ return true;
|
|||
|
|
+
|
|||
|
|
+ t1 = gen_reg_rtx (mode);
|
|||
|
|
+
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ /* Shuffle the lanes around into { 0 4 2 6 } and { 1 5 3 7 }. */
|
|||
|
|
+ if (odd)
|
|||
|
|
+ emit_insn (gen_lasx_xvilvh_d_f (t1, d->op0, d->op1));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvilvl_d_f (t1, d->op0, d->op1));
|
|||
|
|
+
|
|||
|
|
+ /* Shuffle within the 256-bit lanes to produce the result required.
|
|||
|
|
+ { 0 2 4 6 } | { 1 3 5 7 }. */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v4df (d->target, t1, GEN_INT (0xd8)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ if (odd)
|
|||
|
|
+ emit_insn (gen_lasx_xvilvh_d (t1, d->op0, d->op1));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvilvl_d (t1, d->op0, d->op1));
|
|||
|
|
+
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v4di (d->target, t1, GEN_INT (0xd8)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ /* Shuffle the lanes around into:
|
|||
|
|
+ { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */
|
|||
|
|
+ if (odd)
|
|||
|
|
+ emit_insn (gen_lasx_xvpickod_w_f (t1, d->op0, d->op1));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvpickev_w_f (t1, d->op0, d->op1));
|
|||
|
|
+
|
|||
|
|
+ /* Shuffle within the 256-bit lanes to produce the result required.
|
|||
|
|
+ { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v8sf (d->target, t1, GEN_INT (0xd8)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ if (odd)
|
|||
|
|
+ emit_insn (gen_lasx_xvpickod_w (t1, d->op0, d->op1));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvpickev_w (t1, d->op0, d->op1));
|
|||
|
|
+
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v8si (d->target, t1, GEN_INT (0xd8)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ if (odd)
|
|||
|
|
+ emit_insn (gen_lasx_xvpickod_h (t1, d->op0, d->op1));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvpickev_h (t1, d->op0, d->op1));
|
|||
|
|
+
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (d->target, t1, GEN_INT (0xd8)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ if (odd)
|
|||
|
|
+ emit_insn (gen_lasx_xvpickod_b (t1, d->op0, d->op1));
|
|||
|
|
+ else
|
|||
|
|
+ emit_insn (gen_lasx_xvpickev_b (t1, d->op0, d->op1));
|
|||
|
|
+
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (d->target, t1, GEN_INT (0xd8)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return true;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+/* Pattern match extract-even and extract-odd permutations. */
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ unsigned i, odd, nelt = d->nelt;
|
|||
|
|
+ if (!ISA_HAS_LASX)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ odd = d->perm[0];
|
|||
|
|
+ if (odd != 0 && odd != 1)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ for (i = 1; i < nelt; ++i)
|
|||
|
|
+ if (d->perm[i] != 2 * i + odd)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ return loongarch_expand_vec_perm_even_odd_1 (d, odd);
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+/* Expand a variable vector permutation for LASX. */
|
|||
|
|
+
|
|||
|
|
+void
|
|||
|
|
+loongarch_expand_vec_perm_1 (rtx operands[])
|
|||
|
|
+{
|
|||
|
|
+ rtx target = operands[0];
|
|||
|
|
+ rtx op0 = operands[1];
|
|||
|
|
+ rtx op1 = operands[2];
|
|||
|
|
+ rtx mask = operands[3];
|
|||
|
|
+
|
|||
|
|
+ bool one_operand_shuffle = rtx_equal_p (op0, op1);
|
|||
|
|
+ rtx t1 = NULL;
|
|||
|
|
+ rtx t2 = NULL;
|
|||
|
|
+ rtx t3, t4, t5, t6, vt = NULL;
|
|||
|
|
+ rtx vec[32] = {NULL};
|
|||
|
|
+ machine_mode mode = GET_MODE (op0);
|
|||
|
|
+ machine_mode maskmode = GET_MODE (mask);
|
|||
|
|
+ int w, i;
|
|||
|
|
+
|
|||
|
|
+ /* Number of elements in the vector. */
|
|||
|
|
+ w = GET_MODE_NUNITS (mode);
|
|||
|
|
+
|
|||
|
|
+ rtx round_data[MAX_VECT_LEN];
|
|||
|
|
+ rtx round_reg, round_data_rtx;
|
|||
|
|
+
|
|||
|
|
+ if (mode != E_V32QImode)
|
|||
|
|
+ {
|
|||
|
|
+ for (int i = 0; i < w; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ round_data[i] = GEN_INT (0x1f);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (mode == E_V4DFmode)
|
|||
|
|
+ {
|
|||
|
|
+ round_data_rtx = gen_rtx_CONST_VECTOR (E_V4DImode,
|
|||
|
|
+ gen_rtvec_v (w, round_data));
|
|||
|
|
+ round_reg = gen_reg_rtx (E_V4DImode);
|
|||
|
|
+ }
|
|||
|
|
+ else if (mode == E_V8SFmode)
|
|||
|
|
+ {
|
|||
|
|
+
|
|||
|
|
+ round_data_rtx = gen_rtx_CONST_VECTOR (E_V8SImode,
|
|||
|
|
+ gen_rtvec_v (w, round_data));
|
|||
|
|
+ round_reg = gen_reg_rtx (E_V8SImode);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ round_data_rtx = gen_rtx_CONST_VECTOR (mode,
|
|||
|
|
+ gen_rtvec_v (w, round_data));
|
|||
|
|
+ round_reg = gen_reg_rtx (mode);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ emit_move_insn (round_reg, round_data_rtx);
|
|||
|
|
+ switch (mode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ emit_insn (gen_andv32qi3 (mask, mask, round_reg));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ emit_insn (gen_andv16hi3 (mask, mask, round_reg));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ emit_insn (gen_andv8si3 (mask, mask, round_reg));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ emit_insn (gen_andv4di3 (mask, mask, round_reg));
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (mode == V4DImode || mode == V4DFmode)
|
|||
|
|
+ {
|
|||
|
|
+ maskmode = mode = V8SImode;
|
|||
|
|
+ w = 8;
|
|||
|
|
+ t1 = gen_reg_rtx (maskmode);
|
|||
|
|
+
|
|||
|
|
+ /* Replicate the low bits of the V4DImode mask into V8SImode:
|
|||
|
|
+ mask = { A B C D }
|
|||
|
|
+ t1 = { A A B B C C D D }. */
|
|||
|
|
+ for (i = 0; i < w / 2; ++i)
|
|||
|
|
+ vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
|
|||
|
|
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
|
|||
|
|
+ vt = force_reg (maskmode, vt);
|
|||
|
|
+ mask = gen_lowpart (maskmode, mask);
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w (t1, mask, vt));
|
|||
|
|
+
|
|||
|
|
+ /* Multiply the shuffle indicies by two. */
|
|||
|
|
+ t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
|
|||
|
|
+ OPTAB_DIRECT);
|
|||
|
|
+
|
|||
|
|
+ /* Add one to the odd shuffle indicies:
|
|||
|
|
+ t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
|
|||
|
|
+ for (i = 0; i < w / 2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ vec[i * 2] = const0_rtx;
|
|||
|
|
+ vec[i * 2 + 1] = const1_rtx;
|
|||
|
|
+ }
|
|||
|
|
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
|
|||
|
|
+ vt = validize_mem (force_const_mem (maskmode, vt));
|
|||
|
|
+ t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
|
|||
|
|
+ OPTAB_DIRECT);
|
|||
|
|
+
|
|||
|
|
+ /* Continue as if V8SImode (resp. V32QImode) was used initially. */
|
|||
|
|
+ operands[3] = mask = t1;
|
|||
|
|
+ target = gen_reg_rtx (mode);
|
|||
|
|
+ op0 = gen_lowpart (mode, op0);
|
|||
|
|
+ op1 = gen_lowpart (mode, op1);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ switch (mode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ if (one_operand_shuffle)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w (target, op0, mask));
|
|||
|
|
+ if (target != operands[0])
|
|||
|
|
+ emit_move_insn (operands[0],
|
|||
|
|
+ gen_lowpart (GET_MODE (operands[0]), target));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ t1 = gen_reg_rtx (V8SImode);
|
|||
|
|
+ t2 = gen_reg_rtx (V8SImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w (t1, op0, mask));
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w (t2, op1, mask));
|
|||
|
|
+ goto merge_two;
|
|||
|
|
+ }
|
|||
|
|
+ return;
|
|||
|
|
+
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ mask = gen_lowpart (V8SImode, mask);
|
|||
|
|
+ if (one_operand_shuffle)
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w_f (target, op0, mask));
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ t1 = gen_reg_rtx (V8SFmode);
|
|||
|
|
+ t2 = gen_reg_rtx (V8SFmode);
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w_f (t1, op0, mask));
|
|||
|
|
+ emit_insn (gen_lasx_xvperm_w_f (t2, op1, mask));
|
|||
|
|
+ goto merge_two;
|
|||
|
|
+ }
|
|||
|
|
+ return;
|
|||
|
|
+
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ if (one_operand_shuffle)
|
|||
|
|
+ {
|
|||
|
|
+ t1 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ t2 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (t1, op0, GEN_INT (0x44)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (t2, op0, GEN_INT (0xee)));
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_h (target, mask, t2, t1));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ t1 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ t2 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ t3 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ t4 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ t5 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ t6 = gen_reg_rtx (V16HImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (t3, op0, GEN_INT (0x44)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (t4, op0, GEN_INT (0xee)));
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_h (t1, mask, t4, t3));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (t5, op1, GEN_INT (0x44)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (t6, op1, GEN_INT (0xee)));
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_h (t2, mask, t6, t5));
|
|||
|
|
+ goto merge_two;
|
|||
|
|
+ }
|
|||
|
|
+ return;
|
|||
|
|
+
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ if (one_operand_shuffle)
|
|||
|
|
+ {
|
|||
|
|
+ t1 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ t2 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (t1, op0, GEN_INT (0x44)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (t2, op0, GEN_INT (0xee)));
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_b (target, t2, t1, mask));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ t1 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ t2 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ t3 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ t4 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ t5 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ t6 = gen_reg_rtx (V32QImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (t3, op0, GEN_INT (0x44)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (t4, op0, GEN_INT (0xee)));
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_b (t1, t4, t3, mask));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (t5, op1, GEN_INT (0x44)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (t6, op1, GEN_INT (0xee)));
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_b (t2, t6, t5, mask));
|
|||
|
|
+ goto merge_two;
|
|||
|
|
+ }
|
|||
|
|
+ return;
|
|||
|
|
+
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_assert (GET_MODE_SIZE (mode) == 32);
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+merge_two:
|
|||
|
|
+ /* Then merge them together. The key is whether any given control
|
|||
|
|
+ element contained a bit set that indicates the second word. */
|
|||
|
|
+ rtx xops[6];
|
|||
|
|
+ mask = operands[3];
|
|||
|
|
+ vt = GEN_INT (w);
|
|||
|
|
+ vt = gen_const_vec_duplicate (maskmode, vt);
|
|||
|
|
+ vt = force_reg (maskmode, vt);
|
|||
|
|
+ mask = expand_simple_binop (maskmode, AND, mask, vt,
|
|||
|
|
+ NULL_RTX, 0, OPTAB_DIRECT);
|
|||
|
|
+ if (GET_MODE (target) != mode)
|
|||
|
|
+ target = gen_reg_rtx (mode);
|
|||
|
|
+ xops[0] = target;
|
|||
|
|
+ xops[1] = gen_lowpart (mode, t2);
|
|||
|
|
+ xops[2] = gen_lowpart (mode, t1);
|
|||
|
|
+ xops[3] = gen_rtx_EQ (maskmode, mask, vt);
|
|||
|
|
+ xops[4] = mask;
|
|||
|
|
+ xops[5] = vt;
|
|||
|
|
+
|
|||
|
|
+ loongarch_expand_vec_cond_expr (mode, maskmode, xops);
|
|||
|
|
+ if (target != operands[0])
|
|||
|
|
+ emit_move_insn (operands[0],
|
|||
|
|
+ gen_lowpart (GET_MODE (operands[0]), target));
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+void
|
|||
|
|
+loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel)
|
|||
|
|
+{
|
|||
|
|
+ machine_mode vmode = GET_MODE (target);
|
|||
|
|
+ auto nelt = GET_MODE_NUNITS (vmode);
|
|||
|
|
+ auto round_reg = gen_reg_rtx (vmode);
|
|||
|
|
+ rtx round_data[MAX_VECT_LEN];
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ round_data[i] = GEN_INT (0x1f);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ rtx round_data_rtx = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, round_data));
|
|||
|
|
+ emit_move_insn (round_reg, round_data_rtx);
|
|||
|
|
+
|
|||
|
|
+ switch (vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V16QImode:
|
|||
|
|
+ emit_insn (gen_andv16qi3 (sel, sel, round_reg));
|
|||
|
|
+ emit_insn (gen_lsx_vshuf_b (target, op1, op0, sel));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V2DFmode:
|
|||
|
|
+ emit_insn (gen_andv2di3 (sel, sel, round_reg));
|
|||
|
|
+ emit_insn (gen_lsx_vshuf_d_f (target, sel, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V2DImode:
|
|||
|
|
+ emit_insn (gen_andv2di3 (sel, sel, round_reg));
|
|||
|
|
+ emit_insn (gen_lsx_vshuf_d (target, sel, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4SFmode:
|
|||
|
|
+ emit_insn (gen_andv4si3 (sel, sel, round_reg));
|
|||
|
|
+ emit_insn (gen_lsx_vshuf_w_f (target, sel, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4SImode:
|
|||
|
|
+ emit_insn (gen_andv4si3 (sel, sel, round_reg));
|
|||
|
|
+ emit_insn (gen_lsx_vshuf_w (target, sel, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8HImode:
|
|||
|
|
+ emit_insn (gen_andv8hi3 (sel, sel, round_reg));
|
|||
|
|
+ emit_insn (gen_lsx_vshuf_h (target, sel, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_try_expand_lsx_vshuf_const (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ int i;
|
|||
|
|
rtx target, op0, op1, sel, tmp;
|
|||
|
|
rtx rperm[MAX_VECT_LEN];
|
|||
|
|
|
|||
|
|
@@ -7724,25 +8362,1302 @@ loongarch_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
- if (loongarch_expand_lsx_shuffle (d))
|
|||
|
|
- return true;
|
|||
|
|
- return false;
|
|||
|
|
-}
|
|||
|
|
-
|
|||
|
|
-/* Implementation of constant vector permuatation. This function identifies
|
|||
|
|
- * recognized pattern of permuation selector argument, and use one or more
|
|||
|
|
- * instruction(s) to finish the permutation job correctly. For unsupported
|
|||
|
|
- * patterns, it will return false. */
|
|||
|
|
-
|
|||
|
|
-static bool
|
|||
|
|
-loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
|||
|
|
-{
|
|||
|
|
- /* Although we have the LSX vec_perm<mode> template, there's still some
|
|||
|
|
- 128bit vector permuatation operations send to vectorize_vec_perm_const.
|
|||
|
|
- In this case, we just simpliy wrap them by single vshuf.* instruction,
|
|||
|
|
- because LSX vshuf.* instruction just have the same behavior that GCC
|
|||
|
|
- expects. */
|
|||
|
|
- return loongarch_try_expand_lsx_vshuf_const (d);
|
|||
|
|
+ if (loongarch_expand_lsx_shuffle (d))
|
|||
|
|
+ return true;
|
|||
|
|
+ if (loongarch_expand_vec_perm_even_odd (d))
|
|||
|
|
+ return true;
|
|||
|
|
+ if (loongarch_expand_vec_perm_interleave (d))
|
|||
|
|
+ return true;
|
|||
|
|
+ return false;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+/* Following are the assist function for const vector permutation support. */
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_quad_duplicate (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (d->perm[0] >= d->nelt / 2)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char lhs = d->perm[0];
|
|||
|
|
+ unsigned char rhs = d->perm[d->nelt / 2];
|
|||
|
|
+
|
|||
|
|
+ if ((rhs - lhs) != d->nelt / 2)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 1; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if ((i < d->nelt / 2) && (d->perm[i] != lhs))
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ if ((i > d->nelt / 2) && (d->perm[i] != rhs))
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_double_duplicate (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (!d->one_vector_p)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ if (d->nelt < 8)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = d->perm[0];
|
|||
|
|
+
|
|||
|
|
+ for (int i = 1; i < d->nelt; i += 2)
|
|||
|
|
+ {
|
|||
|
|
+ if (d->perm[i] != buf)
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ if (d->perm[i - 1] != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += d->nelt / 4;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_odd_extraction (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 1;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 2;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_even_extraction (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 0;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_extraction_permutation (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = d->perm[0];
|
|||
|
|
+
|
|||
|
|
+ if (buf != 0 || buf != d->nelt)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 2;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_center_extraction (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned buf = d->nelt / 2;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_reversing_permutation (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (!d->one_vector_p)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = d->nelt - 1;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (d->perm[i] != buf)
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ buf -= 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_di_misalign_extract (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (d->nelt != 4 && d->nelt != 8)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf;
|
|||
|
|
+
|
|||
|
|
+ if (d->nelt == 4)
|
|||
|
|
+ {
|
|||
|
|
+ buf = 1;
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (d->nelt == 8)
|
|||
|
|
+ {
|
|||
|
|
+ buf = 2;
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_si_misalign_extract (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (d->vmode != E_V8SImode && d->vmode != E_V8SFmode)
|
|||
|
|
+ return false;
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 1;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_lasx_lowpart_interleave (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 0;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0;i < d->nelt; i += 2)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (result)
|
|||
|
|
+ {
|
|||
|
|
+ buf = d->nelt;
|
|||
|
|
+ for (int i = 1; i < d->nelt; i += 2)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_lasx_lowpart_interleave_2 (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (d->vmode != E_V32QImode)
|
|||
|
|
+ return false;
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 0;
|
|||
|
|
+
|
|||
|
|
+#define COMPARE_SELECTOR(INIT, BEGIN, END) \
|
|||
|
|
+ buf = INIT; \
|
|||
|
|
+ for (int i = BEGIN; i < END && result; i += 1) \
|
|||
|
|
+ { \
|
|||
|
|
+ if (buf != d->perm[i]) \
|
|||
|
|
+ { \
|
|||
|
|
+ result = false; \
|
|||
|
|
+ break; \
|
|||
|
|
+ } \
|
|||
|
|
+ buf += 1; \
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ COMPARE_SELECTOR (0, 0, 8);
|
|||
|
|
+ COMPARE_SELECTOR (32, 8, 16);
|
|||
|
|
+ COMPARE_SELECTOR (8, 16, 24);
|
|||
|
|
+ COMPARE_SELECTOR (40, 24, 32);
|
|||
|
|
+
|
|||
|
|
+#undef COMPARE_SELECTOR
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_lasx_lowpart_extract (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 0;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (result)
|
|||
|
|
+ {
|
|||
|
|
+ buf = d->nelt;
|
|||
|
|
+ for (int i = d->nelt / 2; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_lasx_highpart_interleave (expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = d->nelt / 2;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 2)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (result)
|
|||
|
|
+ {
|
|||
|
|
+ buf = d->nelt + d->nelt / 2;
|
|||
|
|
+ for (int i = 1; i < d->nelt;i += 2)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ buf += 1;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_lasx_highpart_interleave_2 (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ if (d->vmode != E_V32QImode)
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = 0;
|
|||
|
|
+
|
|||
|
|
+#define COMPARE_SELECTOR(INIT, BEGIN, END) \
|
|||
|
|
+ buf = INIT; \
|
|||
|
|
+ for (int i = BEGIN; i < END && result; i += 1) \
|
|||
|
|
+ { \
|
|||
|
|
+ if (buf != d->perm[i]) \
|
|||
|
|
+ { \
|
|||
|
|
+ result = false; \
|
|||
|
|
+ break; \
|
|||
|
|
+ } \
|
|||
|
|
+ buf += 1; \
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ COMPARE_SELECTOR (16, 0, 8);
|
|||
|
|
+ COMPARE_SELECTOR (48, 8, 16);
|
|||
|
|
+ COMPARE_SELECTOR (24, 16, 24);
|
|||
|
|
+ COMPARE_SELECTOR (56, 24, 32);
|
|||
|
|
+
|
|||
|
|
+#undef COMPARE_SELECTOR
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_elem_duplicate (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+ unsigned char buf = d->perm[0];
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (buf != d->perm[i])
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+inline bool
|
|||
|
|
+loongarch_is_op_reverse_perm (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ return (d->vmode == E_V4DFmode)
|
|||
|
|
+ && d->perm[0] == 2 && d->perm[1] == 3
|
|||
|
|
+ && d->perm[2] == 0 && d->perm[3] == 1;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_single_op_perm (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (d->perm[i] >= d->nelt)
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_is_divisible_perm (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ bool result = true;
|
|||
|
|
+
|
|||
|
|
+ for (int i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (d->perm[i] >= d->nelt)
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (result)
|
|||
|
|
+ {
|
|||
|
|
+ for (int i = d->nelt / 2; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ if (d->perm[i] < d->nelt)
|
|||
|
|
+ {
|
|||
|
|
+ result = false;
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ return result;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+inline bool
|
|||
|
|
+loongarch_is_triple_stride_extract (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ return (d->vmode == E_V4DImode || d->vmode == E_V4DFmode)
|
|||
|
|
+ && d->perm[0] == 1 && d->perm[1] == 4
|
|||
|
|
+ && d->perm[2] == 7 && d->perm[3] == 0;
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
+/* In LASX, some permutation insn does not have the behavior that gcc expects
|
|||
|
|
+ * when compiler wants to emit a vector permutation.
|
|||
|
|
+ *
|
|||
|
|
+ * 1. What GCC provides via vectorize_vec_perm_const ()'s paramater:
|
|||
|
|
+ * When GCC wants to performs a vector permutation, it provides two op
|
|||
|
|
+ * reigster, one target register, and a selector.
|
|||
|
|
+ * In const vector permutation case, GCC provides selector as a char array
|
|||
|
|
+ * that contains original value; in variable vector permuatation
|
|||
|
|
+ * (performs via vec_perm<mode> insn template), it provides a vector register.
|
|||
|
|
+ * We assume that nelt is the elements numbers inside single vector in current
|
|||
|
|
+ * 256bit vector mode.
|
|||
|
|
+ *
|
|||
|
|
+ * 2. What GCC expects to perform:
|
|||
|
|
+ * Two op registers (op0, op1) will "combine" into a 512bit temp vector storage
|
|||
|
|
+ * that has 2*nelt elements inside it; the low 256bit is op0, and high 256bit
|
|||
|
|
+ * is op1, then the elements are indexed as below:
|
|||
|
|
+ * 0 ~ nelt - 1 nelt ~ 2 * nelt - 1
|
|||
|
|
+ * |-------------------------|-------------------------|
|
|||
|
|
+ * Low 256bit (op0) High 256bit (op1)
|
|||
|
|
+ * For example, the second element in op1 (V8SImode) will be indexed with 9.
|
|||
|
|
+ * Selector is a vector that has the same mode and number of elements with
|
|||
|
|
+ * op0,op1 and target, it's look like this:
|
|||
|
|
+ * 0 ~ nelt - 1
|
|||
|
|
+ * |-------------------------|
|
|||
|
|
+ * 256bit (selector)
|
|||
|
|
+ * It describes which element from 512bit temp vector storage will fit into
|
|||
|
|
+ * target's every element slot.
|
|||
|
|
+ * GCC expects that every element in selector can be ANY indices of 512bit
|
|||
|
|
+ * vector storage (Selector can pick literally any element from op0 and op1, and
|
|||
|
|
+ * then fits into any place of target register). This is also what LSX 128bit
|
|||
|
|
+ * vshuf.* instruction do similarly, so we can handle 128bit vector permutation
|
|||
|
|
+ * by single instruction easily.
|
|||
|
|
+ *
|
|||
|
|
+ * 3. What LASX permutation instruction does:
|
|||
|
|
+ * In short, it just execute two independent 128bit vector permuatation, and
|
|||
|
|
+ * it's the reason that we need to do the jobs below. We will explain it.
|
|||
|
|
+ * op0, op1, target, and selector will be separate into high 128bit and low
|
|||
|
|
+ * 128bit, and do permutation as the description below:
|
|||
|
|
+ *
|
|||
|
|
+ * a) op0's low 128bit and op1's low 128bit "combines" into a 256bit temp
|
|||
|
|
+ * vector storage (TVS1), elements are indexed as below:
|
|||
|
|
+ * 0 ~ nelt / 2 - 1 nelt / 2 ~ nelt - 1
|
|||
|
|
+ * |---------------------|---------------------| TVS1
|
|||
|
|
+ * op0's low 128bit op1's low 128bit
|
|||
|
|
+ * op0's high 128bit and op1's high 128bit are "combined" into TVS2 in the
|
|||
|
|
+ * same way.
|
|||
|
|
+ * 0 ~ nelt / 2 - 1 nelt / 2 ~ nelt - 1
|
|||
|
|
+ * |---------------------|---------------------| TVS2
|
|||
|
|
+ * op0's high 128bit op1's high 128bit
|
|||
|
|
+ * b) Selector's low 128bit describes which elements from TVS1 will fit into
|
|||
|
|
+ * target vector's low 128bit. No TVS2 elements are allowed.
|
|||
|
|
+ * c) Selector's high 128bit describes which elements from TVS2 will fit into
|
|||
|
|
+ * target vector's high 128bit. No TVS1 elements are allowed.
|
|||
|
|
+ *
|
|||
|
|
+ * As we can see, if we want to handle vector permutation correctly, we can
|
|||
|
|
+ * achieve it in three ways:
|
|||
|
|
+ * a) Modify selector's elements, to make sure that every elements can inform
|
|||
|
|
+ * correct value that will put into target vector.
|
|||
|
|
+ b) Generate extra instruction before/after permutation instruction, for
|
|||
|
|
+ adjusting op vector or target vector, to make sure target vector's value is
|
|||
|
|
+ what GCC expects.
|
|||
|
|
+ c) Use other instructions to process op and put correct result into target.
|
|||
|
|
+ */
|
|||
|
|
+
|
|||
|
|
+/* Implementation of constant vector permuatation. This function identifies
|
|||
|
|
+ * recognized pattern of permuation selector argument, and use one or more
|
|||
|
|
+ * instruction(s) to finish the permutation job correctly. For unsupported
|
|||
|
|
+ * patterns, it will return false. */
|
|||
|
|
+
|
|||
|
|
+static bool
|
|||
|
|
+loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
|||
|
|
+{
|
|||
|
|
+ /* Although we have the LSX vec_perm<mode> template, there's still some
|
|||
|
|
+ 128bit vector permuatation operations send to vectorize_vec_perm_const.
|
|||
|
|
+ In this case, we just simpliy wrap them by single vshuf.* instruction,
|
|||
|
|
+ because LSX vshuf.* instruction just have the same behavior that GCC
|
|||
|
|
+ expects. */
|
|||
|
|
+ if (GET_MODE_SIZE (d->vmode) == 16)
|
|||
|
|
+ return loongarch_try_expand_lsx_vshuf_const (d);
|
|||
|
|
+ else
|
|||
|
|
+ return false;
|
|||
|
|
+
|
|||
|
|
+ bool ok = false, reverse_hi_lo = false, extract_ev_od = false,
|
|||
|
|
+ use_alt_op = false;
|
|||
|
|
+ unsigned char idx;
|
|||
|
|
+ int i;
|
|||
|
|
+ rtx target, op0, op1, sel, tmp;
|
|||
|
|
+ rtx op0_alt = NULL_RTX, op1_alt = NULL_RTX;
|
|||
|
|
+ rtx rperm[MAX_VECT_LEN];
|
|||
|
|
+ unsigned int remapped[MAX_VECT_LEN];
|
|||
|
|
+
|
|||
|
|
+ /* Try to figure out whether is a recognized permutation selector pattern, if
|
|||
|
|
+ yes, we will reassign some elements with new value in selector argument,
|
|||
|
|
+ and in some cases we will generate some assist insn to complete the
|
|||
|
|
+ permutation. (Even in some cases, we use other insn to impl permutation
|
|||
|
|
+ instead of xvshuf!)
|
|||
|
|
+
|
|||
|
|
+ Make sure to check d->testing_p is false everytime if you want to emit new
|
|||
|
|
+ insn, unless you want to crash into ICE directly. */
|
|||
|
|
+ if (loongarch_is_quad_duplicate (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Selector example: E_V8SImode, { 0, 0, 0, 0, 4, 4, 4, 4 }
|
|||
|
|
+ copy first elem from original selector to all elem in new selector. */
|
|||
|
|
+ idx = d->perm[0];
|
|||
|
|
+ for (i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ remapped[i] = idx;
|
|||
|
|
+ }
|
|||
|
|
+ /* Selector after: { 0, 0, 0, 0, 0, 0, 0, 0 }. */
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_double_duplicate (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Selector example: E_V8SImode, { 1, 1, 3, 3, 5, 5, 7, 7 }
|
|||
|
|
+ one_vector_p == true. */
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ idx = d->perm[i];
|
|||
|
|
+ remapped[i] = idx;
|
|||
|
|
+ remapped[i + d->nelt / 2] = idx;
|
|||
|
|
+ }
|
|||
|
|
+ /* Selector after: { 1, 1, 3, 3, 1, 1, 3, 3 }. */
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_odd_extraction (d)
|
|||
|
|
+ || loongarch_is_even_extraction (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Odd extraction selector sample: E_V4DImode, { 1, 3, 5, 7 }
|
|||
|
|
+ Selector after: { 1, 3, 1, 3 }.
|
|||
|
|
+ Even extraction selector sample: E_V4DImode, { 0, 2, 4, 6 }
|
|||
|
|
+ Selector after: { 0, 2, 0, 2 }. */
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ idx = d->perm[i];
|
|||
|
|
+ remapped[i] = idx;
|
|||
|
|
+ remapped[i + d->nelt / 2] = idx;
|
|||
|
|
+ }
|
|||
|
|
+ /* Additional insn is required for correct result. See codes below. */
|
|||
|
|
+ extract_ev_od = true;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_extraction_permutation (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Selector sample: E_V8SImode, { 0, 1, 2, 3, 4, 5, 6, 7 }. */
|
|||
|
|
+ if (d->perm[0] == 0)
|
|||
|
|
+ {
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ remapped[i] = i;
|
|||
|
|
+ remapped[i + d->nelt / 2] = i;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ /* { 8, 9, 10, 11, 12, 13, 14, 15 }. */
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ idx = i + d->nelt / 2;
|
|||
|
|
+ remapped[i] = idx;
|
|||
|
|
+ remapped[i + d->nelt / 2] = idx;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ /* Selector after: { 0, 1, 2, 3, 0, 1, 2, 3 }
|
|||
|
|
+ { 8, 9, 10, 11, 8, 9, 10, 11 } */
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_center_extraction (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* sample: E_V4DImode, { 2, 3, 4, 5 }
|
|||
|
|
+ In this condition, we can just copy high 128bit of op0 and low 128bit
|
|||
|
|
+ of op1 to the target register by using xvpermi.q insn. */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ emit_move_insn (d->target, d->op1);
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (d->target, d->target,
|
|||
|
|
+ d->op0, GEN_INT (0x21)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4df (d->target, d->target,
|
|||
|
|
+ d->op0, GEN_INT (0x21)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v8si (d->target, d->target,
|
|||
|
|
+ d->op0, GEN_INT (0x21)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v8sf (d->target, d->target,
|
|||
|
|
+ d->op0, GEN_INT (0x21)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v16hi (d->target, d->target,
|
|||
|
|
+ d->op0, GEN_INT (0x21)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v32qi (d->target, d->target,
|
|||
|
|
+ d->op0, GEN_INT (0x21)));
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ ok = true;
|
|||
|
|
+ /* Finish the funtion directly. */
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_reversing_permutation (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Selector sample: E_V8SImode, { 7, 6, 5, 4, 3, 2, 1, 0 }
|
|||
|
|
+ one_vector_p == true */
|
|||
|
|
+ idx = d->nelt / 2 - 1;
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ remapped[i] = idx;
|
|||
|
|
+ remapped[i + d->nelt / 2] = idx;
|
|||
|
|
+ idx -= 1;
|
|||
|
|
+ }
|
|||
|
|
+ /* Selector after: { 3, 2, 1, 0, 3, 2, 1, 0 }
|
|||
|
|
+ Additional insn will be generated to swap hi and lo 128bit of target
|
|||
|
|
+ register. */
|
|||
|
|
+ reverse_hi_lo = true;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_di_misalign_extract (d)
|
|||
|
|
+ || loongarch_is_si_misalign_extract (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Selector Sample:
|
|||
|
|
+ DI misalign: E_V4DImode, { 1, 2, 3, 4 }
|
|||
|
|
+ SI misalign: E_V8SImode, { 1, 2, 3, 4, 5, 6, 7, 8 } */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Copy original op0/op1 value to new temp register.
|
|||
|
|
+ In some cases, operand register may be used in multiple place, so
|
|||
|
|
+ we need new regiter instead modify original one, to avoid runtime
|
|||
|
|
+ crashing or wrong value after execution. */
|
|||
|
|
+ use_alt_op = true;
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+
|
|||
|
|
+ /* Adjust op1 for selecting correct value in high 128bit of target
|
|||
|
|
+ register.
|
|||
|
|
+ op1: E_V4DImode, { 4, 5, 6, 7 } -> { 2, 3, 4, 5 }. */
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
|||
|
|
+ conv_op0, GEN_INT (0x21)));
|
|||
|
|
+
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ remapped[i] = d->perm[i];
|
|||
|
|
+ remapped[i + d->nelt / 2] = d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ /* Selector after:
|
|||
|
|
+ DI misalign: { 1, 2, 1, 2 }
|
|||
|
|
+ SI misalign: { 1, 2, 3, 4, 1, 2, 3, 4 } */
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_lasx_lowpart_interleave (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Elements from op0's low 18bit and op1's 128bit are inserted into
|
|||
|
|
+ target register alternately.
|
|||
|
|
+ sample: E_V4DImode, { 0, 4, 1, 5 } */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Prepare temp register instead of modify original op. */
|
|||
|
|
+ use_alt_op = true;
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ op0_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+ emit_move_insn (op0_alt, d->op0);
|
|||
|
|
+
|
|||
|
|
+ /* Generate subreg for fitting into insn gen function. */
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
|||
|
|
+
|
|||
|
|
+ /* Adjust op value in temp register.
|
|||
|
|
+ op0 = {0,1,2,3}, op1 = {4,5,0,1} */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
|||
|
|
+ conv_op0, GEN_INT (0x02)));
|
|||
|
|
+ /* op0 = {0,1,4,5}, op1 = {4,5,0,1} */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op0, conv_op0,
|
|||
|
|
+ conv_op1, GEN_INT (0x01)));
|
|||
|
|
+
|
|||
|
|
+ /* Remap indices in selector based on the location of index inside
|
|||
|
|
+ selector, and vector element numbers in current vector mode. */
|
|||
|
|
+
|
|||
|
|
+ /* Filling low 128bit of new selector. */
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ /* value in odd-indexed slot of low 128bit part of selector
|
|||
|
|
+ vector. */
|
|||
|
|
+ remapped[i] = i % 2 != 0 ? d->perm[i] - d->nelt / 2 : d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ /* Then filling the high 128bit. */
|
|||
|
|
+ for (i = d->nelt / 2; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ /* value in even-indexed slot of high 128bit part of
|
|||
|
|
+ selector vector. */
|
|||
|
|
+ remapped[i] = i % 2 == 0
|
|||
|
|
+ ? d->perm[i] + (d->nelt / 2) * 3 : d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_lasx_lowpart_interleave_2 (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Special lowpart interleave case in V32QI vector mode. It does the same
|
|||
|
|
+ thing as we can see in if branch that above this line.
|
|||
|
|
+ Selector sample: E_V32QImode,
|
|||
|
|
+ {0, 1, 2, 3, 4, 5, 6, 7, 32, 33, 34, 35, 36, 37, 38, 39, 8,
|
|||
|
|
+ 9, 10, 11, 12, 13, 14, 15, 40, 41, 42, 43, 44, 45, 46, 47} */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Solution for this case in very simple - covert op into V4DI mode,
|
|||
|
|
+ and do same thing as previous if branch. */
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ op0_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+ emit_move_insn (op0_alt, d->op0);
|
|||
|
|
+
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
|||
|
|
+ rtx conv_target = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
|||
|
|
+
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
|||
|
|
+ conv_op0, GEN_INT (0x02)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op0, conv_op0,
|
|||
|
|
+ conv_op1, GEN_INT (0x01)));
|
|||
|
|
+ remapped[0] = 0;
|
|||
|
|
+ remapped[1] = 4;
|
|||
|
|
+ remapped[2] = 1;
|
|||
|
|
+ remapped[3] = 5;
|
|||
|
|
+
|
|||
|
|
+ for (i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ rperm[i] = GEN_INT (remapped[i]);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ sel = gen_rtx_CONST_VECTOR (E_V4DImode, gen_rtvec_v (4, rperm));
|
|||
|
|
+ sel = force_reg (E_V4DImode, sel);
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_d (conv_target, sel,
|
|||
|
|
+ conv_op1, conv_op0));
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ ok = true;
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_lasx_lowpart_extract (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Copy op0's low 128bit to target's low 128bit, and copy op1's low
|
|||
|
|
+ 128bit to target's high 128bit.
|
|||
|
|
+ Selector sample: E_V4DImode, { 0, 1, 4 ,5 } */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, d->op1, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
|||
|
|
+ rtx conv_target = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
|||
|
|
+
|
|||
|
|
+ /* We can achieve the expectation by using sinple xvpermi.q insn. */
|
|||
|
|
+ emit_move_insn (conv_target, conv_op1);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_target, conv_target,
|
|||
|
|
+ conv_op0, GEN_INT (0x20)));
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ ok = true;
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_lasx_highpart_interleave (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Similar to lowpart interleave, elements from op0's high 128bit and
|
|||
|
|
+ op1's high 128bit are inserted into target regiter alternately.
|
|||
|
|
+ Selector sample: E_V8SImode, { 4, 12, 5, 13, 6, 14, 7, 15 } */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Prepare temp op register. */
|
|||
|
|
+ use_alt_op = true;
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ op0_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+ emit_move_insn (op0_alt, d->op0);
|
|||
|
|
+
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
|||
|
|
+ /* Adjust op value in temp regiter.
|
|||
|
|
+ op0 = { 0, 1, 2, 3 }, op1 = { 6, 7, 2, 3 } */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
|||
|
|
+ conv_op0, GEN_INT (0x13)));
|
|||
|
|
+ /* op0 = { 2, 3, 6, 7 }, op1 = { 6, 7, 2, 3 } */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op0, conv_op0,
|
|||
|
|
+ conv_op1, GEN_INT (0x01)));
|
|||
|
|
+ /* Remap indices in selector based on the location of index inside
|
|||
|
|
+ selector, and vector element numbers in current vector mode. */
|
|||
|
|
+
|
|||
|
|
+ /* Filling low 128bit of new selector. */
|
|||
|
|
+ for (i = 0; i < d->nelt / 2; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ /* value in even-indexed slot of low 128bit part of selector
|
|||
|
|
+ vector. */
|
|||
|
|
+ remapped[i] = i % 2 == 0 ? d->perm[i] - d->nelt / 2 : d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ /* Then filling the high 128bit. */
|
|||
|
|
+ for (i = d->nelt / 2; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ /* value in odd-indexed slot of high 128bit part of selector
|
|||
|
|
+ vector. */
|
|||
|
|
+ remapped[i] = i % 2 != 0
|
|||
|
|
+ ? d->perm[i] - (d->nelt / 2) * 3 : d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_lasx_highpart_interleave_2 (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Special highpart interleave case in V32QI vector mode. It does the
|
|||
|
|
+ same thing as the normal version above.
|
|||
|
|
+ Selector sample: E_V32QImode,
|
|||
|
|
+ {16, 17, 18, 19, 20, 21, 22, 23, 48, 49, 50, 51, 52, 53, 54, 55,
|
|||
|
|
+ 24, 25, 26, 27, 28, 29, 30, 31, 56, 57, 58, 59, 60, 61, 62, 63}
|
|||
|
|
+ */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Convert op into V4DImode and do the things. */
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ op0_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+ emit_move_insn (op0_alt, d->op0);
|
|||
|
|
+
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
|||
|
|
+ rtx conv_target = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
|||
|
|
+
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
|||
|
|
+ conv_op0, GEN_INT (0x13)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op0, conv_op0,
|
|||
|
|
+ conv_op1, GEN_INT (0x01)));
|
|||
|
|
+ remapped[0] = 2;
|
|||
|
|
+ remapped[1] = 6;
|
|||
|
|
+ remapped[2] = 3;
|
|||
|
|
+ remapped[3] = 7;
|
|||
|
|
+
|
|||
|
|
+ for (i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ rperm[i] = GEN_INT (remapped[i]);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ sel = gen_rtx_CONST_VECTOR (E_V4DImode, gen_rtvec_v (4, rperm));
|
|||
|
|
+ sel = force_reg (E_V4DImode, sel);
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_d (conv_target, sel,
|
|||
|
|
+ conv_op1, conv_op0));
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ ok = true;
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_elem_duplicate (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Brocast single element (from op0 or op1) to all slot of target
|
|||
|
|
+ register.
|
|||
|
|
+ Selector sample:E_V8SImode, { 2, 2, 2, 2, 2, 2, 2, 2 } */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, d->op1, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
|||
|
|
+ rtx temp_reg = gen_reg_rtx (d->vmode);
|
|||
|
|
+ rtx conv_temp = gen_rtx_SUBREG (E_V4DImode, temp_reg, 0);
|
|||
|
|
+
|
|||
|
|
+ emit_move_insn (temp_reg, d->op0);
|
|||
|
|
+
|
|||
|
|
+ idx = d->perm[0];
|
|||
|
|
+ /* We will use xvrepl128vei.* insn to achieve the result, but we need
|
|||
|
|
+ to make the high/low 128bit has the same contents that contain the
|
|||
|
|
+ value that we need to broardcast, because xvrepl128vei does the
|
|||
|
|
+ broardcast job from every 128bit of source register to
|
|||
|
|
+ corresponded part of target register! (A deep sigh.) */
|
|||
|
|
+ if (/*idx >= 0 &&*/ idx < d->nelt / 2)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
|
|||
|
|
+ conv_op0, GEN_INT (0x0)));
|
|||
|
|
+ }
|
|||
|
|
+ else if (idx >= d->nelt / 2 && idx < d->nelt)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
|
|||
|
|
+ conv_op0, GEN_INT (0x11)));
|
|||
|
|
+ idx -= d->nelt / 2;
|
|||
|
|
+ }
|
|||
|
|
+ else if (idx >= d->nelt && idx < (d->nelt + d->nelt / 2))
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
|
|||
|
|
+ conv_op1, GEN_INT (0x0)));
|
|||
|
|
+ }
|
|||
|
|
+ else if (idx >= (d->nelt + d->nelt / 2) && idx < d->nelt * 2)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp,
|
|||
|
|
+ conv_op1, GEN_INT (0x11)));
|
|||
|
|
+ idx -= d->nelt / 2;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* Then we can finally generate this insn. */
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvrepl128vei_d (d->target, temp_reg,
|
|||
|
|
+ GEN_INT (idx)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvrepl128vei_d_f (d->target, temp_reg,
|
|||
|
|
+ GEN_INT (idx)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvrepl128vei_w (d->target, temp_reg,
|
|||
|
|
+ GEN_INT (idx)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvrepl128vei_w_f (d->target, temp_reg,
|
|||
|
|
+ GEN_INT (idx)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvrepl128vei_h (d->target, temp_reg,
|
|||
|
|
+ GEN_INT (idx)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvrepl128vei_b (d->target, temp_reg,
|
|||
|
|
+ GEN_INT (idx)));
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* finish func directly. */
|
|||
|
|
+ ok = true;
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_op_reverse_perm (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* reverse high 128bit and low 128bit in op0.
|
|||
|
|
+ Selector sample: E_V4DFmode, { 2, 3, 0, 1 }
|
|||
|
|
+ Use xvpermi.q for doing this job. */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ if (d->vmode == E_V4DImode)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (d->target, d->target, d->op0,
|
|||
|
|
+ GEN_INT (0x01)));
|
|||
|
|
+ }
|
|||
|
|
+ else if (d->vmode == E_V4DFmode)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4df (d->target, d->target, d->op0,
|
|||
|
|
+ GEN_INT (0x01)));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ ok = true;
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_single_op_perm (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Permutation that only select elements from op0. */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Prepare temp register instead of modify original op. */
|
|||
|
|
+ use_alt_op = true;
|
|||
|
|
+ op0_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+
|
|||
|
|
+ emit_move_insn (op0_alt, d->op0);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
|||
|
|
+ rtx conv_op0a = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
|||
|
|
+ rtx conv_op1a = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+
|
|||
|
|
+ /* Duplicate op0's low 128bit in op0, then duplicate high 128bit
|
|||
|
|
+ in op1. After this, xvshuf.* insn's selector argument can
|
|||
|
|
+ access all elements we need for correct permutation result. */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op0a, conv_op0a, conv_op0,
|
|||
|
|
+ GEN_INT (0x00)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1a, conv_op1a, conv_op0,
|
|||
|
|
+ GEN_INT (0x11)));
|
|||
|
|
+
|
|||
|
|
+ /* In this case, there's no need to remap selector's indices. */
|
|||
|
|
+ for (i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ remapped[i] = d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_divisible_perm (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Divisible perm:
|
|||
|
|
+ Low 128bit of selector only selects elements of op0,
|
|||
|
|
+ and high 128bit of selector only selects elements of op1. */
|
|||
|
|
+
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Prepare temp register instead of modify original op. */
|
|||
|
|
+ use_alt_op = true;
|
|||
|
|
+ op0_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+ op1_alt = gen_reg_rtx (d->vmode);
|
|||
|
|
+
|
|||
|
|
+ emit_move_insn (op0_alt, d->op0);
|
|||
|
|
+ emit_move_insn (op1_alt, d->op1);
|
|||
|
|
+
|
|||
|
|
+ rtx conv_op0a = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
|||
|
|
+ rtx conv_op1a = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
|||
|
|
+ rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
|||
|
|
+ rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, d->op1, 0);
|
|||
|
|
+
|
|||
|
|
+ /* Reorganize op0's hi/lo 128bit and op1's hi/lo 128bit, to make sure
|
|||
|
|
+ that selector's low 128bit can access all op0's elements, and
|
|||
|
|
+ selector's high 128bit can access all op1's elements. */
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op0a, conv_op0a, conv_op1,
|
|||
|
|
+ GEN_INT (0x02)));
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1a, conv_op1a, conv_op0,
|
|||
|
|
+ GEN_INT (0x31)));
|
|||
|
|
+
|
|||
|
|
+ /* No need to modify indices. */
|
|||
|
|
+ for (i = 0; i < d->nelt;i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ remapped[i] = d->perm[i];
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else if (loongarch_is_triple_stride_extract (d))
|
|||
|
|
+ {
|
|||
|
|
+ /* Selector sample: E_V4DFmode, { 1, 4, 7, 0 }. */
|
|||
|
|
+ if (!d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ /* Resolve it with brute force modification. */
|
|||
|
|
+ remapped[0] = 1;
|
|||
|
|
+ remapped[1] = 2;
|
|||
|
|
+ remapped[2] = 3;
|
|||
|
|
+ remapped[3] = 0;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ /* When all of the detections above are failed, we will try last
|
|||
|
|
+ strategy.
|
|||
|
|
+ The for loop tries to detect following rules based on indices' value,
|
|||
|
|
+ its position inside of selector vector ,and strange behavior of
|
|||
|
|
+ xvshuf.* insn; Then we take corresponding action. (Replace with new
|
|||
|
|
+ value, or give up whole permutation expansion.) */
|
|||
|
|
+ for (i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ /* % (2 * d->nelt) */
|
|||
|
|
+ idx = d->perm[i];
|
|||
|
|
+
|
|||
|
|
+ /* if index is located in low 128bit of selector vector. */
|
|||
|
|
+ if (i < d->nelt / 2)
|
|||
|
|
+ {
|
|||
|
|
+ /* Fail case 1: index tries to reach element that located in op0's
|
|||
|
|
+ high 128bit. */
|
|||
|
|
+ if (idx >= d->nelt / 2 && idx < d->nelt)
|
|||
|
|
+ {
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ /* Fail case 2: index tries to reach element that located in
|
|||
|
|
+ op1's high 128bit. */
|
|||
|
|
+ if (idx >= (d->nelt + d->nelt / 2))
|
|||
|
|
+ {
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* Success case: index tries to reach elements that located in
|
|||
|
|
+ op1's low 128bit. Apply - (nelt / 2) offset to original
|
|||
|
|
+ value. */
|
|||
|
|
+ if (idx >= d->nelt && idx < (d->nelt + d->nelt / 2))
|
|||
|
|
+ {
|
|||
|
|
+ idx -= d->nelt / 2;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ /* if index is located in high 128bit of selector vector. */
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ /* Fail case 1: index tries to reach element that located in
|
|||
|
|
+ op1's low 128bit. */
|
|||
|
|
+ if (idx >= d->nelt && idx < (d->nelt + d->nelt / 2))
|
|||
|
|
+ {
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ /* Fail case 2: index tries to reach element that located in
|
|||
|
|
+ op0's low 128bit. */
|
|||
|
|
+ if (idx < (d->nelt / 2))
|
|||
|
|
+ {
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+ /* Success case: index tries to reach element that located in
|
|||
|
|
+ op0's high 128bit. */
|
|||
|
|
+ if (idx >= d->nelt / 2 && idx < d->nelt)
|
|||
|
|
+ {
|
|||
|
|
+ idx -= d->nelt / 2;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ /* No need to process other case that we did not mentioned. */
|
|||
|
|
+
|
|||
|
|
+ /* Assign with original or processed value. */
|
|||
|
|
+ remapped[i] = idx;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ ok = true;
|
|||
|
|
+ /* If testing_p is true, compiler is trying to figure out that backend can
|
|||
|
|
+ handle this permutation, but doesn't want to generate actual insn. So
|
|||
|
|
+ if true, exit directly. */
|
|||
|
|
+ if (d->testing_p)
|
|||
|
|
+ {
|
|||
|
|
+ goto expand_perm_const_2_end;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* Convert remapped selector array to RTL array. */
|
|||
|
|
+ for (i = 0; i < d->nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ rperm[i] = GEN_INT (remapped[i]);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* Copy selector vector from memory to vector regiter for later insn gen
|
|||
|
|
+ function.
|
|||
|
|
+ If vector's element in floating point value, we cannot fit selector
|
|||
|
|
+ argument into insn gen function directly, because of the insn template
|
|||
|
|
+ definition. As a solution, generate a integral mode subreg of target,
|
|||
|
|
+ then copy selector vector (that is in integral mode) to this subreg. */
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ sel = gen_rtx_CONST_VECTOR (E_V4DImode, gen_rtvec_v (d->nelt, rperm));
|
|||
|
|
+ tmp = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
|||
|
|
+ emit_move_insn (tmp, sel);
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ sel = gen_rtx_CONST_VECTOR (E_V8SImode, gen_rtvec_v (d->nelt, rperm));
|
|||
|
|
+ tmp = gen_rtx_SUBREG (E_V8SImode, d->target, 0);
|
|||
|
|
+ emit_move_insn (tmp, sel);
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ sel = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (d->nelt, rperm));
|
|||
|
|
+ emit_move_insn (d->target, sel);
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ target = d->target;
|
|||
|
|
+ /* If temp op registers are requested in previous if branch, then use temp
|
|||
|
|
+ register intead of original one. */
|
|||
|
|
+ if (use_alt_op)
|
|||
|
|
+ {
|
|||
|
|
+ op0 = op0_alt != NULL_RTX ? op0_alt : d->op0;
|
|||
|
|
+ op1 = op1_alt != NULL_RTX ? op1_alt : d->op1;
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ op0 = d->op0;
|
|||
|
|
+ op1 = d->one_vector_p ? d->op0 : d->op1;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* We FINALLY can generate xvshuf.* insn. */
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_d_f (target, target, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_d (target, target, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_w_f (target, target, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_w (target, target, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_h (target, target, op1, op0));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvshuf_b (target, op1, op0, target));
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ /* Extra insn for swapping the hi/lo 128bit of target vector register. */
|
|||
|
|
+ if (reverse_hi_lo)
|
|||
|
|
+ {
|
|||
|
|
+ switch (d->vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4df (d->target, d->target,
|
|||
|
|
+ d->target, GEN_INT (0x1)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v4di (d->target, d->target,
|
|||
|
|
+ d->target, GEN_INT (0x1)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v8sf (d->target, d->target,
|
|||
|
|
+ d->target, GEN_INT (0x1)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v8si (d->target, d->target,
|
|||
|
|
+ d->target, GEN_INT (0x1)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v16hi (d->target, d->target,
|
|||
|
|
+ d->target, GEN_INT (0x1)));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_q_v32qi (d->target, d->target,
|
|||
|
|
+ d->target, GEN_INT (0x1)));
|
|||
|
|
+ break;
|
|||
|
|
+ default:
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ /* Extra insn required by odd/even extraction. Swapping the second and third
|
|||
|
|
+ 64bit in target vector register. */
|
|||
|
|
+ else if (extract_ev_od)
|
|||
|
|
+ {
|
|||
|
|
+ rtx converted = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v4di (converted, converted,
|
|||
|
|
+ GEN_INT (0xD8)));
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+expand_perm_const_2_end:
|
|||
|
|
+ return ok;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
|
|||
|
|
@@ -7813,6 +9728,12 @@ loongarch_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode,
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+ // Do rounding for selector to avoid vshuf undefined behavior.
|
|||
|
|
+ for (i = 0; i < d.nelt; i += 1)
|
|||
|
|
+ {
|
|||
|
|
+ d.perm[i] %= (d.nelt * 2);
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
if (d.testing_p)
|
|||
|
|
{
|
|||
|
|
d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
|
|||
|
|
@@ -7865,7 +9786,7 @@ loongarch_cpu_sched_reassociation_width (struct loongarch_target *target,
|
|||
|
|
case CPU_LOONGARCH64:
|
|||
|
|
case CPU_LA464:
|
|||
|
|
/* Vector part. */
|
|||
|
|
- if (LSX_SUPPORTED_MODE_P (mode))
|
|||
|
|
+ if (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))
|
|||
|
|
{
|
|||
|
|
/* Integer vector instructions execute in FP unit.
|
|||
|
|
The width of integer/float-point vector instructions is 3. */
|
|||
|
|
@@ -7915,6 +9836,44 @@ loongarch_expand_vector_extract (rtx target, rtx vec, int elt)
|
|||
|
|
case E_V16QImode:
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ if (ISA_HAS_LASX)
|
|||
|
|
+ {
|
|||
|
|
+ if (elt >= 16)
|
|||
|
|
+ {
|
|||
|
|
+ tmp = gen_reg_rtx (V32QImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v32qi (tmp, vec, GEN_INT (0xe)));
|
|||
|
|
+ loongarch_expand_vector_extract (target,
|
|||
|
|
+ gen_lowpart (V16QImode, tmp),
|
|||
|
|
+ elt & 15);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ loongarch_expand_vector_extract (target,
|
|||
|
|
+ gen_lowpart (V16QImode, vec),
|
|||
|
|
+ elt & 15);
|
|||
|
|
+ return;
|
|||
|
|
+ }
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ if (ISA_HAS_LASX)
|
|||
|
|
+ {
|
|||
|
|
+ if (elt >= 8)
|
|||
|
|
+ {
|
|||
|
|
+ tmp = gen_reg_rtx (V16HImode);
|
|||
|
|
+ emit_insn (gen_lasx_xvpermi_d_v16hi (tmp, vec, GEN_INT (0xe)));
|
|||
|
|
+ loongarch_expand_vector_extract (target,
|
|||
|
|
+ gen_lowpart (V8HImode, tmp),
|
|||
|
|
+ elt & 7);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ loongarch_expand_vector_extract (target,
|
|||
|
|
+ gen_lowpart (V8HImode, vec),
|
|||
|
|
+ elt & 7);
|
|||
|
|
+ return;
|
|||
|
|
+ }
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
default:
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
@@ -7953,6 +9912,31 @@ emit_reduc_half (rtx dest, rtx src, int i)
|
|||
|
|
case E_V2DFmode:
|
|||
|
|
tem = gen_lsx_vbsrl_d_f (dest, src, GEN_INT (8));
|
|||
|
|
break;
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ if (i == 256)
|
|||
|
|
+ tem = gen_lasx_xvpermi_d_v8sf (dest, src, GEN_INT (0xe));
|
|||
|
|
+ else
|
|||
|
|
+ tem = gen_lasx_xvshuf4i_w_f (dest, src,
|
|||
|
|
+ GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ if (i == 256)
|
|||
|
|
+ tem = gen_lasx_xvpermi_d_v4df (dest, src, GEN_INT (0xe));
|
|||
|
|
+ else
|
|||
|
|
+ tem = gen_lasx_xvpermi_d_v4df (dest, src, const1_rtx);
|
|||
|
|
+ break;
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ d = gen_reg_rtx (V4DImode);
|
|||
|
|
+ if (i == 256)
|
|||
|
|
+ tem = gen_lasx_xvpermi_d_v4di (d, gen_lowpart (V4DImode, src),
|
|||
|
|
+ GEN_INT (0xe));
|
|||
|
|
+ else
|
|||
|
|
+ tem = gen_lasx_xvbsrl_d (d, gen_lowpart (V4DImode, src),
|
|||
|
|
+ GEN_INT (i/16));
|
|||
|
|
+ break;
|
|||
|
|
case E_V16QImode:
|
|||
|
|
case E_V8HImode:
|
|||
|
|
case E_V4SImode:
|
|||
|
|
@@ -8000,10 +9984,57 @@ loongarch_expand_vec_unpack (rtx operands[2], bool unsigned_p, bool high_p)
|
|||
|
|
{
|
|||
|
|
machine_mode imode = GET_MODE (operands[1]);
|
|||
|
|
rtx (*unpack) (rtx, rtx, rtx);
|
|||
|
|
+ rtx (*extend) (rtx, rtx);
|
|||
|
|
rtx (*cmpFunc) (rtx, rtx, rtx);
|
|||
|
|
+ rtx (*swap_hi_lo) (rtx, rtx, rtx, rtx);
|
|||
|
|
rtx tmp, dest;
|
|||
|
|
|
|||
|
|
- if (ISA_HAS_LSX)
|
|||
|
|
+ if (ISA_HAS_LASX && GET_MODE_SIZE (imode) == 32)
|
|||
|
|
+ {
|
|||
|
|
+ switch (imode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ if (unsigned_p)
|
|||
|
|
+ extend = gen_lasx_vext2xv_du_wu;
|
|||
|
|
+ else
|
|||
|
|
+ extend = gen_lasx_vext2xv_d_w;
|
|||
|
|
+ swap_hi_lo = gen_lasx_xvpermi_q_v8si;
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ if (unsigned_p)
|
|||
|
|
+ extend = gen_lasx_vext2xv_wu_hu;
|
|||
|
|
+ else
|
|||
|
|
+ extend = gen_lasx_vext2xv_w_h;
|
|||
|
|
+ swap_hi_lo = gen_lasx_xvpermi_q_v16hi;
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ if (unsigned_p)
|
|||
|
|
+ extend = gen_lasx_vext2xv_hu_bu;
|
|||
|
|
+ else
|
|||
|
|
+ extend = gen_lasx_vext2xv_h_b;
|
|||
|
|
+ swap_hi_lo = gen_lasx_xvpermi_q_v32qi;
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ break;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ if (high_p)
|
|||
|
|
+ {
|
|||
|
|
+ tmp = gen_reg_rtx (imode);
|
|||
|
|
+ emit_insn (swap_hi_lo (tmp, tmp, operands[1], const1_rtx));
|
|||
|
|
+ emit_insn (extend (operands[0], tmp));
|
|||
|
|
+ return;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ emit_insn (extend (operands[0], operands[1]));
|
|||
|
|
+ return;
|
|||
|
|
+
|
|||
|
|
+ }
|
|||
|
|
+ else if (ISA_HAS_LSX)
|
|||
|
|
{
|
|||
|
|
switch (imode)
|
|||
|
|
{
|
|||
|
|
@@ -8104,8 +10135,17 @@ loongarch_gen_const_int_vector_shuffle (machine_mode mode, int val)
|
|||
|
|
return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nunits, elts));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+
|
|||
|
|
/* Expand a vector initialization. */
|
|||
|
|
|
|||
|
|
+void
|
|||
|
|
+loongarch_expand_vector_group_init (rtx target, rtx vals)
|
|||
|
|
+{
|
|||
|
|
+ rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
|
|||
|
|
+ emit_insn (gen_rtx_SET (target, gen_rtx_VEC_CONCAT (E_V32QImode, ops[0],
|
|||
|
|
+ ops[1])));
|
|||
|
|
+}
|
|||
|
|
+
|
|||
|
|
void
|
|||
|
|
loongarch_expand_vector_init (rtx target, rtx vals)
|
|||
|
|
{
|
|||
|
|
@@ -8125,6 +10165,285 @@ loongarch_expand_vector_init (rtx target, rtx vals)
|
|||
|
|
all_same = false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
+ if (ISA_HAS_LASX && GET_MODE_SIZE (vmode) == 32)
|
|||
|
|
+ {
|
|||
|
|
+ if (all_same)
|
|||
|
|
+ {
|
|||
|
|
+ rtx same = XVECEXP (vals, 0, 0);
|
|||
|
|
+ rtx temp, temp2;
|
|||
|
|
+
|
|||
|
|
+ if (CONST_INT_P (same) && nvar == 0
|
|||
|
|
+ && loongarch_signed_immediate_p (INTVAL (same), 10, 0))
|
|||
|
|
+ {
|
|||
|
|
+ switch (vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ temp = gen_rtx_CONST_VECTOR (vmode, XVEC (vals, 0));
|
|||
|
|
+ emit_move_insn (target, temp);
|
|||
|
|
+ return;
|
|||
|
|
+
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ temp = gen_reg_rtx (imode);
|
|||
|
|
+ if (imode == GET_MODE (same))
|
|||
|
|
+ temp2 = same;
|
|||
|
|
+ else if (GET_MODE_SIZE (imode) >= UNITS_PER_WORD)
|
|||
|
|
+ {
|
|||
|
|
+ if (GET_CODE (same) == MEM)
|
|||
|
|
+ {
|
|||
|
|
+ rtx reg_tmp = gen_reg_rtx (GET_MODE (same));
|
|||
|
|
+ loongarch_emit_move (reg_tmp, same);
|
|||
|
|
+ temp2 = simplify_gen_subreg (imode, reg_tmp,
|
|||
|
|
+ GET_MODE (reg_tmp), 0);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ temp2 = simplify_gen_subreg (imode, same,
|
|||
|
|
+ GET_MODE (same), 0);
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ if (GET_CODE (same) == MEM)
|
|||
|
|
+ {
|
|||
|
|
+ rtx reg_tmp = gen_reg_rtx (GET_MODE (same));
|
|||
|
|
+ loongarch_emit_move (reg_tmp, same);
|
|||
|
|
+ temp2 = lowpart_subreg (imode, reg_tmp,
|
|||
|
|
+ GET_MODE (reg_tmp));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ temp2 = lowpart_subreg (imode, same, GET_MODE (same));
|
|||
|
|
+ }
|
|||
|
|
+ emit_move_insn (temp, temp2);
|
|||
|
|
+
|
|||
|
|
+ switch (vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ loongarch_emit_move (target,
|
|||
|
|
+ gen_rtx_VEC_DUPLICATE (vmode, temp));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvreplve0_w_f_scalar (target, temp));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ emit_insn (gen_lasx_xvreplve0_d_f_scalar (target, temp));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ rtvec vec = shallow_copy_rtvec (XVEC (vals, 0));
|
|||
|
|
+
|
|||
|
|
+ for (i = 0; i < nelt; ++i)
|
|||
|
|
+ RTVEC_ELT (vec, i) = CONST0_RTX (imode);
|
|||
|
|
+
|
|||
|
|
+ emit_move_insn (target, gen_rtx_CONST_VECTOR (vmode, vec));
|
|||
|
|
+
|
|||
|
|
+ machine_mode half_mode = VOIDmode;
|
|||
|
|
+ rtx target_hi, target_lo;
|
|||
|
|
+
|
|||
|
|
+ switch (vmode)
|
|||
|
|
+ {
|
|||
|
|
+ case E_V32QImode:
|
|||
|
|
+ half_mode=E_V16QImode;
|
|||
|
|
+ target_hi = gen_reg_rtx (half_mode);
|
|||
|
|
+ target_lo = gen_reg_rtx (half_mode);
|
|||
|
|
+ for (i = 0; i < nelt/2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ rtx temp_hi = gen_reg_rtx (imode);
|
|||
|
|
+ rtx temp_lo = gen_reg_rtx (imode);
|
|||
|
|
+ emit_move_insn (temp_hi, XVECEXP (vals, 0, i+nelt/2));
|
|||
|
|
+ emit_move_insn (temp_lo, XVECEXP (vals, 0, i));
|
|||
|
|
+ if (i == 0)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_b_scalar (target_hi,
|
|||
|
|
+ temp_hi));
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_b_scalar (target_lo,
|
|||
|
|
+ temp_lo));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_vec_setv16qi (target_hi, temp_hi,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ emit_insn (gen_vec_setv16qi (target_lo, temp_lo,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ emit_insn (gen_rtx_SET (target,
|
|||
|
|
+ gen_rtx_VEC_CONCAT (vmode, target_hi,
|
|||
|
|
+ target_lo)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V16HImode:
|
|||
|
|
+ half_mode=E_V8HImode;
|
|||
|
|
+ target_hi = gen_reg_rtx (half_mode);
|
|||
|
|
+ target_lo = gen_reg_rtx (half_mode);
|
|||
|
|
+ for (i = 0; i < nelt/2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ rtx temp_hi = gen_reg_rtx (imode);
|
|||
|
|
+ rtx temp_lo = gen_reg_rtx (imode);
|
|||
|
|
+ emit_move_insn (temp_hi, XVECEXP (vals, 0, i+nelt/2));
|
|||
|
|
+ emit_move_insn (temp_lo, XVECEXP (vals, 0, i));
|
|||
|
|
+ if (i == 0)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_h_scalar (target_hi,
|
|||
|
|
+ temp_hi));
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_h_scalar (target_lo,
|
|||
|
|
+ temp_lo));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_vec_setv8hi (target_hi, temp_hi,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ emit_insn (gen_vec_setv8hi (target_lo, temp_lo,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ emit_insn (gen_rtx_SET (target,
|
|||
|
|
+ gen_rtx_VEC_CONCAT (vmode, target_hi,
|
|||
|
|
+ target_lo)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V8SImode:
|
|||
|
|
+ half_mode=V4SImode;
|
|||
|
|
+ target_hi = gen_reg_rtx (half_mode);
|
|||
|
|
+ target_lo = gen_reg_rtx (half_mode);
|
|||
|
|
+ for (i = 0; i < nelt/2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ rtx temp_hi = gen_reg_rtx (imode);
|
|||
|
|
+ rtx temp_lo = gen_reg_rtx (imode);
|
|||
|
|
+ emit_move_insn (temp_hi, XVECEXP (vals, 0, i+nelt/2));
|
|||
|
|
+ emit_move_insn (temp_lo, XVECEXP (vals, 0, i));
|
|||
|
|
+ if (i == 0)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_w_scalar (target_hi,
|
|||
|
|
+ temp_hi));
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_w_scalar (target_lo,
|
|||
|
|
+ temp_lo));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_vec_setv4si (target_hi, temp_hi,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ emit_insn (gen_vec_setv4si (target_lo, temp_lo,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ emit_insn (gen_rtx_SET (target,
|
|||
|
|
+ gen_rtx_VEC_CONCAT (vmode, target_hi,
|
|||
|
|
+ target_lo)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V4DImode:
|
|||
|
|
+ half_mode=E_V2DImode;
|
|||
|
|
+ target_hi = gen_reg_rtx (half_mode);
|
|||
|
|
+ target_lo = gen_reg_rtx (half_mode);
|
|||
|
|
+ for (i = 0; i < nelt/2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ rtx temp_hi = gen_reg_rtx (imode);
|
|||
|
|
+ rtx temp_lo = gen_reg_rtx (imode);
|
|||
|
|
+ emit_move_insn (temp_hi, XVECEXP (vals, 0, i+nelt/2));
|
|||
|
|
+ emit_move_insn (temp_lo, XVECEXP (vals, 0, i));
|
|||
|
|
+ if (i == 0)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_d_scalar (target_hi,
|
|||
|
|
+ temp_hi));
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_d_scalar (target_lo,
|
|||
|
|
+ temp_lo));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_vec_setv2di (target_hi, temp_hi,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ emit_insn (gen_vec_setv2di (target_lo, temp_lo,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ emit_insn (gen_rtx_SET (target,
|
|||
|
|
+ gen_rtx_VEC_CONCAT (vmode, target_hi,
|
|||
|
|
+ target_lo)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ half_mode=E_V4SFmode;
|
|||
|
|
+ target_hi = gen_reg_rtx (half_mode);
|
|||
|
|
+ target_lo = gen_reg_rtx (half_mode);
|
|||
|
|
+ for (i = 0; i < nelt/2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ rtx temp_hi = gen_reg_rtx (imode);
|
|||
|
|
+ rtx temp_lo = gen_reg_rtx (imode);
|
|||
|
|
+ emit_move_insn (temp_hi, XVECEXP (vals, 0, i+nelt/2));
|
|||
|
|
+ emit_move_insn (temp_lo, XVECEXP (vals, 0, i));
|
|||
|
|
+ if (i == 0)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_w_f_scalar (target_hi,
|
|||
|
|
+ temp_hi));
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_w_f_scalar (target_lo,
|
|||
|
|
+ temp_lo));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_vec_setv4sf (target_hi, temp_hi,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ emit_insn (gen_vec_setv4sf (target_lo, temp_lo,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ emit_insn (gen_rtx_SET (target,
|
|||
|
|
+ gen_rtx_VEC_CONCAT (vmode, target_hi,
|
|||
|
|
+ target_lo)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ half_mode=E_V2DFmode;
|
|||
|
|
+ target_hi = gen_reg_rtx (half_mode);
|
|||
|
|
+ target_lo = gen_reg_rtx (half_mode);
|
|||
|
|
+ for (i = 0; i < nelt/2; ++i)
|
|||
|
|
+ {
|
|||
|
|
+ rtx temp_hi = gen_reg_rtx (imode);
|
|||
|
|
+ rtx temp_lo = gen_reg_rtx (imode);
|
|||
|
|
+ emit_move_insn (temp_hi, XVECEXP (vals, 0, i+nelt/2));
|
|||
|
|
+ emit_move_insn (temp_lo, XVECEXP (vals, 0, i));
|
|||
|
|
+ if (i == 0)
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_d_f_scalar (target_hi,
|
|||
|
|
+ temp_hi));
|
|||
|
|
+ emit_insn (gen_lsx_vreplvei_d_f_scalar (target_lo,
|
|||
|
|
+ temp_lo));
|
|||
|
|
+ }
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ emit_insn (gen_vec_setv2df (target_hi, temp_hi,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ emit_insn (gen_vec_setv2df (target_lo, temp_lo,
|
|||
|
|
+ GEN_INT (i)));
|
|||
|
|
+ }
|
|||
|
|
+ }
|
|||
|
|
+ emit_insn (gen_rtx_SET (target,
|
|||
|
|
+ gen_rtx_VEC_CONCAT (vmode, target_hi,
|
|||
|
|
+ target_lo)));
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
+ }
|
|||
|
|
+ return;
|
|||
|
|
+ }
|
|||
|
|
+
|
|||
|
|
if (ISA_HAS_LSX)
|
|||
|
|
{
|
|||
|
|
if (all_same)
|
|||
|
|
@@ -8372,6 +10691,38 @@ loongarch_expand_lsx_cmp (rtx dest, enum rtx_code cond, rtx op0, rtx op1)
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
+ case E_V8SFmode:
|
|||
|
|
+ case E_V4DFmode:
|
|||
|
|
+ switch (cond)
|
|||
|
|
+ {
|
|||
|
|
+ case UNORDERED:
|
|||
|
|
+ case ORDERED:
|
|||
|
|
+ case EQ:
|
|||
|
|
+ case NE:
|
|||
|
|
+ case UNEQ:
|
|||
|
|
+ case UNLE:
|
|||
|
|
+ case UNLT:
|
|||
|
|
+ break;
|
|||
|
|
+ case LTGT: cond = NE; break;
|
|||
|
|
+ case UNGE: cond = UNLE; std::swap (op0, op1); break;
|
|||
|
|
+ case UNGT: cond = UNLT; std::swap (op0, op1); break;
|
|||
|
|
+ case LE: unspec = UNSPEC_LASX_XVFCMP_SLE; break;
|
|||
|
|
+ case LT: unspec = UNSPEC_LASX_XVFCMP_SLT; break;
|
|||
|
|
+ case GE: unspec = UNSPEC_LASX_XVFCMP_SLE; std::swap (op0, op1); break;
|
|||
|
|
+ case GT: unspec = UNSPEC_LASX_XVFCMP_SLT; std::swap (op0, op1); break;
|
|||
|
|
+ default:
|
|||
|
|
+ gcc_unreachable ();
|
|||
|
|
+ }
|
|||
|
|
+ if (unspec < 0)
|
|||
|
|
+ loongarch_emit_binary (cond, dest, op0, op1);
|
|||
|
|
+ else
|
|||
|
|
+ {
|
|||
|
|
+ rtx x = gen_rtx_UNSPEC (GET_MODE (dest),
|
|||
|
|
+ gen_rtvec (2, op0, op1), unspec);
|
|||
|
|
+ emit_insn (gen_rtx_SET (dest, x));
|
|||
|
|
+ }
|
|||
|
|
+ break;
|
|||
|
|
+
|
|||
|
|
default:
|
|||
|
|
gcc_unreachable ();
|
|||
|
|
break;
|
|||
|
|
@@ -8709,7 +11060,7 @@ loongarch_builtin_support_vector_misalignment (machine_mode mode,
|
|||
|
|
int misalignment,
|
|||
|
|
bool is_packed)
|
|||
|
|
{
|
|||
|
|
- if (ISA_HAS_LSX && STRICT_ALIGNMENT)
|
|||
|
|
+ if ((ISA_HAS_LSX || ISA_HAS_LASX) && STRICT_ALIGNMENT)
|
|||
|
|
{
|
|||
|
|
if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing)
|
|||
|
|
return false;
|
|||
|
|
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
|
|||
|
|
index c3ebea2f2..b2295c589 100644
|
|||
|
|
--- a/gcc/config/loongarch/loongarch.h
|
|||
|
|
+++ b/gcc/config/loongarch/loongarch.h
|
|||
|
|
@@ -186,6 +186,11 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
|
/* Width of a LSX vector register in bits. */
|
|||
|
|
#define BITS_PER_LSX_REG (UNITS_PER_LSX_REG * BITS_PER_UNIT)
|
|||
|
|
|
|||
|
|
+/* Width of a LASX vector register in bytes. */
|
|||
|
|
+#define UNITS_PER_LASX_REG 32
|
|||
|
|
+/* Width of a LASX vector register in bits. */
|
|||
|
|
+#define BITS_PER_LASX_REG (UNITS_PER_LASX_REG * BITS_PER_UNIT)
|
|||
|
|
+
|
|||
|
|
/* For LARCH, width of a floating point register. */
|
|||
|
|
#define UNITS_PER_FPREG (TARGET_DOUBLE_FLOAT ? 8 : 4)
|
|||
|
|
|
|||
|
|
@@ -248,10 +253,11 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
|
#define STRUCTURE_SIZE_BOUNDARY 8
|
|||
|
|
|
|||
|
|
/* There is no point aligning anything to a rounder boundary than
|
|||
|
|
- LONG_DOUBLE_TYPE_SIZE, unless under LSX the bigggest alignment is
|
|||
|
|
- BITS_PER_LSX_REG/.. */
|
|||
|
|
+ LONG_DOUBLE_TYPE_SIZE, unless under LSX/LASX the bigggest alignment is
|
|||
|
|
+ BITS_PER_LSX_REG/BITS_PER_LASX_REG/.. */
|
|||
|
|
#define BIGGEST_ALIGNMENT \
|
|||
|
|
- (ISA_HAS_LSX ? BITS_PER_LSX_REG : LONG_DOUBLE_TYPE_SIZE)
|
|||
|
|
+ (ISA_HAS_LASX? BITS_PER_LASX_REG \
|
|||
|
|
+ : (ISA_HAS_LSX ? BITS_PER_LSX_REG : LONG_DOUBLE_TYPE_SIZE))
|
|||
|
|
|
|||
|
|
/* All accesses must be aligned. */
|
|||
|
|
#define STRICT_ALIGNMENT (TARGET_STRICT_ALIGN)
|
|||
|
|
@@ -391,6 +397,10 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
|
#define LSX_REG_LAST FP_REG_LAST
|
|||
|
|
#define LSX_REG_NUM FP_REG_NUM
|
|||
|
|
|
|||
|
|
+#define LASX_REG_FIRST FP_REG_FIRST
|
|||
|
|
+#define LASX_REG_LAST FP_REG_LAST
|
|||
|
|
+#define LASX_REG_NUM FP_REG_NUM
|
|||
|
|
+
|
|||
|
|
/* The DWARF 2 CFA column which tracks the return address from a
|
|||
|
|
signal handler context. This means that to maintain backwards
|
|||
|
|
compatibility, no hard register can be assigned this column if it
|
|||
|
|
@@ -409,9 +419,12 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
|
((unsigned int) ((int) (REGNO) - FCC_REG_FIRST) < FCC_REG_NUM)
|
|||
|
|
#define LSX_REG_P(REGNO) \
|
|||
|
|
((unsigned int) ((int) (REGNO) - LSX_REG_FIRST) < LSX_REG_NUM)
|
|||
|
|
+#define LASX_REG_P(REGNO) \
|
|||
|
|
+ ((unsigned int) ((int) (REGNO) - LASX_REG_FIRST) < LASX_REG_NUM)
|
|||
|
|
|
|||
|
|
#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
|
|||
|
|
#define LSX_REG_RTX_P(X) (REG_P (X) && LSX_REG_P (REGNO (X)))
|
|||
|
|
+#define LASX_REG_RTX_P(X) (REG_P (X) && LASX_REG_P (REGNO (X)))
|
|||
|
|
|
|||
|
|
/* Select a register mode required for caller save of hard regno REGNO. */
|
|||
|
|
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
|
|||
|
|
@@ -733,6 +746,13 @@ enum reg_class
|
|||
|
|
&& (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
|
|||
|
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT))
|
|||
|
|
|
|||
|
|
+#define LASX_SUPPORTED_MODE_P(MODE) \
|
|||
|
|
+ (ISA_HAS_LASX \
|
|||
|
|
+ && (GET_MODE_SIZE (MODE) == UNITS_PER_LSX_REG \
|
|||
|
|
+ ||GET_MODE_SIZE (MODE) == UNITS_PER_LASX_REG) \
|
|||
|
|
+ && (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
|
|||
|
|
+ || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT))
|
|||
|
|
+
|
|||
|
|
/* 1 if N is a possible register number for function argument passing.
|
|||
|
|
We have no FP argument registers when soft-float. */
|
|||
|
|
|
|||
|
|
@@ -985,7 +1005,39 @@ typedef struct {
|
|||
|
|
{ "vr28", 28 + FP_REG_FIRST }, \
|
|||
|
|
{ "vr29", 29 + FP_REG_FIRST }, \
|
|||
|
|
{ "vr30", 30 + FP_REG_FIRST }, \
|
|||
|
|
- { "vr31", 31 + FP_REG_FIRST } \
|
|||
|
|
+ { "vr31", 31 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr0", 0 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr1", 1 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr2", 2 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr3", 3 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr4", 4 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr5", 5 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr6", 6 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr7", 7 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr8", 8 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr9", 9 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr10", 10 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr11", 11 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr12", 12 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr13", 13 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr14", 14 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr15", 15 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr16", 16 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr17", 17 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr18", 18 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr19", 19 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr20", 20 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr21", 21 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr22", 22 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr23", 23 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr24", 24 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr25", 25 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr26", 26 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr27", 27 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr28", 28 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr29", 29 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr30", 30 + FP_REG_FIRST }, \
|
|||
|
|
+ { "xr31", 31 + FP_REG_FIRST } \
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Globalizing directive for a label. */
|
|||
|
|
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
|
|||
|
|
index fb3828262..3dde0ceb1 100644
|
|||
|
|
--- a/gcc/config/loongarch/loongarch.md
|
|||
|
|
+++ b/gcc/config/loongarch/loongarch.md
|
|||
|
|
@@ -163,7 +163,7 @@
|
|||
|
|
|
|||
|
|
;; Main data type used by the insn
|
|||
|
|
(define_attr "mode" "unknown,none,QI,HI,SI,DI,TI,SF,DF,TF,FCC,
|
|||
|
|
- V2DI,V4SI,V8HI,V16QI,V2DF,V4SF"
|
|||
|
|
+ V2DI,V4SI,V8HI,V16QI,V2DF,V4SF,V4DI,V8SI,V16HI,V32QI,V4DF,V8SF"
|
|||
|
|
(const_string "unknown"))
|
|||
|
|
|
|||
|
|
;; True if the main data type is twice the size of a word.
|
|||
|
|
@@ -422,12 +422,14 @@
|
|||
|
|
;; floating-point mode or vector mode.
|
|||
|
|
(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF") (V4SF "SF")
|
|||
|
|
(V16QI "QI") (V8HI "HI") (V4SI "SI") (V2DI "DI")
|
|||
|
|
- (V2DF "DF")])
|
|||
|
|
+ (V2DF "DF")(V8SF "SF")(V32QI "QI")(V16HI "HI")(V8SI "SI")(V4DI "DI")(V4DF "DF")])
|
|||
|
|
|
|||
|
|
;; As above, but in lower case.
|
|||
|
|
(define_mode_attr unitmode [(SF "sf") (DF "df") (V2SF "sf") (V4SF "sf")
|
|||
|
|
(V16QI "qi") (V8QI "qi") (V8HI "hi") (V4HI "hi")
|
|||
|
|
- (V4SI "si") (V2SI "si") (V2DI "di") (V2DF "df")])
|
|||
|
|
+ (V4SI "si") (V2SI "si") (V2DI "di") (V2DF "df")
|
|||
|
|
+ (V8SI "si") (V4DI "di") (V32QI "qi") (V16HI "hi")
|
|||
|
|
+ (V8SF "sf") (V4DF "df")])
|
|||
|
|
|
|||
|
|
;; This attribute gives the integer mode that has half the size of
|
|||
|
|
;; the controlling mode.
|
|||
|
|
@@ -711,16 +713,17 @@
|
|||
|
|
[(set_attr "alu_type" "sub")
|
|||
|
|
(set_attr "mode" "<MODE>")])
|
|||
|
|
|
|||
|
|
+
|
|||
|
|
(define_insn "*subsi3_extended"
|
|||
|
|
- [(set (match_operand:DI 0 "register_operand" "= r")
|
|||
|
|
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
|||
|
|
(sign_extend:DI
|
|||
|
|
- (minus:SI (match_operand:SI 1 "reg_or_0_operand" " rJ")
|
|||
|
|
- (match_operand:SI 2 "register_operand" " r"))))]
|
|||
|
|
+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
|
|||
|
|
+ (match_operand:SI 2 "register_operand" "r"))))]
|
|||
|
|
"TARGET_64BIT"
|
|||
|
|
"sub.w\t%0,%z1,%2"
|
|||
|
|
[(set_attr "type" "arith")
|
|||
|
|
(set_attr "mode" "SI")])
|
|||
|
|
-
|
|||
|
|
+
|
|||
|
|
;;
|
|||
|
|
;; ....................
|
|||
|
|
;;
|
|||
|
|
@@ -3638,6 +3641,9 @@
|
|||
|
|
; The LoongArch SX Instructions.
|
|||
|
|
(include "lsx.md")
|
|||
|
|
|
|||
|
|
+; The LoongArch ASX Instructions.
|
|||
|
|
+(include "lasx.md")
|
|||
|
|
+
|
|||
|
|
(define_c_enum "unspec" [
|
|||
|
|
UNSPEC_ADDRESS_FIRST
|
|||
|
|
])
|
|||
|
|
--
|
|||
|
|
2.33.0
|
|||
|
|
|