+2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
+ Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+ Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * config.gcc (aarch64*-*-*): Add arm_sve.h to extra_headers.
+ Add aarch64-sve-builtins.o, aarch64-sve-builtins-shapes.o and
+ aarch64-sve-builtins-base.o to extra_objs. Add
+ aarch64-sve-builtins.h and aarch64-sve-builtins.cc to target_gtfiles.
+ * config/aarch64/t-aarch64 (aarch64-sve-builtins.o): New rule.
+ (aarch64-sve-builtins-shapes.o): Likewise.
+ (aarch64-sve-builtins-base.o): New rules.
+ * config/aarch64/aarch64-c.c (aarch64_pragma_aarch64): New function.
+ (aarch64_resolve_overloaded_builtin): Likewise.
+ (aarch64_check_builtin_call): Likewise.
+ (aarch64_register_pragmas): Install aarch64_resolve_overloaded_builtin
+ and aarch64_check_builtin_call in targetm. Register the GCC aarch64
+ pragma.
+ * config/aarch64/aarch64-protos.h (AARCH64_FOR_SVPRFOP): New macro.
+ (aarch64_svprfop): New enum.
+ (AARCH64_BUILTIN_SVE): New aarch64_builtin_class enum value.
+ (aarch64_sve_int_mode, aarch64_sve_data_mode): Declare.
+ (aarch64_fold_sve_cnt_pat, aarch64_output_sve_prefetch): Likewise.
+ (aarch64_output_sve_cnt_pat_immediate): Likewise.
+ (aarch64_output_sve_ptrues, aarch64_sve_ptrue_svpattern_p): Likewise.
+ (aarch64_sve_sqadd_sqsub_immediate_p, aarch64_sve_ldff1_operand_p)
+ (aarch64_sve_ldnf1_operand_p, aarch64_sve_prefetch_operand_p)
+ (aarch64_ptrue_all_mode, aarch64_convert_sve_data_to_pred): Likewise.
+ (aarch64_expand_sve_dupq, aarch64_replace_reg_mode): Likewise.
+ (aarch64_sve::init_builtins, aarch64_sve::handle_arm_sve_h): Likewise.
+ (aarch64_sve::builtin_decl, aarch64_sve::builtin_type_p): Likewise.
+ (aarch64_sve::mangle_builtin_type): Likewise.
+ (aarch64_sve::resolve_overloaded_builtin): Likewise.
+ (aarch64_sve::check_builtin_call, aarch64_sve::gimple_fold_builtin)
+ (aarch64_sve::expand_builtin): Likewise.
+ * config/aarch64/aarch64.c (aarch64_sve_data_mode): Make public.
+ (aarch64_sve_int_mode): Likewise.
+ (aarch64_ptrue_all_mode): New function.
+ (aarch64_convert_sve_data_to_pred): Make public.
+ (svprfop_token): New function.
+ (aarch64_output_sve_prefetch): Likewise.
+ (aarch64_fold_sve_cnt_pat): Likewise.
+ (aarch64_output_sve_cnt_pat_immediate): Likewise.
+ (aarch64_sve_move_pred_via_while): Use gen_while with UNSPEC_WHILE_LO
+ instead of gen_while_ult.
+ (aarch64_replace_reg_mode): Make public.
+ (aarch64_init_builtins): Call aarch64_sve::init_builtins.
+ (aarch64_fold_builtin): Handle AARCH64_BUILTIN_SVE.
+ (aarch64_gimple_fold_builtin, aarch64_expand_builtin): Likewise.
+ (aarch64_builtin_decl, aarch64_builtin_reciprocal): Likewise.
+ (aarch64_mangle_type): Call aarch64_sve::mangle_type.
+ (aarch64_sve_sqadd_sqsub_immediate_p): New function.
+ (aarch64_sve_ptrue_svpattern_p): Likewise.
+ (aarch64_sve_pred_valid_immediate): Check
+ aarch64_sve_ptrue_svpattern_p.
+ (aarch64_sve_ldff1_operand_p, aarch64_sve_ldnf1_operand_p)
+ (aarch64_sve_prefetch_operand_p, aarch64_output_sve_ptrues): New
+ functions.
+ * config/aarch64/aarch64.md (UNSPEC_LDNT1_SVE, UNSPEC_STNT1_SVE)
+ (UNSPEC_LDFF1_GATHER, UNSPEC_PTRUE, UNSPEC_WHILE_LE, UNSPEC_WHILE_LS)
+ (UNSPEC_WHILE_LT, UNSPEC_CLASTA, UNSPEC_UPDATE_FFR)
+ (UNSPEC_UPDATE_FFRT, UNSPEC_RDFFR, UNSPEC_WRFFR)
+ (UNSPEC_SVE_LANE_SELECT, UNSPEC_SVE_CNT_PAT, UNSPEC_SVE_PREFETCH)
+ (UNSPEC_SVE_PREFETCH_GATHER, UNSPEC_SVE_COMPACT, UNSPEC_SVE_SPLICE):
+ New unspecs.
+ * config/aarch64/iterators.md (SI_ONLY, DI_ONLY, VNx8HI_ONLY)
+ (VNx2DI_ONLY, SVE_PARTIAL, VNx8_NARROW, VNx8_WIDE, VNx4_NARROW)
+ (VNx4_WIDE, VNx2_NARROW, VNx2_WIDE, PRED_HSD): New mode iterators.
+ (UNSPEC_ADR, UNSPEC_BRKA, UNSPEC_BRKB, UNSPEC_BRKN, UNSPEC_BRKPA)
+ (UNSPEC_BRKPB, UNSPEC_PFIRST, UNSPEC_PNEXT, UNSPEC_CNTP, UNSPEC_SADDV)
+ (UNSPEC_UADDV, UNSPEC_FMLA, UNSPEC_FMLS, UNSPEC_FEXPA, UNSPEC_FTMAD)
+ (UNSPEC_FTSMUL, UNSPEC_FTSSEL, UNSPEC_COND_CMPEQ_WIDE): New unspecs.
+ (UNSPEC_COND_CMPGE_WIDE, UNSPEC_COND_CMPGT_WIDE): Likewise.
+ (UNSPEC_COND_CMPHI_WIDE, UNSPEC_COND_CMPHS_WIDE): Likewise.
+ (UNSPEC_COND_CMPLE_WIDE, UNSPEC_COND_CMPLO_WIDE): Likewise.
+ (UNSPEC_COND_CMPLS_WIDE, UNSPEC_COND_CMPLT_WIDE): Likewise.
+ (UNSPEC_COND_CMPNE_WIDE, UNSPEC_COND_FCADD90, UNSPEC_COND_FCADD270)
+ (UNSPEC_COND_FCMLA, UNSPEC_COND_FCMLA90, UNSPEC_COND_FCMLA180)
+ (UNSPEC_COND_FCMLA270, UNSPEC_COND_FMAX, UNSPEC_COND_FMIN): Likewise.
+ (UNSPEC_COND_FMULX, UNSPEC_COND_FRECPX, UNSPEC_COND_FSCALE): Likewise.
+ (UNSPEC_LASTA, UNSPEC_ASHIFT_WIDE, UNSPEC_ASHIFTRT_WIDE): Likewise.
+ (UNSPEC_LSHIFTRT_WIDE, UNSPEC_LDFF1, UNSPEC_LDNF1): Likewise.
+ (Vesize): Handle partial vector modes.
+ (self_mask, narrower_mask, sve_lane_con, sve_lane_pair_con): New
+ mode attributes.
+ (UBINQOPS, ANY_PLUS, SAT_PLUS, ANY_MINUS, SAT_MINUS): New code
+ iterators.
+ (s, paired_extend, inc_dec): New code attributes.
+ (SVE_INT_ADDV, CLAST, LAST): New int iterators.
+ (SVE_INT_UNARY): Add UNSPEC_RBIT.
+ (SVE_FP_UNARY, SVE_FP_UNARY_INT): New int iterators.
+ (SVE_FP_BINARY, SVE_FP_BINARY_INT): Likewise.
+ (SVE_COND_FP_UNARY): Add UNSPEC_COND_FRECPX.
+ (SVE_COND_FP_BINARY): Add UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and
+ UNSPEC_COND_FMULX.
+ (SVE_COND_FP_BINARY_INT, SVE_COND_FP_ADD): New int iterators.
+ (SVE_COND_FP_SUB, SVE_COND_FP_MUL): Likewise.
+ (SVE_COND_FP_BINARY_I1): Add UNSPEC_COND_FMAX and UNSPEC_COND_FMIN.
+ (SVE_COND_FP_BINARY_REG): Add UNSPEC_COND_FMULX.
+ (SVE_COND_FCADD, SVE_COND_FP_MAXMIN, SVE_COND_FCMLA)
+ (SVE_COND_INT_CMP_WIDE, SVE_FP_TERNARY_LANE, SVE_CFP_TERNARY_LANE)
+ (SVE_WHILE, SVE_SHIFT_WIDE, SVE_LDFF1_LDNF1, SVE_BRK_UNARY)
+ (SVE_BRK_BINARY, SVE_PITER): New int iterators.
+ (optab): Handle UNSPEC_SADDV, UNSPEC_UADDV, UNSPEC_FRECPE,
+ UNSPEC_FRECPS, UNSPEC_RSQRTE, UNSPEC_RSQRTS, UNSPEC_RBIT,
+ UNSPEC_SMUL_HIGHPART, UNSPEC_UMUL_HIGHPART, UNSPEC_FMLA, UNSPEC_FMLS,
+ UNSPEC_FCMLA, UNSPEC_FCMLA90, UNSPEC_FCMLA180, UNSPEC_FCMLA270,
+ UNSPEC_FEXPA, UNSPEC_FTSMUL, UNSPEC_FTSSEL, UNSPEC_COND_FCADD90,
+ UNSPEC_COND_FCADD270, UNSPEC_COND_FCMLA, UNSPEC_COND_FCMLA90,
+ UNSPEC_COND_FCMLA180, UNSPEC_COND_FCMLA270, UNSPEC_COND_FMAX,
+ UNSPEC_COND_FMIN, UNSPEC_COND_FMULX, UNSPEC_COND_FRECPX and
+ UNSPEC_COND_FSCALE.
+ (maxmin_uns): Handle UNSPEC_COND_FMAX and UNSPEC_COND_FMIN.
+ (binqops_op, binqops_op_rev, last_op): New int attributes.
+ (su): Handle UNSPEC_SADDV and UNSPEC_UADDV.
+ (fn, ab): New int attributes.
+ (cmp_op): Handle UNSPEC_COND_CMP*_WIDE and UNSPEC_WHILE_*.
+ (while_optab_cmp, brk_op, sve_pred_op): New int attributes.
+ (sve_int_op): Handle UNSPEC_SMUL_HIGHPART, UNSPEC_UMUL_HIGHPART,
+ UNSPEC_ASHIFT_WIDE, UNSPEC_ASHIFTRT_WIDE, UNSPEC_LSHIFTRT_WIDE and
+ UNSPEC_RBIT.
+ (sve_fp_op): Handle UNSPEC_FRECPE, UNSPEC_FRECPS, UNSPEC_RSQRTE,
+ UNSPEC_RSQRTS, UNSPEC_FMLA, UNSPEC_FMLS, UNSPEC_FEXPA, UNSPEC_FTSMUL,
+ UNSPEC_FTSSEL, UNSPEC_COND_FMAX, UNSPEC_COND_FMIN, UNSPEC_COND_FMULX,
+ UNSPEC_COND_FRECPX and UNSPEC_COND_FSCALE.
+ (sve_fp_op_rev): Handle UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and
+ UNSPEC_COND_FMULX.
+ (rot): Handle UNSPEC_COND_FCADD* and UNSPEC_COND_FCMLA*.
+ (brk_reg_con, brk_reg_opno): New int attributes.
+ (sve_pred_fp_rhs1_operand, sve_pred_fp_rhs2_operand): Handle
+ UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and UNSPEC_COND_FMULX.
+ (sve_pred_fp_rhs2_immediate): Handle UNSPEC_COND_FMAX and
+ UNSPEC_COND_FMIN.
+ (max_elem_bits): New int attribute.
+ (min_elem_bits): Handle UNSPEC_RBIT.
+ * config/aarch64/predicates.md (subreg_lowpart_operator): Handle
+ TRUNCATE as well as SUBREG.
+ (ascending_int_parallel, aarch64_simd_reg_or_minus_one)
+ (aarch64_sve_ldff1_operand, aarch64_sve_ldnf1_operand)
+ (aarch64_sve_prefetch_operand, aarch64_sve_ptrue_svpattern_immediate)
+ (aarch64_sve_qadd_immediate, aarch64_sve_qsub_immediate)
+ (aarch64_sve_gather_immediate_b, aarch64_sve_gather_immediate_h)
+ (aarch64_sve_gather_immediate_w, aarch64_sve_gather_immediate_d)
+ (aarch64_sve_sqadd_operand, aarch64_sve_gather_offset_b)
+ (aarch64_sve_gather_offset_h, aarch64_sve_gather_offset_w)
+ (aarch64_sve_gather_offset_d, aarch64_gather_scale_operand_b)
+ (aarch64_gather_scale_operand_h): New predicates.
+ * config/aarch64/constraints.md (UPb, UPd, UPh, UPw, Utf, Utn, vgb)
+ (vgd, vgh, vgw, vsQ, vsS): New constraints.
+ * config/aarch64/aarch64-sve.md: Add a note on the FFR handling.
+ (*aarch64_sve_reinterpret<mode>): Allow any source register
+ instead of requiring an exact match.
+ (*aarch64_sve_ptruevnx16bi_cc, *aarch64_sve_ptrue<mode>_cc)
+ (*aarch64_sve_ptruevnx16bi_ptest, *aarch64_sve_ptrue<mode>_ptest)
+ (aarch64_wrffr, aarch64_update_ffr_for_load, aarch64_copy_ffr_to_ffrt)
+ (aarch64_rdffr, aarch64_rdffr_z, *aarch64_rdffr_z_ptest)
+ (*aarch64_rdffr_ptest, *aarch64_rdffr_z_cc, *aarch64_rdffr_cc)
+ (aarch64_update_ffrt): New patterns.
+ (@aarch64_load_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>)
+ (@aarch64_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+ (@aarch64_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+ (@aarch64_ld<fn>f1<mode>): New patterns.
+ (@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>)
+ (@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+ (@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+ (@aarch64_ldnt1<mode>): New patterns.
+ (gather_load<mode>): Use aarch64_sve_gather_offset_<Vesize> for
+ the scalar part of the address.
+ (mask_gather_load<SVE_S:mode>): Use aarch64_sve_gather_offset_w for the
+ scalar part of the addresse and add an alternative for handling
+ nonzero offsets.
+ (mask_gather_load<SVE_D:mode>): Likewise aarch64_sve_gather_offset_d.
+ (*mask_gather_load<mode>_sxtw, *mask_gather_load<mode>_uxtw)
+ (@aarch64_gather_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+ (@aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+ (*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw)
+ (*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw)
+ (@aarch64_ldff1_gather<SVE_S:mode>, @aarch64_ldff1_gather<SVE_D:mode>)
+ (*aarch64_ldff1_gather<mode>_sxtw, *aarch64_ldff1_gather<mode>_uxtw)
+ (@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+ (@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+ (*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw)
+ (*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw)
+ (@aarch64_sve_prefetch<mode>): New patterns.
+ (@aarch64_sve_gather_prefetch<SVE_I:mode><VNx4SI_ONLY:mode>)
+ (@aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>)
+ (*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_sxtw)
+ (*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_uxtw)
+ (@aarch64_store_trunc<VNx8_NARROW:mode><VNx8_WIDE:mode>)
+ (@aarch64_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>)
+ (@aarch64_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>)
+ (@aarch64_stnt1<mode>): New patterns.
+ (scatter_store<mode>): Use aarch64_sve_gather_offset_<Vesize> for
+ the scalar part of the address.
+ (mask_scatter_store<SVE_S:mode>): Use aarch64_sve_gather_offset_w for
+ the scalar part of the addresse and add an alternative for handling
+ nonzero offsets.
+ (mask_scatter_store<SVE_D:mode>): Likewise aarch64_sve_gather_offset_d.
+ (*mask_scatter_store<mode>_sxtw, *mask_scatter_store<mode>_uxtw)
+ (@aarch64_scatter_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>)
+ (@aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>)
+ (*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_sxtw)
+ (*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_uxtw):
+ New patterns.
+ (vec_duplicate<mode>): Use QI as the mode of the input operand.
+ (extract_last_<mode>): Generalize to...
+ (@extract_<LAST:last_op>_<mode>): ...this.
+ (*<SVE_INT_UNARY:optab><mode>2): Rename to...
+ (@aarch64_pred_<SVE_INT_UNARY:optab><mode>): ...this.
+ (@cond_<SVE_INT_UNARY:optab><mode>): New expander.
+ (@aarch64_pred_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>): New pattern.
+ (@aarch64_cond_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>): Likewise.
+ (@aarch64_pred_cnot<mode>, @cond_cnot<mode>): New expanders.
+ (@aarch64_sve_<SVE_FP_UNARY_INT:optab><mode>): New pattern.
+ (@aarch64_sve_<SVE_FP_UNARY:optab><mode>): Likewise.
+ (*<SVE_COND_FP_UNARY:optab><mode>2): Rename to...
+ (@aarch64_pred_<SVE_COND_FP_UNARY:optab><mode>): ...this.
+ (@cond_<SVE_COND_FP_UNARY:optab><mode>): New expander.
+ (*<SVE_INT_BINARY_IMM:optab><mode>3): Rename to...
+ (@aarch64_pred_<SVE_INT_BINARY_IMM:optab><mode>): ...this.
+ (@aarch64_adr<mode>, *aarch64_adr_sxtw): New patterns.
+ (*aarch64_adr_uxtw_unspec): Likewise.
+ (*aarch64_adr_uxtw): Rename to...
+ (*aarch64_adr_uxtw_and): ...this.
+ (@aarch64_adr<mode>_shift): New expander.
+ (*aarch64_adr_shift_sxtw): New pattern.
+ (aarch64_<su>abd<mode>_3): Rename to...
+ (@aarch64_pred_<su>abd<mode>): ...this.
+ (<su>abd<mode>_3): Update accordingly.
+ (@aarch64_cond_<su>abd<mode>): New expander.
+ (@aarch64_<SBINQOPS:su_optab><optab><mode>): New pattern.
+ (@aarch64_<UBINQOPS:su_optab><optab><mode>): Likewise.
+ (*<su>mul<mode>3_highpart): Rename to...
+ (@aarch64_pred_<optab><mode>): ...this.
+ (@cond_<MUL_HIGHPART:optab><mode>): New expander.
+ (*cond_<MUL_HIGHPART:optab><mode>_2): New pattern.
+ (*cond_<MUL_HIGHPART:optab><mode>_z): Likewise.
+ (*<SVE_INT_BINARY_SD:optab><mode>3): Rename to...
+ (@aarch64_pred_<SVE_INT_BINARY_SD:optab><mode>): ...this.
+ (cond_<SVE_INT_BINARY_SD:optab><mode>): Add a "@" marker.
+ (@aarch64_bic<mode>, @cond_bic<mode>): New expanders.
+ (*v<ASHIFT:optab><mode>3): Rename to...
+ (@aarch64_pred_<ASHIFT:optab><mode>): ...this.
+ (@aarch64_sve_<SVE_SHIFT_WIDE:sve_int_op><mode>): New pattern.
+ (@cond_<SVE_SHIFT_WIDE:sve_int_op><mode>): New expander.
+ (*cond_<SVE_SHIFT_WIDE:sve_int_op><mode>_m): New pattern.
+ (*cond_<SVE_SHIFT_WIDE:sve_int_op><mode>_z): Likewise.
+ (@cond_asrd<mode>): New expander.
+ (*cond_asrd<mode>_2, *cond_asrd<mode>_z): New patterns.
+ (sdiv_pow2<mode>3): Expand to *cond_asrd<mode>_2.
+ (*sdiv_pow2<mode>3): Delete.
+ (@cond_<SVE_COND_FP_BINARY_INT:optab><mode>): New expander.
+ (*cond_<SVE_COND_FP_BINARY_INT:optab><mode>_2): New pattern.
+ (*cond_<SVE_COND_FP_BINARY_INT:optab><mode>_any): Likewise.
+ (@aarch64_sve_<SVE_FP_BINARY:optab><mode>): New pattern.
+ (@aarch64_sve_<SVE_FP_BINARY_INT:optab><mode>): Likewise.
+ (*<SVE_COND_FP_BINARY_REG:optab><mode>3): Rename to...
+ (@aarch64_pred_<SVE_COND_FP_BINARY_REG:optab><mode>): ...this.
+ (@aarch64_pred_<SVE_COND_FP_BINARY_INT:optab><mode>): New pattern.
+ (cond_<SVE_COND_FP_BINARY:optab><mode>): Add a "@" marker.
+ (*add<SVE_F:mode>3): Rename to...
+ (@aarch64_pred_add<SVE_F:mode>): ...this and add alternatives
+ for SVE_STRICT_GP.
+ (@aarch64_pred_<SVE_COND_FCADD:optab><mode>): New pattern.
+ (@cond_<SVE_COND_FCADD:optab><mode>): New expander.
+ (*cond_<SVE_COND_FCADD:optab><mode>_2): New pattern.
+ (*cond_<SVE_COND_FCADD:optab><mode>_any): Likewise.
+ (*sub<SVE_F:mode>3): Rename to...
+ (@aarch64_pred_sub<SVE_F:mode>): ...this and add alternatives
+ for SVE_STRICT_GP.
+ (@aarch64_pred_abd<SVE_F:mode>): New expander.
+ (*fabd<SVE_F:mode>3): Rename to...
+ (*aarch64_pred_abd<SVE_F:mode>): ...this.
+ (@aarch64_cond_abd<SVE_F:mode>): New expander.
+ (*mul<SVE_F:mode>3): Rename to...
+ (@aarch64_pred_<SVE_F:optab><mode>): ...this and add alternatives
+ for SVE_STRICT_GP.
+ (@aarch64_mul_lane_<SVE_F:mode>): New pattern.
+ (*<SVE_COND_FP_MAXMIN_PUBLIC:optab><mode>3): Rename and generalize
+ to...
+ (@aarch64_pred_<SVE_COND_FP_MAXMIN:optab><mode>): ...this.
+ (*<LOGICAL:optab><PRED_ALL:mode>3_ptest): New pattern.
+ (*<nlogical><PRED_ALL:mode>3): Rename to...
+ (aarch64_pred_<nlogical><PRED_ALL:mode>_z): ...this.
+ (*<nlogical><PRED_ALL:mode>3_cc): New pattern.
+ (*<nlogical><PRED_ALL:mode>3_ptest): Likewise.
+ (*<logical_nn><PRED_ALL:mode>3): Rename to...
+ (aarch64_pred_<logical_nn><mode>_z): ...this.
+ (*<logical_nn><PRED_ALL:mode>3_cc): New pattern.
+ (*<logical_nn><PRED_ALL:mode>3_ptest): Likewise.
+ (*fma<SVE_I:mode>4): Rename to...
+ (@aarch64_pred_fma<SVE_I:mode>): ...this.
+ (*fnma<SVE_I:mode>4): Rename to...
+ (@aarch64_pred_fnma<SVE_I:mode>): ...this.
+ (@aarch64_<sur>dot_prod_lane<vsi2qi>): New pattern.
+ (*<SVE_FP_TERNARY:optab><mode>4): Rename to...
+ (@aarch64_pred_<SVE_FP_TERNARY:optab><mode>): ...this.
+ (cond_<SVE_FP_TERNARY:optab><mode>): Add a "@" marker.
+ (@aarch64_<SVE_FP_TERNARY_LANE:optab>_lane_<mode>): New pattern.
+ (@aarch64_pred_<SVE_COND_FCMLA:optab><mode>): Likewise.
+ (@cond_<SVE_COND_FCMLA:optab><mode>): New expander.
+ (*cond_<SVE_COND_FCMLA:optab><mode>_4): New pattern.
+ (*cond_<SVE_COND_FCMLA:optab><mode>_any): Likewise.
+ (@aarch64_<FCMLA:optab>_lane_<mode>): Likewise.
+ (@aarch64_sve_tmad<mode>): Likewise.
+ (vcond_mask_<SVE_ALL:mode><vpred>): Add a "@" marker.
+ (*aarch64_sel_dup<mode>): Rename to...
+ (@aarch64_sel_dup<mode>): ...this.
+ (@aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide): New pattern.
+ (*aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide_cc): Likewise.
+ (*aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide_ptest): Likewise.
+ (@while_ult<GPI:mode><PRED_ALL:mode>): Generalize to...
+ (@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>): ...this.
+ (*while_ult<GPI:mode><PRED_ALL:mode>_cc): Generalize to.
+ (*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_cc): ...this.
+ (*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest): New pattern.
+ (*fcm<cmp_op><mode>): Rename to...
+ (@aarch64_pred_fcm<cmp_op><mode>): ...this. Make operand order
+ match @aarch64_pred_cmp<cmp_op><SVE_I:mode>.
+ (*fcmuo<mode>): Rename to...
+ (@aarch64_pred_fcmuo<mode>): ...this. Make operand order
+ match @aarch64_pred_cmp<cmp_op><SVE_I:mode>.
+ (@aarch64_pred_fac<cmp_op><mode>): New expander.
+ (@vcond_mask_<PRED_ALL:mode><mode>): New pattern.
+ (fold_extract_last_<mode>): Generalize to...
+ (@fold_extract_<last_op>_<mode>): ...this.
+ (@aarch64_fold_extract_vector_<last_op>_<mode>): New pattern.
+ (*reduc_plus_scal_<SVE_I:mode>): Replace with...
+ (@aarch64_pred_reduc_<optab>_<mode>): ...this pattern, making the
+ DImode result explicit.
+ (reduc_plus_scal_<mode>): Update accordingly.
+ (*reduc_<optab>_scal_<SVE_I:mode>): Rename to...
+ (@aarch64_pred_reduc_<optab>_<SVE_I:mode>): ...this.
+ (*reduc_<optab>_scal_<SVE_F:mode>): Rename to...
+ (@aarch64_pred_reduc_<optab>_<SVE_F:mode>): ...this.
+ (*aarch64_sve_tbl<mode>): Rename to...
+ (@aarch64_sve_tbl<mode>): ...this.
+ (@aarch64_sve_compact<mode>): New pattern.
+ (*aarch64_sve_dup_lane<mode>): Rename to...
+ (@aarch64_sve_dup_lane<mode>): ...this.
+ (@aarch64_sve_dupq_lane<mode>): New pattern.
+ (@aarch64_sve_splice<mode>): Likewise.
+ (aarch64_sve_<perm_insn><mode>): Rename to...
+ (@aarch64_sve_<perm_insn><mode>): ...this.
+ (*aarch64_sve_ext<mode>): Rename to...
+ (@aarch64_sve_ext<mode>): ...this.
+ (aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>): Add a "@" marker.
+ (*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): Rename
+ to...
+ (@aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): ...this.
+ (*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
+ Rename to...
+ (@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
+ ...this.
+ (@cond_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): New expander.
+ (@cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>): Likewise.
+ (*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>): New pattern.
+ (*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): Rename
+ to...
+ (@aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): ...this.
+ (aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): Add
+ a "@" marker.
+ (@cond_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): New expander.
+ (@cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): Likewise.
+ (*cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): New
+ pattern.
+ (*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): Rename to...
+ (@aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): ...this.
+ (@cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): New expander.
+ (*cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): New pattern.
+ (aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): Add a
+ "@" marker.
+ (@cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): New expander.
+ (*cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): New pattern.
+ (aarch64_sve_punpk<perm_hilo>_<mode>): Add a "@" marker.
+ (@aarch64_brk<SVE_BRK_UNARY:brk_op>): New pattern.
+ (*aarch64_brk<SVE_BRK_UNARY:brk_op>_cc): Likewise.
+ (*aarch64_brk<SVE_BRK_UNARY:brk_op>_ptest): Likewise.
+ (@aarch64_brk<SVE_BRK_BINARY:brk_op>): Likewise.
+ (*aarch64_brk<SVE_BRK_BINARY:brk_op>_cc): Likewise.
+ (*aarch64_brk<SVE_BRK_BINARY:brk_op>_ptest): Likewise.
+ (@aarch64_sve_<SVE_PITER:sve_pred_op><mode>): Likewise.
+ (*aarch64_sve_<SVE_PITER:sve_pred_op><mode>_cc): Likewise.
+ (*aarch64_sve_<SVE_PITER:sve_pred_op><mode>_ptest): Likewise.
+ (aarch64_sve_cnt_pat): Likewise.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode>_pat): Likewise.
+ (*aarch64_sve_incsi_pat): Likewise.
+ (@aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode>_pat): Likewise.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_pat): Likewise.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_pat): Likewise.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_pat): New expander.
+ (*aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_pat): New pattern.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode>_pat): Likewise.
+ (*aarch64_sve_decsi_pat): Likewise.
+ (@aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode>_pat): Likewise.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_pat): Likewise.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_pat): Likewise.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_pat): New expander.
+ (*aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_pat): New pattern.
+ (@aarch64_pred_cntp<mode>): Likewise.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp):
+ New expander.
+ (*aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp)
+ (*aarch64_incsi<PRED_ALL:mode>_cntp): New patterns.
+ (@aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+ New expander.
+ (*aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+ New pattern.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New expander.
+ (*aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New pattern.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New expander.
+ (*aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New pattern.
+ (@aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New expander.
+ (*aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New pattern.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp):
+ New expander.
+ (*aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp)
+ (*aarch64_incsi<PRED_ALL:mode>_cntp): New patterns.
+ (@aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+ New expander.
+ (*aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+ New pattern.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New
+ expander.
+ (*aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New pattern.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New
+ expander.
+ (*aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New pattern.
+ (@aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New
+ expander.
+ (*aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New pattern.
+ * config/aarch64/arm_sve.h: New file.
+ * config/aarch64/aarch64-sve-builtins.h: Likewise.
+ * config/aarch64/aarch64-sve-builtins.cc: Likewise.
+ * config/aarch64/aarch64-sve-builtins.def: Likewise.
+ * config/aarch64/aarch64-sve-builtins-base.h: Likewise.
+ * config/aarch64/aarch64-sve-builtins-base.cc: Likewise.
+ * config/aarch64/aarch64-sve-builtins-base.def: Likewise.
+ * config/aarch64/aarch64-sve-builtins-functions.h: Likewise.
+ * config/aarch64/aarch64-sve-builtins-shapes.h: Likewise.
+ * config/aarch64/aarch64-sve-builtins-shapes.cc: Likewise.
+
2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
* config/aarch64/aarch64-sve.md (@aarch64_sve_rev<PRED_ALL:mode>):
;;
aarch64*-*-*)
cpu_type=aarch64
- extra_headers="arm_fp16.h arm_neon.h arm_acle.h"
+ extra_headers="arm_fp16.h arm_neon.h arm_acle.h arm_sve.h"
c_target_objs="aarch64-c.o"
cxx_target_objs="aarch64-c.o"
d_target_objs="aarch64-d.o"
- extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o"
- target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c"
+ extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o"
+ target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
target_has_targetm_common=yes
;;
alpha*-*-*)
return true;
}
+/* Implement "#pragma GCC aarch64". */
+static void
+aarch64_pragma_aarch64 (cpp_reader *)
+{
+ tree x;
+ if (pragma_lex (&x) != CPP_STRING)
+ {
+ error ("%<#pragma GCC aarch64%> requires a string parameter");
+ return;
+ }
+
+ const char *name = TREE_STRING_POINTER (x);
+ if (strcmp (name, "arm_sve.h") == 0)
+ aarch64_sve::handle_arm_sve_h ();
+ else
+ error ("unknown %<#pragma GCC aarch64%> option %qs", name);
+}
+
+/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN. */
+static tree
+aarch64_resolve_overloaded_builtin (unsigned int uncast_location,
+ tree fndecl, void *uncast_arglist)
+{
+ vec<tree, va_gc> empty = {};
+ location_t location = (location_t) uncast_location;
+ vec<tree, va_gc> *arglist = (uncast_arglist
+ ? (vec<tree, va_gc> *) uncast_arglist
+ : &empty);
+ unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
+ unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
+ tree new_fndecl;
+ switch (code & AARCH64_BUILTIN_CLASS)
+ {
+ case AARCH64_BUILTIN_GENERAL:
+ return NULL_TREE;
+
+ case AARCH64_BUILTIN_SVE:
+ new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode,
+ arglist);
+ break;
+ }
+ if (new_fndecl == NULL_TREE || new_fndecl == error_mark_node)
+ return new_fndecl;
+ return build_function_call_vec (location, vNULL, new_fndecl, arglist,
+ NULL, fndecl);
+}
+
+/* Implement TARGET_CHECK_BUILTIN_CALL. */
+static bool
+aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc,
+ tree fndecl, tree orig_fndecl,
+ unsigned int nargs, tree *args)
+{
+ unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
+ unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
+ switch (code & AARCH64_BUILTIN_CLASS)
+ {
+ case AARCH64_BUILTIN_GENERAL:
+ return true;
+
+ case AARCH64_BUILTIN_SVE:
+ return aarch64_sve::check_builtin_call (loc, arg_loc, subcode,
+ orig_fndecl, nargs, args);
+ }
+ gcc_unreachable ();
+}
+
/* Implement REGISTER_TARGET_PRAGMAS. */
void
{
/* Update pragma hook to allow parsing #pragma GCC target. */
targetm.target_option.pragma_parse = aarch64_pragma_target_parse;
+
+ targetm.resolve_overloaded_builtin = aarch64_resolve_overloaded_builtin;
+ targetm.check_builtin_call = aarch64_check_builtin_call;
+
+ c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64);
}
T (MUL3, mul3, 30) \
T (ALL, all, 31)
+/* The available SVE prefetch operations, known in the ACLE as "svprfop". */
+#define AARCH64_FOR_SVPRFOP(T) \
+ T (PLDL1KEEP, pldl1keep, 0) \
+ T (PLDL1STRM, pldl1strm, 1) \
+ T (PLDL2KEEP, pldl2keep, 2) \
+ T (PLDL2STRM, pldl2strm, 3) \
+ T (PLDL3KEEP, pldl3keep, 4) \
+ T (PLDL3STRM, pldl3strm, 5) \
+ T (PSTL1KEEP, pstl1keep, 8) \
+ T (PSTL1STRM, pstl1strm, 9) \
+ T (PSTL2KEEP, pstl2keep, 10) \
+ T (PSTL2STRM, pstl2strm, 11) \
+ T (PSTL3KEEP, pstl3keep, 12) \
+ T (PSTL3STRM, pstl3strm, 13)
+
#define AARCH64_SVENUM(UPPER, LOWER, VALUE) AARCH64_SV_##UPPER = VALUE,
enum aarch64_svpattern {
AARCH64_FOR_SVPATTERN (AARCH64_SVENUM)
AARCH64_NUM_SVPATTERNS
};
+
+enum aarch64_svprfop {
+ AARCH64_FOR_SVPRFOP (AARCH64_SVENUM)
+ AARCH64_NUM_SVPRFOPS
+};
#undef AARCH64_SVENUM
/* It's convenient to divide the built-in function codes into groups,
those groups. */
enum aarch64_builtin_class
{
- AARCH64_BUILTIN_GENERAL
+ AARCH64_BUILTIN_GENERAL,
+ AARCH64_BUILTIN_SVE
};
/* Built-in function codes are structured so that the low
unsigned HOST_WIDE_INT);
bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
+machine_mode aarch64_sve_int_mode (machine_mode);
opt_machine_mode aarch64_sve_pred_mode (unsigned int);
+opt_machine_mode aarch64_sve_data_mode (scalar_mode, poly_uint64);
bool aarch64_sve_mode_p (machine_mode);
+HOST_WIDE_INT aarch64_fold_sve_cnt_pat (aarch64_svpattern, unsigned int);
bool aarch64_sve_cnt_immediate_p (rtx);
bool aarch64_sve_scalar_inc_dec_immediate_p (rtx);
bool aarch64_sve_addvl_addpl_immediate_p (rtx);
rtx aarch64_reverse_mask (machine_mode, unsigned int);
bool aarch64_offset_7bit_signed_scaled_p (machine_mode, poly_int64);
bool aarch64_offset_9bit_signed_unscaled_p (machine_mode, poly_int64);
+char *aarch64_output_sve_prefetch (const char *, rtx, const char *);
char *aarch64_output_sve_cnt_immediate (const char *, const char *, rtx);
+char *aarch64_output_sve_cnt_pat_immediate (const char *, const char *, rtx *);
char *aarch64_output_sve_scalar_inc_dec (rtx);
char *aarch64_output_sve_addvl_addpl (rtx);
char *aarch64_output_sve_vector_inc_dec (const char *, rtx);
char *aarch64_output_simd_mov_immediate (rtx, unsigned,
enum simd_immediate_check w = AARCH64_CHECK_MOV);
char *aarch64_output_sve_mov_immediate (rtx);
+char *aarch64_output_sve_ptrues (rtx);
bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
bool aarch64_regno_ok_for_base_p (int, bool);
bool aarch64_regno_ok_for_index_p (int, bool);
bool high);
bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode);
bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
+bool aarch64_sve_ptrue_svpattern_p (rtx, struct simd_immediate_info *);
bool aarch64_simd_valid_immediate (rtx, struct simd_immediate_info *,
enum simd_immediate_check w = AARCH64_CHECK_MOV);
rtx aarch64_check_zero_based_sve_index_immediate (rtx);
bool aarch64_sve_index_immediate_p (rtx);
bool aarch64_sve_arith_immediate_p (rtx, bool);
+bool aarch64_sve_sqadd_sqsub_immediate_p (rtx, bool);
bool aarch64_sve_bitmask_immediate_p (rtx);
bool aarch64_sve_dup_immediate_p (rtx);
bool aarch64_sve_cmp_immediate_p (rtx, bool);
bool aarch64_simd_mem_operand_p (rtx);
bool aarch64_sve_ld1r_operand_p (rtx);
bool aarch64_sve_ld1rq_operand_p (rtx);
+bool aarch64_sve_ldff1_operand_p (rtx);
+bool aarch64_sve_ldnf1_operand_p (rtx);
bool aarch64_sve_ldr_operand_p (rtx);
+bool aarch64_sve_prefetch_operand_p (rtx, machine_mode);
bool aarch64_sve_struct_memory_operand_p (rtx);
rtx aarch64_simd_vect_par_cnst_half (machine_mode, int, bool);
rtx aarch64_gen_stepped_int_parallel (unsigned int, int, int);
void aarch64_err_no_fpadvsimd (machine_mode);
void aarch64_expand_epilogue (bool);
rtx aarch64_ptrue_all (unsigned int);
+opt_machine_mode aarch64_ptrue_all_mode (rtx);
+rtx aarch64_convert_sve_data_to_pred (rtx, machine_mode, rtx);
+rtx aarch64_expand_sve_dupq (rtx, machine_mode, rtx);
void aarch64_expand_mov_immediate (rtx, rtx);
rtx aarch64_ptrue_reg (machine_mode);
rtx aarch64_pfalse_reg (machine_mode);
void aarch64_emit_sve_pred_move (rtx, rtx, rtx);
void aarch64_expand_sve_mem_move (rtx, rtx, machine_mode);
bool aarch64_maybe_expand_sve_subreg_move (rtx, rtx);
+rtx aarch64_replace_reg_mode (rtx, machine_mode);
void aarch64_split_sve_subreg_move (rtx, rtx, rtx);
void aarch64_expand_prologue (void);
void aarch64_expand_vector_init (rtx, rtx);
tree aarch64_general_builtin_rsqrt (unsigned int);
tree aarch64_builtin_vectorized_function (unsigned int, tree, tree);
+namespace aarch64_sve {
+ void init_builtins ();
+ void handle_arm_sve_h ();
+ tree builtin_decl (unsigned, bool);
+ bool builtin_type_p (const_tree);
+ const char *mangle_builtin_type (const_tree);
+ tree resolve_overloaded_builtin (location_t, unsigned int,
+ vec<tree, va_gc> *);
+ bool check_builtin_call (location_t, vec<location_t>, unsigned int,
+ tree, unsigned int, tree *);
+ gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *);
+ rtx expand_builtin (unsigned int, tree, rtx);
+}
+
extern void aarch64_split_combinev16qi (rtx operands[3]);
extern void aarch64_expand_vec_perm (rtx, rtx, rtx, rtx, unsigned int);
extern void aarch64_expand_sve_vec_perm (rtx, rtx, rtx, rtx);
--- /dev/null
+/* ACLE support for AArch64 SVE (__ARM_FEATURE_SVE intrinsics)
+ Copyright (C) 2018-2019 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "function.h"
+#include "fold-const.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "tree-vector-builder.h"
+#include "rtx-vector-builder.h"
+#include "vec-perm-indices.h"
+#include "aarch64-sve-builtins.h"
+#include "aarch64-sve-builtins-shapes.h"
+#include "aarch64-sve-builtins-base.h"
+#include "aarch64-sve-builtins-functions.h"
+
+using namespace aarch64_sve;
+
+namespace {
+
+/* Expand a call to svmad, or svmla after reordering its operands.
+ Make _m forms merge with argument MERGE_ARGNO. */
+static rtx
+expand_mad (function_expander &e,
+ unsigned int merge_argno = DEFAULT_MERGE_ARGNO)
+{
+ if (e.pred == PRED_x)
+ {
+ insn_code icode;
+ if (e.type_suffix (0).integer_p)
+ icode = code_for_aarch64_pred_fma (e.vector_mode (0));
+ else
+ icode = code_for_aarch64_pred (UNSPEC_COND_FMLA, e.vector_mode (0));
+ return e.use_pred_x_insn (icode);
+ }
+
+ insn_code icode = e.direct_optab_handler (cond_fma_optab);
+ return e.use_cond_insn (icode, merge_argno);
+}
+
+/* Expand a call to svmsb, or svmls after reordering its operands.
+ Make _m forms merge with argument MERGE_ARGNO. */
+static rtx
+expand_msb (function_expander &e,
+ unsigned int merge_argno = DEFAULT_MERGE_ARGNO)
+{
+ if (e.pred == PRED_x)
+ {
+ insn_code icode;
+ if (e.type_suffix (0).integer_p)
+ icode = code_for_aarch64_pred_fnma (e.vector_mode (0));
+ else
+ icode = code_for_aarch64_pred (UNSPEC_COND_FMLS, e.vector_mode (0));
+ return e.use_pred_x_insn (icode);
+ }
+
+ insn_code icode = e.direct_optab_handler (cond_fnma_optab);
+ return e.use_cond_insn (icode, merge_argno);
+}
+
+class svabd_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* The integer operations are represented as the subtraction of the
+ minimum from the maximum, with the signedness of the instruction
+ keyed off the signedness of the maximum operation. */
+ rtx_code max_code = e.type_suffix (0).unsigned_p ? UMAX : SMAX;
+ insn_code icode;
+ if (e.pred == PRED_x)
+ {
+ if (e.type_suffix (0).integer_p)
+ icode = code_for_aarch64_pred_abd (max_code, e.vector_mode (0));
+ else
+ icode = code_for_aarch64_pred_abd (e.vector_mode (0));
+ return e.use_pred_x_insn (icode);
+ }
+
+ if (e.type_suffix (0).integer_p)
+ icode = code_for_aarch64_cond_abd (max_code, e.vector_mode (0));
+ else
+ icode = code_for_aarch64_cond_abd (e.vector_mode (0));
+ return e.use_cond_insn (icode);
+ }
+};
+
+/* Implements svacge, svacgt, svacle and svaclt. */
+class svac_impl : public function_base
+{
+public:
+ CONSTEXPR svac_impl (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.add_ptrue_hint (0, e.gp_mode (0));
+ insn_code icode = code_for_aarch64_pred_fac (m_unspec, e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+
+ /* The unspec code for the underlying comparison. */
+ int m_unspec;
+};
+
+class svadda_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Put the predicate last, as required by mask_fold_left_plus_optab. */
+ e.rotate_inputs_left (0, 3);
+ machine_mode mode = e.vector_mode (0);
+ insn_code icode = direct_optab_handler (mask_fold_left_plus_optab, mode);
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements svadr[bhwd]. */
+class svadr_bhwd_impl : public function_base
+{
+public:
+ CONSTEXPR svadr_bhwd_impl (unsigned int shift) : m_shift (shift) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = GET_MODE (e.args[0]);
+ if (m_shift == 0)
+ return e.use_exact_insn (code_for_aarch64_adr (mode));
+
+ /* Turn the access size into an extra shift argument. */
+ rtx shift = gen_int_mode (m_shift, GET_MODE_INNER (mode));
+ e.args.quick_push (expand_vector_broadcast (mode, shift));
+ return e.use_exact_insn (code_for_aarch64_adr_shift (mode));
+ }
+
+ /* How many bits left to shift the vector displacement. */
+ unsigned int m_shift;
+};
+
+class svasrd_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_cond_insn (code_for_cond_asrd (e.vector_mode (0)));
+ }
+};
+
+class svbic_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Convert svbic of a constant into svand of its inverse. */
+ if (CONST_INT_P (e.args[2]))
+ {
+ machine_mode mode = GET_MODE_INNER (e.vector_mode (0));
+ e.args[2] = simplify_unary_operation (NOT, mode, e.args[2], mode);
+ return e.map_to_rtx_codes (AND, AND, -1);
+ }
+
+ if (e.type_suffix_ids[0] == TYPE_SUFFIX_b)
+ {
+ gcc_assert (e.pred == PRED_z);
+ return e.use_exact_insn (CODE_FOR_aarch64_pred_bicvnx16bi_z);
+ }
+
+ if (e.pred == PRED_x)
+ return e.use_unpred_insn (code_for_aarch64_bic (e.vector_mode (0)));
+
+ return e.use_cond_insn (code_for_cond_bic (e.vector_mode (0)));
+ }
+};
+
+/* Implements svbrkn, svbrkpa and svbrkpb. */
+class svbrk_binary_impl : public function_base
+{
+public:
+ CONSTEXPR svbrk_binary_impl (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_brk (m_unspec));
+ }
+
+ /* The unspec code associated with the operation. */
+ int m_unspec;
+};
+
+/* Implements svbrka and svbrkb. */
+class svbrk_unary_impl : public function_base
+{
+public:
+ CONSTEXPR svbrk_unary_impl (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_cond_insn (code_for_aarch64_brk (m_unspec));
+ }
+
+ /* The unspec code associated with the operation. */
+ int m_unspec;
+};
+
+class svcadd_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Convert the rotation amount into a specific unspec. */
+ int rot = INTVAL (e.args[3]);
+ e.args.ordered_remove (3);
+ int unspec = (rot == 90 ? UNSPEC_COND_FCADD90
+ : rot == 270 ? UNSPEC_COND_FCADD270
+ : (gcc_unreachable (), 0));
+ return e.map_to_unspecs (-1, -1, unspec);
+ }
+};
+
+/* Implements svclasta and svclastb. */
+class svclast_impl : public quiet<function_base>
+{
+public:
+ CONSTEXPR svclast_impl (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Match the fold_extract_optab order. */
+ std::swap (e.args[0], e.args[1]);
+ machine_mode mode = e.vector_mode (0);
+ insn_code icode;
+ if (e.mode_suffix_id == MODE_n)
+ icode = code_for_fold_extract (m_unspec, mode);
+ else
+ icode = code_for_aarch64_fold_extract_vector (m_unspec, mode);
+ return e.use_exact_insn (icode);
+ }
+
+ /* The unspec code associated with the operation. */
+ int m_unspec;
+};
+
+class svcmla_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Convert the rotation amount into a specific unspec. */
+ int rot = INTVAL (e.args[4]);
+ e.args.ordered_remove (4);
+ int unspec = (rot == 0 ? UNSPEC_COND_FCMLA
+ : rot == 90 ? UNSPEC_COND_FCMLA90
+ : rot == 180 ? UNSPEC_COND_FCMLA180
+ : rot == 270 ? UNSPEC_COND_FCMLA270
+ : (gcc_unreachable (), 0));
+
+ /* Make the operand order the same as the one used by the fma optabs,
+ with the accumulator last. */
+ e.rotate_inputs_left (1, 4);
+ return e.map_to_unspecs (-1, -1, unspec, 3);
+ }
+};
+
+class svcmla_lane_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Convert the rotation amount into a specific unspec. */
+ int rot = INTVAL (e.args[4]);
+ e.args.ordered_remove (4);
+ int unspec = (rot == 0 ? UNSPEC_FCMLA
+ : rot == 90 ? UNSPEC_FCMLA90
+ : rot == 180 ? UNSPEC_FCMLA180
+ : rot == 270 ? UNSPEC_FCMLA270
+ : (gcc_unreachable (), 0));
+
+ /* Make the operand order the same as the one used by the fma optabs,
+ with the accumulator last. */
+ e.rotate_inputs_left (0, 4);
+ insn_code icode = code_for_aarch64_lane (unspec, e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements svcmp<cc> (except svcmpuo, which is handled separately). */
+class svcmp_impl : public function_base
+{
+public:
+ CONSTEXPR svcmp_impl (tree_code code, int unspec_for_fp)
+ : m_code (code), m_unspec_for_fp (unspec_for_fp) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+
+ /* Comparisons are UNSPEC_PRED_Z operations and so need a hint
+ operand. */
+ e.add_ptrue_hint (0, e.gp_mode (0));
+
+ if (e.type_suffix (0).integer_p)
+ {
+ bool unsigned_p = e.type_suffix (0).unsigned_p;
+ rtx_code code = get_rtx_code (m_code, unsigned_p);
+ return e.use_exact_insn (code_for_aarch64_pred_cmp (code, mode));
+ }
+
+ insn_code icode = code_for_aarch64_pred_fcm (m_unspec_for_fp, mode);
+ return e.use_exact_insn (icode);
+ }
+
+ /* The tree code associated with the comparison. */
+ tree_code m_code;
+
+ /* The unspec code to use for floating-point comparisons. */
+ int m_unspec_for_fp;
+};
+
+/* Implements svcmp<cc>_wide. */
+class svcmp_wide_impl : public function_base
+{
+public:
+ CONSTEXPR svcmp_wide_impl (tree_code code, int unspec_for_sint,
+ int unspec_for_uint)
+ : m_code (code), m_unspec_for_sint (unspec_for_sint),
+ m_unspec_for_uint (unspec_for_uint) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ bool unsigned_p = e.type_suffix (0).unsigned_p;
+ rtx_code code = get_rtx_code (m_code, unsigned_p);
+
+ /* Comparisons are UNSPEC_PRED_Z operations and so need a hint
+ operand. */
+ e.add_ptrue_hint (0, e.gp_mode (0));
+
+ /* If the argument is a constant that the unwidened comparisons
+ can handle directly, use them instead. */
+ insn_code icode = code_for_aarch64_pred_cmp (code, mode);
+ rtx op2 = unwrap_const_vec_duplicate (e.args[3]);
+ if (CONSTANT_P (op2)
+ && insn_data[icode].operand[4].predicate (op2, DImode))
+ {
+ e.args[3] = op2;
+ return e.use_exact_insn (icode);
+ }
+
+ int unspec = (unsigned_p ? m_unspec_for_uint : m_unspec_for_sint);
+ return e.use_exact_insn (code_for_aarch64_pred_cmp_wide (unspec, mode));
+ }
+
+ /* The tree code associated with the comparison. */
+ tree_code m_code;
+
+ /* The unspec codes for signed and unsigned wide comparisons
+ respectively. */
+ int m_unspec_for_sint;
+ int m_unspec_for_uint;
+};
+
+class svcmpuo_impl : public quiet<function_base>
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.add_ptrue_hint (0, e.gp_mode (0));
+ return e.use_exact_insn (code_for_aarch64_pred_fcmuo (e.vector_mode (0)));
+ }
+};
+
+class svcnot_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ if (e.pred == PRED_x)
+ {
+ /* The pattern for CNOT includes an UNSPEC_PRED_Z, so needs
+ a ptrue hint. */
+ e.add_ptrue_hint (0, e.gp_mode (0));
+ return e.use_pred_x_insn (code_for_aarch64_pred_cnot (mode));
+ }
+
+ return e.use_cond_insn (code_for_cond_cnot (mode), 0);
+ }
+};
+
+/* Implements svcnt[bhwd], which count the number of elements
+ in a particular vector mode. */
+class svcnt_bhwd_impl : public function_base
+{
+public:
+ CONSTEXPR svcnt_bhwd_impl (machine_mode ref_mode) : m_ref_mode (ref_mode) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree count = build_int_cstu (TREE_TYPE (f.lhs),
+ GET_MODE_NUNITS (m_ref_mode));
+ return gimple_build_assign (f.lhs, count);
+ }
+
+ rtx
+ expand (function_expander &) const OVERRIDE
+ {
+ return gen_int_mode (GET_MODE_NUNITS (m_ref_mode), DImode);
+ }
+
+ /* The mode of the vector associated with the [bhwd] suffix. */
+ machine_mode m_ref_mode;
+};
+
+/* Implements svcnt[bhwd]_pat. */
+class svcnt_bhwd_pat_impl : public svcnt_bhwd_impl
+{
+public:
+ CONSTEXPR svcnt_bhwd_pat_impl (machine_mode ref_mode)
+ : svcnt_bhwd_impl (ref_mode) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree pattern_arg = gimple_call_arg (f.call, 0);
+ aarch64_svpattern pattern = (aarch64_svpattern) tree_to_shwi (pattern_arg);
+
+ if (pattern == AARCH64_SV_ALL)
+ /* svcvnt[bwhd]_pat (SV_ALL) == svcnt[bwhd] (). */
+ return svcnt_bhwd_impl::fold (f);
+
+ /* See whether we can count the number of elements in the pattern
+ at compile time. */
+ unsigned int elements_per_vq = 128 / GET_MODE_UNIT_BITSIZE (m_ref_mode);
+ HOST_WIDE_INT value = aarch64_fold_sve_cnt_pat (pattern, elements_per_vq);
+ if (value >= 0)
+ {
+ tree count = build_int_cstu (TREE_TYPE (f.lhs), value);
+ return gimple_build_assign (f.lhs, count);
+ }
+
+ return NULL;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ unsigned int elements_per_vq = 128 / GET_MODE_UNIT_BITSIZE (m_ref_mode);
+ e.args.quick_push (gen_int_mode (elements_per_vq, DImode));
+ e.args.quick_push (const1_rtx);
+ return e.use_exact_insn (CODE_FOR_aarch64_sve_cnt_pat);
+ }
+};
+
+class svcntp_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ e.add_ptrue_hint (0, mode);
+ return e.use_exact_insn (code_for_aarch64_pred_cntp (mode));
+ }
+};
+
+class svcompact_impl : public quiet<function_base>
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_sve_compact (e.vector_mode (0)));
+ }
+};
+
+/* Implements svcreate2, svcreate3 and svcreate4. */
+class svcreate_impl : public quiet<multi_vector_function>
+{
+public:
+ CONSTEXPR svcreate_impl (unsigned int vectors_per_tuple)
+ : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ unsigned int nargs = gimple_call_num_args (f.call);
+ tree lhs_type = TREE_TYPE (f.lhs);
+
+ /* Replace the call with a clobber of the result (to prevent it from
+ becoming upwards exposed) followed by stores into each individual
+ vector of tuple.
+
+ The fold routines expect the replacement statement to have the
+ same lhs as the original call, so return the clobber statement
+ rather than the final vector store. */
+ gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type));
+
+ for (unsigned int i = nargs; i-- > 0; )
+ {
+ tree rhs_vector = gimple_call_arg (f.call, i);
+ tree field = tuple_type_field (TREE_TYPE (f.lhs));
+ tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+ unshare_expr (f.lhs), field, NULL_TREE);
+ tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
+ lhs_array, size_int (i),
+ NULL_TREE, NULL_TREE);
+ gassign *assign = gimple_build_assign (lhs_vector, rhs_vector);
+ gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
+ }
+ return clobber;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ rtx lhs_tuple = e.get_nonoverlapping_reg_target ();
+
+ /* Record that LHS_TUPLE is dead before the first store. */
+ emit_clobber (lhs_tuple);
+ for (unsigned int i = 0; i < e.args.length (); ++i)
+ {
+ /* Use an lvalue subreg to refer to vector I in LHS_TUPLE. */
+ rtx lhs_vector = simplify_gen_subreg (GET_MODE (e.args[i]),
+ lhs_tuple, GET_MODE (lhs_tuple),
+ i * BYTES_PER_SVE_VECTOR);
+ emit_move_insn (lhs_vector, e.args[i]);
+ }
+ return lhs_tuple;
+ }
+};
+
+class svcvt_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode0 = e.vector_mode (0);
+ machine_mode mode1 = e.vector_mode (1);
+ insn_code icode;
+ /* All this complication comes from the need to select four things
+ simultaneously:
+
+ (1) the kind of conversion (int<-float, float<-int, float<-float)
+ (2) signed vs. unsigned integers, where relevant
+ (3) the predication mode, which must be the wider of the predication
+ modes for MODE0 and MODE1
+ (4) the predication type (m, x or z)
+
+ The only supported int<->float conversions for which the integer is
+ narrower than the float are SI<->DF. It's therefore more convenient
+ to handle (3) by defining two patterns for int<->float conversions:
+ one in which the integer is at least as wide as the float and so
+ determines the predication mode, and another single SI<->DF pattern
+ in which the float's mode determines the predication mode (which is
+ always VNx2BI in that case).
+
+ The names of the patterns follow the optab convention of giving
+ the source mode before the destination mode. */
+ if (e.type_suffix (1).integer_p)
+ {
+ int unspec = (e.type_suffix (1).unsigned_p
+ ? UNSPEC_COND_UCVTF
+ : UNSPEC_COND_SCVTF);
+ if (e.type_suffix (0).element_bytes <= e.type_suffix (1).element_bytes)
+ icode = (e.pred == PRED_x
+ ? code_for_aarch64_sve_nonextend (unspec, mode1, mode0)
+ : code_for_cond_nonextend (unspec, mode1, mode0));
+ else
+ icode = (e.pred == PRED_x
+ ? code_for_aarch64_sve_extend (unspec, mode1, mode0)
+ : code_for_cond_extend (unspec, mode1, mode0));
+ }
+ else
+ {
+ int unspec = (!e.type_suffix (0).integer_p ? UNSPEC_COND_FCVT
+ : e.type_suffix (0).unsigned_p ? UNSPEC_COND_FCVTZU
+ : UNSPEC_COND_FCVTZS);
+ if (e.type_suffix (0).element_bytes >= e.type_suffix (1).element_bytes)
+ icode = (e.pred == PRED_x
+ ? code_for_aarch64_sve_nontrunc (unspec, mode1, mode0)
+ : code_for_cond_nontrunc (unspec, mode1, mode0));
+ else
+ icode = (e.pred == PRED_x
+ ? code_for_aarch64_sve_trunc (unspec, mode1, mode0)
+ : code_for_cond_trunc (unspec, mode1, mode0));
+ }
+
+ if (e.pred == PRED_x)
+ return e.use_pred_x_insn (icode);
+ return e.use_cond_insn (icode);
+ }
+};
+
+class svdot_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* In the optab, the multiplication operands come before the accumulator
+ operand. The optab is keyed off the multiplication mode. */
+ e.rotate_inputs_left (0, 3);
+ insn_code icode
+ = e.direct_optab_handler_for_sign (sdot_prod_optab, udot_prod_optab,
+ 0, GET_MODE (e.args[0]));
+ return e.use_unpred_insn (icode);
+ }
+};
+
+class svdot_lane_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Use the same ordering as the dot_prod_optab, with the
+ accumulator last. */
+ e.rotate_inputs_left (0, 4);
+ int unspec = (e.type_suffix (0).unsigned_p ? UNSPEC_UDOT : UNSPEC_SDOT);
+ machine_mode mode = e.vector_mode (0);
+ return e.use_exact_insn (code_for_aarch64_dot_prod_lane (unspec, mode));
+ }
+};
+
+class svdup_impl : public quiet<function_base>
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree vec_type = TREE_TYPE (f.lhs);
+ tree rhs = gimple_call_arg (f.call, f.pred == PRED_none ? 0 : 1);
+
+ if (f.pred == PRED_none || f.pred == PRED_x)
+ {
+ if (CONSTANT_CLASS_P (rhs))
+ {
+ if (f.type_suffix (0).bool_p)
+ return (tree_to_shwi (rhs)
+ ? f.fold_to_ptrue ()
+ : f.fold_to_pfalse ());
+
+ tree rhs_vector = build_vector_from_val (vec_type, rhs);
+ return gimple_build_assign (f.lhs, rhs_vector);
+ }
+
+ /* Avoid folding _b to a VEC_DUPLICATE_EXPR, since to do that we
+ would need to introduce an extra and unwanted conversion to
+ the truth vector element type. */
+ if (!f.type_suffix (0).bool_p)
+ return gimple_build_assign (f.lhs, VEC_DUPLICATE_EXPR, rhs);
+ }
+
+ return NULL;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ if (e.pred == PRED_none || e.pred == PRED_x)
+ /* There's no benefit to using predicated instructions for _x here. */
+ return e.use_unpred_insn (e.direct_optab_handler (vec_duplicate_optab));
+
+ /* Model predicated svdups as a SEL in which the "true" value is
+ the duplicate of the function argument and the "false" value
+ is the value of inactive lanes. */
+ insn_code icode;
+ machine_mode mode = e.vector_mode (0);
+ if (valid_for_const_vector_p (GET_MODE_INNER (mode), e.args.last ()))
+ /* Duplicate the constant to fill a vector. The pattern optimizes
+ various cases involving constant operands, falling back to SEL
+ if necessary. */
+ icode = code_for_vcond_mask (mode, mode);
+ else
+ /* Use the pattern for selecting between a duplicated scalar
+ variable and a vector fallback. */
+ icode = code_for_aarch64_sel_dup (mode);
+ return e.use_vcond_mask_insn (icode);
+ }
+};
+
+class svdup_lane_impl : public quiet<function_base>
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* The native DUP lane has an index range of 64 bytes. */
+ machine_mode mode = e.vector_mode (0);
+ if (CONST_INT_P (e.args[1])
+ && IN_RANGE (INTVAL (e.args[1]) * GET_MODE_UNIT_SIZE (mode), 0, 63))
+ return e.use_exact_insn (code_for_aarch64_sve_dup_lane (mode));
+
+ /* Treat svdup_lane as if it were svtbl_n. */
+ return e.use_exact_insn (code_for_aarch64_sve_tbl (e.vector_mode (0)));
+ }
+};
+
+class svdupq_impl : public quiet<function_base>
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree vec_type = TREE_TYPE (f.lhs);
+ unsigned int nargs = gimple_call_num_args (f.call);
+ /* For predicates, pad out each argument so that we have one element
+ per bit. */
+ unsigned int factor = (f.type_suffix (0).bool_p
+ ? f.type_suffix (0).element_bytes : 1);
+ tree_vector_builder builder (vec_type, nargs * factor, 1);
+ for (unsigned int i = 0; i < nargs; ++i)
+ {
+ tree elt = gimple_call_arg (f.call, i);
+ if (!CONSTANT_CLASS_P (elt))
+ return NULL;
+ builder.quick_push (elt);
+ for (unsigned int j = 1; j < factor; ++j)
+ builder.quick_push (build_zero_cst (TREE_TYPE (vec_type)));
+ }
+ return gimple_build_assign (f.lhs, builder.build ());
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ unsigned int elements_per_vq = e.args.length ();
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+ {
+ /* Construct a vector of integers so that we can compare them against
+ zero below. Zero vs. nonzero is the only distinction that
+ matters. */
+ mode = aarch64_sve_int_mode (mode);
+ for (unsigned int i = 0; i < elements_per_vq; ++i)
+ e.args[i] = simplify_gen_unary (ZERO_EXTEND, GET_MODE_INNER (mode),
+ e.args[i], QImode);
+ }
+
+ /* Get the 128-bit Advanced SIMD vector for this data size. */
+ scalar_mode element_mode = GET_MODE_INNER (mode);
+ machine_mode vq_mode = aarch64_vq_mode (element_mode).require ();
+ gcc_assert (known_eq (elements_per_vq, GET_MODE_NUNITS (vq_mode)));
+
+ /* Put the arguments into a 128-bit Advanced SIMD vector. We want
+ argument N to go into architectural lane N, whereas Advanced SIMD
+ vectors are loaded memory lsb to register lsb. We therefore need
+ to reverse the elements for big-endian targets. */
+ rtx vq_reg = gen_reg_rtx (vq_mode);
+ rtvec vec = rtvec_alloc (elements_per_vq);
+ for (unsigned int i = 0; i < elements_per_vq; ++i)
+ {
+ unsigned int argno = BYTES_BIG_ENDIAN ? elements_per_vq - i - 1 : i;
+ RTVEC_ELT (vec, i) = e.args[argno];
+ }
+ aarch64_expand_vector_init (vq_reg, gen_rtx_PARALLEL (vq_mode, vec));
+
+ /* If the result is a boolean, compare the data vector against zero. */
+ if (mode != e.vector_mode (0))
+ {
+ rtx data_dupq = aarch64_expand_sve_dupq (NULL, mode, vq_reg);
+ return aarch64_convert_sve_data_to_pred (e.possible_target,
+ e.vector_mode (0), data_dupq);
+ }
+
+ return aarch64_expand_sve_dupq (e.possible_target, mode, vq_reg);
+ }
+};
+
+class svdupq_lane_impl : public quiet<function_base>
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ rtx index = e.args[1];
+ if (CONST_INT_P (index) && IN_RANGE (INTVAL (index), 0, 3))
+ {
+ /* Use the .Q form of DUP, which is the native instruction for
+ this function. */
+ insn_code icode = code_for_aarch64_sve_dupq_lane (mode);
+ unsigned int num_indices = e.elements_per_vq (0);
+ rtx indices = aarch64_gen_stepped_int_parallel
+ (num_indices, INTVAL (index) * num_indices, 1);
+
+ e.add_output_operand (icode);
+ e.add_input_operand (icode, e.args[0]);
+ e.add_fixed_operand (indices);
+ return e.generate_insn (icode);
+ }
+
+ /* Build a .D TBL index for the pairs of doublewords that we want to
+ duplicate. */
+ if (CONST_INT_P (index))
+ {
+ /* The index vector is a constant. */
+ rtx_vector_builder builder (VNx2DImode, 2, 1);
+ builder.quick_push (gen_int_mode (INTVAL (index) * 2, DImode));
+ builder.quick_push (gen_int_mode (INTVAL (index) * 2 + 1, DImode));
+ index = builder.build ();
+ }
+ else
+ {
+ /* Duplicate INDEX * 2 to fill a DImode vector. The ACLE spec
+ explicitly allows the top of the index to be dropped. */
+ index = force_reg (DImode, simplify_gen_binary (ASHIFT, DImode,
+ index, const1_rtx));
+ index = expand_vector_broadcast (VNx2DImode, index);
+
+ /* Get an alternating 0, 1 predicate. */
+ rtx_vector_builder builder (VNx2BImode, 2, 1);
+ builder.quick_push (const0_rtx);
+ builder.quick_push (constm1_rtx);
+ rtx pg = force_reg (VNx2BImode, builder.build ());
+
+ /* Add one to the odd elements of the index. */
+ rtx one = force_reg (VNx2DImode, CONST1_RTX (VNx2DImode));
+ rtx target = gen_reg_rtx (VNx2DImode);
+ emit_insn (gen_cond_addvnx2di (target, pg, index, one, index));
+ index = target;
+ }
+
+ e.args[0] = gen_lowpart (VNx2DImode, e.args[0]);
+ e.args[1] = index;
+ return e.use_exact_insn (CODE_FOR_aarch64_sve_tblvnx2di);
+ }
+};
+
+class svext_impl : public quiet<function_base>
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_sve_ext (e.vector_mode (0)));
+ }
+};
+
+/* Implements svextb, svexth and svextw. */
+class svext_bhw_impl : public function_base
+{
+public:
+ CONSTEXPR svext_bhw_impl (scalar_int_mode from_mode)
+ : m_from_mode (from_mode) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ if (e.type_suffix (0).unsigned_p)
+ {
+ /* Convert to an AND. The widest we go is 0xffffffff, which fits
+ in a CONST_INT. */
+ e.args.quick_push (GEN_INT (GET_MODE_MASK (m_from_mode)));
+ if (e.pred == PRED_m)
+ /* We now have arguments "(inactive, pg, op, mask)". Convert this
+ to "(pg, op, mask, inactive)" so that the order matches svand_m
+ with an extra argument on the end. Take the inactive elements
+ from this extra argument. */
+ e.rotate_inputs_left (0, 4);
+ return e.map_to_rtx_codes (AND, AND, -1, 3);
+ }
+
+ machine_mode wide_mode = e.vector_mode (0);
+ poly_uint64 nunits = GET_MODE_NUNITS (wide_mode);
+ machine_mode narrow_mode
+ = aarch64_sve_data_mode (m_from_mode, nunits).require ();
+ if (e.pred == PRED_x)
+ {
+ insn_code icode = code_for_aarch64_pred_sxt (wide_mode, narrow_mode);
+ return e.use_pred_x_insn (icode);
+ }
+
+ insn_code icode = code_for_aarch64_cond_sxt (wide_mode, narrow_mode);
+ return e.use_cond_insn (icode);
+ }
+
+ /* The element mode that we're extending from. */
+ scalar_int_mode m_from_mode;
+};
+
+/* Implements svget2, svget3 and svget4. */
+class svget_impl : public quiet<multi_vector_function>
+{
+public:
+ CONSTEXPR svget_impl (unsigned int vectors_per_tuple)
+ : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* Fold into a normal gimple component access. */
+ tree rhs_tuple = gimple_call_arg (f.call, 0);
+ tree index = gimple_call_arg (f.call, 1);
+ tree field = tuple_type_field (TREE_TYPE (rhs_tuple));
+ tree rhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+ rhs_tuple, field, NULL_TREE);
+ tree rhs_vector = build4 (ARRAY_REF, TREE_TYPE (f.lhs),
+ rhs_array, index, NULL_TREE, NULL_TREE);
+ return gimple_build_assign (f.lhs, rhs_vector);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Fold the access into a subreg rvalue. */
+ return simplify_gen_subreg (e.vector_mode (0), e.args[0],
+ GET_MODE (e.args[0]),
+ INTVAL (e.args[1]) * BYTES_PER_SVE_VECTOR);
+ }
+};
+
+class svindex_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (e.direct_optab_handler (vec_series_optab));
+ }
+};
+
+class svinsr_impl : public quiet<function_base>
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ gcall *new_call = gimple_build_call_internal (IFN_VEC_SHL_INSERT, 2,
+ gimple_call_arg (f.call, 0),
+ gimple_call_arg (f.call, 1));
+ gimple_call_set_lhs (new_call, f.lhs);
+ return new_call;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = direct_optab_handler (vec_shl_insert_optab,
+ e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements svlasta and svlastb. */
+class svlast_impl : public quiet<function_base>
+{
+public:
+ CONSTEXPR svlast_impl (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_extract (m_unspec, e.vector_mode (0)));
+ }
+
+ /* The unspec code associated with the operation. */
+ int m_unspec;
+};
+
+class svld1_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY;
+ }
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree vectype = f.vector_type (0);
+
+ /* Get the predicate and base pointer. */
+ gimple_seq stmts = NULL;
+ tree pred = f.convert_pred (stmts, vectype, 0);
+ tree base = f.fold_contiguous_base (stmts, vectype);
+ gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+ tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+ gcall *new_call = gimple_build_call_internal (IFN_MASK_LOAD, 3,
+ base, cookie, pred);
+ gimple_call_set_lhs (new_call, f.lhs);
+ return new_call;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = convert_optab_handler (maskload_optab,
+ e.vector_mode (0), e.gp_mode (0));
+ return e.use_contiguous_load_insn (icode);
+ }
+};
+
+/* Implements extending contiguous forms of svld1. */
+class svld1_extend_impl : public extending_load
+{
+public:
+ CONSTEXPR svld1_extend_impl (type_suffix_index memory_type)
+ : extending_load (memory_type) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = code_for_aarch64_load (extend_rtx_code (),
+ e.vector_mode (0),
+ e.memory_vector_mode ());
+ return e.use_contiguous_load_insn (icode);
+ }
+};
+
+class svld1_gather_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.prepare_gather_address_operands (1);
+ /* Put the predicate last, as required by mask_gather_load_optab. */
+ e.rotate_inputs_left (0, 5);
+ machine_mode mem_mode = e.memory_vector_mode ();
+ insn_code icode = direct_optab_handler (mask_gather_load_optab, mem_mode);
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements extending forms of svld1_gather. */
+class svld1_gather_extend_impl : public extending_load
+{
+public:
+ CONSTEXPR svld1_gather_extend_impl (type_suffix_index memory_type)
+ : extending_load (memory_type) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.prepare_gather_address_operands (1);
+ /* Put the predicate last, since the extending gathers use the same
+ operand order as mask_gather_load_optab. */
+ e.rotate_inputs_left (0, 5);
+ insn_code icode = code_for_aarch64_gather_load (extend_rtx_code (),
+ e.vector_mode (0),
+ e.memory_vector_mode ());
+ return e.use_exact_insn (icode);
+ }
+};
+
+class svld1rq_impl : public function_base
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY;
+ }
+
+ tree
+ memory_scalar_type (const function_instance &fi) const OVERRIDE
+ {
+ return fi.scalar_type (0);
+ }
+
+ machine_mode
+ memory_vector_mode (const function_instance &fi) const OVERRIDE
+ {
+ return aarch64_vq_mode (GET_MODE_INNER (fi.vector_mode (0))).require ();
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = code_for_aarch64_sve_ld1rq (e.vector_mode (0));
+ return e.use_contiguous_load_insn (icode);
+ }
+};
+
+/* Implements svld2, svld3 and svld4. */
+class svld234_impl : public full_width_access
+{
+public:
+ CONSTEXPR svld234_impl (unsigned int vectors_per_tuple)
+ : full_width_access (vectors_per_tuple) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY;
+ }
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree tuple_type = TREE_TYPE (f.lhs);
+ tree vectype = f.vector_type (0);
+
+ /* Get the predicate and base pointer. */
+ gimple_seq stmts = NULL;
+ tree pred = f.convert_pred (stmts, vectype, 0);
+ tree base = f.fold_contiguous_base (stmts, vectype);
+ gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+ /* Emit two statements: a clobber of the lhs, so that it isn't
+ upwards exposed, and then the load itself.
+
+ The fold routines expect the replacement statement to have the
+ same lhs as the original call, so return the clobber statement
+ rather than the load. */
+ gimple *clobber = gimple_build_assign (f.lhs, build_clobber (tuple_type));
+
+ /* View the loaded data as an array of vectors. */
+ tree field = tuple_type_field (tuple_type);
+ tree lhs_array = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (field),
+ unshare_expr (f.lhs));
+
+ /* Emit the load itself. */
+ tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+ gcall *new_call = gimple_build_call_internal (IFN_MASK_LOAD_LANES, 3,
+ base, cookie, pred);
+ gimple_call_set_lhs (new_call, lhs_array);
+ gsi_insert_after (f.gsi, new_call, GSI_SAME_STMT);
+
+ return clobber;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode tuple_mode = TYPE_MODE (TREE_TYPE (e.call_expr));
+ insn_code icode = convert_optab_handler (vec_mask_load_lanes_optab,
+ tuple_mode, e.vector_mode (0));
+ return e.use_contiguous_load_insn (icode);
+ }
+};
+
+class svldff1_gather_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY | CP_READ_FFR | CP_WRITE_FFR;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* See the block comment in aarch64-sve.md for details about the
+ FFR handling. */
+ emit_insn (gen_aarch64_update_ffr_for_load ());
+
+ e.prepare_gather_address_operands (1);
+ /* Put the predicate last, since ldff1_gather uses the same operand
+ order as mask_gather_load_optab. */
+ e.rotate_inputs_left (0, 5);
+ machine_mode mem_mode = e.memory_vector_mode ();
+ return e.use_exact_insn (code_for_aarch64_ldff1_gather (mem_mode));
+ }
+};
+
+/* Implements extending forms of svldff1_gather. */
+class svldff1_gather_extend : public extending_load
+{
+public:
+ CONSTEXPR svldff1_gather_extend (type_suffix_index memory_type)
+ : extending_load (memory_type) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* See the block comment in aarch64-sve.md for details about the
+ FFR handling. */
+ emit_insn (gen_aarch64_update_ffr_for_load ());
+
+ e.prepare_gather_address_operands (1);
+ /* Put the predicate last, since ldff1_gather uses the same operand
+ order as mask_gather_load_optab. */
+ e.rotate_inputs_left (0, 5);
+ insn_code icode = code_for_aarch64_ldff1_gather (extend_rtx_code (),
+ e.vector_mode (0),
+ e.memory_vector_mode ());
+ return e.use_exact_insn (icode);
+ }
+};
+
+class svldnt1_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = code_for_aarch64_ldnt1 (e.vector_mode (0));
+ return e.use_contiguous_load_insn (icode);
+ }
+};
+
+/* Implements svldff1 and svldnf1. */
+class svldxf1_impl : public full_width_access
+{
+public:
+ CONSTEXPR svldxf1_impl (int unspec) : m_unspec (unspec) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY | CP_READ_FFR | CP_WRITE_FFR;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* See the block comment in aarch64-sve.md for details about the
+ FFR handling. */
+ emit_insn (gen_aarch64_update_ffr_for_load ());
+
+ machine_mode mode = e.vector_mode (0);
+ return e.use_contiguous_load_insn (code_for_aarch64_ldf1 (m_unspec, mode));
+ }
+
+ /* The unspec associated with the load. */
+ int m_unspec;
+};
+
+/* Implements extending contiguous forms of svldff1 and svldnf1. */
+class svldxf1_extend_impl : public extending_load
+{
+public:
+ CONSTEXPR svldxf1_extend_impl (type_suffix_index memory_type, int unspec)
+ : extending_load (memory_type), m_unspec (unspec) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY | CP_READ_FFR | CP_WRITE_FFR;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* See the block comment in aarch64-sve.md for details about the
+ FFR handling. */
+ emit_insn (gen_aarch64_update_ffr_for_load ());
+
+ insn_code icode = code_for_aarch64_ldf1 (m_unspec, extend_rtx_code (),
+ e.vector_mode (0),
+ e.memory_vector_mode ());
+ return e.use_contiguous_load_insn (icode);
+ }
+
+ /* The unspec associated with the load. */
+ int m_unspec;
+};
+
+class svlen_impl : public quiet<function_base>
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* The argument only exists for its type. */
+ tree rhs_type = TREE_TYPE (gimple_call_arg (f.call, 0));
+ tree count = build_int_cstu (TREE_TYPE (f.lhs),
+ TYPE_VECTOR_SUBPARTS (rhs_type));
+ return gimple_build_assign (f.lhs, count);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* The argument only exists for its type. */
+ return gen_int_mode (GET_MODE_NUNITS (e.vector_mode (0)), DImode);
+ }
+};
+
+class svmad_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return expand_mad (e);
+ }
+};
+
+class svmla_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Put the accumulator at the end (argument 3), but keep it as the
+ merge input for _m functions. */
+ e.rotate_inputs_left (1, 4);
+ return expand_mad (e, 3);
+ }
+};
+
+/* Base class for svmla_lane and svmls_lane. */
+class svmla_svmls_lane_impl : public function_base
+{
+public:
+ CONSTEXPR svmla_svmls_lane_impl (int unspec)
+ : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Put the operands in the normal (fma ...) order, with the accumulator
+ last. This fits naturally since that's also the unprinted operand
+ in the asm output. */
+ e.rotate_inputs_left (0, 4);
+ insn_code icode = code_for_aarch64_lane (m_unspec, e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+
+ /* The unspec code associated with the operation. */
+ int m_unspec;
+};
+
+class svmls_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Put the accumulator at the end (argument 3), but keep it as the
+ merge input for _m functions. */
+ e.rotate_inputs_left (1, 4);
+ return expand_msb (e, 3);
+ }
+};
+
+class svmov_impl : public function_base
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ return gimple_build_assign (f.lhs, BIT_AND_EXPR,
+ gimple_call_arg (f.call, 0),
+ gimple_call_arg (f.call, 1));
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* The canonical form for the assembler alias "MOV Pa.B, Pb/Z, Pc.B"
+ is "AND Pa.B, Pb/Z, Pc.B, Pc.B". */
+ gcc_assert (e.pred == PRED_z);
+ e.args.quick_push (e.args[1]);
+ return e.use_exact_insn (CODE_FOR_aarch64_pred_andvnx16bi_z);
+ }
+};
+
+class svmsb_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return expand_msb (e);
+ }
+};
+
+class svmul_lane_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_mul_lane (e.vector_mode (0)));
+ }
+};
+
+class svnand_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ gcc_assert (e.pred == PRED_z);
+ return e.use_exact_insn (CODE_FOR_aarch64_pred_nandvnx16bi_z);
+ }
+};
+
+class svnor_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ gcc_assert (e.pred == PRED_z);
+ return e.use_exact_insn (CODE_FOR_aarch64_pred_norvnx16bi_z);
+ }
+};
+
+class svnot_impl : public rtx_code_function
+{
+public:
+ CONSTEXPR svnot_impl () : rtx_code_function (NOT, NOT, -1) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ if (e.type_suffix_ids[0] == TYPE_SUFFIX_b)
+ {
+ /* The canonical form for the assembler alias "NOT Pa.B, Pb/Z, Pc.B"
+ is "EOR Pa.B, Pb/Z, Pb.B, Pc.B". */
+ gcc_assert (e.pred == PRED_z);
+ e.args.quick_insert (1, e.args[0]);
+ return e.use_exact_insn (CODE_FOR_aarch64_pred_xorvnx16bi_z);
+ }
+ return rtx_code_function::expand (e);
+ }
+};
+
+class svorn_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ gcc_assert (e.pred == PRED_z);
+ return e.use_exact_insn (CODE_FOR_aarch64_pred_ornvnx16bi_z);
+ }
+};
+
+class svpfalse_impl : public function_base
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ return f.fold_to_pfalse ();
+ }
+
+ rtx
+ expand (function_expander &) const OVERRIDE
+ {
+ return CONST0_RTX (VNx16BImode);
+ }
+};
+
+/* Implements svpfirst and svpnext, which share the same .md patterns. */
+class svpfirst_svpnext_impl : public function_base
+{
+public:
+ CONSTEXPR svpfirst_svpnext_impl (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ e.add_ptrue_hint (0, mode);
+ return e.use_exact_insn (code_for_aarch64_sve (m_unspec, mode));
+ }
+
+ /* The unspec associated with the operation. */
+ int m_unspec;
+};
+
+/* Implements contiguous forms of svprf[bhwd]. */
+class svprf_bhwd_impl : public function_base
+{
+public:
+ CONSTEXPR svprf_bhwd_impl (machine_mode mode) : m_mode (mode) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_PREFETCH_MEMORY;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.prepare_prefetch_operands ();
+ insn_code icode = code_for_aarch64_sve_prefetch (m_mode);
+ return e.use_contiguous_prefetch_insn (icode);
+ }
+
+ /* The mode that we'd use to hold one vector of prefetched data. */
+ machine_mode m_mode;
+};
+
+/* Implements svprf[bhwd]_gather. */
+class svprf_bhwd_gather_impl : public function_base
+{
+public:
+ CONSTEXPR svprf_bhwd_gather_impl (machine_mode mode) : m_mode (mode) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_PREFETCH_MEMORY;
+ }
+
+ machine_mode
+ memory_vector_mode (const function_instance &) const OVERRIDE
+ {
+ return m_mode;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.prepare_prefetch_operands ();
+ e.prepare_gather_address_operands (1);
+
+ /* Insert a zero operand to identify the mode of the memory being
+ accessed. This goes between the gather operands and prefetch
+ operands created above. */
+ e.args.quick_insert (5, CONST0_RTX (m_mode));
+
+ machine_mode reg_mode = GET_MODE (e.args[2]);
+ insn_code icode = code_for_aarch64_sve_gather_prefetch (m_mode, reg_mode);
+ return e.use_exact_insn (icode);
+ }
+
+ /* The mode that we'd use to hold one vector of prefetched data. */
+ machine_mode m_mode;
+};
+
+/* Implements svptest_any, svptest_first and svptest_last. */
+class svptest_impl : public function_base
+{
+public:
+ CONSTEXPR svptest_impl (rtx_code compare) : m_compare (compare) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* See whether GP is an exact ptrue for some predicate mode;
+ i.e. whether converting the GP to that mode will not drop
+ set bits and will leave all significant bits set. */
+ machine_mode wide_mode;
+ int hint;
+ if (aarch64_ptrue_all_mode (e.args[0]).exists (&wide_mode))
+ hint = SVE_KNOWN_PTRUE;
+ else
+ {
+ hint = SVE_MAYBE_NOT_PTRUE;
+ wide_mode = VNx16BImode;
+ }
+
+ /* Generate the PTEST itself. */
+ rtx pg = force_reg (VNx16BImode, e.args[0]);
+ rtx wide_pg = gen_lowpart (wide_mode, pg);
+ rtx hint_rtx = gen_int_mode (hint, DImode);
+ rtx op = force_reg (wide_mode, gen_lowpart (wide_mode, e.args[1]));
+ emit_insn (gen_aarch64_ptestvnx16bi (pg, wide_pg, hint_rtx, op));
+
+ /* Get the location of the boolean result. We can provide SImode and
+ DImode values directly; rely on generic code to convert others. */
+ rtx target = e.possible_target;
+ if (!target
+ || !REG_P (target)
+ || (GET_MODE (target) != SImode && GET_MODE (target) != DImode))
+ target = gen_reg_rtx (DImode);
+
+ /* Generate a CSET to convert the CC result of the PTEST to a boolean. */
+ rtx cc_reg = gen_rtx_REG (CC_NZCmode, CC_REGNUM);
+ rtx compare = gen_rtx_fmt_ee (m_compare, GET_MODE (target),
+ cc_reg, const0_rtx);
+ emit_insn (gen_rtx_SET (target, compare));
+ return target;
+ }
+
+ /* The comparison code associated with ptest condition. */
+ rtx_code m_compare;
+};
+
+class svptrue_impl : public function_base
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ return f.fold_to_ptrue ();
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return aarch64_ptrue_all (e.type_suffix (0).element_bytes);
+ }
+};
+
+class svptrue_pat_impl : public function_base
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree pattern_arg = gimple_call_arg (f.call, 0);
+ aarch64_svpattern pattern = (aarch64_svpattern) tree_to_shwi (pattern_arg);
+
+ if (pattern == AARCH64_SV_ALL)
+ /* svptrue_pat_bN (SV_ALL) == svptrue_bN (). */
+ return f.fold_to_ptrue ();
+
+ /* See whether we can count the number of elements in the pattern
+ at compile time. If so, construct a predicate with that number
+ of 1s followed by all 0s. */
+ int nelts_per_vq = f.elements_per_vq (0);
+ HOST_WIDE_INT value = aarch64_fold_sve_cnt_pat (pattern, nelts_per_vq);
+ if (value >= 0)
+ return f.fold_to_vl_pred (value);
+
+ return NULL;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* In rtl, the predicate is represented as the constant:
+
+ (const:V16BI (unspec:V16BI [(const_int PATTERN)
+ (const_vector:VnnBI [zeros])]
+ UNSPEC_PTRUE))
+
+ where nn determines the element size. */
+ rtvec vec = gen_rtvec (2, e.args[0], CONST0_RTX (e.vector_mode (0)));
+ return gen_rtx_CONST (VNx16BImode,
+ gen_rtx_UNSPEC (VNx16BImode, vec, UNSPEC_PTRUE));
+ }
+};
+
+class svqadd_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.expand_signed_unpred_op (SS_PLUS, US_PLUS);
+ }
+};
+
+/* Implements svqdec[bhwd]{,_pat} and svqinc[bhwd]{,_pat}. */
+class svqdec_svqinc_bhwd_impl : public function_base
+{
+public:
+ CONSTEXPR svqdec_svqinc_bhwd_impl (rtx_code code_for_sint,
+ rtx_code code_for_uint,
+ scalar_int_mode elem_mode)
+ : m_code_for_sint (code_for_sint),
+ m_code_for_uint (code_for_uint),
+ m_elem_mode (elem_mode)
+ {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Treat non-_pat functions in the same way as _pat functions with
+ an SV_ALL argument. */
+ if (e.args.length () == 2)
+ e.args.quick_insert (1, gen_int_mode (AARCH64_SV_ALL, DImode));
+
+ /* Insert the number of elements per 128-bit block as a fake argument,
+ between the pattern and the multiplier. Arguments 1, 2 and 3 then
+ correspond exactly with the 3 UNSPEC_SVE_CNT_PAT operands; see
+ aarch64_sve_cnt_pat for details. */
+ unsigned int elements_per_vq = 128 / GET_MODE_BITSIZE (m_elem_mode);
+ e.args.quick_insert (2, gen_int_mode (elements_per_vq, DImode));
+
+ rtx_code code = (e.type_suffix (0).unsigned_p
+ ? m_code_for_uint
+ : m_code_for_sint);
+
+ /* Choose between operating on integer scalars or integer vectors. */
+ machine_mode mode = e.vector_mode (0);
+ if (e.mode_suffix_id == MODE_n)
+ mode = GET_MODE_INNER (mode);
+ return e.use_exact_insn (code_for_aarch64_sve_pat (code, mode));
+ }
+
+ /* The saturating addition or subtraction codes to use for signed and
+ unsigned values respectively. */
+ rtx_code m_code_for_sint;
+ rtx_code m_code_for_uint;
+
+ /* The integer mode associated with the [bhwd] suffix. */
+ scalar_int_mode m_elem_mode;
+};
+
+/* Implements svqdec[bhwd]{,_pat}. */
+class svqdec_bhwd_impl : public svqdec_svqinc_bhwd_impl
+{
+public:
+ CONSTEXPR svqdec_bhwd_impl (scalar_int_mode elem_mode)
+ : svqdec_svqinc_bhwd_impl (SS_MINUS, US_MINUS, elem_mode) {}
+};
+
+/* Implements svqinc[bhwd]{,_pat}. */
+class svqinc_bhwd_impl : public svqdec_svqinc_bhwd_impl
+{
+public:
+ CONSTEXPR svqinc_bhwd_impl (scalar_int_mode elem_mode)
+ : svqdec_svqinc_bhwd_impl (SS_PLUS, US_PLUS, elem_mode) {}
+};
+
+/* Implements svqdecp and svqincp. */
+class svqdecp_svqincp_impl : public function_base
+{
+public:
+ CONSTEXPR svqdecp_svqincp_impl (rtx_code code_for_sint,
+ rtx_code code_for_uint)
+ : m_code_for_sint (code_for_sint),
+ m_code_for_uint (code_for_uint)
+ {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ rtx_code code = (e.type_suffix (0).unsigned_p
+ ? m_code_for_uint
+ : m_code_for_sint);
+ insn_code icode;
+ if (e.mode_suffix_id == MODE_n)
+ {
+ /* Increment or decrement a scalar (whose mode is given by the first
+ type suffix) by the number of active elements in a predicate
+ (whose mode is given by the second type suffix). */
+ machine_mode mode = GET_MODE_INNER (e.vector_mode (0));
+ icode = code_for_aarch64_sve_cntp (code, mode, e.vector_mode (1));
+ }
+ else
+ /* Increment a vector by the number of active elements in a predicate,
+ with the vector mode determining the predicate mode. */
+ icode = code_for_aarch64_sve_cntp (code, e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+
+ /* The saturating addition or subtraction codes to use for signed and
+ unsigned values respectively. */
+ rtx_code m_code_for_sint;
+ rtx_code m_code_for_uint;
+};
+
+class svqsub_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.expand_signed_unpred_op (SS_MINUS, US_MINUS);
+ }
+};
+
+class svrdffr_impl : public function_base
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_FFR;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* See the block comment in aarch64-sve.md for details about the
+ FFR handling. */
+ emit_insn (gen_aarch64_copy_ffr_to_ffrt ());
+ rtx result = e.use_exact_insn (e.pred == PRED_z
+ ? CODE_FOR_aarch64_rdffr_z
+ : CODE_FOR_aarch64_rdffr);
+ emit_insn (gen_aarch64_update_ffrt ());
+ return result;
+ }
+};
+
+class svreinterpret_impl : public quiet<function_base>
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* Punt to rtl if the effect of the reinterpret on registers does not
+ conform to GCC's endianness model. */
+ if (!targetm.can_change_mode_class (f.vector_mode (0),
+ f.vector_mode (1), FP_REGS))
+ return NULL;
+
+ /* Otherwise svreinterpret corresponds directly to a VIEW_CONVERT_EXPR
+ reinterpretation. */
+ tree rhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (f.lhs),
+ gimple_call_arg (f.call, 0));
+ return gimple_build_assign (f.lhs, VIEW_CONVERT_EXPR, rhs);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ return e.use_exact_insn (code_for_aarch64_sve_reinterpret (mode));
+ }
+};
+
+class svrev_impl : public permute
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* Punt for now on _b16 and wider; we'd need more complex evpc logic
+ to rerecognize the result. */
+ if (f.type_suffix (0).bool_p && f.type_suffix (0).element_bits > 8)
+ return NULL;
+
+ /* Permute as { nelts - 1, nelts - 2, nelts - 3, ... }. */
+ poly_int64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+ vec_perm_builder builder (nelts, 1, 3);
+ for (int i = 0; i < 3; ++i)
+ builder.quick_push (nelts - i - 1);
+ return fold_permute (f, builder);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_sve_rev (e.vector_mode (0)));
+ }
+};
+
+class svsel_impl : public quiet<function_base>
+{
+public:
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* svsel corresponds exactly to VEC_COND_EXPR. */
+ gimple_seq stmts = NULL;
+ tree pred = f.convert_pred (stmts, f.vector_type (0), 0);
+ gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+ return gimple_build_assign (f.lhs, VEC_COND_EXPR, pred,
+ gimple_call_arg (f.call, 1),
+ gimple_call_arg (f.call, 2));
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* svsel (cond, truev, falsev) is vcond_mask (truev, falsev, cond). */
+ e.rotate_inputs_left (0, 3);
+ insn_code icode = convert_optab_handler (vcond_mask_optab,
+ e.vector_mode (0),
+ e.gp_mode (0));
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements svset2, svset3 and svset4. */
+class svset_impl : public quiet<multi_vector_function>
+{
+public:
+ CONSTEXPR svset_impl (unsigned int vectors_per_tuple)
+ : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree rhs_tuple = gimple_call_arg (f.call, 0);
+ tree index = gimple_call_arg (f.call, 1);
+ tree rhs_vector = gimple_call_arg (f.call, 2);
+
+ /* Replace the call with two statements: a copy of the full tuple
+ to the call result, followed by an update of the individual vector.
+
+ The fold routines expect the replacement statement to have the
+ same lhs as the original call, so return the copy statement
+ rather than the field update. */
+ gassign *copy = gimple_build_assign (unshare_expr (f.lhs), rhs_tuple);
+
+ /* Get a reference to the individual vector. */
+ tree field = tuple_type_field (TREE_TYPE (f.lhs));
+ tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+ f.lhs, field, NULL_TREE);
+ tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
+ lhs_array, index, NULL_TREE, NULL_TREE);
+ gassign *update = gimple_build_assign (lhs_vector, rhs_vector);
+ gsi_insert_after (f.gsi, update, GSI_SAME_STMT);
+
+ return copy;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ rtx rhs_tuple = e.args[0];
+ unsigned int index = INTVAL (e.args[1]);
+ rtx rhs_vector = e.args[2];
+
+ /* First copy the full tuple to the target register. */
+ rtx lhs_tuple = e.get_nonoverlapping_reg_target ();
+ emit_move_insn (lhs_tuple, rhs_tuple);
+
+ /* ...then update the individual vector. */
+ rtx lhs_vector = simplify_gen_subreg (GET_MODE (rhs_vector),
+ lhs_tuple, GET_MODE (lhs_tuple),
+ index * BYTES_PER_SVE_VECTOR);
+ emit_move_insn (lhs_vector, rhs_vector);
+ return lhs_vector;
+ }
+};
+
+class svsetffr_impl : public function_base
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_FFR;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.args.quick_push (CONSTM1_RTX (VNx16BImode));
+ return e.use_exact_insn (CODE_FOR_aarch64_wrffr);
+ }
+};
+
+class svsplice_impl : public quiet<function_base>
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_sve_splice (e.vector_mode (0)));
+ }
+};
+
+class svst1_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_MEMORY;
+ }
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree vectype = f.vector_type (0);
+
+ /* Get the predicate and base pointer. */
+ gimple_seq stmts = NULL;
+ tree pred = f.convert_pred (stmts, vectype, 0);
+ tree base = f.fold_contiguous_base (stmts, vectype);
+ gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+ tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+ tree rhs = gimple_call_arg (f.call, gimple_call_num_args (f.call) - 1);
+ return gimple_build_call_internal (IFN_MASK_STORE, 4,
+ base, cookie, pred, rhs);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = convert_optab_handler (maskstore_optab,
+ e.vector_mode (0), e.gp_mode (0));
+ return e.use_contiguous_store_insn (icode);
+ }
+};
+
+class svst1_scatter_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_MEMORY;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.prepare_gather_address_operands (1);
+ /* Put the predicate last, as required by mask_scatter_store_optab. */
+ e.rotate_inputs_left (0, 6);
+ insn_code icode = direct_optab_handler (mask_scatter_store_optab,
+ e.memory_vector_mode ());
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements truncating forms of svst1_scatter. */
+class svst1_scatter_truncate_impl : public truncating_store
+{
+public:
+ CONSTEXPR svst1_scatter_truncate_impl (scalar_int_mode to_mode)
+ : truncating_store (to_mode) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ e.prepare_gather_address_operands (1);
+ /* Put the predicate last, since the truncating scatters use the same
+ operand order as mask_scatter_store_optab. */
+ e.rotate_inputs_left (0, 6);
+ insn_code icode = code_for_aarch64_scatter_store_trunc
+ (e.memory_vector_mode (), e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+};
+
+/* Implements truncating contiguous forms of svst1. */
+class svst1_truncate_impl : public truncating_store
+{
+public:
+ CONSTEXPR svst1_truncate_impl (scalar_int_mode to_mode)
+ : truncating_store (to_mode) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = code_for_aarch64_store_trunc (e.memory_vector_mode (),
+ e.vector_mode (0));
+ return e.use_contiguous_store_insn (icode);
+ }
+};
+
+/* Implements svst2, svst3 and svst4. */
+class svst234_impl : public full_width_access
+{
+public:
+ CONSTEXPR svst234_impl (unsigned int vectors_per_tuple)
+ : full_width_access (vectors_per_tuple) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_MEMORY;
+ }
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ tree vectype = f.vector_type (0);
+
+ /* Get the predicate and base pointer. */
+ gimple_seq stmts = NULL;
+ tree pred = f.convert_pred (stmts, vectype, 0);
+ tree base = f.fold_contiguous_base (stmts, vectype);
+ gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+ /* View the stored data as an array of vectors. */
+ unsigned int num_args = gimple_call_num_args (f.call);
+ tree rhs_tuple = gimple_call_arg (f.call, num_args - 1);
+ tree field = tuple_type_field (TREE_TYPE (rhs_tuple));
+ tree rhs_array = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (field), rhs_tuple);
+
+ tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+ return gimple_build_call_internal (IFN_MASK_STORE_LANES, 4,
+ base, cookie, pred, rhs_array);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode tuple_mode = GET_MODE (e.args.last ());
+ insn_code icode = convert_optab_handler (vec_mask_store_lanes_optab,
+ tuple_mode, e.vector_mode (0));
+ return e.use_contiguous_store_insn (icode);
+ }
+};
+
+class svstnt1_impl : public full_width_access
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_MEMORY;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = code_for_aarch64_stnt1 (e.vector_mode (0));
+ return e.use_contiguous_store_insn (icode);
+ }
+};
+
+class svsub_impl : public rtx_code_function
+{
+public:
+ CONSTEXPR svsub_impl ()
+ : rtx_code_function (MINUS, MINUS, UNSPEC_COND_FSUB) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Canonicalize subtractions of constants to additions. */
+ machine_mode mode = e.vector_mode (0);
+ if (e.try_negating_argument (2, mode))
+ return e.map_to_rtx_codes (PLUS, PLUS, UNSPEC_COND_FADD);
+
+ return rtx_code_function::expand (e);
+ }
+};
+
+class svtbl_impl : public permute
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_sve_tbl (e.vector_mode (0)));
+ }
+};
+
+class svtmad_impl : public function_base
+{
+public:
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (code_for_aarch64_sve_tmad (e.vector_mode (0)));
+ }
+};
+
+/* Implements svtrn1 and svtrn2. */
+class svtrn_impl : public binary_permute
+{
+public:
+ CONSTEXPR svtrn_impl (int base)
+ : binary_permute (base ? UNSPEC_TRN2 : UNSPEC_TRN1), m_base (base) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* svtrn1: { 0, nelts, 2, nelts + 2, 4, nelts + 4, ... }
+ svtrn2: as for svtrn1, but with 1 added to each index. */
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+ vec_perm_builder builder (nelts, 2, 3);
+ for (unsigned int i = 0; i < 3; ++i)
+ {
+ builder.quick_push (m_base + i * 2);
+ builder.quick_push (m_base + i * 2 + nelts);
+ }
+ return fold_permute (f, builder);
+ }
+
+ /* 0 for svtrn1, 1 for svtrn2. */
+ unsigned int m_base;
+};
+
+/* Base class for svundef{,2,3,4}. */
+class svundef_impl : public quiet<multi_vector_function>
+{
+public:
+ CONSTEXPR svundef_impl (unsigned int vectors_per_tuple)
+ : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* Don't fold svundef at the gimple level. There's no exact
+ correspondence for SSA_NAMEs, and we explicitly don't want
+ to generate a specific value (like an all-zeros vector). */
+ if (vectors_per_tuple () == 1)
+ return NULL;
+ return gimple_build_assign (f.lhs, build_clobber (TREE_TYPE (f.lhs)));
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ rtx target = e.get_reg_target ();
+ emit_clobber (copy_rtx (target));
+ return target;
+ }
+};
+
+/* Implements svunpklo and svunpkhi. */
+class svunpk_impl : public quiet<function_base>
+{
+public:
+ CONSTEXPR svunpk_impl (bool high_p) : m_high_p (high_p) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* Don't fold the predicate ops, since every bit of the svbool_t
+ result is significant. */
+ if (f.type_suffix_ids[0] == TYPE_SUFFIX_b)
+ return NULL;
+
+ /* The first half in memory is VEC_UNPACK_LO_EXPR for little-endian
+ and VEC_UNPACK_HI_EXPR for big-endian. */
+ bool high_p = BYTES_BIG_ENDIAN ? !m_high_p : m_high_p;
+ tree_code code = high_p ? VEC_UNPACK_HI_EXPR : VEC_UNPACK_LO_EXPR;
+ return gimple_build_assign (f.lhs, code, gimple_call_arg (f.call, 0));
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = GET_MODE (e.args[0]);
+ unsigned int unpacku = m_high_p ? UNSPEC_UNPACKUHI : UNSPEC_UNPACKULO;
+ unsigned int unpacks = m_high_p ? UNSPEC_UNPACKSHI : UNSPEC_UNPACKSLO;
+ insn_code icode;
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+ icode = code_for_aarch64_sve_punpk (unpacku, mode);
+ else
+ {
+ int unspec = e.type_suffix (0).unsigned_p ? unpacku : unpacks;
+ icode = code_for_aarch64_sve_unpk (unspec, unspec, mode);
+ }
+ return e.use_exact_insn (icode);
+ }
+
+ /* True for svunpkhi, false for svunpklo. */
+ bool m_high_p;
+};
+
+/* Implements svuzp1 and svuzp2. */
+class svuzp_impl : public binary_permute
+{
+public:
+ CONSTEXPR svuzp_impl (unsigned int base)
+ : binary_permute (base ? UNSPEC_UZP2 : UNSPEC_UZP1), m_base (base) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* svuzp1: { 0, 2, 4, 6, ... }
+ svuzp2: { 1, 3, 5, 7, ... }. */
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+ vec_perm_builder builder (nelts, 1, 3);
+ for (unsigned int i = 0; i < 3; ++i)
+ builder.quick_push (m_base + i * 2);
+ return fold_permute (f, builder);
+ }
+
+ /* 0 for svuzp1, 1 for svuzp2. */
+ unsigned int m_base;
+};
+
+/* A function_base for svwhilele and svwhilelt functions. */
+class svwhile_impl : public function_base
+{
+public:
+ CONSTEXPR svwhile_impl (int unspec_for_sint, int unspec_for_uint, bool eq_p)
+ : m_unspec_for_sint (unspec_for_sint),
+ m_unspec_for_uint (unspec_for_uint), m_eq_p (eq_p)
+ {}
+
+ /* Try to fold a call by treating its arguments as constants of type T. */
+ template<typename T>
+ gimple *
+ fold_type (gimple_folder &f) const
+ {
+ /* Only handle cases in which both operands are constant. */
+ T arg0, arg1;
+ if (!poly_int_tree_p (gimple_call_arg (f.call, 0), &arg0)
+ || !poly_int_tree_p (gimple_call_arg (f.call, 1), &arg1))
+ return NULL;
+
+ /* Check whether the result is known to be all-false. */
+ if (m_eq_p ? known_gt (arg0, arg1) : known_ge (arg0, arg1))
+ return f.fold_to_pfalse ();
+
+ /* Punt if we can't tell at compile time whether the result
+ is all-false. */
+ if (m_eq_p ? maybe_gt (arg0, arg1) : maybe_ge (arg0, arg1))
+ return NULL;
+
+ /* At this point we know the result has at least one set element. */
+ poly_uint64 diff = arg1 - arg0;
+ poly_uint64 nelts = GET_MODE_NUNITS (f.vector_mode (0));
+
+ /* Canonicalize the svwhilele form to the svwhilelt form. Subtract
+ from NELTS rather than adding to DIFF, to prevent overflow. */
+ if (m_eq_p)
+ nelts -= 1;
+
+ /* Check whether the result is known to be all-true. */
+ if (known_ge (diff, nelts))
+ return f.fold_to_ptrue ();
+
+ /* Punt if DIFF might not be the actual number of set elements
+ in the result. Conditional equality is fine. */
+ if (maybe_gt (diff, nelts))
+ return NULL;
+
+ /* At this point we know that the predicate will have DIFF set elements
+ for svwhilelt and DIFF + 1 set elements for svwhilele (which stops
+ after rather than before ARG1 is reached). See if we can create
+ the predicate at compile time. */
+ unsigned HOST_WIDE_INT vl;
+ if (diff.is_constant (&vl))
+ /* Overflow is no longer possible after the checks above. */
+ return f.fold_to_vl_pred (m_eq_p ? vl + 1 : vl);
+
+ return NULL;
+ }
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ if (f.type_suffix (1).unsigned_p)
+ return fold_type<poly_uint64> (f);
+ else
+ return fold_type<poly_int64> (f);
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Suffix 0 determines the predicate mode, suffix 1 determines the
+ scalar mode and signedness. */
+ int unspec = (e.type_suffix (1).unsigned_p
+ ? m_unspec_for_uint
+ : m_unspec_for_sint);
+ machine_mode pred_mode = e.vector_mode (0);
+ scalar_mode reg_mode = GET_MODE_INNER (e.vector_mode (1));
+ return e.use_exact_insn (code_for_while (unspec, reg_mode, pred_mode));
+ }
+
+ /* The unspec codes associated with signed and unsigned operations
+ respectively. */
+ int m_unspec_for_sint;
+ int m_unspec_for_uint;
+
+ /* True svwhilele, false for svwhilelt. */
+ bool m_eq_p;
+};
+
+class svwrffr_impl : public function_base
+{
+public:
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_FFR;
+ }
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.use_exact_insn (CODE_FOR_aarch64_wrffr);
+ }
+};
+
+/* Implements svzip1 and svzip2. */
+class svzip_impl : public binary_permute
+{
+public:
+ CONSTEXPR svzip_impl (unsigned int base)
+ : binary_permute (base ? UNSPEC_ZIP2 : UNSPEC_ZIP1), m_base (base) {}
+
+ gimple *
+ fold (gimple_folder &f) const OVERRIDE
+ {
+ /* svzip1: { 0, nelts, 1, nelts + 1, 2, nelts + 2, ... }
+ svzip2: as for svzip1, but with nelts / 2 added to each index. */
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+ poly_uint64 base = m_base * exact_div (nelts, 2);
+ vec_perm_builder builder (nelts, 2, 3);
+ for (unsigned int i = 0; i < 3; ++i)
+ {
+ builder.quick_push (base + i);
+ builder.quick_push (base + i + nelts);
+ }
+ return fold_permute (f, builder);
+ }
+
+ /* 0 for svzip1, 1 for svzip2. */
+ unsigned int m_base;
+};
+
+} /* end anonymous namespace */
+
+namespace aarch64_sve {
+
+FUNCTION (svabd, svabd_impl,)
+FUNCTION (svabs, quiet<rtx_code_function>, (ABS, ABS, UNSPEC_COND_FABS))
+FUNCTION (svacge, svac_impl, (UNSPEC_COND_FCMGE))
+FUNCTION (svacgt, svac_impl, (UNSPEC_COND_FCMGT))
+FUNCTION (svacle, svac_impl, (UNSPEC_COND_FCMLE))
+FUNCTION (svaclt, svac_impl, (UNSPEC_COND_FCMLT))
+FUNCTION (svadd, rtx_code_function, (PLUS, PLUS, UNSPEC_COND_FADD))
+FUNCTION (svadda, svadda_impl,)
+FUNCTION (svaddv, reduction, (UNSPEC_SADDV, UNSPEC_UADDV, UNSPEC_FADDV))
+FUNCTION (svadrb, svadr_bhwd_impl, (0))
+FUNCTION (svadrd, svadr_bhwd_impl, (3))
+FUNCTION (svadrh, svadr_bhwd_impl, (1))
+FUNCTION (svadrw, svadr_bhwd_impl, (2))
+FUNCTION (svand, rtx_code_function, (AND, AND))
+FUNCTION (svandv, reduction, (UNSPEC_ANDV))
+FUNCTION (svasr, rtx_code_function, (ASHIFTRT, ASHIFTRT))
+FUNCTION (svasr_wide, shift_wide, (ASHIFTRT, UNSPEC_ASHIFTRT_WIDE))
+FUNCTION (svasrd, svasrd_impl,)
+FUNCTION (svbic, svbic_impl,)
+FUNCTION (svbrka, svbrk_unary_impl, (UNSPEC_BRKA))
+FUNCTION (svbrkb, svbrk_unary_impl, (UNSPEC_BRKB))
+FUNCTION (svbrkn, svbrk_binary_impl, (UNSPEC_BRKN))
+FUNCTION (svbrkpa, svbrk_binary_impl, (UNSPEC_BRKPA))
+FUNCTION (svbrkpb, svbrk_binary_impl, (UNSPEC_BRKPB))
+FUNCTION (svcadd, svcadd_impl,)
+FUNCTION (svclasta, svclast_impl, (UNSPEC_CLASTA))
+FUNCTION (svclastb, svclast_impl, (UNSPEC_CLASTB))
+FUNCTION (svcls, unary_count, (CLRSB))
+FUNCTION (svclz, unary_count, (CLZ))
+FUNCTION (svcmla, svcmla_impl,)
+FUNCTION (svcmla_lane, svcmla_lane_impl,)
+FUNCTION (svcmpeq, svcmp_impl, (EQ_EXPR, UNSPEC_COND_FCMEQ))
+FUNCTION (svcmpeq_wide, svcmp_wide_impl, (EQ_EXPR, UNSPEC_COND_CMPEQ_WIDE,
+ UNSPEC_COND_CMPEQ_WIDE))
+FUNCTION (svcmpge, svcmp_impl, (GE_EXPR, UNSPEC_COND_FCMGE))
+FUNCTION (svcmpge_wide, svcmp_wide_impl, (GE_EXPR, UNSPEC_COND_CMPGE_WIDE,
+ UNSPEC_COND_CMPHS_WIDE))
+FUNCTION (svcmpgt, svcmp_impl, (GT_EXPR, UNSPEC_COND_FCMGT))
+FUNCTION (svcmpgt_wide, svcmp_wide_impl, (GT_EXPR, UNSPEC_COND_CMPGT_WIDE,
+ UNSPEC_COND_CMPHI_WIDE))
+FUNCTION (svcmple, svcmp_impl, (LE_EXPR, UNSPEC_COND_FCMLE))
+FUNCTION (svcmple_wide, svcmp_wide_impl, (LE_EXPR, UNSPEC_COND_CMPLE_WIDE,
+ UNSPEC_COND_CMPLS_WIDE))
+FUNCTION (svcmplt, svcmp_impl, (LT_EXPR, UNSPEC_COND_FCMLT))
+FUNCTION (svcmplt_wide, svcmp_wide_impl, (LT_EXPR, UNSPEC_COND_CMPLT_WIDE,
+ UNSPEC_COND_CMPLO_WIDE))
+FUNCTION (svcmpne, svcmp_impl, (NE_EXPR, UNSPEC_COND_FCMNE))
+FUNCTION (svcmpne_wide, svcmp_wide_impl, (NE_EXPR, UNSPEC_COND_CMPNE_WIDE,
+ UNSPEC_COND_CMPNE_WIDE))
+FUNCTION (svcmpuo, svcmpuo_impl,)
+FUNCTION (svcnot, svcnot_impl,)
+FUNCTION (svcnt, unary_count, (POPCOUNT))
+FUNCTION (svcntb, svcnt_bhwd_impl, (VNx16QImode))
+FUNCTION (svcntb_pat, svcnt_bhwd_pat_impl, (VNx16QImode))
+FUNCTION (svcntd, svcnt_bhwd_impl, (VNx2DImode))
+FUNCTION (svcntd_pat, svcnt_bhwd_pat_impl, (VNx2DImode))
+FUNCTION (svcnth, svcnt_bhwd_impl, (VNx8HImode))
+FUNCTION (svcnth_pat, svcnt_bhwd_pat_impl, (VNx8HImode))
+FUNCTION (svcntp, svcntp_impl,)
+FUNCTION (svcntw, svcnt_bhwd_impl, (VNx4SImode))
+FUNCTION (svcntw_pat, svcnt_bhwd_pat_impl, (VNx4SImode))
+FUNCTION (svcompact, svcompact_impl,)
+FUNCTION (svcreate2, svcreate_impl, (2))
+FUNCTION (svcreate3, svcreate_impl, (3))
+FUNCTION (svcreate4, svcreate_impl, (4))
+FUNCTION (svcvt, svcvt_impl,)
+FUNCTION (svdiv, rtx_code_function, (DIV, UDIV, UNSPEC_COND_FDIV))
+FUNCTION (svdivr, rtx_code_function_rotated, (DIV, UDIV, UNSPEC_COND_FDIV))
+FUNCTION (svdot, svdot_impl,)
+FUNCTION (svdot_lane, svdot_lane_impl,)
+FUNCTION (svdup, svdup_impl,)
+FUNCTION (svdup_lane, svdup_lane_impl,)
+FUNCTION (svdupq, svdupq_impl,)
+FUNCTION (svdupq_lane, svdupq_lane_impl,)
+FUNCTION (sveor, rtx_code_function, (XOR, XOR, -1))
+FUNCTION (sveorv, reduction, (UNSPEC_XORV))
+FUNCTION (svexpa, unspec_based_function, (-1, -1, UNSPEC_FEXPA))
+FUNCTION (svext, svext_impl,)
+FUNCTION (svextb, svext_bhw_impl, (QImode))
+FUNCTION (svexth, svext_bhw_impl, (HImode))
+FUNCTION (svextw, svext_bhw_impl, (SImode))
+FUNCTION (svget2, svget_impl, (2))
+FUNCTION (svget3, svget_impl, (3))
+FUNCTION (svget4, svget_impl, (4))
+FUNCTION (svindex, svindex_impl,)
+FUNCTION (svinsr, svinsr_impl,)
+FUNCTION (svlasta, svlast_impl, (UNSPEC_LASTA))
+FUNCTION (svlastb, svlast_impl, (UNSPEC_LASTB))
+FUNCTION (svld1, svld1_impl,)
+FUNCTION (svld1_gather, svld1_gather_impl,)
+FUNCTION (svld1rq, svld1rq_impl,)
+FUNCTION (svld1sb, svld1_extend_impl, (TYPE_SUFFIX_s8))
+FUNCTION (svld1sb_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s8))
+FUNCTION (svld1sh, svld1_extend_impl, (TYPE_SUFFIX_s16))
+FUNCTION (svld1sh_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s16))
+FUNCTION (svld1sw, svld1_extend_impl, (TYPE_SUFFIX_s32))
+FUNCTION (svld1sw_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s32))
+FUNCTION (svld1ub, svld1_extend_impl, (TYPE_SUFFIX_u8))
+FUNCTION (svld1ub_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_u8))
+FUNCTION (svld1uh, svld1_extend_impl, (TYPE_SUFFIX_u16))
+FUNCTION (svld1uh_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_u16))
+FUNCTION (svld1uw, svld1_extend_impl, (TYPE_SUFFIX_u32))
+FUNCTION (svld1uw_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_u32))
+FUNCTION (svld2, svld234_impl, (2))
+FUNCTION (svld3, svld234_impl, (3))
+FUNCTION (svld4, svld234_impl, (4))
+FUNCTION (svldff1, svldxf1_impl, (UNSPEC_LDFF1))
+FUNCTION (svldff1_gather, svldff1_gather_impl,)
+FUNCTION (svldff1sb, svldxf1_extend_impl, (TYPE_SUFFIX_s8, UNSPEC_LDFF1))
+FUNCTION (svldff1sb_gather, svldff1_gather_extend, (TYPE_SUFFIX_s8))
+FUNCTION (svldff1sh, svldxf1_extend_impl, (TYPE_SUFFIX_s16, UNSPEC_LDFF1))
+FUNCTION (svldff1sh_gather, svldff1_gather_extend, (TYPE_SUFFIX_s16))
+FUNCTION (svldff1sw, svldxf1_extend_impl, (TYPE_SUFFIX_s32, UNSPEC_LDFF1))
+FUNCTION (svldff1sw_gather, svldff1_gather_extend, (TYPE_SUFFIX_s32))
+FUNCTION (svldff1ub, svldxf1_extend_impl, (TYPE_SUFFIX_u8, UNSPEC_LDFF1))
+FUNCTION (svldff1ub_gather, svldff1_gather_extend, (TYPE_SUFFIX_u8))
+FUNCTION (svldff1uh, svldxf1_extend_impl, (TYPE_SUFFIX_u16, UNSPEC_LDFF1))
+FUNCTION (svldff1uh_gather, svldff1_gather_extend, (TYPE_SUFFIX_u16))
+FUNCTION (svldff1uw, svldxf1_extend_impl, (TYPE_SUFFIX_u32, UNSPEC_LDFF1))
+FUNCTION (svldff1uw_gather, svldff1_gather_extend, (TYPE_SUFFIX_u32))
+FUNCTION (svldnf1, svldxf1_impl, (UNSPEC_LDNF1))
+FUNCTION (svldnf1sb, svldxf1_extend_impl, (TYPE_SUFFIX_s8, UNSPEC_LDNF1))
+FUNCTION (svldnf1sh, svldxf1_extend_impl, (TYPE_SUFFIX_s16, UNSPEC_LDNF1))
+FUNCTION (svldnf1sw, svldxf1_extend_impl, (TYPE_SUFFIX_s32, UNSPEC_LDNF1))
+FUNCTION (svldnf1ub, svldxf1_extend_impl, (TYPE_SUFFIX_u8, UNSPEC_LDNF1))
+FUNCTION (svldnf1uh, svldxf1_extend_impl, (TYPE_SUFFIX_u16, UNSPEC_LDNF1))
+FUNCTION (svldnf1uw, svldxf1_extend_impl, (TYPE_SUFFIX_u32, UNSPEC_LDNF1))
+FUNCTION (svldnt1, svldnt1_impl,)
+FUNCTION (svlen, svlen_impl,)
+FUNCTION (svlsl, rtx_code_function, (ASHIFT, ASHIFT))
+FUNCTION (svlsl_wide, shift_wide, (ASHIFT, UNSPEC_ASHIFT_WIDE))
+FUNCTION (svlsr, rtx_code_function, (LSHIFTRT, LSHIFTRT))
+FUNCTION (svlsr_wide, shift_wide, (LSHIFTRT, UNSPEC_LSHIFTRT_WIDE))
+FUNCTION (svmad, svmad_impl,)
+FUNCTION (svmax, rtx_code_function, (SMAX, UMAX, UNSPEC_COND_FMAX))
+FUNCTION (svmaxnm, unspec_based_function, (-1, -1, UNSPEC_COND_FMAXNM))
+FUNCTION (svmaxnmv, reduction, (UNSPEC_FMAXNMV))
+FUNCTION (svmaxv, reduction, (UNSPEC_SMAXV, UNSPEC_UMAXV, UNSPEC_FMAXV))
+FUNCTION (svmin, rtx_code_function, (SMIN, UMIN, UNSPEC_COND_FMIN))
+FUNCTION (svminnm, unspec_based_function, (-1, -1, UNSPEC_COND_FMINNM))
+FUNCTION (svminnmv, reduction, (UNSPEC_FMINNMV))
+FUNCTION (svminv, reduction, (UNSPEC_SMINV, UNSPEC_UMINV, UNSPEC_FMINV))
+FUNCTION (svmla, svmla_impl,)
+FUNCTION (svmla_lane, svmla_svmls_lane_impl, (UNSPEC_FMLA))
+FUNCTION (svmls, svmls_impl,)
+FUNCTION (svmls_lane, svmla_svmls_lane_impl, (UNSPEC_FMLS))
+FUNCTION (svmov, svmov_impl,)
+FUNCTION (svmsb, svmsb_impl,)
+FUNCTION (svmul, rtx_code_function, (MULT, MULT, UNSPEC_COND_FMUL))
+FUNCTION (svmul_lane, svmul_lane_impl,)
+FUNCTION (svmulh, unspec_based_function, (UNSPEC_SMUL_HIGHPART,
+ UNSPEC_UMUL_HIGHPART, -1))
+FUNCTION (svmulx, unspec_based_function, (-1, -1, UNSPEC_COND_FMULX))
+FUNCTION (svnand, svnand_impl,)
+FUNCTION (svneg, quiet<rtx_code_function>, (NEG, NEG, UNSPEC_COND_FNEG))
+FUNCTION (svnmad, unspec_based_function, (-1, -1, UNSPEC_COND_FNMLA))
+FUNCTION (svnmla, unspec_based_function_rotated, (-1, -1, UNSPEC_COND_FNMLA))
+FUNCTION (svnmls, unspec_based_function_rotated, (-1, -1, UNSPEC_COND_FNMLS))
+FUNCTION (svnmsb, unspec_based_function, (-1, -1, UNSPEC_COND_FNMLS))
+FUNCTION (svnor, svnor_impl,)
+FUNCTION (svnot, svnot_impl,)
+FUNCTION (svorn, svorn_impl,)
+FUNCTION (svorr, rtx_code_function, (IOR, IOR))
+FUNCTION (svorv, reduction, (UNSPEC_IORV))
+FUNCTION (svpfalse, svpfalse_impl,)
+FUNCTION (svpfirst, svpfirst_svpnext_impl, (UNSPEC_PFIRST))
+FUNCTION (svpnext, svpfirst_svpnext_impl, (UNSPEC_PNEXT))
+FUNCTION (svprfb, svprf_bhwd_impl, (VNx16QImode))
+FUNCTION (svprfb_gather, svprf_bhwd_gather_impl, (VNx16QImode))
+FUNCTION (svprfd, svprf_bhwd_impl, (VNx2DImode))
+FUNCTION (svprfd_gather, svprf_bhwd_gather_impl, (VNx2DImode))
+FUNCTION (svprfh, svprf_bhwd_impl, (VNx8HImode))
+FUNCTION (svprfh_gather, svprf_bhwd_gather_impl, (VNx8HImode))
+FUNCTION (svprfw, svprf_bhwd_impl, (VNx4SImode))
+FUNCTION (svprfw_gather, svprf_bhwd_gather_impl, (VNx4SImode))
+FUNCTION (svptest_any, svptest_impl, (NE))
+FUNCTION (svptest_first, svptest_impl, (LT))
+FUNCTION (svptest_last, svptest_impl, (LTU))
+FUNCTION (svptrue, svptrue_impl,)
+FUNCTION (svptrue_pat, svptrue_pat_impl,)
+FUNCTION (svqadd, svqadd_impl,)
+FUNCTION (svqdecb, svqdec_bhwd_impl, (QImode))
+FUNCTION (svqdecb_pat, svqdec_bhwd_impl, (QImode))
+FUNCTION (svqdecd, svqdec_bhwd_impl, (DImode))
+FUNCTION (svqdecd_pat, svqdec_bhwd_impl, (DImode))
+FUNCTION (svqdech, svqdec_bhwd_impl, (HImode))
+FUNCTION (svqdech_pat, svqdec_bhwd_impl, (HImode))
+FUNCTION (svqdecp, svqdecp_svqincp_impl, (SS_MINUS, US_MINUS))
+FUNCTION (svqdecw, svqdec_bhwd_impl, (SImode))
+FUNCTION (svqdecw_pat, svqdec_bhwd_impl, (SImode))
+FUNCTION (svqincb, svqinc_bhwd_impl, (QImode))
+FUNCTION (svqincb_pat, svqinc_bhwd_impl, (QImode))
+FUNCTION (svqincd, svqinc_bhwd_impl, (DImode))
+FUNCTION (svqincd_pat, svqinc_bhwd_impl, (DImode))
+FUNCTION (svqinch, svqinc_bhwd_impl, (HImode))
+FUNCTION (svqinch_pat, svqinc_bhwd_impl, (HImode))
+FUNCTION (svqincp, svqdecp_svqincp_impl, (SS_PLUS, US_PLUS))
+FUNCTION (svqincw, svqinc_bhwd_impl, (SImode))
+FUNCTION (svqincw_pat, svqinc_bhwd_impl, (SImode))
+FUNCTION (svqsub, svqsub_impl,)
+FUNCTION (svrbit, unspec_based_function, (UNSPEC_RBIT, UNSPEC_RBIT, -1))
+FUNCTION (svrdffr, svrdffr_impl,)
+FUNCTION (svrecpe, unspec_based_function, (-1, -1, UNSPEC_FRECPE))
+FUNCTION (svrecps, unspec_based_function, (-1, -1, UNSPEC_FRECPS))
+FUNCTION (svrecpx, unspec_based_function, (-1, -1, UNSPEC_COND_FRECPX))
+FUNCTION (svreinterpret, svreinterpret_impl,)
+FUNCTION (svrev, svrev_impl,)
+FUNCTION (svrevb, unspec_based_function, (UNSPEC_REVB, UNSPEC_REVB, -1))
+FUNCTION (svrevh, unspec_based_function, (UNSPEC_REVH, UNSPEC_REVH, -1))
+FUNCTION (svrevw, unspec_based_function, (UNSPEC_REVW, UNSPEC_REVW, -1))
+FUNCTION (svrinta, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTA))
+FUNCTION (svrinti, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTI))
+FUNCTION (svrintm, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTM))
+FUNCTION (svrintn, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTN))
+FUNCTION (svrintp, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTP))
+FUNCTION (svrintx, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTX))
+FUNCTION (svrintz, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTZ))
+FUNCTION (svrsqrte, unspec_based_function, (-1, -1, UNSPEC_RSQRTE))
+FUNCTION (svrsqrts, unspec_based_function, (-1, -1, UNSPEC_RSQRTS))
+FUNCTION (svscale, unspec_based_function, (-1, -1, UNSPEC_COND_FSCALE))
+FUNCTION (svsel, svsel_impl,)
+FUNCTION (svset2, svset_impl, (2))
+FUNCTION (svset3, svset_impl, (3))
+FUNCTION (svset4, svset_impl, (4))
+FUNCTION (svsetffr, svsetffr_impl,)
+FUNCTION (svsplice, svsplice_impl,)
+FUNCTION (svsqrt, rtx_code_function, (SQRT, SQRT, UNSPEC_COND_FSQRT))
+FUNCTION (svst1, svst1_impl,)
+FUNCTION (svst1_scatter, svst1_scatter_impl,)
+FUNCTION (svst1b, svst1_truncate_impl, (QImode))
+FUNCTION (svst1b_scatter, svst1_scatter_truncate_impl, (QImode))
+FUNCTION (svst1h, svst1_truncate_impl, (HImode))
+FUNCTION (svst1h_scatter, svst1_scatter_truncate_impl, (HImode))
+FUNCTION (svst1w, svst1_truncate_impl, (SImode))
+FUNCTION (svst1w_scatter, svst1_scatter_truncate_impl, (SImode))
+FUNCTION (svst2, svst234_impl, (2))
+FUNCTION (svst3, svst234_impl, (3))
+FUNCTION (svst4, svst234_impl, (4))
+FUNCTION (svstnt1, svstnt1_impl,)
+FUNCTION (svsub, svsub_impl,)
+FUNCTION (svsubr, rtx_code_function_rotated, (MINUS, MINUS, UNSPEC_COND_FSUB))
+FUNCTION (svtbl, svtbl_impl,)
+FUNCTION (svtmad, svtmad_impl,)
+FUNCTION (svtrn1, svtrn_impl, (0))
+FUNCTION (svtrn2, svtrn_impl, (1))
+FUNCTION (svtsmul, unspec_based_function, (-1, -1, UNSPEC_FTSMUL))
+FUNCTION (svtssel, unspec_based_function, (-1, -1, UNSPEC_FTSSEL))
+FUNCTION (svundef, svundef_impl, (1))
+FUNCTION (svundef2, svundef_impl, (2))
+FUNCTION (svundef3, svundef_impl, (3))
+FUNCTION (svundef4, svundef_impl, (4))
+FUNCTION (svunpkhi, svunpk_impl, (true))
+FUNCTION (svunpklo, svunpk_impl, (false))
+FUNCTION (svuzp1, svuzp_impl, (0))
+FUNCTION (svuzp2, svuzp_impl, (1))
+FUNCTION (svwhilele, svwhile_impl, (UNSPEC_WHILE_LE, UNSPEC_WHILE_LS, true))
+FUNCTION (svwhilelt, svwhile_impl, (UNSPEC_WHILE_LT, UNSPEC_WHILE_LO, false))
+FUNCTION (svwrffr, svwrffr_impl,)
+FUNCTION (svzip1, svzip_impl, (0))
+FUNCTION (svzip2, svzip_impl, (1))
+
+} /* end namespace aarch64_sve */
--- /dev/null
+/* ACLE support for AArch64 SVE (__ARM_FEATURE_SVE intrinsics)
+ Copyright (C) 2018-2019 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 REQUIRED_EXTENSIONS 0
+DEF_SVE_FUNCTION (svabd, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svabs, unary, all_float_and_signed, mxz)
+DEF_SVE_FUNCTION (svacge, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svacgt, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svacle, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svaclt, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svadd, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svadda, fold_left, all_float, implicit)
+DEF_SVE_FUNCTION (svaddv, reduction_wide, all_data, implicit)
+DEF_SVE_FUNCTION (svadrb, adr_offset, none, none)
+DEF_SVE_FUNCTION (svadrd, adr_index, none, none)
+DEF_SVE_FUNCTION (svadrh, adr_index, none, none)
+DEF_SVE_FUNCTION (svadrw, adr_index, none, none)
+DEF_SVE_FUNCTION (svand, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svand, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svandv, reduction, all_integer, implicit)
+DEF_SVE_FUNCTION (svasr, binary_uint_opt_n, all_signed, mxz)
+DEF_SVE_FUNCTION (svasr_wide, binary_uint64_opt_n, bhs_signed, mxz)
+DEF_SVE_FUNCTION (svasrd, shift_right_imm, all_signed, mxz)
+DEF_SVE_FUNCTION (svbic, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svbic, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svbrka, unary, b, mz)
+DEF_SVE_FUNCTION (svbrkb, unary, b, mz)
+DEF_SVE_FUNCTION (svbrkn, binary, b, z)
+DEF_SVE_FUNCTION (svbrkpa, binary, b, z)
+DEF_SVE_FUNCTION (svbrkpb, binary, b, z)
+DEF_SVE_FUNCTION (svcadd, binary_rotate, all_float, mxz)
+DEF_SVE_FUNCTION (svclasta, clast, all_data, implicit)
+DEF_SVE_FUNCTION (svclastb, clast, all_data, implicit)
+DEF_SVE_FUNCTION (svcls, unary_count, all_signed, mxz)
+DEF_SVE_FUNCTION (svclz, unary_count, all_integer, mxz)
+DEF_SVE_FUNCTION (svcmla, ternary_rotate, all_float, mxz)
+DEF_SVE_FUNCTION (svcmla_lane, ternary_lane_rotate, hs_float, none)
+DEF_SVE_FUNCTION (svcmpeq, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpeq_wide, compare_wide_opt_n, bhs_signed, implicit)
+DEF_SVE_FUNCTION (svcmpge, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpge_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmpgt, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpgt_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmple, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmple_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmplt, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmplt_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmpne, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpne_wide, compare_wide_opt_n, bhs_signed, implicit)
+DEF_SVE_FUNCTION (svcmpuo, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svcnot, unary, all_integer, mxz)
+DEF_SVE_FUNCTION (svcnt, unary_count, all_data, mxz)
+DEF_SVE_FUNCTION (svcntb, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcntb_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcntd, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcntd_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcnth, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcnth_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcntp, count_pred, all_pred, implicit)
+DEF_SVE_FUNCTION (svcntw, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcntw_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcompact, unary, sd_data, implicit)
+DEF_SVE_FUNCTION (svcreate2, create, all_data, none)
+DEF_SVE_FUNCTION (svcreate3, create, all_data, none)
+DEF_SVE_FUNCTION (svcreate4, create, all_data, none)
+DEF_SVE_FUNCTION (svcvt, unary_convert, cvt, mxz)
+DEF_SVE_FUNCTION (svdiv, binary_opt_n, all_float_and_sd_integer, mxz)
+DEF_SVE_FUNCTION (svdivr, binary_opt_n, all_float_and_sd_integer, mxz)
+DEF_SVE_FUNCTION (svdot, ternary_qq_opt_n, sd_integer, none)
+DEF_SVE_FUNCTION (svdot_lane, ternary_qq_lane, sd_integer, none)
+DEF_SVE_FUNCTION (svdup, unary_n, all_data, mxz_or_none)
+DEF_SVE_FUNCTION (svdup, unary_n, all_pred, none)
+DEF_SVE_FUNCTION (svdup_lane, binary_uint_n, all_data, none)
+DEF_SVE_FUNCTION (svdupq, dupq, all_data, none)
+DEF_SVE_FUNCTION (svdupq, dupq, all_pred, none)
+DEF_SVE_FUNCTION (svdupq_lane, binary_uint64_n, all_data, none)
+DEF_SVE_FUNCTION (sveor, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (sveor, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (sveorv, reduction, all_integer, implicit)
+DEF_SVE_FUNCTION (svexpa, unary_uint, all_float, none)
+DEF_SVE_FUNCTION (svext, ext, all_data, none)
+DEF_SVE_FUNCTION (svextb, unary, hsd_integer, mxz)
+DEF_SVE_FUNCTION (svexth, unary, sd_integer, mxz)
+DEF_SVE_FUNCTION (svextw, unary, d_integer, mxz)
+DEF_SVE_FUNCTION (svget2, get, all_data, none)
+DEF_SVE_FUNCTION (svget3, get, all_data, none)
+DEF_SVE_FUNCTION (svget4, get, all_data, none)
+DEF_SVE_FUNCTION (svindex, binary_scalar, all_integer, none)
+DEF_SVE_FUNCTION (svinsr, binary_n, all_data, none)
+DEF_SVE_FUNCTION (svlasta, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svlastb, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svld1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld1_gather, load_gather_sv, sd_data, implicit)
+DEF_SVE_FUNCTION (svld1_gather, load_gather_vs, sd_data, implicit)
+DEF_SVE_FUNCTION (svld1rq, load_replicate, all_data, implicit)
+DEF_SVE_FUNCTION (svld1sb, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sb_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1ub, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svld1ub_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svldff1_gather, load_gather_sv, sd_data, implicit)
+DEF_SVE_FUNCTION (svldff1_gather, load_gather_vs, sd_data, implicit)
+DEF_SVE_FUNCTION (svldff1sb, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sb_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1ub, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1ub_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svldnf1sb, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1sh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1sw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1ub, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1uh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1uw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldnt1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld2, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld3, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld4, load, all_data, implicit)
+DEF_SVE_FUNCTION (svlen, count_vector, all_data, none)
+DEF_SVE_FUNCTION (svlsl, binary_uint_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svlsl_wide, binary_uint64_opt_n, bhs_integer, mxz)
+DEF_SVE_FUNCTION (svlsr, binary_uint_opt_n, all_unsigned, mxz)
+DEF_SVE_FUNCTION (svlsr_wide, binary_uint64_opt_n, bhs_unsigned, mxz)
+DEF_SVE_FUNCTION (svmad, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmax, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmaxnm, binary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svmaxnmv, reduction, all_float, implicit)
+DEF_SVE_FUNCTION (svmaxv, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svmin, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svminnm, binary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svminnmv, reduction, all_float, implicit)
+DEF_SVE_FUNCTION (svminv, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svmla, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmla_lane, ternary_lane, all_float, none)
+DEF_SVE_FUNCTION (svmls, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmls_lane, ternary_lane, all_float, none)
+DEF_SVE_FUNCTION (svmov, unary, b, z)
+DEF_SVE_FUNCTION (svmsb, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmul, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmul_lane, binary_lane, all_float, none)
+DEF_SVE_FUNCTION (svmulh, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svmulx, binary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnand, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svneg, unary, all_float_and_signed, mxz)
+DEF_SVE_FUNCTION (svnmad, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnmla, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnmls, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnmsb, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnor, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svnot, unary, all_integer, mxz)
+DEF_SVE_FUNCTION (svnot, unary, b, z)
+DEF_SVE_FUNCTION (svorn, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svorr, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svorr, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svorv, reduction, all_integer, implicit)
+DEF_SVE_FUNCTION (svpfalse, inherent_b, b, none)
+DEF_SVE_FUNCTION (svpfirst, unary, b, implicit)
+DEF_SVE_FUNCTION (svpnext, unary_pred, all_pred, implicit)
+DEF_SVE_FUNCTION (svprfb, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfb_gather, prefetch_gather_offset, none, implicit)
+DEF_SVE_FUNCTION (svprfd, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfd_gather, prefetch_gather_index, none, implicit)
+DEF_SVE_FUNCTION (svprfh, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfh_gather, prefetch_gather_index, none, implicit)
+DEF_SVE_FUNCTION (svprfw, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfw_gather, prefetch_gather_index, none, implicit)
+DEF_SVE_FUNCTION (svptest_any, ptest, none, implicit)
+DEF_SVE_FUNCTION (svptest_first, ptest, none, implicit)
+DEF_SVE_FUNCTION (svptest_last, ptest, none, implicit)
+DEF_SVE_FUNCTION (svptrue, inherent, all_pred, none)
+DEF_SVE_FUNCTION (svptrue_pat, pattern_pred, all_pred, none)
+DEF_SVE_FUNCTION (svqadd, binary_opt_n, all_integer, none)
+DEF_SVE_FUNCTION (svqdecb, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecb_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecd, inc_dec, d_integer, none)
+DEF_SVE_FUNCTION (svqdecd, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecd_pat, inc_dec_pat, d_integer, none)
+DEF_SVE_FUNCTION (svqdecd_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqdech, inc_dec, h_integer, none)
+DEF_SVE_FUNCTION (svqdech, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdech_pat, inc_dec_pat, h_integer, none)
+DEF_SVE_FUNCTION (svqdech_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecp, inc_dec_pred, hsd_integer, none)
+DEF_SVE_FUNCTION (svqdecp, inc_dec_pred_scalar, inc_dec_n, none)
+DEF_SVE_FUNCTION (svqdecw, inc_dec, s_integer, none)
+DEF_SVE_FUNCTION (svqdecw, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecw_pat, inc_dec_pat, s_integer, none)
+DEF_SVE_FUNCTION (svqdecw_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqincb, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqincb_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqincd, inc_dec, d_integer, none)
+DEF_SVE_FUNCTION (svqincd, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqincd_pat, inc_dec_pat, d_integer, none)
+DEF_SVE_FUNCTION (svqincd_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqinch, inc_dec, h_integer, none)
+DEF_SVE_FUNCTION (svqinch, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqinch_pat, inc_dec_pat, h_integer, none)
+DEF_SVE_FUNCTION (svqinch_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqincp, inc_dec_pred, hsd_integer, none)
+DEF_SVE_FUNCTION (svqincp, inc_dec_pred_scalar, inc_dec_n, none)
+DEF_SVE_FUNCTION (svqincw, inc_dec, s_integer, none)
+DEF_SVE_FUNCTION (svqincw, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqincw_pat, inc_dec_pat, s_integer, none)
+DEF_SVE_FUNCTION (svqincw_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqsub, binary_opt_n, all_integer, none)
+DEF_SVE_FUNCTION (svrbit, unary, all_integer, mxz)
+DEF_SVE_FUNCTION (svrdffr, rdffr, none, z_or_none)
+DEF_SVE_FUNCTION (svrecpe, unary, all_float, none)
+DEF_SVE_FUNCTION (svrecps, binary, all_float, none)
+DEF_SVE_FUNCTION (svrecpx, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svreinterpret, unary_convert, reinterpret, none)
+DEF_SVE_FUNCTION (svrev, unary, all_data, none)
+DEF_SVE_FUNCTION (svrev, unary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svrevb, unary, hsd_integer, mxz)
+DEF_SVE_FUNCTION (svrevh, unary, sd_integer, mxz)
+DEF_SVE_FUNCTION (svrevw, unary, d_integer, mxz)
+DEF_SVE_FUNCTION (svrinta, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrinti, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintm, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintn, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintp, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintx, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintz, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrsqrte, unary, all_float, none)
+DEF_SVE_FUNCTION (svrsqrts, binary, all_float, none)
+DEF_SVE_FUNCTION (svscale, binary_int_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svsel, binary, all_data, implicit)
+DEF_SVE_FUNCTION (svsel, binary, b, implicit)
+DEF_SVE_FUNCTION (svset2, set, all_data, none)
+DEF_SVE_FUNCTION (svset3, set, all_data, none)
+DEF_SVE_FUNCTION (svset4, set, all_data, none)
+DEF_SVE_FUNCTION (svsetffr, setffr, none, none)
+DEF_SVE_FUNCTION (svsplice, binary, all_data, implicit)
+DEF_SVE_FUNCTION (svsqrt, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svst1, store, all_data, implicit)
+DEF_SVE_FUNCTION (svst1_scatter, store_scatter_index, sd_data, implicit)
+DEF_SVE_FUNCTION (svst1_scatter, store_scatter_offset, sd_data, implicit)
+DEF_SVE_FUNCTION (svst1b, store, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svst1b_scatter, store_scatter_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1h, store, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1w, store, d_integer, implicit)
+DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svst2, store, all_data, implicit)
+DEF_SVE_FUNCTION (svst3, store, all_data, implicit)
+DEF_SVE_FUNCTION (svst4, store, all_data, implicit)
+DEF_SVE_FUNCTION (svstnt1, store, all_data, implicit)
+DEF_SVE_FUNCTION (svsub, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svsubr, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svtbl, binary_uint, all_data, none)
+DEF_SVE_FUNCTION (svtmad, tmad, all_float, none)
+DEF_SVE_FUNCTION (svtrn1, binary, all_data, none)
+DEF_SVE_FUNCTION (svtrn1, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svtrn2, binary, all_data, none)
+DEF_SVE_FUNCTION (svtrn2, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svtsmul, binary_uint, all_float, none)
+DEF_SVE_FUNCTION (svtssel, binary_uint, all_float, none)
+DEF_SVE_FUNCTION (svundef, inherent, all_data, none)
+DEF_SVE_FUNCTION (svundef2, inherent, all_data, none)
+DEF_SVE_FUNCTION (svundef3, inherent, all_data, none)
+DEF_SVE_FUNCTION (svundef4, inherent, all_data, none)
+DEF_SVE_FUNCTION (svunpkhi, unary_widen, hsd_integer, none)
+DEF_SVE_FUNCTION (svunpkhi, unary_widen, b, none)
+DEF_SVE_FUNCTION (svunpklo, unary_widen, hsd_integer, none)
+DEF_SVE_FUNCTION (svunpklo, unary_widen, b, none)
+DEF_SVE_FUNCTION (svuzp1, binary, all_data, none)
+DEF_SVE_FUNCTION (svuzp1, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svuzp2, binary, all_data, none)
+DEF_SVE_FUNCTION (svuzp2, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svwhilele, compare_scalar, while, none)
+DEF_SVE_FUNCTION (svwhilelt, compare_scalar, while, none)
+DEF_SVE_FUNCTION (svwrffr, setffr, none, implicit)
+DEF_SVE_FUNCTION (svzip1, binary, all_data, none)
+DEF_SVE_FUNCTION (svzip1, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svzip2, binary, all_data, none)
+DEF_SVE_FUNCTION (svzip2, binary_pred, all_pred, none)
+#undef REQUIRED_EXTENSIONS
--- /dev/null
+/* ACLE support for AArch64 SVE (__ARM_FEATURE_SVE intrinsics)
+ Copyright (C) 2018-2019 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/>. */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_BASE_H
+#define GCC_AARCH64_SVE_BUILTINS_BASE_H
+
+namespace aarch64_sve
+{
+ namespace functions
+ {
+ extern const function_base *const svabd;
+ extern const function_base *const svabs;
+ extern const function_base *const svacge;
+ extern const function_base *const svacgt;
+ extern const function_base *const svacle;
+ extern const function_base *const svaclt;
+ extern const function_base *const svadd;
+ extern const function_base *const svadda;
+ extern const function_base *const svaddv;
+ extern const function_base *const svadrb;
+ extern const function_base *const svadrd;
+ extern const function_base *const svadrh;
+ extern const function_base *const svadrw;
+ extern const function_base *const svand;
+ extern const function_base *const svandv;
+ extern const function_base *const svasr;
+ extern const function_base *const svasr_wide;
+ extern const function_base *const svasrd;
+ extern const function_base *const svbic;
+ extern const function_base *const svbrka;
+ extern const function_base *const svbrkb;
+ extern const function_base *const svbrkn;
+ extern const function_base *const svbrkpa;
+ extern const function_base *const svbrkpb;
+ extern const function_base *const svcadd;
+ extern const function_base *const svclasta;
+ extern const function_base *const svclastb;
+ extern const function_base *const svcls;
+ extern const function_base *const svclz;
+ extern const function_base *const svcmla;
+ extern const function_base *const svcmla_lane;
+ extern const function_base *const svcmpeq;
+ extern const function_base *const svcmpeq_wide;
+ extern const function_base *const svcmpge;
+ extern const function_base *const svcmpge_wide;
+ extern const function_base *const svcmpgt;
+ extern const function_base *const svcmpgt_wide;
+ extern const function_base *const svcmple;
+ extern const function_base *const svcmple_wide;
+ extern const function_base *const svcmplt;
+ extern const function_base *const svcmplt_wide;
+ extern const function_base *const svcmpne;
+ extern const function_base *const svcmpne_wide;
+ extern const function_base *const svcmpuo;
+ extern const function_base *const svcnot;
+ extern const function_base *const svcnt;
+ extern const function_base *const svcntb;
+ extern const function_base *const svcntb_pat;
+ extern const function_base *const svcntd;
+ extern const function_base *const svcntd_pat;
+ extern const function_base *const svcnth;
+ extern const function_base *const svcnth_pat;
+ extern const function_base *const svcntp;
+ extern const function_base *const svcntw;
+ extern const function_base *const svcntw_pat;
+ extern const function_base *const svcompact;
+ extern const function_base *const svcreate2;
+ extern const function_base *const svcreate3;
+ extern const function_base *const svcreate4;
+ extern const function_base *const svcvt;
+ extern const function_base *const svdiv;
+ extern const function_base *const svdivr;
+ extern const function_base *const svdot;
+ extern const function_base *const svdot_lane;
+ extern const function_base *const svdup;
+ extern const function_base *const svdup_lane;
+ extern const function_base *const svdupq;
+ extern const function_base *const svdupq_lane;
+ extern const function_base *const sveor;
+ extern const function_base *const sveorv;
+ extern const function_base *const svexpa;
+ extern const function_base *const svext;
+ extern const function_base *const svextb;
+ extern const function_base *const svexth;
+ extern const function_base *const svextw;
+ extern const function_base *const svget2;
+ extern const function_base *const svget3;
+ extern const function_base *const svget4;
+ extern const function_base *const svindex;
+ extern const function_base *const svinsr;
+ extern const function_base *const svlasta;
+ extern const function_base *const svlastb;
+ extern const function_base *const svld1;
+ extern const function_base *const svld1_gather;
+ extern const function_base *const svld1rq;
+ extern const function_base *const svld1sb;
+ extern const function_base *const svld1sb_gather;
+ extern const function_base *const svld1sh;
+ extern const function_base *const svld1sh_gather;
+ extern const function_base *const svld1sw;
+ extern const function_base *const svld1sw_gather;
+ extern const function_base *const svld1ub;
+ extern const function_base *const svld1ub_gather;
+ extern const function_base *const svld1uh;
+ extern const function_base *const svld1uh_gather;
+ extern const function_base *const svld1uw;
+ extern const function_base *const svld1uw_gather;
+ extern const function_base *const svld2;
+ extern const function_base *const svld3;
+ extern const function_base *const svld4;
+ extern const function_base *const svldff1;
+ extern const function_base *const svldff1_gather;
+ extern const function_base *const svldff1sb;
+ extern const function_base *const svldff1sb_gather;
+ extern const function_base *const svldff1sh;
+ extern const function_base *const svldff1sh_gather;
+ extern const function_base *const svldff1sw;
+ extern const function_base *const svldff1sw_gather;
+ extern const function_base *const svldff1ub;
+ extern const function_base *const svldff1ub_gather;
+ extern const function_base *const svldff1uh;
+ extern const function_base *const svldff1uh_gather;
+ extern const function_base *const svldff1uw;
+ extern const function_base *const svldff1uw_gather;
+ extern const function_base *const svldnf1;
+ extern const function_base *const svldnf1sb;
+ extern const function_base *const svldnf1sh;
+ extern const function_base *const svldnf1sw;
+ extern const function_base *const svldnf1ub;
+ extern const function_base *const svldnf1uh;
+ extern const function_base *const svldnf1uw;
+ extern const function_base *const svldnt1;
+ extern const function_base *const svlen;
+ extern const function_base *const svlsl;
+ extern const function_base *const svlsl_wide;
+ extern const function_base *const svlsr;
+ extern const function_base *const svlsr_wide;
+ extern const function_base *const svmad;
+ extern const function_base *const svmax;
+ extern const function_base *const svmaxnm;
+ extern const function_base *const svmaxnmv;
+ extern const function_base *const svmaxv;
+ extern const function_base *const svmin;
+ extern const function_base *const svminnm;
+ extern const function_base *const svminnmv;
+ extern const function_base *const svminv;
+ extern const function_base *const svmla;
+ extern const function_base *const svmla_lane;
+ extern const function_base *const svmls;
+ extern const function_base *const svmls_lane;
+ extern const function_base *const svmov;
+ extern const function_base *const svmsb;
+ extern const function_base *const svmul;
+ extern const function_base *const svmul_lane;
+ extern const function_base *const svmulh;
+ extern const function_base *const svmulx;
+ extern const function_base *const svnand;
+ extern const function_base *const svneg;
+ extern const function_base *const svnmad;
+ extern const function_base *const svnmla;
+ extern const function_base *const svnmls;
+ extern const function_base *const svnmsb;
+ extern const function_base *const svnor;
+ extern const function_base *const svnot;
+ extern const function_base *const svorn;
+ extern const function_base *const svorr;
+ extern const function_base *const svorv;
+ extern const function_base *const svpfalse;
+ extern const function_base *const svpfirst;
+ extern const function_base *const svpnext;
+ extern const function_base *const svprfb;
+ extern const function_base *const svprfb_gather;
+ extern const function_base *const svprfd;
+ extern const function_base *const svprfd_gather;
+ extern const function_base *const svprfh;
+ extern const function_base *const svprfh_gather;
+ extern const function_base *const svprfw;
+ extern const function_base *const svprfw_gather;
+ extern const function_base *const svptest_any;
+ extern const function_base *const svptest_first;
+ extern const function_base *const svptest_last;
+ extern const function_base *const svptrue;
+ extern const function_base *const svptrue_pat;
+ extern const function_base *const svqadd;
+ extern const function_base *const svqdecb;
+ extern const function_base *const svqdecb_pat;
+ extern const function_base *const svqdecd;
+ extern const function_base *const svqdecd_pat;
+ extern const function_base *const svqdech;
+ extern const function_base *const svqdech_pat;
+ extern const function_base *const svqdecp;
+ extern const function_base *const svqdecw;
+ extern const function_base *const svqdecw_pat;
+ extern const function_base *const svqincb;
+ extern const function_base *const svqincb_pat;
+ extern const function_base *const svqincd;
+ extern const function_base *const svqincd_pat;
+ extern const function_base *const svqinch;
+ extern const function_base *const svqinch_pat;
+ extern const function_base *const svqincp;
+ extern const function_base *const svqincw;
+ extern const function_base *const svqincw_pat;
+ extern const function_base *const svqsub;
+ extern const function_base *const svrbit;
+ extern const function_base *const svrdffr;
+ extern const function_base *const svrecpe;
+ extern const function_base *const svrecps;
+ extern const function_base *const svrecpx;
+ extern const function_base *const svreinterpret;
+ extern const function_base *const svrev;
+ extern const function_base *const svrevb;
+ extern const function_base *const svrevh;
+ extern const function_base *const svrevw;
+ extern const function_base *const svrinta;
+ extern const function_base *const svrinti;
+ extern const function_base *const svrintm;
+ extern const function_base *const svrintn;
+ extern const function_base *const svrintp;
+ extern const function_base *const svrintx;
+ extern const function_base *const svrintz;
+ extern const function_base *const svrsqrte;
+ extern const function_base *const svrsqrts;
+ extern const function_base *const svscale;
+ extern const function_base *const svsel;
+ extern const function_base *const svset2;
+ extern const function_base *const svset3;
+ extern const function_base *const svset4;
+ extern const function_base *const svsetffr;
+ extern const function_base *const svsplice;
+ extern const function_base *const svsqrt;
+ extern const function_base *const svst1;
+ extern const function_base *const svst1_scatter;
+ extern const function_base *const svst1b;
+ extern const function_base *const svst1b_scatter;
+ extern const function_base *const svst1h;
+ extern const function_base *const svst1h_scatter;
+ extern const function_base *const svst1w;
+ extern const function_base *const svst1w_scatter;
+ extern const function_base *const svst2;
+ extern const function_base *const svst3;
+ extern const function_base *const svst4;
+ extern const function_base *const svstnt1;
+ extern const function_base *const svsub;
+ extern const function_base *const svsubr;
+ extern const function_base *const svtbl;
+ extern const function_base *const svtmad;
+ extern const function_base *const svtrn1;
+ extern const function_base *const svtrn2;
+ extern const function_base *const svtsmul;
+ extern const function_base *const svtssel;
+ extern const function_base *const svundef;
+ extern const function_base *const svundef2;
+ extern const function_base *const svundef3;
+ extern const function_base *const svundef4;
+ extern const function_base *const svunpkhi;
+ extern const function_base *const svunpklo;
+ extern const function_base *const svuzp1;
+ extern const function_base *const svuzp2;
+ extern const function_base *const svwhilele;
+ extern const function_base *const svwhilelt;
+ extern const function_base *const svwrffr;
+ extern const function_base *const svzip1;
+ extern const function_base *const svzip2;
+ }
+}
+
+#endif
--- /dev/null
+/* ACLE support for AArch64 SVE (function_base classes)
+ Copyright (C) 2018-2019 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/>. */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_FUNCTIONS_H
+#define GCC_AARCH64_SVE_BUILTINS_FUNCTIONS_H
+
+namespace aarch64_sve {
+
+/* Wrap T, which is derived from function_base, and indicate that the
+ function never has side effects. It is only necessary to use this
+ wrapper on functions that might have floating-point suffixes, since
+ otherwise we assume by default that the function has no side effects. */
+template<typename T>
+class quiet : public T
+{
+public:
+ CONSTEXPR quiet () : T () {}
+
+ /* Unfortunately we can't use parameter packs yet. */
+ template<typename T1>
+ CONSTEXPR quiet (const T1 &t1) : T (t1) {}
+
+ template<typename T1, typename T2>
+ CONSTEXPR quiet (const T1 &t1, const T2 &t2) : T (t1, t2) {}
+
+ template<typename T1, typename T2, typename T3>
+ CONSTEXPR quiet (const T1 &t1, const T2 &t2, const T3 &t3)
+ : T (t1, t2, t3) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return 0;
+ }
+};
+
+/* A function_base that sometimes or always operates on tuples of
+ vectors. */
+class multi_vector_function : public function_base
+{
+public:
+ CONSTEXPR multi_vector_function (unsigned int vectors_per_tuple)
+ : m_vectors_per_tuple (vectors_per_tuple) {}
+
+ unsigned int
+ vectors_per_tuple () const OVERRIDE
+ {
+ return m_vectors_per_tuple;
+ }
+
+ /* The number of vectors in a tuple, or 1 if the function only operates
+ on single vectors. */
+ unsigned int m_vectors_per_tuple;
+};
+
+/* A function_base that loads or stores contiguous memory elements
+ without extending or truncating them. */
+class full_width_access : public multi_vector_function
+{
+public:
+ CONSTEXPR full_width_access (unsigned int vectors_per_tuple = 1)
+ : multi_vector_function (vectors_per_tuple) {}
+
+ tree
+ memory_scalar_type (const function_instance &fi) const OVERRIDE
+ {
+ return fi.scalar_type (0);
+ }
+
+ machine_mode
+ memory_vector_mode (const function_instance &fi) const OVERRIDE
+ {
+ machine_mode mode = fi.vector_mode (0);
+ if (m_vectors_per_tuple != 1)
+ mode = targetm.array_mode (mode, m_vectors_per_tuple).require ();
+ return mode;
+ }
+};
+
+/* A function_base that loads elements from memory and extends them
+ to a wider element. The memory element type is a fixed part of
+ the function base name. */
+class extending_load : public function_base
+{
+public:
+ CONSTEXPR extending_load (type_suffix_index memory_type)
+ : m_memory_type (memory_type) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_READ_MEMORY;
+ }
+
+ tree
+ memory_scalar_type (const function_instance &) const OVERRIDE
+ {
+ return scalar_types[type_suffixes[m_memory_type].vector_type];
+ }
+
+ machine_mode
+ memory_vector_mode (const function_instance &fi) const OVERRIDE
+ {
+ machine_mode mem_mode = type_suffixes[m_memory_type].vector_mode;
+ machine_mode reg_mode = fi.vector_mode (0);
+ return aarch64_sve_data_mode (GET_MODE_INNER (mem_mode),
+ GET_MODE_NUNITS (reg_mode)).require ();
+ }
+
+ /* Return the rtx code associated with the kind of extension that
+ the load performs. */
+ rtx_code
+ extend_rtx_code () const
+ {
+ return (type_suffixes[m_memory_type].unsigned_p
+ ? ZERO_EXTEND : SIGN_EXTEND);
+ }
+
+ /* The type of the memory elements. This is part of the function base
+ name rather than a true type suffix. */
+ type_suffix_index m_memory_type;
+};
+
+/* A function_base that truncates vector elements and stores them to memory.
+ The memory element width is a fixed part of the function base name. */
+class truncating_store : public function_base
+{
+public:
+ CONSTEXPR truncating_store (scalar_int_mode to_mode) : m_to_mode (to_mode) {}
+
+ unsigned int
+ call_properties (const function_instance &) const OVERRIDE
+ {
+ return CP_WRITE_MEMORY;
+ }
+
+ tree
+ memory_scalar_type (const function_instance &fi) const OVERRIDE
+ {
+ /* In truncating stores, the signedness of the memory element is defined
+ to be the same as the signedness of the vector element. The signedness
+ doesn't make any difference to the behavior of the function. */
+ type_class_index tclass = fi.type_suffix (0).tclass;
+ unsigned int element_bits = GET_MODE_BITSIZE (m_to_mode);
+ type_suffix_index suffix = find_type_suffix (tclass, element_bits);
+ return scalar_types[type_suffixes[suffix].vector_type];
+ }
+
+ machine_mode
+ memory_vector_mode (const function_instance &fi) const OVERRIDE
+ {
+ poly_uint64 nunits = GET_MODE_NUNITS (fi.vector_mode (0));
+ return aarch64_sve_data_mode (m_to_mode, nunits).require ();
+ }
+
+ /* The mode of a single memory element. */
+ scalar_int_mode m_to_mode;
+};
+
+/* A function_base for functions that have an associated rtx code.
+ It supports all forms of predication except PRED_implicit. */
+class rtx_code_function : public function_base
+{
+public:
+ CONSTEXPR rtx_code_function (rtx_code code_for_sint, rtx_code code_for_uint,
+ int unspec_for_fp = -1)
+ : m_code_for_sint (code_for_sint), m_code_for_uint (code_for_uint),
+ m_unspec_for_fp (unspec_for_fp) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint,
+ m_unspec_for_fp);
+ }
+
+ /* The rtx code to use for signed and unsigned integers respectively.
+ Can be UNKNOWN for functions that don't have integer forms. */
+ rtx_code m_code_for_sint;
+ rtx_code m_code_for_uint;
+
+ /* The UNSPEC_COND_* to use for floating-point operations. Can be -1
+ for functions that only operate on integers. */
+ int m_unspec_for_fp;
+};
+
+/* Like rtx_code_function, but for functions that take what is normally
+ the final argument first. One use of this class is to handle binary
+ reversed operations; another is to handle MLA-style operations that
+ are normally expressed in GCC as MAD-style operations. */
+class rtx_code_function_rotated : public function_base
+{
+public:
+ CONSTEXPR rtx_code_function_rotated (rtx_code code_for_sint,
+ rtx_code code_for_uint,
+ int unspec_for_fp = -1)
+ : m_code_for_sint (code_for_sint), m_code_for_uint (code_for_uint),
+ m_unspec_for_fp (unspec_for_fp) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Rotate the inputs into their normal order, but continue to make _m
+ functions merge with what was originally the first vector argument. */
+ unsigned int nargs = e.args.length ();
+ e.rotate_inputs_left (e.pred != PRED_none ? 1 : 0, nargs);
+ return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint,
+ m_unspec_for_fp, nargs - 1);
+ }
+
+ /* The rtx code to use for signed and unsigned integers respectively.
+ Can be UNKNOWN for functions that don't have integer forms. */
+ rtx_code m_code_for_sint;
+ rtx_code m_code_for_uint;
+
+ /* The UNSPEC_COND_* to use for floating-point operations. Can be -1
+ for functions that only operate on integers. */
+ int m_unspec_for_fp;
+};
+
+/* A function_base for functions that have an associated unspec code.
+ It supports all forms of predication except PRED_implicit. */
+class unspec_based_function : public function_base
+{
+public:
+ CONSTEXPR unspec_based_function (int unspec_for_sint, int unspec_for_uint,
+ int unspec_for_fp)
+ : m_unspec_for_sint (unspec_for_sint),
+ m_unspec_for_uint (unspec_for_uint),
+ m_unspec_for_fp (unspec_for_fp)
+ {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ return e.map_to_unspecs (m_unspec_for_sint, m_unspec_for_uint,
+ m_unspec_for_fp);
+ }
+
+ /* The unspec code associated with signed-integer, unsigned-integer
+ and floating-point operations respectively. */
+ int m_unspec_for_sint;
+ int m_unspec_for_uint;
+ int m_unspec_for_fp;
+};
+
+/* Like unspec_based_function, but for functions that take what is normally
+ the final argument first. One use of this class is to handle binary
+ reversed operations; another is to handle MLA-style operations that
+ are normally expressed in GCC as MAD-style operations. */
+class unspec_based_function_rotated : public function_base
+{
+public:
+ CONSTEXPR unspec_based_function_rotated (int unspec_for_sint,
+ int unspec_for_uint,
+ int unspec_for_fp)
+ : m_unspec_for_sint (unspec_for_sint),
+ m_unspec_for_uint (unspec_for_uint),
+ m_unspec_for_fp (unspec_for_fp)
+ {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* Rotate the inputs into their normal order, but continue to make _m
+ functions merge with what was originally the first vector argument. */
+ unsigned int nargs = e.args.length ();
+ e.rotate_inputs_left (e.pred != PRED_none ? 1 : 0, nargs);
+ return e.map_to_unspecs (m_unspec_for_sint, m_unspec_for_uint,
+ m_unspec_for_fp, nargs - 1);
+ }
+
+ /* The unspec code associated with signed-integer, unsigned-integer
+ and floating-point operations respectively. */
+ int m_unspec_for_sint;
+ int m_unspec_for_uint;
+ int m_unspec_for_fp;
+};
+
+/* A function_base for functions that permute their arguments. */
+class permute : public quiet<function_base>
+{
+public:
+ /* Fold a unary or binary permute with the permute vector given by
+ BUILDER. */
+ gimple *
+ fold_permute (const gimple_folder &f, const vec_perm_builder &builder) const
+ {
+ /* Punt for now on _b16 and wider; we'd need more complex evpc logic
+ to rerecognize the result. */
+ if (f.type_suffix (0).bool_p && f.type_suffix (0).element_bits > 8)
+ return NULL;
+
+ unsigned int nargs = gimple_call_num_args (f.call);
+ poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+ vec_perm_indices indices (builder, nargs, nelts);
+ tree perm_type = build_vector_type (ssizetype, nelts);
+ return gimple_build_assign (f.lhs, VEC_PERM_EXPR,
+ gimple_call_arg (f.call, 0),
+ gimple_call_arg (f.call, nargs - 1),
+ vec_perm_indices_to_tree (perm_type, indices));
+ }
+};
+
+/* A function_base for functions that permute two vectors using a fixed
+ choice of indices. */
+class binary_permute : public permute
+{
+public:
+ CONSTEXPR binary_permute (int unspec) : m_unspec (unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ insn_code icode = code_for_aarch64_sve (m_unspec, e.vector_mode (0));
+ return e.use_exact_insn (icode);
+ }
+
+ /* The unspec code associated with the operation. */
+ int m_unspec;
+};
+
+/* A function_base for functions that reduce a vector to a scalar. */
+class reduction : public function_base
+{
+public:
+ CONSTEXPR reduction (int unspec)
+ : m_unspec_for_sint (unspec),
+ m_unspec_for_uint (unspec),
+ m_unspec_for_fp (unspec)
+ {}
+
+ CONSTEXPR reduction (int unspec_for_sint, int unspec_for_uint,
+ int unspec_for_fp)
+ : m_unspec_for_sint (unspec_for_sint),
+ m_unspec_for_uint (unspec_for_uint),
+ m_unspec_for_fp (unspec_for_fp)
+ {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ int unspec = (!e.type_suffix (0).integer_p ? m_unspec_for_fp
+ : e.type_suffix (0).unsigned_p ? m_unspec_for_uint
+ : m_unspec_for_sint);
+ /* There's no distinction between SADDV and UADDV for 64-bit elements;
+ the signed versions only exist for narrower elements. */
+ if (GET_MODE_UNIT_BITSIZE (mode) == 64 && unspec == UNSPEC_SADDV)
+ unspec = UNSPEC_UADDV;
+ return e.use_exact_insn (code_for_aarch64_pred_reduc (unspec, mode));
+ }
+
+ /* The unspec code associated with signed-integer, unsigned-integer
+ and floating-point operations respectively. */
+ int m_unspec_for_sint;
+ int m_unspec_for_uint;
+ int m_unspec_for_fp;
+};
+
+/* A function_base for functions that shift narrower-than-64-bit values
+ by 64-bit amounts. */
+class shift_wide : public function_base
+{
+public:
+ CONSTEXPR shift_wide (rtx_code code, int wide_unspec)
+ : m_code (code), m_wide_unspec (wide_unspec) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ machine_mode mode = e.vector_mode (0);
+ machine_mode elem_mode = GET_MODE_INNER (mode);
+
+ /* If the argument is a constant that the normal shifts can handle
+ directly, use them instead. */
+ rtx shift = unwrap_const_vec_duplicate (e.args.last ());
+ if (aarch64_simd_shift_imm_p (shift, elem_mode, m_code == ASHIFT))
+ {
+ e.args.last () = shift;
+ return e.map_to_rtx_codes (m_code, m_code, -1);
+ }
+
+ if (e.pred == PRED_x)
+ return e.use_unpred_insn (code_for_aarch64_sve (m_wide_unspec, mode));
+
+ return e.use_cond_insn (code_for_cond (m_wide_unspec, mode));
+ }
+
+ /* The rtx code associated with a "normal" shift. */
+ rtx_code m_code;
+
+ /* The unspec code associated with the wide shift. */
+ int m_wide_unspec;
+};
+
+/* A function_base for unary functions that count bits. */
+class unary_count : public quiet<function_base>
+{
+public:
+ CONSTEXPR unary_count (rtx_code code) : m_code (code) {}
+
+ rtx
+ expand (function_expander &e) const OVERRIDE
+ {
+ /* The md patterns treat the operand as an integer. */
+ machine_mode mode = mode_for_int_vector (e.vector_mode (0)).require ();
+ e.args.last () = gen_lowpart (mode, e.args.last ());
+
+ if (e.pred == PRED_x)
+ return e.use_pred_x_insn (code_for_aarch64_pred (m_code, mode));
+
+ return e.use_cond_insn (code_for_cond (m_code, mode));
+ }
+
+ /* The rtx code associated with the operation. */
+ rtx_code m_code;
+};
+
+}
+
+/* Declare the global function base NAME, creating it from an instance
+ of class CLASS with constructor arguments ARGS. */
+#define FUNCTION(NAME, CLASS, ARGS) \
+ namespace { static CONSTEXPR const CLASS NAME##_obj ARGS; } \
+ namespace functions { const function_base *const NAME = &NAME##_obj; }
+
+#endif
--- /dev/null
+/* ACLE support for AArch64 SVE (function shapes)
+ Copyright (C) 2018-2019 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/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "aarch64-sve-builtins.h"
+#include "aarch64-sve-builtins-shapes.h"
+
+/* In the comments below, _t0 represents the first type suffix and _t1
+ represents the second. Square brackets enclose characters that are
+ present in only the full name, not the overloaded name. Governing
+ predicate arguments and predicate suffixes are not shown, since they
+ depend on the predication type, which is a separate piece of
+ information from the shape.
+
+ Non-overloaded functions may have additional suffixes beyond the
+ ones shown, if those suffixes don't affect the types in the type
+ signature. E.g. the predicate form of svtrn1 has a _b<bits> suffix,
+ but this does not affect the prototype, which is always
+ "svbool_t(svbool_t, svbool_t)". */
+
+namespace aarch64_sve {
+
+/* Return a representation of "const T *". */
+static tree
+build_const_pointer (tree t)
+{
+ return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
+}
+
+/* If INSTANCE has a governing predicate, add it to the list of argument
+ types in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the
+ function. */
+static void
+apply_predication (const function_instance &instance, tree return_type,
+ vec<tree> &argument_types)
+{
+ if (instance.pred != PRED_none)
+ {
+ argument_types.quick_insert (0, get_svbool_t ());
+ /* For unary merge operations, the first argument is a vector with
+ the same type as the result. */
+ if (argument_types.length () == 2 && instance.pred == PRED_m)
+ argument_types.quick_insert (0, return_type);
+ }
+}
+
+/* Parse and move past an element type in FORMAT and return it as a type
+ suffix. The format is:
+
+ [01] - the element type in type suffix 0 or 1 of INSTANCE
+ f<bits> - a floating-point type with the given number of bits
+ f[01] - a floating-point type with the same width as type suffix 0 or 1
+ h<elt> - a half-sized version of <elt>
+ p - a predicate (represented as TYPE_SUFFIX_b)
+ q<elt> - a quarter-sized version of <elt>
+ s<bits> - a signed type with the given number of bits
+ s[01] - a signed type with the same width as type suffix 0 or 1
+ u<bits> - an unsigned type with the given number of bits
+ u[01] - an unsigned type with the same width as type suffix 0 or 1
+ w<elt> - a 64-bit version of <elt> if <elt> is integral, otherwise <elt>
+
+ where <elt> is another element type. */
+static type_suffix_index
+parse_element_type (const function_instance &instance, const char *&format)
+{
+ int ch = *format++;
+
+ if (ch == 'f' || ch == 's' || ch == 'u')
+ {
+ type_class_index tclass = (ch == 'f' ? TYPE_float
+ : ch == 's' ? TYPE_signed
+ : TYPE_unsigned);
+ char *end;
+ unsigned int bits = strtol (format, &end, 10);
+ format = end;
+ if (bits == 0 || bits == 1)
+ bits = instance.type_suffix (bits).element_bits;
+ return find_type_suffix (tclass, bits);
+ }
+
+ if (ch == 'w')
+ {
+ type_suffix_index suffix = parse_element_type (instance, format);
+ if (type_suffixes[suffix].integer_p)
+ return find_type_suffix (type_suffixes[suffix].tclass, 64);
+ return suffix;
+ }
+
+ if (ch == 'p')
+ return TYPE_SUFFIX_b;
+
+ if (ch == 'q')
+ {
+ type_suffix_index suffix = parse_element_type (instance, format);
+ return find_type_suffix (type_suffixes[suffix].tclass,
+ type_suffixes[suffix].element_bits / 4);
+ }
+
+ if (ch == 'h')
+ {
+ type_suffix_index suffix = parse_element_type (instance, format);
+ /* Widening and narrowing doesn't change the type for predicates;
+ everything's still an svbool_t. */
+ if (suffix == TYPE_SUFFIX_b)
+ return suffix;
+ return find_type_suffix (type_suffixes[suffix].tclass,
+ type_suffixes[suffix].element_bits / 2);
+ }
+
+ if (ch == '0' || ch == '1')
+ return instance.type_suffix_ids[ch - '0'];
+
+ gcc_unreachable ();
+}
+
+/* Read and return a type from FORMAT for function INSTANCE. Advance
+ FORMAT beyond the type string. The format is:
+
+ _ - void
+ al - array pointer for loads
+ ap - array pointer for prefetches
+ as - array pointer for stores
+ b - base vector type (from a _<m0>base suffix)
+ d - displacement vector type (from a _<m1>index or _<m1>offset suffix)
+ e<name> - an enum with the given name
+ s<elt> - a scalar type with the given element suffix
+ t<elt> - a vector or tuple type with given element suffix [*1]
+ v<elt> - a vector with the given element suffix
+
+ where <elt> has the format described above parse_element_type
+
+ [*1] the vectors_per_tuple function indicates whether the type should
+ be a tuple, and if so, how many vectors it should contain. */
+static tree
+parse_type (const function_instance &instance, const char *&format)
+{
+ int ch = *format++;
+
+ if (ch == '_')
+ return void_type_node;
+
+ if (ch == 'a')
+ {
+ ch = *format++;
+ if (ch == 'l')
+ return build_const_pointer (instance.memory_scalar_type ());
+ if (ch == 'p')
+ return const_ptr_type_node;
+ if (ch == 's')
+ return build_pointer_type (instance.memory_scalar_type ());
+ gcc_unreachable ();
+ }
+
+ if (ch == 'b')
+ return instance.base_vector_type ();
+
+ if (ch == 'd')
+ return instance.displacement_vector_type ();
+
+ if (ch == 'e')
+ {
+ if (strncmp (format, "pattern", 7) == 0)
+ {
+ format += 7;
+ return acle_svpattern;
+ }
+ if (strncmp (format, "prfop", 5) == 0)
+ {
+ format += 5;
+ return acle_svprfop;
+ }
+ gcc_unreachable ();
+ }
+
+ if (ch == 's')
+ {
+ type_suffix_index suffix = parse_element_type (instance, format);
+ return scalar_types[type_suffixes[suffix].vector_type];
+ }
+
+ if (ch == 't')
+ {
+ type_suffix_index suffix = parse_element_type (instance, format);
+ vector_type_index vector_type = type_suffixes[suffix].vector_type;
+ unsigned int num_vectors = instance.vectors_per_tuple ();
+ return acle_vector_types[num_vectors - 1][vector_type];
+ }
+
+ if (ch == 'v')
+ {
+ type_suffix_index suffix = parse_element_type (instance, format);
+ return acle_vector_types[0][type_suffixes[suffix].vector_type];
+ }
+
+ gcc_unreachable ();
+}
+
+/* Read and move past any argument count at FORMAT for the function
+ signature of INSTANCE. The counts are:
+
+ *q: one argument per element in a 128-bit quadword (as for svdupq)
+ *t: one argument per vector in a tuple (as for svcreate)
+
+ Otherwise the count is 1. */
+static unsigned int
+parse_count (const function_instance &instance, const char *&format)
+{
+ if (format[0] == '*' && format[1] == 'q')
+ {
+ format += 2;
+ return instance.elements_per_vq (0);
+ }
+ if (format[0] == '*' && format[1] == 't')
+ {
+ format += 2;
+ return instance.vectors_per_tuple ();
+ }
+ return 1;
+}
+
+/* Read a type signature for INSTANCE from FORMAT. Add the argument types
+ to ARGUMENT_TYPES and return the return type.
+
+ The format is a comma-separated list of types (as for parse_type),
+ with the first type being the return type and the rest being the
+ argument types. Each argument type can be followed by an optional
+ count (as for parse_count). */
+static tree
+parse_signature (const function_instance &instance, const char *format,
+ vec<tree> &argument_types)
+{
+ tree return_type = parse_type (instance, format);
+ while (format[0] == ',')
+ {
+ format += 1;
+ tree argument_type = parse_type (instance, format);
+ unsigned int count = parse_count (instance, format);
+ for (unsigned int i = 0; i < count; ++i)
+ argument_types.quick_push (argument_type);
+ }
+ gcc_assert (format[0] == 0);
+ return return_type;
+}
+
+/* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
+ the type suffixes at index TI and the predication suffix at index PI.
+ The other arguments are as for build_all. */
+static void
+build_one (function_builder &b, const char *signature,
+ const function_group_info &group, mode_suffix_index mode_suffix_id,
+ unsigned int ti, unsigned int pi, bool force_direct_overloads)
+{
+ /* Byte forms of svdupq take 16 arguments. */
+ auto_vec<tree, 16> argument_types;
+ function_instance instance (group.base_name, *group.base, *group.shape,
+ mode_suffix_id, group.types[ti],
+ group.preds[pi]);
+ tree return_type = parse_signature (instance, signature, argument_types);
+ apply_predication (instance, return_type, argument_types);
+ b.add_unique_function (instance, return_type, argument_types,
+ group.required_extensions, force_direct_overloads);
+}
+
+/* Add a function instance for every type and predicate combination
+ in GROUP, which describes some sort of gather or scatter operation.
+ If the function has any type suffixes (as for loads and stores),
+ the first function type suffix specifies either a 32-bit or a 64-bit
+ type; use MODE32 for the former and MODE64 for the latter. If the
+ function has no type suffixes (as for prefetches), add one MODE32 form
+ and one MODE64 form for each predication type.
+
+ The other arguments are as for build_all. */
+static void
+build_32_64 (function_builder &b, const char *signature,
+ const function_group_info &group, mode_suffix_index mode32,
+ mode_suffix_index mode64, bool force_direct_overloads = false)
+{
+ for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+ if (group.types[0][0] == NUM_TYPE_SUFFIXES)
+ {
+ build_one (b, signature, group, mode32, 0, pi,
+ force_direct_overloads);
+ build_one (b, signature, group, mode64, 0, pi,
+ force_direct_overloads);
+ }
+ else
+ for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
+ {
+ unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
+ gcc_assert (bits == 32 || bits == 64);
+ mode_suffix_index mode = bits == 32 ? mode32 : mode64;
+ build_one (b, signature, group, mode, ti, pi,
+ force_direct_overloads);
+ }
+}
+
+/* For every type and predicate combination in GROUP, add one function
+ that takes a scalar (pointer) base and a signed vector array index,
+ and another that instead takes an unsigned vector array index.
+ The vector array index has the same element size as the first
+ function type suffix. SIGNATURE is as for build_all. */
+static void
+build_sv_index (function_builder &b, const char *signature,
+ const function_group_info &group)
+{
+ build_32_64 (b, signature, group, MODE_s32index, MODE_s64index);
+ build_32_64 (b, signature, group, MODE_u32index, MODE_u64index);
+}
+
+/* Like build_sv_index, but taking vector byte offsets instead of vector
+ array indices. */
+static void
+build_sv_offset (function_builder &b, const char *signature,
+ const function_group_info &group)
+{
+ build_32_64 (b, signature, group, MODE_s32offset, MODE_s64offset);
+ build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
+}
+
+/* For every type and predicate combination in GROUP, add a function
+ that takes a vector base address and no displacement. The vector
+ base has the same element size as the first type suffix.
+
+ The other arguments are as for build_all. */
+static void
+build_v_base (function_builder &b, const char *signature,
+ const function_group_info &group,
+ bool force_direct_overloads = false)
+{
+ build_32_64 (b, signature, group, MODE_u32base, MODE_u64base,
+ force_direct_overloads);
+}
+
+/* Like build_v_base, but for functions that also take a scalar array
+ index. */
+static void
+build_vs_index (function_builder &b, const char *signature,
+ const function_group_info &group,
+ bool force_direct_overloads = false)
+{
+ build_32_64 (b, signature, group, MODE_u32base_index, MODE_u64base_index,
+ force_direct_overloads);
+}
+
+/* Like build_v_base, but for functions that also take a scalar byte
+ offset. */
+static void
+build_vs_offset (function_builder &b, const char *signature,
+ const function_group_info &group,
+ bool force_direct_overloads = false)
+{
+ build_32_64 (b, signature, group, MODE_u32base_offset, MODE_u64base_offset,
+ force_direct_overloads);
+}
+
+/* Add a function instance for every type and predicate combination
+ in GROUP. Take the function base name from GROUP and the mode suffix
+ from MODE_SUFFIX_ID. Use SIGNATURE to construct the function signature
+ without a governing predicate, then use apply_predication to add in the
+ predicate. FORCE_DIRECT_OVERLOADS is true if there is a one-to-one
+ mapping between "short" and "full" names, and if standard overload
+ resolution therefore isn't necessary. */
+static void
+build_all (function_builder &b, const char *signature,
+ const function_group_info &group, mode_suffix_index mode_suffix_id,
+ bool force_direct_overloads = false)
+{
+ for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+ for (unsigned int ti = 0;
+ ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
+ build_one (b, signature, group, mode_suffix_id, ti, pi,
+ force_direct_overloads);
+}
+
+/* Declare the function shape NAME, pointing it to an instance
+ of class <NAME>_def. */
+#define SHAPE(NAME) \
+ static CONSTEXPR const NAME##_def NAME##_obj; \
+ namespace shapes { const function_shape *const NAME = &NAME##_obj; }
+
+/* Base class for functions that are not overloaded. */
+struct nonoverloaded_base : public function_shape
+{
+ bool
+ explicit_type_suffix_p (unsigned int) const OVERRIDE
+ {
+ return true;
+ }
+
+ tree
+ resolve (function_resolver &) const OVERRIDE
+ {
+ gcc_unreachable ();
+ }
+};
+
+/* Base class for overloaded functions. Bit N of EXPLICIT_MASK is true
+ if type suffix N appears in the overloaded name. */
+template<unsigned int EXPLICIT_MASK>
+struct overloaded_base : public function_shape
+{
+ bool
+ explicit_type_suffix_p (unsigned int i) const OVERRIDE
+ {
+ return (EXPLICIT_MASK >> i) & 1;
+ }
+};
+
+/* Base class for adr_index and adr_offset. */
+struct adr_base : public overloaded_base<0>
+{
+ /* The function takes two arguments: a vector base and a vector displacement
+ (either an index or an offset). Resolve based on them both. */
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ mode_suffix_index mode;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (mode = r.resolve_adr_address (0)) == MODE_none)
+ return error_mark_node;
+
+ return r.resolve_to (mode);
+ };
+};
+
+/* Base class for inc_dec and inc_dec_pat. */
+struct inc_dec_base : public overloaded_base<0>
+{
+ CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
+
+ /* Resolve based on the first argument only, which must be either a
+ scalar or a vector. If it's a scalar, it must be a 32-bit or
+ 64-bit integer. */
+ tree
+ resolve (function_resolver &r) const
+ {
+ unsigned int i, nargs;
+ if (!r.check_gp_argument (m_pat_p ? 3 : 2, i, nargs)
+ || !r.require_vector_or_scalar_type (i))
+ return error_mark_node;
+
+ mode_suffix_index mode;
+ type_suffix_index type;
+ if (r.scalar_argument_p (i))
+ {
+ mode = MODE_n;
+ type = r.infer_integer_scalar_type (i);
+ }
+ else
+ {
+ mode = MODE_none;
+ type = r.infer_vector_type (i);
+ }
+ if (type == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ for (++i; i < nargs; ++i)
+ if (!r.require_integer_immediate (i))
+ return error_mark_node;
+
+ return r.resolve_to (mode, type);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_range (m_pat_p ? 2 : 1, 1, 16);
+ }
+
+ bool m_pat_p;
+};
+
+/* Base class for load and load_replicate. */
+struct load_contiguous_base : public overloaded_base<0>
+{
+ /* Resolve a call based purely on a pointer argument. The other arguments
+ are a governing predicate and (for MODE_vnum) a vnum offset. */
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ bool vnum_p = r.mode_suffix_id == MODE_vnum;
+ gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
+
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (vnum_p ? 2 : 1, i, nargs)
+ || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
+ || (vnum_p && !r.require_scalar_type (i + 1, "int64_t")))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+
+/* Base class for load_ext_gather_index and load_ext_gather_offset,
+ which differ only in the units of the displacement. */
+struct load_ext_gather_base : public overloaded_base<1>
+{
+ /* Resolve a gather load that takes one of:
+
+ - a scalar pointer base and a vector displacement
+ - a vector base with no displacement or
+ - a vector base and a scalar displacement
+
+ The function has an explicit type suffix that determines the type
+ of the loaded data. */
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ /* No resolution is needed for a vector base with no displacement;
+ there's a one-to-one mapping between short and long names. */
+ gcc_assert (r.displacement_units () != UNITS_none);
+
+ type_suffix_index type = r.type_suffix_ids[0];
+
+ unsigned int i, nargs;
+ mode_suffix_index mode;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (mode = r.resolve_gather_address (i, type, true)) == MODE_none)
+ return error_mark_node;
+
+ return r.resolve_to (mode, type);
+ }
+};
+
+/* Base class for prefetch_gather_index and prefetch_gather_offset,
+ which differ only in the units of the displacement. */
+struct prefetch_gather_base : public overloaded_base<0>
+{
+ /* Resolve a gather prefetch that takes one of:
+
+ - a scalar pointer base (const void *) and a vector displacement
+ - a vector base with no displacement or
+ - a vector base and a scalar displacement
+
+ The prefetch operation is the final argument. This is purely a
+ mode-based resolution; there are no type suffixes. */
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ bool has_displacement_p = r.displacement_units () != UNITS_none;
+
+ unsigned int i, nargs;
+ mode_suffix_index mode;
+ if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
+ || (mode = r.resolve_gather_address (i, NUM_TYPE_SUFFIXES,
+ false)) == MODE_none
+ || !r.require_integer_immediate (nargs - 1))
+ return error_mark_node;
+
+ return r.resolve_to (mode);
+ }
+};
+
+/* Base class for store_scatter_index and store_scatter_offset,
+ which differ only in the units of the displacement. */
+struct store_scatter_base : public overloaded_base<0>
+{
+ /* Resolve a scatter store that takes one of:
+
+ - a scalar pointer base and a vector displacement
+ - a vector base with no displacement or
+ - a vector base and a scalar displacement
+
+ The stored data is the final argument, and it determines the
+ type suffix. */
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ bool has_displacement_p = r.displacement_units () != UNITS_none;
+
+ unsigned int i, nargs;
+ mode_suffix_index mode;
+ type_suffix_index type;
+ if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
+ || (type = r.infer_sd_vector_type (nargs - 1)) == NUM_TYPE_SUFFIXES
+ || (mode = r.resolve_gather_address (i, type, false)) == MODE_none)
+ return error_mark_node;
+
+ return r.resolve_to (mode, type);
+ }
+};
+
+/* sv<m0>_t svfoo[_m0base]_[m1]index(sv<m0>_t, sv<m1>_t)
+
+ for all valid combinations of vector base type <m0> and vector
+ displacement type <m1>. */
+struct adr_index_def : public adr_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_index);
+ build_all (b, "b,b,d", group, MODE_u32base_s32index);
+ build_all (b, "b,b,d", group, MODE_u32base_u32index);
+ build_all (b, "b,b,d", group, MODE_u64base_s64index);
+ build_all (b, "b,b,d", group, MODE_u64base_u64index);
+ }
+};
+SHAPE (adr_index)
+
+/* sv<m0>_t svfoo[_m0base]_[m1]offset(sv<m0>_t, sv<m1>_t).
+
+ for all valid combinations of vector base type <m0> and vector
+ displacement type <m1>. */
+struct adr_offset_def : public adr_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_offset);
+ build_all (b, "b,b,d", group, MODE_u32base_s32offset);
+ build_all (b, "b,b,d", group, MODE_u32base_u32offset);
+ build_all (b, "b,b,d", group, MODE_u64base_s64offset);
+ build_all (b, "b,b,d", group, MODE_u64base_u64offset);
+ }
+};
+SHAPE (adr_offset)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+
+ i.e. a binary operation with uniform types, but with no scalar form. */
+struct binary_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (2);
+ }
+};
+SHAPE (binary)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int>_t)
+ sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:int>_t).
+
+ i.e. a version of the standard binary shape binary_opt_n in which
+ the final argument is always a signed integer. */
+struct binary_int_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vs0", group, MODE_none);
+ build_all (b, "v0,v0,ss0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ return r.finish_opt_n_resolution (i + 1, i, type, TYPE_signed);
+ }
+};
+SHAPE (binary_int_opt_n)
+
+/* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t)
+
+ where the final argument is an integer constant expression in the
+ range [0, 16 / sizeof (<t0>_t) - 1]. */
+struct binary_lane_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (2, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_lane_index (2);
+ }
+};
+SHAPE (binary_lane)
+
+/* sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t).
+
+ i.e. a binary operation in which the final argument is always a scalar
+ rather than a vector. */
+struct binary_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_n);
+ build_all (b, "v0,v0,s0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_derived_scalar_type (i + 1, r.SAME_TYPE_CLASS))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (binary_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+ sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
+
+ i.e. the standard shape for binary operations that operate on
+ uniform types. */
+struct binary_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0", group, MODE_none);
+ /* _b functions do not have an _n form, but are classified as
+ binary_opt_n so that they can be overloaded with vector
+ functions. */
+ if (group.types[0][0] == TYPE_SUFFIX_b)
+ gcc_assert (group.types[0][1] == NUM_TYPE_SUFFIXES);
+ else
+ build_all (b, "v0,v0,s0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform_opt_n (2);
+ }
+};
+SHAPE (binary_opt_n)
+
+/* svbool_t svfoo(svbool_t, svbool_t). */
+struct binary_pred_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "v0,v0,v0", group, MODE_none);
+ }
+};
+SHAPE (binary_pred)
+
+/* sv<t0>_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
+
+ where the final argument must be 90 or 270. */
+struct binary_rotate_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (2, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_either_or (2, 90, 270);
+ }
+};
+SHAPE (binary_rotate)
+
+/* sv<t0>_t svfoo_t0(<t0>_t, <t0>_t)
+
+ i.e. a binary function that takes two scalars and returns a vector.
+ An explicit type suffix is required. */
+struct binary_scalar_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "v0,s0,s0", group, MODE_none);
+ }
+};
+SHAPE (binary_scalar)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
+
+ i.e. a version of "binary" in which the final argument is always an
+ unsigned integer. */
+struct binary_uint_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vu0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (binary_uint)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0:uint>_t)
+
+ i.e. a version of binary_n in which the final argument is always an
+ unsigned integer. */
+struct binary_uint_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,su0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_derived_scalar_type (i + 1, TYPE_unsigned))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (binary_uint_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
+ sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:uint>_t)
+
+ i.e. a version of the standard binary shape binary_opt_n in which
+ the final argument is always an unsigned integer. */
+struct binary_uint_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vu0", group, MODE_none);
+ build_all (b, "v0,v0,su0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned);
+ }
+};
+SHAPE (binary_uint_opt_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t).
+
+ i.e. a version of binary_n in which the final argument is always
+ a 64-bit unsigned integer. */
+struct binary_uint64_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_scalar_type (i + 1, "uint64_t"))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (binary_uint64_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, svuint64_t)
+ sv<t0>_t svfoo[_n_t0](sv<t0>_t, uint64_t)
+
+ i.e. a version of the standard binary shape binary_opt_n in which
+ the final argument is always a uint64_t. */
+struct binary_uint64_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vu64", group, MODE_none);
+ build_all (b, "v0,v0,su64", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned, 64);
+ }
+};
+SHAPE (binary_uint64_opt_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+ <t0>_t svfoo[_n_t0](<t0>_t, sv<t0>_t). */
+struct clast_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0", group, MODE_none);
+ build_all (b, "s0,s0,v0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ if (!r.check_gp_argument (2, i, nargs)
+ || !r.require_vector_or_scalar_type (i))
+ return error_mark_node;
+
+ if (r.scalar_argument_p (i))
+ {
+ type_suffix_index type;
+ if (!r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
+ || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+ return r.resolve_to (MODE_n, type);
+ }
+ else
+ {
+ type_suffix_index type;
+ if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_matching_vector_type (i + 1, type))
+ return error_mark_node;
+ return r.resolve_to (MODE_none, type);
+ }
+ }
+};
+SHAPE (clast)
+
+/* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+ svbool_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
+
+ i.e. a comparison between two vectors, or between a vector and a scalar. */
+struct compare_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "vp,v0,v0", group, MODE_none);
+ build_all (b, "vp,v0,s0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform_opt_n (2);
+ }
+};
+SHAPE (compare_opt_n)
+
+/* svbool_t svfoo_t0[_t1](<t1>_t, <t1>_t)
+
+ where _t0 is a _b<bits> suffix that describes the predicate result.
+ There is no direct relationship between the element sizes of _t0
+ and _t1. */
+struct compare_scalar_def : public overloaded_base<1>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "vp,s1,s1", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_matching_integer_scalar_type (i + 1, i, type))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
+ }
+};
+SHAPE (compare_scalar)
+
+/* svbool_t svfoo[_t0](sv<t0>_t, svint64_t) (for signed t0)
+ svbool_t svfoo[_n_t0](sv<t0>_t, int64_t) (for signed t0)
+ svbool_t svfoo[_t0](sv<t0>_t, svuint64_t) (for unsigned t0)
+ svbool_t svfoo[_n_t0](sv<t0>_t, uint64_t) (for unsigned t0)
+
+ i.e. a comparison in which the second argument is 64 bits. */
+struct compare_wide_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "vp,v0,vw0", group, MODE_none);
+ build_all (b, "vp,v0,sw0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 64);
+ }
+};
+SHAPE (compare_wide_opt_n)
+
+/* uint64_t svfoo(). */
+struct count_inherent_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "su64", group, MODE_none);
+ }
+};
+SHAPE (count_inherent)
+
+/* uint64_t svfoo(enum svpattern). */
+struct count_pat_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "su64,epattern", group, MODE_none);
+ }
+};
+SHAPE (count_pat)
+
+/* uint64_t svfoo(svbool_t). */
+struct count_pred_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "su64,vp", group, MODE_none);
+ }
+};
+SHAPE (count_pred)
+
+/* uint64_t svfoo[_t0](sv<t0>_t). */
+struct count_vector_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "su64,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (1);
+ }
+};
+SHAPE (count_vector)
+
+/* sv<t0>xN_t svfoo[_t0](sv<t0>_t, ..., sv<t0>_t)
+
+ where there are N arguments in total. */
+struct create_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "t0,v0*t", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (r.vectors_per_tuple ());
+ }
+};
+SHAPE (create)
+
+/* sv<t0>_t svfoo[_n]_t0(<t0>_t, ..., <t0>_t)
+
+ where there are enough arguments to fill 128 bits of data (or to
+ control 128 bits of data in the case of predicates). */
+struct dupq_def : public overloaded_base<1>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ /* The "_n" suffix is optional; the full name has it, but the short
+ name doesn't. */
+ build_all (b, "v0,s0*q", group, MODE_n, true);
+ }
+
+ tree
+ resolve (function_resolver &) const OVERRIDE
+ {
+ /* The short forms just make "_n" implicit, so no resolution is needed. */
+ gcc_unreachable ();
+ }
+};
+SHAPE (dupq)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t)
+
+ where the final argument is an integer constant expression that when
+ multiplied by the number of bytes in t0 is in the range [0, 255]. */
+struct ext_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (2, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ unsigned int bytes = c.type_suffix (0).element_bytes;
+ return c.require_immediate_range (2, 0, 256 / bytes - 1);
+ }
+};
+SHAPE (ext)
+
+/* <t0>_t svfoo[_t0](<t0>_t, sv<t0>_t). */
+struct fold_left_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "s0,s0,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || !r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
+ || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (fold_left)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>xN_t, uint64_t)
+
+ where the final argument is an integer constant expression in
+ the range [0, N - 1]. */
+struct get_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,t0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_integer_immediate (i + 1))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ unsigned int nvectors = c.vectors_per_tuple ();
+ return c.require_immediate_range (1, 0, nvectors - 1);
+ }
+};
+SHAPE (get)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t)
+ <t0>_t svfoo[_n_t0](<t0>_t, uint64_t)
+
+ where the t0 in the vector form is a signed or unsigned integer
+ whose size is tied to the [bhwd] suffix of "svfoo". */
+struct inc_dec_def : public inc_dec_base
+{
+ CONSTEXPR inc_dec_def () : inc_dec_base (false) {}
+
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ /* These functions are unusual in that the type suffixes for
+ the scalar and vector forms are not related. The vector
+ form always has exactly two potential suffixes while the
+ scalar form always has four. */
+ if (group.types[2][0] == NUM_TYPE_SUFFIXES)
+ build_all (b, "v0,v0,su64", group, MODE_none);
+ else
+ build_all (b, "s0,s0,su64", group, MODE_n);
+ }
+};
+SHAPE (inc_dec)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, enum svpattern, uint64_t)
+ <t0>_t svfoo[_n_t0](<t0>_t, enum svpattern, uint64_t)
+
+ where the t0 in the vector form is a signed or unsigned integer
+ whose size is tied to the [bhwd] suffix of "svfoo". */
+struct inc_dec_pat_def : public inc_dec_base
+{
+ CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {}
+
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ /* These functions are unusual in that the type suffixes for
+ the scalar and vector forms are not related. The vector
+ form always has exactly two potential suffixes while the
+ scalar form always has four. */
+ if (group.types[2][0] == NUM_TYPE_SUFFIXES)
+ build_all (b, "v0,v0,epattern,su64", group, MODE_none);
+ else
+ build_all (b, "s0,s0,epattern,su64", group, MODE_n);
+ }
+};
+SHAPE (inc_dec_pat)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, svbool_t). */
+struct inc_dec_pred_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vp", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (inc_dec_pred)
+
+/* <t0>_t svfoo[_n_t0]_t1(<t0>_t, svbool_t)
+
+ where _t1 is a _b<bits> suffix that describes the svbool_t argument. */
+struct inc_dec_pred_scalar_def : public overloaded_base<2>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_n);
+ build_all (b, "s0,s0,vp", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type, r.type_suffix_ids[1]);
+ }
+};
+SHAPE (inc_dec_pred_scalar)
+
+/* sv<t0>[xN]_t svfoo_t0(). */
+struct inherent_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "t0", group, MODE_none);
+ }
+};
+SHAPE (inherent)
+
+/* svbool_t svfoo[_b](). */
+struct inherent_b_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ /* The "_b" suffix is optional; the full name has it, but the short
+ name doesn't. */
+ build_all (b, "v0", group, MODE_none, true);
+ }
+
+ tree
+ resolve (function_resolver &) const OVERRIDE
+ {
+ /* The short forms just make "_b" implicit, so no resolution is needed. */
+ gcc_unreachable ();
+ }
+};
+SHAPE (inherent_b)
+
+/* sv<t0>[xN]_t svfoo[_t0](const <t0>_t *)
+ sv<t0>[xN]_t svfoo_vnum[_t0](const <t0>_t *, int64_t). */
+struct load_def : public load_contiguous_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ b.add_overloaded_functions (group, MODE_vnum);
+ build_all (b, "t0,al", group, MODE_none);
+ build_all (b, "t0,al,ss64", group, MODE_vnum);
+ }
+};
+SHAPE (load)
+
+/* sv<t0>_t svfoo_t0(const <X>_t *)
+ sv<t0>_t svfoo_vnum_t0(const <X>_t *, int64_t)
+
+ where <X> is determined by the function base name. */
+struct load_ext_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "t0,al", group, MODE_none);
+ build_all (b, "t0,al,ss64", group, MODE_vnum);
+ }
+};
+SHAPE (load_ext)
+
+/* sv<t0>_t svfoo_[s32]index_t0(const <X>_t *, svint32_t)
+ sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
+ sv<t0>_t svfoo_[u32]index_t0(const <X>_t *, svuint32_t)
+ sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
+
+ sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
+ sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
+
+ where <X> is determined by the function base name. */
+struct load_ext_gather_index_def : public load_ext_gather_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_index);
+ build_sv_index (b, "t0,al,d", group);
+ build_vs_index (b, "t0,b,ss64", group);
+ }
+};
+SHAPE (load_ext_gather_index)
+
+/* sv<t0>_t svfoo_[s32]offset_t0(const <X>_t *, svint32_t)
+ sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
+ sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
+ sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
+
+ sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
+ sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
+
+ sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
+ sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
+
+ where <X> is determined by the function base name. */
+struct load_ext_gather_offset_def : public load_ext_gather_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_offset);
+ build_sv_offset (b, "t0,al,d", group);
+ build_v_base (b, "t0,b", group, true);
+ build_vs_offset (b, "t0,b,ss64", group);
+ }
+};
+SHAPE (load_ext_gather_offset)
+
+/* sv<t0>_t svfoo_[s32]index[_t0](const <t0>_t *, svint32_t)
+ sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t)
+ sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
+ sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
+
+ sv<t0>_t svfoo_[s32]offset[_t0](const <t0>_t *, svint32_t)
+ sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
+ sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
+ sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t). */
+struct load_gather_sv_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_index);
+ b.add_overloaded_functions (group, MODE_offset);
+ build_sv_index (b, "t0,al,d", group);
+ build_sv_offset (b, "t0,al,d", group);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ mode_suffix_index mode;
+ type_suffix_index type;
+ if (!r.check_gp_argument (2, i, nargs)
+ || (type = r.infer_pointer_type (i, true)) == NUM_TYPE_SUFFIXES
+ || (mode = r.resolve_sv_displacement (i + 1, type, true),
+ mode == MODE_none))
+ return error_mark_node;
+
+ return r.resolve_to (mode, type);
+ }
+};
+SHAPE (load_gather_sv)
+
+/* sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
+ sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
+
+ sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
+ sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
+
+ sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
+ sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t). */
+struct load_gather_vs_def : public overloaded_base<1>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ /* The base vector mode is optional; the full name has it but the
+ short name doesn't. There is no ambiguity with SHAPE_load_gather_sv
+ because the latter uses an implicit type suffix. */
+ build_v_base (b, "t0,b", group, true);
+ build_vs_index (b, "t0,b,ss64", group, true);
+ build_vs_offset (b, "t0,b,ss64", group, true);
+ }
+
+ tree
+ resolve (function_resolver &) const OVERRIDE
+ {
+ /* The short name just makes the base vector mode implicit;
+ no resolution is needed. */
+ gcc_unreachable ();
+ }
+};
+SHAPE (load_gather_vs)
+
+/* sv<t0>_t svfoo[_t0](const <t0>_t *)
+
+ The only difference from "load" is that this shape has no vnum form. */
+struct load_replicate_def : public load_contiguous_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "t0,al", group, MODE_none);
+ }
+};
+SHAPE (load_replicate)
+
+/* svbool_t svfoo(enum svpattern). */
+struct pattern_pred_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "vp,epattern", group, MODE_none);
+ }
+};
+SHAPE (pattern_pred)
+
+/* void svfoo(const void *, svprfop)
+ void svfoo_vnum(const void *, int64_t, svprfop). */
+struct prefetch_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "_,ap,eprfop", group, MODE_none);
+ build_all (b, "_,ap,ss64,eprfop", group, MODE_vnum);
+ }
+};
+SHAPE (prefetch)
+
+/* void svfoo_[s32]index(const void *, svint32_t, svprfop)
+ void svfoo_[s64]index(const void *, svint64_t, svprfop)
+ void svfoo_[u32]index(const void *, svuint32_t, svprfop)
+ void svfoo_[u64]index(const void *, svuint64_t, svprfop)
+
+ void svfoo[_u32base](svuint32_t, svprfop)
+ void svfoo[_u64base](svuint64_t, svprfop)
+
+ void svfoo[_u32base]_index(svuint32_t, int64_t, svprfop)
+ void svfoo[_u64base]_index(svuint64_t, int64_t, svprfop). */
+struct prefetch_gather_index_def : public prefetch_gather_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ b.add_overloaded_functions (group, MODE_index);
+ build_sv_index (b, "_,ap,d,eprfop", group);
+ build_v_base (b, "_,b,eprfop", group);
+ build_vs_index (b, "_,b,ss64,eprfop", group);
+ }
+};
+SHAPE (prefetch_gather_index)
+
+/* void svfoo_[s32]offset(const void *, svint32_t, svprfop)
+ void svfoo_[s64]offset(const void *, svint64_t, svprfop)
+ void svfoo_[u32]offset(const void *, svuint32_t, svprfop)
+ void svfoo_[u64]offset(const void *, svuint64_t, svprfop)
+
+ void svfoo[_u32base](svuint32_t, svprfop)
+ void svfoo[_u64base](svuint64_t, svprfop)
+
+ void svfoo[_u32base]_offset(svuint32_t, int64_t, svprfop)
+ void svfoo[_u64base]_offset(svuint64_t, int64_t, svprfop). */
+struct prefetch_gather_offset_def : public prefetch_gather_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ b.add_overloaded_functions (group, MODE_offset);
+ build_sv_offset (b, "_,ap,d,eprfop", group);
+ build_v_base (b, "_,b,eprfop", group);
+ build_vs_offset (b, "_,b,ss64,eprfop", group);
+ }
+};
+SHAPE (prefetch_gather_offset)
+
+/* bool svfoo(svbool_t). */
+struct ptest_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "sp,vp", group, MODE_none);
+ }
+};
+SHAPE (ptest)
+
+/* svbool_t svfoo(). */
+struct rdffr_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "vp", group, MODE_none);
+ }
+};
+SHAPE (rdffr)
+
+/* <t0>_t svfoo[_t0](sv<t0>_t). */
+struct reduction_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "s0,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (1);
+ }
+};
+SHAPE (reduction)
+
+/* int64_t svfoo[_t0](sv<t0>_t) (for signed t0)
+ uint64_t svfoo[_t0](sv<t0>_t) (for unsigned t0)
+ <t0>_t svfoo[_t0](sv<t0>_t) (for floating-point t0)
+
+ i.e. a version of "reduction" in which the return type for integers
+ always has 64 bits. */
+struct reduction_wide_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "sw0,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (1);
+ }
+};
+SHAPE (reduction_wide)
+
+/* sv<t0>xN_t svfoo[_t0](sv<t0>xN_t, uint64_t, sv<t0>_t)
+
+ where the second argument is an integer constant expression in the
+ range [0, N - 1]. */
+struct set_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "t0,t0,su64,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (3, i, nargs)
+ || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_integer_immediate (i + 1)
+ || !r.require_derived_vector_type (i + 2, i, type))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ unsigned int nvectors = c.vectors_per_tuple ();
+ return c.require_immediate_range (1, 0, nvectors - 1);
+ }
+};
+SHAPE (set)
+
+/* void svfoo(). */
+struct setffr_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "_", group, MODE_none);
+ }
+};
+SHAPE (setffr)
+
+/* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
+
+ where the final argument must be an integer constant expression in the
+ range [1, sizeof (<t0>_t) * 8]. */
+struct shift_right_imm_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_n);
+ build_all (b, "v0,v0,su64", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (1, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ unsigned int bits = c.type_suffix (0).element_bits;
+ return c.require_immediate_range (1, 1, bits);
+ }
+};
+SHAPE (shift_right_imm)
+
+/* void svfoo[_t0](<X>_t *, sv<t0>[xN]_t)
+ void svfoo_vnum[_t0](<X>_t *, int64_t, sv<t0>[xN]_t)
+
+ where <X> might be tied to <t0> (for non-truncating stores) or might
+ depend on the function base name (for truncating stores). */
+struct store_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ b.add_overloaded_functions (group, MODE_vnum);
+ build_all (b, "_,as,t0", group, MODE_none);
+ build_all (b, "_,as,ss64,t0", group, MODE_vnum);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ bool vnum_p = r.mode_suffix_id == MODE_vnum;
+ gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
+
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs)
+ || !r.require_pointer_type (i)
+ || (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))
+ || ((type = r.infer_tuple_type (nargs - 1)) == NUM_TYPE_SUFFIXES))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+};
+SHAPE (store)
+
+/* void svfoo_[s32]index[_t0](<X>_t *, svint32_t, sv<t0>_t)
+ void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
+ void svfoo_[u32]index[_t0](<X>_t *, svuint32_t, sv<t0>_t)
+ void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
+
+ void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
+ void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
+
+ where <X> might be tied to <t0> (for non-truncating stores) or might
+ depend on the function base name (for truncating stores). */
+struct store_scatter_index_def : public store_scatter_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_index);
+ build_sv_index (b, "_,as,d,t0", group);
+ build_vs_index (b, "_,b,ss64,t0", group);
+ }
+};
+SHAPE (store_scatter_index)
+
+/* void svfoo_[s32]offset[_t0](<X>_t *, svint32_t, sv<t0>_t)
+ void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
+ void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
+ void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
+
+ void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
+ void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
+
+ void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
+ void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
+
+ where <X> might be tied to <t0> (for non-truncating stores) or might
+ depend on the function base name (for truncating stores). */
+struct store_scatter_offset_def : public store_scatter_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ b.add_overloaded_functions (group, MODE_offset);
+ build_sv_offset (b, "_,as,d,t0", group);
+ build_v_base (b, "_,b,t0", group);
+ build_vs_offset (b, "_,b,ss64,t0", group);
+ }
+};
+SHAPE (store_scatter_offset)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
+
+ where the final argument is an integer constant expression in the
+ range [0, 16 / sizeof (<t0>_t) - 1]. */
+struct ternary_lane_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (3, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_lane_index (3);
+ }
+};
+SHAPE (ternary_lane)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t, uint64_t)
+
+ where the penultimate argument is an integer constant expression in
+ the range [0, 8 / sizeof (<t0>_t) - 1] and where the final argument
+ is an integer constant expression in {0, 90, 180, 270}. */
+struct ternary_lane_rotate_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,v0,su64,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (3, 2);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return (c.require_immediate_lane_index (3, 2)
+ && c.require_immediate_one_of (4, 0, 90, 180, 270));
+ }
+};
+SHAPE (ternary_lane_rotate)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
+ sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0>_t, <t0>_t)
+
+ i.e. the standard shape for ternary operations that operate on
+ uniform types. */
+struct ternary_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,v0", group, MODE_none);
+ build_all (b, "v0,v0,v0,s0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform_opt_n (3);
+ }
+};
+SHAPE (ternary_opt_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0.quarter>_t, sv<t0.quarter>_t, uint64_t)
+
+ where the final argument is an integer constant expression in the range
+ [0, 16 / sizeof (<t0>_t) - 1]. */
+struct ternary_qq_lane_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (4, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
+ r.QUARTER_SIZE)
+ || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
+ r.QUARTER_SIZE)
+ || !r.require_integer_immediate (i + 3))
+ return error_mark_node;
+
+ return r.resolve_to (r.mode_suffix_id, type);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_lane_index (3, 4);
+ }
+};
+SHAPE (ternary_qq_lane)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0.quarter>_t, sv<t0.quarter>_t)
+ sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0.quarter>_t, <t0.quarter>_t)
+
+ i.e. a version of the standard ternary shape ternary_opt_n in which
+ the element type of the last two arguments is the quarter-sized
+ equivalent of <t0>. */
+struct ternary_qq_opt_n_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
+ build_all (b, "v0,v0,vq0,sq0", group, MODE_n);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (3, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+ || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
+ r.QUARTER_SIZE))
+ return error_mark_node;
+
+ return r.finish_opt_n_resolution (i + 2, i, type, r.SAME_TYPE_CLASS,
+ r.QUARTER_SIZE);
+ }
+};
+SHAPE (ternary_qq_opt_n)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
+
+ where the final argument is an integer constant expression in
+ {0, 90, 180, 270}. */
+struct ternary_rotate_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (3, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_one_of (3, 0, 90, 180, 270);
+ }
+};
+SHAPE (ternary_rotate)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
+
+ where the final argument is an integer constant expression in the
+ range [0, 7]. */
+struct tmad_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0,v0,su64", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_uniform (2, 1);
+ }
+
+ bool
+ check (function_checker &c) const OVERRIDE
+ {
+ return c.require_immediate_range (2, 0, 7);
+ }
+};
+SHAPE (tmad)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t)
+
+ i.e. the standard shape for unary operations that operate on
+ uniform types. */
+struct unary_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_unary ();
+ }
+};
+SHAPE (unary)
+
+/* sv<t0>_t svfoo_t0[_t1](svbool_t, sv<t1>_t)
+
+ where the target type <t0> must be specified explicitly but the source
+ type <t1> can be inferred. */
+struct unary_convert_def : public overloaded_base<1>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,v1", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_unary (r.type_suffix (0).tclass,
+ r.type_suffix (0).element_bits);
+ }
+};
+SHAPE (unary_convert)
+
+/* sv<t0:uint>_t svfoo[_t0](sv<t0>_t)
+
+ i.e. a version of "unary" in which the returned vector contains
+ unsigned integers. */
+struct unary_count_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "vu0,v0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ return r.resolve_unary (TYPE_unsigned);
+ }
+};
+SHAPE (unary_count)
+
+/* sv<t0>_t svfoo[_n]_t0(<t0>_t). */
+struct unary_n_def : public overloaded_base<1>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ /* The "_n" suffix is optional; the full name has it, but the short
+ name doesn't. */
+ build_all (b, "v0,s0", group, MODE_n, true);
+ }
+
+ tree
+ resolve (function_resolver &) const OVERRIDE
+ {
+ /* The short forms just make "_n" implicit, so no resolution is needed. */
+ gcc_unreachable ();
+ }
+};
+SHAPE (unary_n)
+
+/* svbool_t svfoo(svbool_t). */
+struct unary_pred_def : public nonoverloaded_base
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ build_all (b, "v0,v0", group, MODE_none);
+ }
+};
+SHAPE (unary_pred)
+
+/* sv<t0>_t svfoo[_t0](sv<t0:uint>_t)
+
+ where <t0> always belongs a certain type class, and where <t0:uint>
+ therefore uniquely determines <t0>. */
+struct unary_uint_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,vu0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (1, i, nargs)
+ || (type = r.infer_unsigned_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ /* Search for a valid suffix with the same number of bits as TYPE. */
+ unsigned int element_bits = type_suffixes[type].element_bits;
+ if (type_suffixes[type].unsigned_p)
+ for (unsigned int j = 0; j < NUM_TYPE_SUFFIXES; ++j)
+ if (type_suffixes[j].element_bits == element_bits)
+ if (tree res = r.lookup_form (r.mode_suffix_id,
+ type_suffix_index (j)))
+ return res;
+
+ return r.report_no_such_form (type);
+ }
+};
+SHAPE (unary_uint)
+
+/* sv<t0>_t svfoo[_<t0>](sv<t0:half>_t)
+
+ i.e. a version of "unary" in which the source elements are half the
+ size of the destination elements, but have the same type class. */
+struct unary_widen_def : public overloaded_base<0>
+{
+ void
+ build (function_builder &b, const function_group_info &group) const OVERRIDE
+ {
+ b.add_overloaded_functions (group, MODE_none);
+ build_all (b, "v0,vh0", group, MODE_none);
+ }
+
+ tree
+ resolve (function_resolver &r) const OVERRIDE
+ {
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!r.check_gp_argument (1, i, nargs)
+ || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ /* There is only a single form for predicates. */
+ if (type == TYPE_SUFFIX_b)
+ return r.resolve_to (r.mode_suffix_id, type);
+
+ if (type_suffixes[type].integer_p
+ && type_suffixes[type].element_bits < 64)
+ {
+ type_suffix_index wide_suffix
+ = find_type_suffix (type_suffixes[type].tclass,
+ type_suffixes[type].element_bits * 2);
+ if (tree res = r.lookup_form (r.mode_suffix_id, wide_suffix))
+ return res;
+ }
+
+ return r.report_no_such_form (type);
+ }
+};
+SHAPE (unary_widen)
+
+}
--- /dev/null
+/* ACLE support for AArch64 SVE (function shapes)
+ Copyright (C) 2018-2019 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/>. */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_SHAPES_H
+#define GCC_AARCH64_SVE_BUILTINS_SHAPES_H
+
+namespace aarch64_sve
+{
+ /* The naming convention is:
+
+ - to use the name of the function if the rules are very specific to
+ a particular function (e.g. svext, for which the range of the
+ final immediate value is in no way generic).
+
+ - to use names like "unary" etc. if the rules are somewhat generic,
+ especially if there are no ranges involved.
+
+ When using generic names, the handling of the final vector argument
+ can be modified as follows:
+
+ - an "_n" suffix changes the argument from a vector to a scalar.
+
+ - an "_opt_n" suffix says that there are two forms of each function:
+ one in which the argument is the usual vector, and one in which it
+ is replaced by a scalar.
+
+ - "_int" and "_uint" replace the argument's element type with a
+ signed or unsigned integer of the same width. The suffixes above
+ then indicate whether this final argument is or might be a scalar.
+
+ - "_int64" and "_uint64" similarly replace the argument's element type
+ with int64_t or uint64_t.
+
+ - "_wide" replaces the argument's element type with a 64-bit integer
+ of the same signedness. This only makes sense for integer elements.
+
+ - "_lane" indicates that the argument is indexed by a constant lane
+ number, provided as an immediately-following argument of type uint64_t.
+
+ Also:
+
+ - "inherent" means that the function takes no arguments.
+
+ - "_rotate" means that the final argument is a rotation amount
+ (0, 90, 180 or 270).
+
+ - "_scalar" indicates that all data arguments are scalars rather
+ than vectors.
+
+ - in gather/scatter addresses, "sv" stands for "scalar base,
+ vector displacement" while "vs" stands for "vector base,
+ scalar displacement".
+
+ - "_pred" indicates that the function takes an svbool_t argument
+ that does not act as a governing predicate.. */
+ namespace shapes
+ {
+ extern const function_shape *const adr_index;
+ extern const function_shape *const adr_offset;
+ extern const function_shape *const binary;
+ extern const function_shape *const binary_int_opt_n;
+ extern const function_shape *const binary_lane;
+ extern const function_shape *const binary_n;
+ extern const function_shape *const binary_opt_n;
+ extern const function_shape *const binary_pred;
+ extern const function_shape *const binary_rotate;
+ extern const function_shape *const binary_scalar;
+ extern const function_shape *const binary_uint;
+ extern const function_shape *const binary_uint_n;
+ extern const function_shape *const binary_uint_opt_n;
+ extern const function_shape *const binary_uint64_n;
+ extern const function_shape *const binary_uint64_opt_n;
+ extern const function_shape *const clast;
+ extern const function_shape *const compare_opt_n;
+ extern const function_shape *const compare_scalar;
+ extern const function_shape *const compare_wide_opt_n;
+ extern const function_shape *const count_inherent;
+ extern const function_shape *const count_pat;
+ extern const function_shape *const count_pred;
+ extern const function_shape *const count_vector;
+ extern const function_shape *const create;
+ extern const function_shape *const dupq;
+ extern const function_shape *const ext;
+ extern const function_shape *const fold_left;
+ extern const function_shape *const get;
+ extern const function_shape *const inc_dec;
+ extern const function_shape *const inc_dec_pat;
+ extern const function_shape *const inc_dec_pred;
+ extern const function_shape *const inc_dec_pred_scalar;
+ extern const function_shape *const inherent;
+ extern const function_shape *const inherent_b;
+ extern const function_shape *const load;
+ extern const function_shape *const load_ext;
+ extern const function_shape *const load_ext_gather_index;
+ extern const function_shape *const load_ext_gather_offset;
+ extern const function_shape *const load_gather_sv;
+ extern const function_shape *const load_gather_vs;
+ extern const function_shape *const load_replicate;
+ extern const function_shape *const pattern_pred;
+ extern const function_shape *const prefetch;
+ extern const function_shape *const prefetch_gather_index;
+ extern const function_shape *const prefetch_gather_offset;
+ extern const function_shape *const ptest;
+ extern const function_shape *const rdffr;
+ extern const function_shape *const reduction;
+ extern const function_shape *const reduction_wide;
+ extern const function_shape *const set;
+ extern const function_shape *const setffr;
+ extern const function_shape *const shift_right_imm;
+ extern const function_shape *const store;
+ extern const function_shape *const store_scatter_index;
+ extern const function_shape *const store_scatter_offset;
+ extern const function_shape *const ternary_lane;
+ extern const function_shape *const ternary_lane_rotate;
+ extern const function_shape *const ternary_opt_n;
+ extern const function_shape *const ternary_qq_lane;
+ extern const function_shape *const ternary_qq_opt_n;
+ extern const function_shape *const ternary_rotate;
+ extern const function_shape *const tmad;
+ extern const function_shape *const unary;
+ extern const function_shape *const unary_convert;
+ extern const function_shape *const unary_count;
+ extern const function_shape *const unary_n;
+ extern const function_shape *const unary_pred;
+ extern const function_shape *const unary_uint;
+ extern const function_shape *const unary_widen;
+ }
+}
+
+#endif
--- /dev/null
+/* ACLE support for AArch64 SVE
+ Copyright (C) 2018-2019 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "diagnostic.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "function.h"
+#include "fold-const.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "tree-vector-builder.h"
+#include "stor-layout.h"
+#include "regs.h"
+#include "alias.h"
+#include "gimple-fold.h"
+#include "langhooks.h"
+#include "stringpool.h"
+#include "aarch64-sve-builtins.h"
+#include "aarch64-sve-builtins-base.h"
+#include "aarch64-sve-builtins-shapes.h"
+
+namespace aarch64_sve {
+
+/* Static information about each single-predicate or single-vector
+ ABI and ACLE type. */
+struct vector_type_info
+{
+ /* The name of the type as declared by arm_sve.h. */
+ const char *acle_name;
+
+ /* The name of the type specified in AAPCS64. The type is always
+ available under this name, even when arm_sve.h isn't included. */
+ const char *abi_name;
+
+ /* The C++ mangling of ABI_NAME. */
+ const char *mangled_name;
+};
+
+/* Describes a function decl. */
+class GTY(()) registered_function
+{
+public:
+ /* The ACLE function that the decl represents. */
+ function_instance instance GTY ((skip));
+
+ /* The decl itself. */
+ tree decl;
+
+ /* The architecture extensions that the function requires, as a set of
+ AARCH64_FL_* flags. */
+ uint64_t required_extensions;
+
+ /* True if the decl represents an overloaded function that needs to be
+ resolved by function_resolver. */
+ bool overloaded_p;
+};
+
+/* Hash traits for registered_function. */
+struct registered_function_hasher : nofree_ptr_hash <registered_function>
+{
+ typedef function_instance compare_type;
+
+ static hashval_t hash (value_type);
+ static bool equal (value_type, const compare_type &);
+};
+
+/* Information about each single-predicate or single-vector type. */
+static CONSTEXPR const vector_type_info vector_types[] = {
+#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
+ { #ACLE_NAME, #ABI_NAME, #NCHARS #ABI_NAME },
+#include "aarch64-sve-builtins.def"
+};
+
+/* The function name suffix associated with each predication type. */
+static const char *const pred_suffixes[NUM_PREDS + 1] = {
+ "",
+ "",
+ "_m",
+ "_x",
+ "_z",
+ ""
+};
+
+/* Static information about each mode_suffix_index. */
+CONSTEXPR const mode_suffix_info mode_suffixes[] = {
+#define VECTOR_TYPE_none NUM_VECTOR_TYPES
+#define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) \
+ { "_" #NAME, VECTOR_TYPE_##BASE, VECTOR_TYPE_##DISPLACEMENT, UNITS_##UNITS },
+#include "aarch64-sve-builtins.def"
+#undef VECTOR_TYPE_none
+ { "", NUM_VECTOR_TYPES, NUM_VECTOR_TYPES, UNITS_none }
+};
+
+/* Static information about each type_suffix_index. */
+CONSTEXPR const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
+#define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
+ { "_" #NAME, \
+ VECTOR_TYPE_##ACLE_TYPE, \
+ TYPE_##CLASS, \
+ BITS, \
+ BITS / BITS_PER_UNIT, \
+ TYPE_##CLASS == TYPE_signed || TYPE_##CLASS == TYPE_unsigned, \
+ TYPE_##CLASS == TYPE_unsigned, \
+ TYPE_##CLASS == TYPE_float, \
+ TYPE_##CLASS == TYPE_bool, \
+ 0, \
+ MODE },
+#include "aarch64-sve-builtins.def"
+ { "", NUM_VECTOR_TYPES, TYPE_bool, 0, 0, false, false, false, false,
+ 0, VOIDmode }
+};
+
+/* Define a TYPES_<combination> macro for each combination of type
+ suffixes that an ACLE function can have, where <combination> is the
+ name used in DEF_SVE_FUNCTION entries.
+
+ Use S (T) for single type suffix T and D (T1, T2) for a pair of type
+ suffixes T1 and T2. Use commas to separate the suffixes.
+
+ Although the order shouldn't matter, the convention is to sort the
+ suffixes lexicographically after dividing suffixes into a type
+ class ("b", "f", etc.) and a numerical bit count. */
+
+/* _b8 _b16 _b32 _b64. */
+#define TYPES_all_pred(S, D) \
+ S (b8), S (b16), S (b32), S (b64)
+
+/* _f16 _f32 _f64. */
+#define TYPES_all_float(S, D) \
+ S (f16), S (f32), S (f64)
+
+/* _s8 _s16 _s32 _s64. */
+#define TYPES_all_signed(S, D) \
+ S (s8), S (s16), S (s32), S (s64)
+
+/* _f16 _f32 _f64
+ _s8 _s16 _s32 _s64. */
+#define TYPES_all_float_and_signed(S, D) \
+ TYPES_all_float (S, D), TYPES_all_signed (S, D)
+
+/* _u8 _u16 _u32 _u64. */
+#define TYPES_all_unsigned(S, D) \
+ S (u8), S (u16), S (u32), S (u64)
+
+/* _s8 _s16 _s32 _s64
+ _u8 _u16 _u32 _u64. */
+#define TYPES_all_integer(S, D) \
+ TYPES_all_signed (S, D), TYPES_all_unsigned (S, D)
+
+/* _f16 _f32 _f64
+ _s8 _s16 _s32 _s64
+ _u8 _u16 _u32 _u64. */
+#define TYPES_all_data(S, D) \
+ TYPES_all_float (S, D), TYPES_all_integer (S, D)
+
+/* _b only. */
+#define TYPES_b(S, D) \
+ S (b)
+
+/* _s8 _s16 _s32. */
+#define TYPES_bhs_signed(S, D) \
+ S (s8), S (s16), S (s32)
+
+/* _u8 _u16 _u32. */
+#define TYPES_bhs_unsigned(S, D) \
+ S (u8), S (u16), S (u32)
+
+/* _s8 _s16 _s32
+ _u8 _u16 _u32. */
+#define TYPES_bhs_integer(S, D) \
+ TYPES_bhs_signed (S, D), TYPES_bhs_unsigned (S, D)
+
+/* _s16
+ _u16. */
+#define TYPES_h_integer(S, D) \
+ S (s16), S (u16)
+
+/* _f16 _f32. */
+#define TYPES_hs_float(S, D) \
+ S (f16), S (f32)
+
+/* _s16 _s32 _s64
+ _u16 _u32 _u64. */
+#define TYPES_hsd_integer(S, D) \
+ S (s16), S (s32), S (s64), S (u16), S (u32), S (u64)
+
+/* _s32 _u32. */
+#define TYPES_s_integer(S, D) \
+ S (s32), S (u32)
+
+/* _s32 _s64
+ _u32 _u64. */
+#define TYPES_sd_integer(S, D) \
+ S (s32), S (s64), S (u32), S (u64)
+
+/* _f32 _f64
+ _s32 _s64
+ _u32 _u64. */
+#define TYPES_sd_data(S, D) \
+ S (f32), S (f64), TYPES_sd_integer (S, D)
+
+/* _f16 _f32 _f64
+ _s32 _s64
+ _u32 _u64. */
+#define TYPES_all_float_and_sd_integer(S, D) \
+ TYPES_all_float (S, D), TYPES_sd_integer (S, D)
+
+/* _s64
+ _u64. */
+#define TYPES_d_integer(S, D) \
+ S (s64), S (u64)
+
+/* All the type combinations allowed by svcvt. */
+#define TYPES_cvt(S, D) \
+ D (f16, f32), D (f16, f64), \
+ D (f16, s16), D (f16, s32), D (f16, s64), \
+ D (f16, u16), D (f16, u32), D (f16, u64), \
+ \
+ D (f32, f16), D (f32, f64), \
+ D (f32, s32), D (f32, s64), \
+ D (f32, u32), D (f32, u64), \
+ \
+ D (f64, f16), D (f64, f32), \
+ D (f64, s32), D (f64, s64), \
+ D (f64, u32), D (f64, u64), \
+ \
+ D (s16, f16), \
+ D (s32, f16), D (s32, f32), D (s32, f64), \
+ D (s64, f16), D (s64, f32), D (s64, f64), \
+ \
+ D (u16, f16), \
+ D (u32, f16), D (u32, f32), D (u32, f64), \
+ D (u64, f16), D (u64, f32), D (u64, f64)
+
+/* { _s32 _s64 } x { _b8 _b16 _b32 _b64 }
+ { _u32 _u64 }. */
+#define TYPES_inc_dec_n1(D, A) \
+ D (A, b8), D (A, b16), D (A, b32), D (A, b64)
+#define TYPES_inc_dec_n(S, D) \
+ TYPES_inc_dec_n1 (D, s32), \
+ TYPES_inc_dec_n1 (D, s64), \
+ TYPES_inc_dec_n1 (D, u32), \
+ TYPES_inc_dec_n1 (D, u64)
+
+/* { _f16 _f32 _f64 } { _f16 _f32 _f64 }
+ { _s8 _s16 _s32 _s64 } x { _s8 _s16 _s32 _s64 }
+ { _u8 _u16 _u32 _u64 } { _u8 _u16 _u32 _u64 }. */
+#define TYPES_reinterpret1(D, A) \
+ D (A, f16), D (A, f32), D (A, f64), \
+ D (A, s8), D (A, s16), D (A, s32), D (A, s64), \
+ D (A, u8), D (A, u16), D (A, u32), D (A, u64)
+#define TYPES_reinterpret(S, D) \
+ TYPES_reinterpret1 (D, f16), \
+ TYPES_reinterpret1 (D, f32), \
+ TYPES_reinterpret1 (D, f64), \
+ TYPES_reinterpret1 (D, s8), \
+ TYPES_reinterpret1 (D, s16), \
+ TYPES_reinterpret1 (D, s32), \
+ TYPES_reinterpret1 (D, s64), \
+ TYPES_reinterpret1 (D, u8), \
+ TYPES_reinterpret1 (D, u16), \
+ TYPES_reinterpret1 (D, u32), \
+ TYPES_reinterpret1 (D, u64)
+
+/* { _b8 _b16 _b32 _b64 } x { _s32 _s64 }
+ { _u32 _u64 } */
+#define TYPES_while1(D, bn) \
+ D (bn, s32), D (bn, s64), D (bn, u32), D (bn, u64)
+#define TYPES_while(S, D) \
+ TYPES_while1 (D, b8), \
+ TYPES_while1 (D, b16), \
+ TYPES_while1 (D, b32), \
+ TYPES_while1 (D, b64)
+
+/* Describe a pair of type suffixes in which only the first is used. */
+#define DEF_VECTOR_TYPE(X) { TYPE_SUFFIX_ ## X, NUM_TYPE_SUFFIXES }
+
+/* Describe a pair of type suffixes in which both are used. */
+#define DEF_DOUBLE_TYPE(X, Y) { TYPE_SUFFIX_ ## X, TYPE_SUFFIX_ ## Y }
+
+/* Create an array that can be used in aarch64-sve-builtins.def to
+ select the type suffixes in TYPES_<NAME>. */
+#define DEF_SVE_TYPES_ARRAY(NAME) \
+ static const type_suffix_pair types_##NAME[] = { \
+ TYPES_##NAME (DEF_VECTOR_TYPE, DEF_DOUBLE_TYPE), \
+ { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } \
+ }
+
+/* For functions that don't take any type suffixes. */
+static const type_suffix_pair types_none[] = {
+ { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES },
+ { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES }
+};
+
+/* Create an array for each TYPES_<combination> macro above. */
+DEF_SVE_TYPES_ARRAY (all_pred);
+DEF_SVE_TYPES_ARRAY (all_float);
+DEF_SVE_TYPES_ARRAY (all_signed);
+DEF_SVE_TYPES_ARRAY (all_float_and_signed);
+DEF_SVE_TYPES_ARRAY (all_unsigned);
+DEF_SVE_TYPES_ARRAY (all_integer);
+DEF_SVE_TYPES_ARRAY (all_data);
+DEF_SVE_TYPES_ARRAY (b);
+DEF_SVE_TYPES_ARRAY (bhs_signed);
+DEF_SVE_TYPES_ARRAY (bhs_unsigned);
+DEF_SVE_TYPES_ARRAY (bhs_integer);
+DEF_SVE_TYPES_ARRAY (h_integer);
+DEF_SVE_TYPES_ARRAY (hs_float);
+DEF_SVE_TYPES_ARRAY (hsd_integer);
+DEF_SVE_TYPES_ARRAY (s_integer);
+DEF_SVE_TYPES_ARRAY (sd_integer);
+DEF_SVE_TYPES_ARRAY (sd_data);
+DEF_SVE_TYPES_ARRAY (all_float_and_sd_integer);
+DEF_SVE_TYPES_ARRAY (d_integer);
+DEF_SVE_TYPES_ARRAY (cvt);
+DEF_SVE_TYPES_ARRAY (inc_dec_n);
+DEF_SVE_TYPES_ARRAY (reinterpret);
+DEF_SVE_TYPES_ARRAY (while);
+
+/* Used by functions that have no governing predicate. */
+static const predication_index preds_none[] = { PRED_none, NUM_PREDS };
+
+/* Used by functions that have a governing predicate but do not have an
+ explicit suffix. */
+static const predication_index preds_implicit[] = { PRED_implicit, NUM_PREDS };
+
+/* Used by functions that allow merging, zeroing and "don't care"
+ predication. */
+static const predication_index preds_mxz[] = {
+ PRED_m, PRED_x, PRED_z, NUM_PREDS
+};
+
+/* Used by functions that have the mxz predicated forms above, and in addition
+ have an unpredicated form. */
+static const predication_index preds_mxz_or_none[] = {
+ PRED_m, PRED_x, PRED_z, PRED_none, NUM_PREDS
+};
+
+/* Used by functions that allow merging and zeroing predication but have
+ no "_x" form. */
+static const predication_index preds_mz[] = { PRED_m, PRED_z, NUM_PREDS };
+
+/* Used by functions that have an unpredicated form and a _z predicated
+ form. */
+static const predication_index preds_z_or_none[] = {
+ PRED_z, PRED_none, NUM_PREDS
+};
+
+/* Used by (mostly predicate) functions that only support "_z" predication. */
+static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+
+/* A list of all SVE ACLE functions. */
+static CONSTEXPR const function_group_info function_groups[] = {
+#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+ { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, preds_##PREDS, \
+ REQUIRED_EXTENSIONS | AARCH64_FL_SVE },
+#include "aarch64-sve-builtins.def"
+};
+
+/* The scalar type associated with each vector type. */
+GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
+
+/* The single-predicate and single-vector types, with their built-in
+ "__SV..._t" name. Allow an index of NUM_VECTOR_TYPES, which always
+ yields a null tree. */
+static GTY(()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
+
+/* Same, but with the arm_sve.h "sv..._t" name. */
+GTY(()) tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+
+/* The svpattern enum type. */
+GTY(()) tree acle_svpattern;
+
+/* The svprfop enum type. */
+GTY(()) tree acle_svprfop;
+
+/* The list of all registered function decls, indexed by code. */
+static GTY(()) vec<registered_function *, va_gc> *registered_functions;
+
+/* All registered function decls, hashed on the function_instance
+ that they implement. This is used for looking up implementations of
+ overloaded functions. */
+static hash_table<registered_function_hasher> *function_table;
+
+/* True if we've already complained about attempts to use functions
+ when the required extension is disabled. */
+static bool reported_missing_extension_p;
+
+/* If TYPE is an ACLE vector type, return the associated vector_type,
+ otherwise return NUM_VECTOR_TYPES. */
+static vector_type_index
+find_vector_type (const_tree type)
+{
+ /* A linear search should be OK here, since the code isn't hot and
+ the number of types is only small. */
+ type = TYPE_MAIN_VARIANT (type);
+ for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
+ if (type == abi_vector_types[i])
+ return vector_type_index (i);
+ return NUM_VECTOR_TYPES;
+}
+
+/* If TYPE is a valid SVE element type, return the corresponding type
+ suffix, otherwise return NUM_TYPE_SUFFIXES. */
+static type_suffix_index
+find_type_suffix_for_scalar_type (const_tree type)
+{
+ /* A linear search should be OK here, since the code isn't hot and
+ the number of types is only small. */
+ type = TYPE_MAIN_VARIANT (type);
+ for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+ if (!type_suffixes[suffix_i].bool_p)
+ {
+ vector_type_index vector_i = type_suffixes[suffix_i].vector_type;
+ if (type == TYPE_MAIN_VARIANT (scalar_types[vector_i]))
+ return type_suffix_index (suffix_i);
+ }
+ return NUM_TYPE_SUFFIXES;
+}
+
+/* Report an error against LOCATION that the user has tried to use
+ function FNDECL when extension EXTENSION is disabled. */
+static void
+report_missing_extension (location_t location, tree fndecl,
+ const char *extension)
+{
+ /* Avoid reporting a slew of messages for a single oversight. */
+ if (reported_missing_extension_p)
+ return;
+
+ error_at (location, "ACLE function %qD requires ISA extension %qs",
+ fndecl, extension);
+ inform (location, "you can enable %qs using the command-line"
+ " option %<-march%>, or by using the %<target%>"
+ " attribute or pragma", extension);
+ reported_missing_extension_p = true;
+}
+
+/* Check whether all the AARCH64_FL_* values in REQUIRED_EXTENSIONS are
+ enabled, given that those extensions are required for function FNDECL.
+ Report an error against LOCATION if not. */
+static bool
+check_required_extensions (location_t location, tree fndecl,
+ uint64_t required_extensions)
+{
+ uint64_t missing_extensions = required_extensions & ~aarch64_isa_flags;
+ if (missing_extensions == 0)
+ return true;
+
+ static const struct { uint64_t flag; const char *name; } extensions[] = {
+#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+ SYNTHETIC, FEATURE_STRING) \
+ { FLAG_CANONICAL, EXT_NAME },
+#include "aarch64-option-extensions.def"
+ };
+
+ for (unsigned int i = 0; i < ARRAY_SIZE (extensions); ++i)
+ if (missing_extensions & extensions[i].flag)
+ {
+ report_missing_extension (location, fndecl, extensions[i].name);
+ return false;
+ }
+ gcc_unreachable ();
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO
+ was not an integer constant expression. ARGNO counts from zero. */
+static void
+report_non_ice (location_t location, tree fndecl, unsigned int argno)
+{
+ error_at (location, "argument %d of %qE must be an integer constant"
+ " expression", argno + 1, fndecl);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+ the value ACTUAL, whereas the function requires a value in the range
+ [MIN, MAX]. ARGNO counts from zero. */
+static void
+report_out_of_range (location_t location, tree fndecl, unsigned int argno,
+ HOST_WIDE_INT actual, HOST_WIDE_INT min,
+ HOST_WIDE_INT max)
+{
+ error_at (location, "passing %wd to argument %d of %qE, which expects"
+ " a value in the range [%wd, %wd]", actual, argno + 1, fndecl,
+ min, max);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+ the value ACTUAL, whereas the function requires either VALUE0 or
+ VALUE1. ARGNO counts from zero. */
+static void
+report_neither_nor (location_t location, tree fndecl, unsigned int argno,
+ HOST_WIDE_INT actual, HOST_WIDE_INT value0,
+ HOST_WIDE_INT value1)
+{
+ error_at (location, "passing %wd to argument %d of %qE, which expects"
+ " either %wd or %wd", actual, argno + 1, fndecl, value0, value1);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+ the value ACTUAL, whereas the function requires one of VALUE0..3.
+ ARGNO counts from zero. */
+static void
+report_not_one_of (location_t location, tree fndecl, unsigned int argno,
+ HOST_WIDE_INT actual, HOST_WIDE_INT value0,
+ HOST_WIDE_INT value1, HOST_WIDE_INT value2,
+ HOST_WIDE_INT value3)
+{
+ error_at (location, "passing %wd to argument %d of %qE, which expects"
+ " %wd, %wd, %wd or %wd", actual, argno + 1, fndecl, value0, value1,
+ value2, value3);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+ the value ACTUAL, whereas the function requires a valid value of
+ enum type ENUMTYPE. ARGNO counts from zero. */
+static void
+report_not_enum (location_t location, tree fndecl, unsigned int argno,
+ HOST_WIDE_INT actual, tree enumtype)
+{
+ error_at (location, "passing %wd to argument %d of %qE, which expects"
+ " a valid %qT value", actual, argno + 1, fndecl, enumtype);
+}
+
+/* Return a hash code for a function_instance. */
+hashval_t
+function_instance::hash () const
+{
+ inchash::hash h;
+ /* BASE uniquely determines BASE_NAME, so we don't need to hash both. */
+ h.add_ptr (base);
+ h.add_ptr (shape);
+ h.add_int (mode_suffix_id);
+ h.add_int (type_suffix_ids[0]);
+ h.add_int (type_suffix_ids[1]);
+ h.add_int (pred);
+ return h.end ();
+}
+
+/* Return a set of CP_* flags that describe what the function could do,
+ taking the command-line flags into account. */
+unsigned int
+function_instance::call_properties () const
+{
+ unsigned int flags = base->call_properties (*this);
+
+ /* -fno-trapping-math means that we can assume any FP exceptions
+ are not user-visible. */
+ if (!flag_trapping_math)
+ flags &= ~CP_RAISE_FP_EXCEPTIONS;
+
+ return flags;
+}
+
+/* Return true if calls to the function could read some form of
+ global state. */
+bool
+function_instance::reads_global_state_p () const
+{
+ unsigned int flags = call_properties ();
+
+ /* Preserve any dependence on rounding mode, flush to zero mode, etc.
+ There is currently no way of turning this off; in particular,
+ -fno-rounding-math (which is the default) means that we should make
+ the usual assumptions about rounding mode, which for intrinsics means
+ acting as the instructions do. */
+ if (flags & CP_READ_FPCR)
+ return true;
+
+ /* Handle direct reads of global state. */
+ return flags & (CP_READ_MEMORY | CP_READ_FFR);
+}
+
+/* Return true if calls to the function could modify some form of
+ global state. */
+bool
+function_instance::modifies_global_state_p () const
+{
+ unsigned int flags = call_properties ();
+
+ /* Preserve any exception state written back to the FPCR,
+ unless -fno-trapping-math says this is unnecessary. */
+ if (flags & CP_RAISE_FP_EXCEPTIONS)
+ return true;
+
+ /* Treat prefetches as modifying global state, since that's the
+ only means we have of keeping them in their correct position. */
+ if (flags & CP_PREFETCH_MEMORY)
+ return true;
+
+ /* Handle direct modifications of global state. */
+ return flags & (CP_WRITE_MEMORY | CP_WRITE_FFR);
+}
+
+/* Return true if calls to the function could raise a signal. */
+bool
+function_instance::could_trap_p () const
+{
+ unsigned int flags = call_properties ();
+
+ /* Handle functions that could raise SIGFPE. */
+ if (flags & CP_RAISE_FP_EXCEPTIONS)
+ return true;
+
+ /* Handle functions that could raise SIGBUS or SIGSEGV. */
+ if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY))
+ return true;
+
+ return false;
+}
+
+inline hashval_t
+registered_function_hasher::hash (value_type value)
+{
+ return value->instance.hash ();
+}
+
+inline bool
+registered_function_hasher::equal (value_type value, const compare_type &key)
+{
+ return value->instance == key;
+}
+
+sve_switcher::sve_switcher ()
+ : m_old_isa_flags (aarch64_isa_flags)
+{
+ /* Changing the ISA flags and have_regs_of_mode should be enough here.
+ We shouldn't need to pay the compile-time cost of a full target
+ switch. */
+ aarch64_isa_flags = (AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16
+ | AARCH64_FL_SVE);
+
+ memcpy (m_old_have_regs_of_mode, have_regs_of_mode,
+ sizeof (have_regs_of_mode));
+ for (int i = 0; i < NUM_MACHINE_MODES; ++i)
+ if (aarch64_sve_mode_p ((machine_mode) i))
+ have_regs_of_mode[i] = true;
+}
+
+sve_switcher::~sve_switcher ()
+{
+ memcpy (have_regs_of_mode, m_old_have_regs_of_mode,
+ sizeof (have_regs_of_mode));
+ aarch64_isa_flags = m_old_isa_flags;
+}
+
+function_builder::function_builder ()
+{
+ m_overload_type = build_function_type (void_type_node, void_list_node);
+ m_direct_overloads = lang_GNU_CXX ();
+ gcc_obstack_init (&m_string_obstack);
+}
+
+function_builder::~function_builder ()
+{
+ obstack_free (&m_string_obstack, NULL);
+}
+
+/* Add NAME to the end of the function name being built. */
+void
+function_builder::append_name (const char *name)
+{
+ obstack_grow (&m_string_obstack, name, strlen (name));
+}
+
+/* Zero-terminate and complete the function name being built. */
+char *
+function_builder::finish_name ()
+{
+ obstack_1grow (&m_string_obstack, 0);
+ return (char *) obstack_finish (&m_string_obstack);
+}
+
+/* Return the overloaded or full function name for INSTANCE; OVERLOADED_P
+ selects which. Allocate the string on m_string_obstack; the caller
+ must use obstack_free to free it after use. */
+char *
+function_builder::get_name (const function_instance &instance,
+ bool overloaded_p)
+{
+ append_name (instance.base_name);
+ if (overloaded_p)
+ switch (instance.displacement_units ())
+ {
+ case UNITS_none:
+ break;
+
+ case UNITS_bytes:
+ append_name ("_offset");
+ break;
+
+ case UNITS_elements:
+ append_name ("_index");
+ break;
+
+ case UNITS_vectors:
+ append_name ("_vnum");
+ break;
+ }
+ else
+ append_name (instance.mode_suffix ().string);
+ for (unsigned int i = 0; i < 2; ++i)
+ if (!overloaded_p || instance.shape->explicit_type_suffix_p (i))
+ append_name (instance.type_suffix (i).string);
+ append_name (pred_suffixes[instance.pred]);
+ return finish_name ();
+}
+
+/* Add attribute NAME to ATTRS. */
+static tree
+add_attribute (const char *name, tree attrs)
+{
+ return tree_cons (get_identifier (name), NULL_TREE, attrs);
+}
+
+/* Return the appropriate function attributes for INSTANCE. */
+tree
+function_builder::get_attributes (const function_instance &instance)
+{
+ tree attrs = NULL_TREE;
+
+ if (!instance.modifies_global_state_p ())
+ {
+ if (instance.reads_global_state_p ())
+ attrs = add_attribute ("pure", attrs);
+ else
+ attrs = add_attribute ("const", attrs);
+ }
+
+ if (!flag_non_call_exceptions || !instance.could_trap_p ())
+ attrs = add_attribute ("nothrow", attrs);
+
+ return add_attribute ("leaf", attrs);
+}
+
+/* Add a function called NAME with type FNTYPE and attributes ATTRS.
+ INSTANCE describes what the function does and OVERLOADED_P indicates
+ whether it is overloaded. REQUIRED_EXTENSIONS are the set of
+ architecture extensions that the function requires. */
+registered_function &
+function_builder::add_function (const function_instance &instance,
+ const char *name, tree fntype, tree attrs,
+ uint64_t required_extensions,
+ bool overloaded_p)
+{
+ unsigned int code = vec_safe_length (registered_functions);
+ code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_SVE;
+ tree decl = simulate_builtin_function_decl (input_location, name, fntype,
+ code, NULL, attrs);
+
+ registered_function &rfn = *ggc_alloc <registered_function> ();
+ rfn.instance = instance;
+ rfn.decl = decl;
+ rfn.required_extensions = required_extensions;
+ rfn.overloaded_p = overloaded_p;
+ vec_safe_push (registered_functions, &rfn);
+
+ return rfn;
+}
+
+/* Add a built-in function for INSTANCE, with the argument types given
+ by ARGUMENT_TYPES and the return type given by RETURN_TYPE.
+ REQUIRED_EXTENSIONS are the set of architecture extensions that the
+ function requires. FORCE_DIRECT_OVERLOADS is true if there is a
+ one-to-one mapping between "short" and "full" names, and if standard
+ overload resolution therefore isn't necessary. */
+void
+function_builder::add_unique_function (const function_instance &instance,
+ tree return_type,
+ vec<tree> &argument_types,
+ uint64_t required_extensions,
+ bool force_direct_overloads)
+{
+ /* Add the function under its full (unique) name. */
+ char *name = get_name (instance, false);
+ tree fntype = build_function_type_array (return_type,
+ argument_types.length (),
+ argument_types.address ());
+ tree attrs = get_attributes (instance);
+ registered_function &rfn = add_function (instance, name, fntype, attrs,
+ required_extensions, false);
+
+ /* Enter the function into the hash table. */
+ hashval_t hash = instance.hash ();
+ registered_function **rfn_slot
+ = function_table->find_slot_with_hash (instance, hash, INSERT);
+ gcc_assert (!*rfn_slot);
+ *rfn_slot = &rfn;
+
+ /* Also add the function under its overloaded alias, if we want
+ a separate decl for each instance of an overloaded function. */
+ if (m_direct_overloads || force_direct_overloads)
+ {
+ char *overload_name = get_name (instance, true);
+ if (strcmp (name, overload_name) != 0)
+ {
+ /* Attribute lists shouldn't be shared. */
+ tree attrs = get_attributes (instance);
+ add_function (instance, overload_name, fntype, attrs,
+ required_extensions, false);
+ }
+ }
+
+ obstack_free (&m_string_obstack, name);
+}
+
+/* Add one function decl for INSTANCE, to be used with manual overload
+ resolution. REQUIRED_EXTENSIONS are the set of architecture extensions
+ that the function requires.
+
+ For simplicity, deal with duplicate attempts to add the same
+ function. */
+void
+function_builder::add_overloaded_function (const function_instance &instance,
+ uint64_t required_extensions)
+{
+ char *name = get_name (instance, true);
+ if (registered_function **map_value = m_overload_names.get (name))
+ gcc_assert ((*map_value)->instance == instance
+ && (*map_value)->required_extensions == required_extensions);
+ else
+ {
+ registered_function &rfn
+ = add_function (instance, name, m_overload_type, NULL_TREE,
+ required_extensions, true);
+ const char *permanent_name = IDENTIFIER_POINTER (DECL_NAME (rfn.decl));
+ m_overload_names.put (permanent_name, &rfn);
+ }
+ obstack_free (&m_string_obstack, name);
+}
+
+/* If we are using manual overload resolution, add one function decl
+ for each overloaded function in GROUP. Take the function base name
+ from GROUP and the mode from MODE. */
+void
+function_builder::add_overloaded_functions (const function_group_info &group,
+ mode_suffix_index mode)
+{
+ if (m_direct_overloads)
+ return;
+
+ unsigned int explicit_type0 = (*group.shape)->explicit_type_suffix_p (0);
+ unsigned int explicit_type1 = (*group.shape)->explicit_type_suffix_p (1);
+ for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+ {
+ if (!explicit_type0 && !explicit_type1)
+ {
+ /* Deal with the common case in which there is one overloaded
+ function for all type combinations. */
+ function_instance instance (group.base_name, *group.base,
+ *group.shape, mode, types_none[0],
+ group.preds[pi]);
+ add_overloaded_function (instance, group.required_extensions);
+ }
+ else
+ for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
+ ++ti)
+ {
+ /* Stub out the types that are determined by overload
+ resolution. */
+ type_suffix_pair types = {
+ explicit_type0 ? group.types[ti][0] : NUM_TYPE_SUFFIXES,
+ explicit_type1 ? group.types[ti][1] : NUM_TYPE_SUFFIXES
+ };
+ function_instance instance (group.base_name, *group.base,
+ *group.shape, mode, types,
+ group.preds[pi]);
+ add_overloaded_function (instance, group.required_extensions);
+ }
+ }
+}
+
+/* Register all the functions in GROUP. */
+void
+function_builder::register_function_group (const function_group_info &group)
+{
+ (*group.shape)->build (*this, group);
+}
+
+function_call_info::function_call_info (location_t location_in,
+ const function_instance &instance_in,
+ tree fndecl_in)
+ : function_instance (instance_in), location (location_in), fndecl (fndecl_in)
+{
+}
+
+function_resolver::function_resolver (location_t location,
+ const function_instance &instance,
+ tree fndecl, vec<tree, va_gc> &arglist)
+ : function_call_info (location, instance, fndecl), m_arglist (arglist)
+{
+}
+
+/* Return the vector type associated with type suffix TYPE. */
+tree
+function_resolver::get_vector_type (type_suffix_index type)
+{
+ return acle_vector_types[0][type_suffixes[type].vector_type];
+}
+
+/* Return the <stdint.h> name associated with TYPE. Using the <stdint.h>
+ name should be more user-friendly than the underlying canonical type,
+ since it makes the signedness and bitwidth explicit. */
+const char *
+function_resolver::get_scalar_type_name (type_suffix_index type)
+{
+ return vector_types[type_suffixes[type].vector_type].acle_name + 2;
+}
+
+/* Return the type of argument I, or error_mark_node if it isn't
+ well-formed. */
+tree
+function_resolver::get_argument_type (unsigned int i)
+{
+ tree arg = m_arglist[i];
+ return arg == error_mark_node ? arg : TREE_TYPE (arg);
+}
+
+/* Return true if argument I is some form of scalar value. */
+bool
+function_resolver::scalar_argument_p (unsigned int i)
+{
+ tree type = get_argument_type (i);
+ return (INTEGRAL_TYPE_P (type)
+ /* Allow pointer types, leaving the frontend to warn where
+ necessary. */
+ || POINTER_TYPE_P (type)
+ || SCALAR_FLOAT_TYPE_P (type));
+}
+
+/* Report that the function has no form that takes type suffix TYPE.
+ Return error_mark_node. */
+tree
+function_resolver::report_no_such_form (type_suffix_index type)
+{
+ error_at (location, "%qE has no form that takes %qT arguments",
+ fndecl, get_vector_type (type));
+ return error_mark_node;
+}
+
+/* Silently check whether there is an instance of the function with the
+ mode suffix given by MODE and the type suffixes given by TYPE0 and TYPE1.
+ Return its function decl if so, otherwise return null. */
+tree
+function_resolver::lookup_form (mode_suffix_index mode,
+ type_suffix_index type0,
+ type_suffix_index type1)
+{
+ type_suffix_pair types = { type0, type1 };
+ function_instance instance (base_name, base, shape, mode, types, pred);
+ registered_function *rfn
+ = function_table->find_with_hash (instance, instance.hash ());
+ return rfn ? rfn->decl : NULL_TREE;
+}
+
+/* Resolve the function to one with the mode suffix given by MODE and the
+ type suffixes given by TYPE0 and TYPE1. Return its function decl on
+ success, otherwise report an error and return error_mark_node. */
+tree
+function_resolver::resolve_to (mode_suffix_index mode,
+ type_suffix_index type0,
+ type_suffix_index type1)
+{
+ tree res = lookup_form (mode, type0, type1);
+ if (!res)
+ {
+ if (type1 == NUM_TYPE_SUFFIXES)
+ return report_no_such_form (type0);
+ if (type0 == type_suffix_ids[0])
+ return report_no_such_form (type1);
+ /* To be filled in when we have other cases. */
+ gcc_unreachable ();
+ }
+ return res;
+}
+
+/* Require argument ARGNO to be a 32-bit or 64-bit scalar integer type.
+ Return the associated type suffix on success, otherwise report an
+ error and return NUM_TYPE_SUFFIXES. */
+type_suffix_index
+function_resolver::infer_integer_scalar_type (unsigned int argno)
+{
+ tree actual = get_argument_type (argno);
+ if (actual == error_mark_node)
+ return NUM_TYPE_SUFFIXES;
+
+ /* Allow enums and booleans to decay to integers, for compatibility
+ with C++ overloading rules. */
+ if (INTEGRAL_TYPE_P (actual))
+ {
+ bool uns_p = TYPE_UNSIGNED (actual);
+ /* Honor the usual integer promotions, so that resolution works
+ in the same way as for C++. */
+ if (TYPE_PRECISION (actual) < 32)
+ return TYPE_SUFFIX_s32;
+ if (TYPE_PRECISION (actual) == 32)
+ return uns_p ? TYPE_SUFFIX_u32 : TYPE_SUFFIX_s32;
+ if (TYPE_PRECISION (actual) == 64)
+ return uns_p ? TYPE_SUFFIX_u64 : TYPE_SUFFIX_s64;
+ }
+
+ error_at (location, "passing %qT to argument %d of %qE, which expects"
+ " a 32-bit or 64-bit integer type", actual, argno + 1, fndecl);
+ return NUM_TYPE_SUFFIXES;
+}
+
+/* Require argument ARGNO to be a pointer to a scalar type that has a
+ corresponding type suffix. Return that type suffix on success,
+ otherwise report an error and return NUM_TYPE_SUFFIXES.
+ GATHER_SCATTER_P is true if the function is a gather/scatter
+ operation, and so requires a pointer to 32-bit or 64-bit data. */
+type_suffix_index
+function_resolver::infer_pointer_type (unsigned int argno,
+ bool gather_scatter_p)
+{
+ tree actual = get_argument_type (argno);
+ if (actual == error_mark_node)
+ return NUM_TYPE_SUFFIXES;
+
+ if (TREE_CODE (actual) != POINTER_TYPE)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a pointer type", actual, argno + 1, fndecl);
+ if (VECTOR_TYPE_P (actual) && gather_scatter_p)
+ inform (location, "an explicit type suffix is needed"
+ " when using a vector of base addresses");
+ return NUM_TYPE_SUFFIXES;
+ }
+
+ tree target = TREE_TYPE (actual);
+ type_suffix_index type = find_type_suffix_for_scalar_type (target);
+ if (type == NUM_TYPE_SUFFIXES)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, but %qT is not"
+ " a valid SVE element type", actual, argno + 1, fndecl,
+ target);
+ return NUM_TYPE_SUFFIXES;
+ }
+ unsigned int bits = type_suffixes[type].element_bits;
+ if (gather_scatter_p && bits != 32 && bits != 64)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a pointer to 32-bit or 64-bit elements",
+ actual, argno + 1, fndecl);
+ return NUM_TYPE_SUFFIXES;
+ }
+
+ return type;
+}
+
+/* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS
+ vectors; NUM_VECTORS is 1 for the former. Return the associated type
+ suffix on success, using TYPE_SUFFIX_b for predicates. Report an error
+ and return NUM_TYPE_SUFFIXES on failure. */
+type_suffix_index
+function_resolver::infer_vector_or_tuple_type (unsigned int argno,
+ unsigned int num_vectors)
+{
+ tree actual = get_argument_type (argno);
+ if (actual == error_mark_node)
+ return NUM_TYPE_SUFFIXES;
+
+ /* A linear search should be OK here, since the code isn't hot and
+ the number of types is only small. */
+ for (unsigned int size_i = 0; size_i < MAX_TUPLE_SIZE; ++size_i)
+ for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+ {
+ vector_type_index type_i = type_suffixes[suffix_i].vector_type;
+ tree type = acle_vector_types[size_i][type_i];
+ if (type && TYPE_MAIN_VARIANT (actual) == TYPE_MAIN_VARIANT (type))
+ {
+ if (size_i + 1 == num_vectors)
+ return type_suffix_index (suffix_i);
+
+ if (num_vectors == 1)
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a single SVE vector rather than a tuple",
+ actual, argno + 1, fndecl);
+ else if (size_i == 0 && type_i != VECTOR_TYPE_svbool_t)
+ error_at (location, "passing single vector %qT to argument %d"
+ " of %qE, which expects a tuple of %d vectors",
+ actual, argno + 1, fndecl, num_vectors);
+ else
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a tuple of %d vectors", actual, argno + 1,
+ fndecl, num_vectors);
+ return NUM_TYPE_SUFFIXES;
+ }
+ }
+
+ if (num_vectors == 1)
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects an SVE vector type", actual, argno + 1, fndecl);
+ else
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects an SVE tuple type", actual, argno + 1, fndecl);
+ return NUM_TYPE_SUFFIXES;
+}
+
+/* Require argument ARGNO to have some form of vector type. Return the
+ associated type suffix on success, using TYPE_SUFFIX_b for predicates.
+ Report an error and return NUM_TYPE_SUFFIXES on failure. */
+type_suffix_index
+function_resolver::infer_vector_type (unsigned int argno)
+{
+ return infer_vector_or_tuple_type (argno, 1);
+}
+
+/* Like infer_vector_type, but also require the type to be integral. */
+type_suffix_index
+function_resolver::infer_integer_vector_type (unsigned int argno)
+{
+ type_suffix_index type = infer_vector_type (argno);
+ if (type == NUM_TYPE_SUFFIXES)
+ return type;
+
+ if (!type_suffixes[type].integer_p)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of integers", get_argument_type (argno),
+ argno + 1, fndecl);
+ return NUM_TYPE_SUFFIXES;
+ }
+
+ return type;
+}
+
+/* Like infer_vector_type, but also require the type to be an unsigned
+ integer. */
+type_suffix_index
+function_resolver::infer_unsigned_vector_type (unsigned int argno)
+{
+ type_suffix_index type = infer_vector_type (argno);
+ if (type == NUM_TYPE_SUFFIXES)
+ return type;
+
+ if (!type_suffixes[type].unsigned_p)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of unsigned integers",
+ get_argument_type (argno), argno + 1, fndecl);
+ return NUM_TYPE_SUFFIXES;
+ }
+
+ return type;
+}
+
+/* Like infer_vector_type, but also require the element size to be
+ 32 or 64 bits. */
+type_suffix_index
+function_resolver::infer_sd_vector_type (unsigned int argno)
+{
+ type_suffix_index type = infer_vector_type (argno);
+ if (type == NUM_TYPE_SUFFIXES)
+ return type;
+
+ unsigned int bits = type_suffixes[type].element_bits;
+ if (bits != 32 && bits != 64)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of 32-bit or 64-bit elements",
+ get_argument_type (argno), argno + 1, fndecl);
+ return NUM_TYPE_SUFFIXES;
+ }
+
+ return type;
+}
+
+/* If the function operates on tuples of vectors, require argument ARGNO to be
+ a tuple with the appropriate number of vectors, otherwise require it to be
+ a single vector. Return the associated type suffix on success, using
+ TYPE_SUFFIX_b for predicates. Report an error and return NUM_TYPE_SUFFIXES
+ on failure. */
+type_suffix_index
+function_resolver::infer_tuple_type (unsigned int argno)
+{
+ return infer_vector_or_tuple_type (argno, vectors_per_tuple ());
+}
+
+/* Require argument ARGNO to be a vector or scalar argument. Return true
+ if it is, otherwise report an appropriate error. */
+bool
+function_resolver::require_vector_or_scalar_type (unsigned int argno)
+{
+ tree actual = get_argument_type (argno);
+ if (actual == error_mark_node)
+ return false;
+
+ if (!scalar_argument_p (argno) && !VECTOR_TYPE_P (actual))
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector or scalar type", actual, argno + 1, fndecl);
+ return false;
+ }
+
+ return true;
+}
+
+/* Require argument ARGNO to have vector type TYPE, in cases where this
+ requirement holds for all uses of the function. Return true if the
+ argument has the right form, otherwise report an appropriate error. */
+bool
+function_resolver::require_vector_type (unsigned int argno,
+ vector_type_index type)
+{
+ tree expected = acle_vector_types[0][type];
+ tree actual = get_argument_type (argno);
+ if (actual != error_mark_node
+ && TYPE_MAIN_VARIANT (expected) != TYPE_MAIN_VARIANT (actual))
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects %qT", actual, argno + 1, fndecl, expected);
+ return false;
+ }
+ return true;
+}
+
+/* Like require_vector_type, but TYPE is inferred from previous arguments
+ rather than being a fixed part of the function signature. This changes
+ the nature of the error messages. */
+bool
+function_resolver::require_matching_vector_type (unsigned int argno,
+ type_suffix_index type)
+{
+ type_suffix_index new_type = infer_vector_type (argno);
+ if (new_type == NUM_TYPE_SUFFIXES)
+ return false;
+
+ if (type != new_type)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, but"
+ " previous arguments had type %qT",
+ get_vector_type (new_type), argno + 1, fndecl,
+ get_vector_type (type));
+ return false;
+ }
+ return true;
+}
+
+/* Require argument ARGNO to be a vector type with the following properties:
+
+ - the type class must be the same as FIRST_TYPE's if EXPECTED_TCLASS
+ is SAME_TYPE_CLASS, otherwise it must be EXPECTED_TCLASS itself.
+
+ - the element size must be:
+
+ - the same as FIRST_TYPE's if EXPECTED_BITS == SAME_SIZE
+ - half of FIRST_TYPE's if EXPECTED_BITS == HALF_SIZE
+ - a quarter of FIRST_TYPE's if EXPECTED_BITS == QUARTER_SIZE
+ - EXPECTED_BITS itself otherwise
+
+ Return true if the argument has the required type, otherwise report
+ an appropriate error.
+
+ FIRST_ARGNO is the first argument that is known to have type FIRST_TYPE.
+ Usually it comes before ARGNO, but sometimes it is more natural to resolve
+ arguments out of order.
+
+ If the required properties depend on FIRST_TYPE then both FIRST_ARGNO and
+ ARGNO contribute to the resolution process. If the required properties
+ are fixed, only FIRST_ARGNO contributes to the resolution process.
+
+ This function is a bit of a Swiss army knife. The complication comes
+ from trying to give good error messages when FIRST_ARGNO and ARGNO are
+ inconsistent, since either of them might be wrong. */
+bool function_resolver::
+require_derived_vector_type (unsigned int argno,
+ unsigned int first_argno,
+ type_suffix_index first_type,
+ type_class_index expected_tclass,
+ unsigned int expected_bits)
+{
+ /* If the type needs to match FIRST_ARGNO exactly, use the preferred
+ error message for that case. The VECTOR_TYPE_P test excludes tuple
+ types, which we handle below instead. */
+ bool both_vectors_p = VECTOR_TYPE_P (get_argument_type (first_argno));
+ if (both_vectors_p
+ && expected_tclass == SAME_TYPE_CLASS
+ && expected_bits == SAME_SIZE)
+ {
+ /* There's no need to resolve this case out of order. */
+ gcc_assert (argno > first_argno);
+ return require_matching_vector_type (argno, first_type);
+ }
+
+ /* Use FIRST_TYPE to get the expected type class and element size. */
+ type_class_index orig_expected_tclass = expected_tclass;
+ if (expected_tclass == NUM_TYPE_CLASSES)
+ expected_tclass = type_suffixes[first_type].tclass;
+
+ unsigned int orig_expected_bits = expected_bits;
+ if (expected_bits == SAME_SIZE)
+ expected_bits = type_suffixes[first_type].element_bits;
+ else if (expected_bits == HALF_SIZE)
+ expected_bits = type_suffixes[first_type].element_bits / 2;
+ else if (expected_bits == QUARTER_SIZE)
+ expected_bits = type_suffixes[first_type].element_bits / 4;
+
+ /* If the expected type doesn't depend on FIRST_TYPE at all,
+ just check for the fixed choice of vector type. */
+ if (expected_tclass == orig_expected_tclass
+ && expected_bits == orig_expected_bits)
+ {
+ const type_suffix_info &expected_suffix
+ = type_suffixes[find_type_suffix (expected_tclass, expected_bits)];
+ return require_vector_type (argno, expected_suffix.vector_type);
+ }
+
+ /* Require the argument to be some form of SVE vector type,
+ without being specific about the type of vector we want. */
+ type_suffix_index actual_type = infer_vector_type (argno);
+ if (actual_type == NUM_TYPE_SUFFIXES)
+ return false;
+
+ /* Exit now if we got the right type. */
+ bool tclass_ok_p = (type_suffixes[actual_type].tclass == expected_tclass);
+ bool size_ok_p = (type_suffixes[actual_type].element_bits == expected_bits);
+ if (tclass_ok_p && size_ok_p)
+ return true;
+
+ /* First look for cases in which the actual type contravenes a fixed
+ size requirement, without having to refer to FIRST_TYPE. */
+ if (!size_ok_p && expected_bits == orig_expected_bits)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of %d-bit elements",
+ get_vector_type (actual_type), argno + 1, fndecl,
+ expected_bits);
+ return false;
+ }
+
+ /* Likewise for a fixed type class requirement. This is only ever
+ needed for signed and unsigned types, so don't create unnecessary
+ translation work for other type classes. */
+ if (!tclass_ok_p && orig_expected_tclass == TYPE_signed)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of signed integers",
+ get_vector_type (actual_type), argno + 1, fndecl);
+ return false;
+ }
+ if (!tclass_ok_p && orig_expected_tclass == TYPE_unsigned)
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of unsigned integers",
+ get_vector_type (actual_type), argno + 1, fndecl);
+ return false;
+ }
+
+ /* Make sure that FIRST_TYPE itself is sensible before using it
+ as a basis for an error message. */
+ if (resolve_to (mode_suffix_id, first_type) == error_mark_node)
+ return false;
+
+ /* If the arguments have consistent type classes, but a link between
+ the sizes has been broken, try to describe the error in those terms. */
+ if (both_vectors_p && tclass_ok_p && orig_expected_bits == SAME_SIZE)
+ {
+ if (argno < first_argno)
+ {
+ std::swap (argno, first_argno);
+ std::swap (actual_type, first_type);
+ }
+ error_at (location, "arguments %d and %d of %qE must have the"
+ " same element size, but the values passed here have type"
+ " %qT and %qT respectively", first_argno + 1, argno + 1,
+ fndecl, get_vector_type (first_type),
+ get_vector_type (actual_type));
+ return false;
+ }
+
+ /* Likewise in reverse: look for cases in which the sizes are consistent
+ but a link between the type classes has been broken. */
+ if (both_vectors_p
+ && size_ok_p
+ && orig_expected_tclass == SAME_TYPE_CLASS
+ && type_suffixes[first_type].integer_p
+ && type_suffixes[actual_type].integer_p)
+ {
+ if (argno < first_argno)
+ {
+ std::swap (argno, first_argno);
+ std::swap (actual_type, first_type);
+ }
+ error_at (location, "arguments %d and %d of %qE must have the"
+ " same signedness, but the values passed here have type"
+ " %qT and %qT respectively", first_argno + 1, argno + 1,
+ fndecl, get_vector_type (first_type),
+ get_vector_type (actual_type));
+ return false;
+ }
+
+ /* The two arguments are wildly inconsistent. */
+ type_suffix_index expected_type
+ = find_type_suffix (expected_tclass, expected_bits);
+ error_at (location, "passing %qT instead of the expected %qT to argument"
+ " %d of %qE, after passing %qT to argument %d",
+ get_vector_type (actual_type), get_vector_type (expected_type),
+ argno + 1, fndecl, get_argument_type (first_argno),
+ first_argno + 1);
+ return false;
+}
+
+/* Require argument ARGNO to be a (possibly variable) scalar, using EXPECTED
+ as the name of its expected type. Return true if the argument has the
+ right form, otherwise report an appropriate error. */
+bool
+function_resolver::require_scalar_type (unsigned int argno,
+ const char *expected)
+{
+ if (!scalar_argument_p (argno))
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects %qs", get_argument_type (argno), argno + 1,
+ fndecl, expected);
+ return false;
+ }
+ return true;
+}
+
+/* Require argument ARGNO to be some form of pointer, without being specific
+ about its target type. Return true if the argument has the right form,
+ otherwise report an appropriate error. */
+bool
+function_resolver::require_pointer_type (unsigned int argno)
+{
+ if (!scalar_argument_p (argno))
+ {
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a scalar pointer", get_argument_type (argno),
+ argno + 1, fndecl);
+ return false;
+ }
+ return true;
+}
+
+/* Argument FIRST_ARGNO is a scalar with type EXPECTED_TYPE, and argument
+ ARGNO should be consistent with it. Return true if it is, otherwise
+ report an appropriate error. */
+bool function_resolver::
+require_matching_integer_scalar_type (unsigned int argno,
+ unsigned int first_argno,
+ type_suffix_index expected_type)
+{
+ type_suffix_index actual_type = infer_integer_scalar_type (argno);
+ if (actual_type == NUM_TYPE_SUFFIXES)
+ return false;
+
+ if (actual_type == expected_type)
+ return true;
+
+ error_at (location, "call to %qE is ambiguous; argument %d has type"
+ " %qs but argument %d has type %qs", fndecl,
+ first_argno + 1, get_scalar_type_name (expected_type),
+ argno + 1, get_scalar_type_name (actual_type));
+ return false;
+}
+
+/* Require argument ARGNO to be a (possibly variable) scalar, expecting it
+ to have the following properties:
+
+ - the type class must be the same as for type suffix 0 if EXPECTED_TCLASS
+ is SAME_TYPE_CLASS, otherwise it must be EXPECTED_TCLASS itself.
+
+ - the element size must be the same as for type suffix 0 if EXPECTED_BITS
+ is SAME_TYPE_SIZE, otherwise it must be EXPECTED_BITS itself.
+
+ Return true if the argument is valid, otherwise report an appropriate error.
+
+ Note that we don't check whether the scalar type actually has the required
+ properties, since that's subject to implicit promotions and conversions.
+ Instead we just use the expected properties to tune the error message. */
+bool function_resolver::
+require_derived_scalar_type (unsigned int argno,
+ type_class_index expected_tclass,
+ unsigned int expected_bits)
+{
+ gcc_assert (expected_tclass == SAME_TYPE_CLASS
+ || expected_tclass == TYPE_signed
+ || expected_tclass == TYPE_unsigned);
+
+ /* If the expected type doesn't depend on the type suffix at all,
+ just check for the fixed choice of scalar type. */
+ if (expected_tclass != SAME_TYPE_CLASS && expected_bits != SAME_SIZE)
+ {
+ type_suffix_index expected_type
+ = find_type_suffix (expected_tclass, expected_bits);
+ return require_scalar_type (argno, get_scalar_type_name (expected_type));
+ }
+
+ if (scalar_argument_p (argno))
+ return true;
+
+ if (expected_tclass == SAME_TYPE_CLASS)
+ /* It doesn't really matter whether the element is expected to be
+ the same size as type suffix 0. */
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a scalar element", get_argument_type (argno),
+ argno + 1, fndecl);
+ else
+ /* It doesn't seem useful to distinguish between signed and unsigned
+ scalars here. */
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a scalar integer", get_argument_type (argno),
+ argno + 1, fndecl);
+ return false;
+}
+
+/* Require argument ARGNO to be suitable for an integer constant expression.
+ Return true if it is, otherwise report an appropriate error.
+
+ function_checker checks whether the argument is actually constant and
+ has a suitable range. The reason for distinguishing immediate arguments
+ here is because it provides more consistent error messages than
+ require_scalar_type would. */
+bool
+function_resolver::require_integer_immediate (unsigned int argno)
+{
+ if (!scalar_argument_p (argno))
+ {
+ report_non_ice (location, fndecl, argno);
+ return false;
+ }
+ return true;
+}
+
+/* Require argument ARGNO to be a vector base in a gather-style address.
+ Return its type on success, otherwise return NUM_VECTOR_TYPES. */
+vector_type_index
+function_resolver::infer_vector_base_type (unsigned int argno)
+{
+ type_suffix_index type = infer_vector_type (argno);
+ if (type == NUM_TYPE_SUFFIXES)
+ return NUM_VECTOR_TYPES;
+
+ if (type == TYPE_SUFFIX_u32 || type == TYPE_SUFFIX_u64)
+ return type_suffixes[type].vector_type;
+
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects %qs or %qs", get_argument_type (argno),
+ argno + 1, fndecl, "svuint32_t", "svuint64_t");
+ return NUM_VECTOR_TYPES;
+}
+
+/* Require argument ARGNO to be a vector displacement in a gather-style
+ address. Return its type on success, otherwise return NUM_VECTOR_TYPES. */
+vector_type_index
+function_resolver::infer_vector_displacement_type (unsigned int argno)
+{
+ type_suffix_index type = infer_integer_vector_type (argno);
+ if (type == NUM_TYPE_SUFFIXES)
+ return NUM_VECTOR_TYPES;
+
+ if (type_suffixes[type].integer_p
+ && (type_suffixes[type].element_bits == 32
+ || type_suffixes[type].element_bits == 64))
+ return type_suffixes[type].vector_type;
+
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of 32-bit or 64-bit integers",
+ get_argument_type (argno), argno + 1, fndecl);
+ return NUM_VECTOR_TYPES;
+}
+
+/* Require argument ARGNO to be a vector displacement in a gather-style
+ address. There are three possible uses:
+
+ - for loading into elements of type TYPE (when LOAD_P is true)
+ - for storing from elements of type TYPE (when LOAD_P is false)
+ - for prefetching data (when TYPE is NUM_TYPE_SUFFIXES)
+
+ The overloaded function's mode suffix determines the units of the
+ displacement (bytes for "_offset", elements for "_index").
+
+ Return the associated mode on success, otherwise report an error
+ and return MODE_none. */
+mode_suffix_index
+function_resolver::resolve_sv_displacement (unsigned int argno,
+ type_suffix_index type,
+ bool load_p)
+{
+ if (type == NUM_TYPE_SUFFIXES)
+ {
+ /* For prefetches, the base is a void pointer and the displacement
+ can be any valid offset or index type. */
+ vector_type_index displacement_vector_type
+ = infer_vector_displacement_type (argno);
+ if (displacement_vector_type == NUM_VECTOR_TYPES)
+ return MODE_none;
+
+ mode_suffix_index mode = find_mode_suffix (NUM_VECTOR_TYPES,
+ displacement_vector_type,
+ displacement_units ());
+ gcc_assert (mode != MODE_none);
+ return mode;
+ }
+
+ /* Check for some form of vector type, without naming any in particular
+ as being expected. */
+ type_suffix_index displacement_type = infer_vector_type (argno);
+ if (displacement_type == NUM_TYPE_SUFFIXES)
+ return MODE_none;
+
+ /* If the displacement type is consistent with the data vector type,
+ try to find the associated mode suffix. This will fall through
+ for non-integral displacement types. */
+ unsigned int required_bits = type_suffixes[type].element_bits;
+ if (type_suffixes[displacement_type].element_bits == required_bits)
+ {
+ vector_type_index displacement_vector_type
+ = type_suffixes[displacement_type].vector_type;
+ mode_suffix_index mode = find_mode_suffix (NUM_VECTOR_TYPES,
+ displacement_vector_type,
+ displacement_units ());
+ if (mode != MODE_none)
+ return mode;
+ }
+
+ if (type_suffix_ids[0] == NUM_TYPE_SUFFIXES)
+ {
+ /* TYPE has been inferred rather than specified by the user,
+ so mention it in the error messages. */
+ if (load_p)
+ error_at (location, "passing %qT to argument %d of %qE, which when"
+ " loading %qT expects a vector of %d-bit integers",
+ get_argument_type (argno), argno + 1, fndecl,
+ get_vector_type (type), required_bits);
+ else
+ error_at (location, "passing %qT to argument %d of %qE, which when"
+ " storing %qT expects a vector of %d-bit integers",
+ get_argument_type (argno), argno + 1, fndecl,
+ get_vector_type (type), required_bits);
+ }
+ else
+ /* TYPE is part of the function name. */
+ error_at (location, "passing %qT to argument %d of %qE, which"
+ " expects a vector of %d-bit integers",
+ get_argument_type (argno), argno + 1, fndecl, required_bits);
+ return MODE_none;
+}
+
+/* Require the arguments starting at ARGNO to form a gather-style address.
+ There are three possible uses:
+
+ - for loading into elements of type TYPE (when LOAD_P is true)
+ - for storing from elements of type TYPE (when LOAD_P is false)
+ - for prefetching data (when TYPE is NUM_TYPE_SUFFIXES)
+
+ The three possible addresses are:
+
+ - a vector base with no displacement
+ - a vector base and a scalar displacement
+ - a scalar (pointer) base and a vector displacement
+
+ The overloaded function's mode suffix determines whether there is
+ a displacement, and if so, what units it uses:
+
+ - MODE_none: no displacement
+ - MODE_offset: the displacement is measured in bytes
+ - MODE_index: the displacement is measured in elements
+
+ Return the mode of the non-overloaded function on success, otherwise
+ report an error and return MODE_none. */
+mode_suffix_index
+function_resolver::resolve_gather_address (unsigned int argno,
+ type_suffix_index type,
+ bool load_p)
+{
+ tree actual = get_argument_type (argno);
+ if (actual == error_mark_node)
+ return MODE_none;
+
+ if (displacement_units () != UNITS_none)
+ {
+ /* Some form of displacement is needed. First handle a scalar
+ pointer base and a vector displacement. */
+ if (scalar_argument_p (argno))
+ /* Don't check the pointer type here, since there's only one valid
+ choice. Leave that to the frontend. */
+ return resolve_sv_displacement (argno + 1, type, load_p);
+
+ if (!VECTOR_TYPE_P (actual))
+ {
+ error_at (location, "passing %qT to argument %d of %qE,"
+ " which expects a vector or pointer base address",
+ actual, argno + 1, fndecl);
+ return MODE_none;
+ }
+ }
+
+ /* Check for the correct choice of vector base type. */
+ vector_type_index base_vector_type;
+ if (type == NUM_TYPE_SUFFIXES)
+ {
+ /* Since prefetches have no type suffix, there is a free choice
+ between 32-bit and 64-bit base addresses. */
+ base_vector_type = infer_vector_base_type (argno);
+ if (base_vector_type == NUM_VECTOR_TYPES)
+ return MODE_none;
+ }
+ else
+ {
+ /* Check for some form of vector type, without saying which type
+ we expect. */
+ type_suffix_index base_type = infer_vector_type (argno);
+ if (base_type == NUM_TYPE_SUFFIXES)
+ return MODE_none;
+
+ /* Check whether the type is the right one. */
+ unsigned int required_bits = type_suffixes[type].element_bits;
+ gcc_assert (required_bits == 32 || required_bits == 64);
+ type_suffix_index required_type = (required_bits == 32
+ ? TYPE_SUFFIX_u32
+ : TYPE_SUFFIX_u64);
+ if (required_type != base_type)
+ {
+ error_at (location, "passing %qT to argument %d of %qE,"
+ " which expects %qT", actual, argno + 1, fndecl,
+ get_vector_type (required_type));
+ return MODE_none;
+ }
+ base_vector_type = type_suffixes[base_type].vector_type;
+ }
+
+ /* Check the scalar displacement, if any. */
+ if (displacement_units () != UNITS_none
+ && !require_scalar_type (argno + 1, "int64_t"))
+ return MODE_none;
+
+ /* Find the appropriate mode suffix. The checks above should have
+ weeded out all erroneous cases. */
+ for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
+ {
+ const mode_suffix_info &mode = mode_suffixes[mode_i];
+ if (mode.base_vector_type == base_vector_type
+ && mode.displacement_vector_type == NUM_VECTOR_TYPES
+ && mode.displacement_units == displacement_units ())
+ return mode_suffix_index (mode_i);
+ }
+
+ gcc_unreachable ();
+}
+
+/* Require arguments ARGNO and ARGNO + 1 to form an ADR-style address,
+ i.e. one with a vector of base addresses and a vector of displacements.
+ The overloaded function's mode suffix determines the units of the
+ displacement (bytes for "_offset", elements for "_index").
+
+ Return the associated mode suffix on success, otherwise report
+ an error and return MODE_none. */
+mode_suffix_index
+function_resolver::resolve_adr_address (unsigned int argno)
+{
+ vector_type_index base_type = infer_vector_base_type (argno);
+ if (base_type == NUM_VECTOR_TYPES)
+ return MODE_none;
+
+ vector_type_index displacement_type
+ = infer_vector_displacement_type (argno + 1);
+ if (displacement_type == NUM_VECTOR_TYPES)
+ return MODE_none;
+
+ mode_suffix_index mode = find_mode_suffix (base_type, displacement_type,
+ displacement_units ());
+ if (mode == MODE_none)
+ {
+ if (mode_suffix_id == MODE_offset)
+ error_at (location, "cannot combine a base of type %qT with"
+ " an offset of type %qT",
+ get_argument_type (argno), get_argument_type (argno + 1));
+ else
+ error_at (location, "cannot combine a base of type %qT with"
+ " an index of type %qT",
+ get_argument_type (argno), get_argument_type (argno + 1));
+ }
+ return mode;
+}
+
+/* Require the function to have exactly EXPECTED arguments. Return true
+ if it does, otherwise report an appropriate error. */
+bool
+function_resolver::check_num_arguments (unsigned int expected)
+{
+ if (m_arglist.length () < expected)
+ error_at (location, "too few arguments to function %qE", fndecl);
+ else if (m_arglist.length () > expected)
+ error_at (location, "too many arguments to function %qE", fndecl);
+ return m_arglist.length () == expected;
+}
+
+/* If the function is predicated, check that the first argument is a
+ suitable governing predicate. Also check that there are NOPS further
+ arguments after any governing predicate, but don't check what they are.
+
+ Return true on success, otherwise report a suitable error.
+ When returning true:
+
+ - set I to the number of the first unchecked argument.
+ - set NARGS to the total number of arguments. */
+bool
+function_resolver::check_gp_argument (unsigned int nops,
+ unsigned int &i, unsigned int &nargs)
+{
+ i = 0;
+ if (pred != PRED_none)
+ {
+ /* Unary merge operations should use resolve_unary instead. */
+ gcc_assert (nops != 1 || pred != PRED_m);
+ nargs = nops + 1;
+ if (!check_num_arguments (nargs)
+ || !require_vector_type (i, VECTOR_TYPE_svbool_t))
+ return false;
+ i += 1;
+ }
+ else
+ {
+ nargs = nops;
+ if (!check_num_arguments (nargs))
+ return false;
+ }
+
+ return true;
+}
+
+/* Finish resolving a function whose final argument can be a vector
+ or a scalar, with the function having an implicit "_n" suffix
+ in the latter case. This "_n" form might only exist for certain
+ type suffixes.
+
+ ARGNO is the index of the final argument. The inferred type
+ suffix is FIRST_TYPE, which was obtained from argument FIRST_ARGNO.
+ EXPECTED_TCLASS and EXPECTED_BITS describe the expected properties
+ of the final vector or scalar argument, in the same way as for
+ require_derived_vector_type.
+
+ Return the function decl of the resolved function on success,
+ otherwise report a suitable error and return error_mark_node. */
+tree function_resolver::
+finish_opt_n_resolution (unsigned int argno, unsigned int first_argno,
+ type_suffix_index first_type,
+ type_class_index expected_tclass,
+ unsigned int expected_bits)
+{
+ tree scalar_form = lookup_form (MODE_n, first_type);
+
+ /* Allow the final argument to be scalar, if an _n form exists. */
+ if (scalar_argument_p (argno))
+ {
+ if (scalar_form)
+ return scalar_form;
+
+ /* Check the vector form normally. If that succeeds, raise an
+ error about having no corresponding _n form. */
+ tree res = resolve_to (mode_suffix_id, first_type);
+ if (res != error_mark_node)
+ error_at (location, "passing %qT to argument %d of %qE, but its"
+ " %qT form does not accept scalars",
+ get_argument_type (argno), argno + 1, fndecl,
+ get_vector_type (first_type));
+ return error_mark_node;
+ }
+
+ /* If an _n form does exist, provide a more accurate message than
+ require_derived_vector_type would for arguments that are neither
+ vectors nor scalars. */
+ if (scalar_form && !require_vector_or_scalar_type (argno))
+ return error_mark_node;
+
+ /* Check for the correct vector type. */
+ if (!require_derived_vector_type (argno, first_argno, first_type,
+ expected_tclass, expected_bits))
+ return error_mark_node;
+
+ return resolve_to (mode_suffix_id, first_type);
+}
+
+/* Resolve a (possibly predicated) unary function. If the function uses
+ merge predication, there is an extra vector argument before the
+ governing predicate that specifies the values of inactive elements.
+ This argument has the following properties:
+
+ - the type class must be the same as for active elements if MERGE_TCLASS
+ is SAME_TYPE_CLASS, otherwise it must be MERGE_TCLASS itself.
+
+ - the element size must be the same as for active elements if MERGE_BITS
+ is SAME_TYPE_SIZE, otherwise it must be MERGE_BITS itself.
+
+ Return the function decl of the resolved function on success,
+ otherwise report a suitable error and return error_mark_node. */
+tree
+function_resolver::resolve_unary (type_class_index merge_tclass,
+ unsigned int merge_bits)
+{
+ type_suffix_index type;
+ if (pred == PRED_m)
+ {
+ if (!check_num_arguments (3))
+ return error_mark_node;
+ if (merge_tclass == SAME_TYPE_CLASS && merge_bits == SAME_SIZE)
+ {
+ /* The inactive elements are the same as the active elements,
+ so we can use normal left-to-right resolution. */
+ if ((type = infer_vector_type (0)) == NUM_TYPE_SUFFIXES
+ || !require_vector_type (1, VECTOR_TYPE_svbool_t)
+ || !require_matching_vector_type (2, type))
+ return error_mark_node;
+ }
+ else
+ {
+ /* The inactive element type is a function of the active one,
+ so resolve the active one first. */
+ if (!require_vector_type (1, VECTOR_TYPE_svbool_t)
+ || (type = infer_vector_type (2)) == NUM_TYPE_SUFFIXES
+ || !require_derived_vector_type (0, 2, type, merge_tclass,
+ merge_bits))
+ return error_mark_node;
+ }
+ }
+ else
+ {
+ /* We just need to check the predicate (if any) and the single
+ vector argument. */
+ unsigned int i, nargs;
+ if (!check_gp_argument (1, i, nargs)
+ || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+ }
+
+ /* Handle convert-like functions in which the first type suffix is
+ explicit. */
+ if (type_suffix_ids[0] != NUM_TYPE_SUFFIXES)
+ return resolve_to (mode_suffix_id, type_suffix_ids[0], type);
+
+ return resolve_to (mode_suffix_id, type);
+}
+
+/* Resolve a (possibly predicated) function that takes NOPS like-typed
+ vector arguments followed by NIMM integer immediates. Return the
+ function decl of the resolved function on success, otherwise report
+ a suitable error and return error_mark_node. */
+tree
+function_resolver::resolve_uniform (unsigned int nops, unsigned int nimm)
+{
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!check_gp_argument (nops + nimm, i, nargs)
+ || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ i += 1;
+ for (; i < nargs - nimm; ++i)
+ if (!require_matching_vector_type (i, type))
+ return error_mark_node;
+
+ for (; i < nargs; ++i)
+ if (!require_integer_immediate (i))
+ return error_mark_node;
+
+ return resolve_to (mode_suffix_id, type);
+}
+
+/* Resolve a (possibly predicated) function that offers a choice between
+ taking:
+
+ - NOPS like-typed vector arguments or
+ - NOPS - 1 like-typed vector arguments followed by a scalar argument
+
+ Return the function decl of the resolved function on success,
+ otherwise report a suitable error and return error_mark_node. */
+tree
+function_resolver::resolve_uniform_opt_n (unsigned int nops)
+{
+ unsigned int i, nargs;
+ type_suffix_index type;
+ if (!check_gp_argument (nops, i, nargs)
+ || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+ return error_mark_node;
+
+ unsigned int first_arg = i++;
+ for (; i < nargs - 1; ++i)
+ if (!require_matching_vector_type (i, type))
+ return error_mark_node;
+
+ return finish_opt_n_resolution (i, first_arg, type);
+}
+
+/* If the call is erroneous, report an appropriate error and return
+ error_mark_node. Otherwise, if the function is overloaded, return
+ the decl of the non-overloaded function. Return NULL_TREE otherwise,
+ indicating that the call should be processed in the normal way. */
+tree
+function_resolver::resolve ()
+{
+ return shape->resolve (*this);
+}
+
+function_checker::function_checker (location_t location,
+ const function_instance &instance,
+ tree fndecl, tree fntype,
+ unsigned int nargs, tree *args)
+ : function_call_info (location, instance, fndecl),
+ m_fntype (fntype), m_nargs (nargs), m_args (args),
+ /* We don't have to worry about unary _m operations here, since they
+ never have arguments that need checking. */
+ m_base_arg (pred != PRED_none ? 1 : 0)
+{
+}
+
+/* Return true if argument ARGNO exists. which it might not for
+ erroneous calls. It is safe to wave through checks if this
+ function returns false. */
+bool
+function_checker::argument_exists_p (unsigned int argno)
+{
+ gcc_assert (argno < (unsigned int) type_num_arguments (m_fntype));
+ return argno < m_nargs;
+}
+
+/* Check that argument ARGNO is an integer constant expression and
+ store its value in VALUE_OUT if so. The caller should first
+ check that argument ARGNO exists. */
+bool
+function_checker::require_immediate (unsigned int argno,
+ HOST_WIDE_INT &value_out)
+{
+ gcc_assert (argno < m_nargs);
+ tree arg = m_args[argno];
+
+ /* The type and range are unsigned, so read the argument as an
+ unsigned rather than signed HWI. */
+ if (!tree_fits_uhwi_p (arg))
+ {
+ report_non_ice (location, fndecl, argno);
+ return false;
+ }
+
+ /* ...but treat VALUE_OUT as signed for error reporting, since printing
+ -1 is more user-friendly than the maximum uint64_t value. */
+ value_out = tree_to_uhwi (arg);
+ return true;
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression that
+ has the value VALUE0 or VALUE1. REL_ARGNO counts from the end of the
+ predication arguments. */
+bool
+function_checker::require_immediate_either_or (unsigned int rel_argno,
+ HOST_WIDE_INT value0,
+ HOST_WIDE_INT value1)
+{
+ unsigned int argno = m_base_arg + rel_argno;
+ if (!argument_exists_p (argno))
+ return true;
+
+ HOST_WIDE_INT actual;
+ if (!require_immediate (argno, actual))
+ return false;
+
+ if (actual != value0 && actual != value1)
+ {
+ report_neither_nor (location, fndecl, argno, actual, 90, 270);
+ return false;
+ }
+
+ return true;
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression that has
+ a valid value for enumeration type TYPE. REL_ARGNO counts from the end
+ of the predication arguments. */
+bool
+function_checker::require_immediate_enum (unsigned int rel_argno, tree type)
+{
+ unsigned int argno = m_base_arg + rel_argno;
+ if (!argument_exists_p (argno))
+ return true;
+
+ HOST_WIDE_INT actual;
+ if (!require_immediate (argno, actual))
+ return false;
+
+ for (tree entry = TYPE_VALUES (type); entry; entry = TREE_CHAIN (entry))
+ {
+ /* The value is an INTEGER_CST for C and a CONST_DECL wrapper
+ around an INTEGER_CST for C++. */
+ tree value = TREE_VALUE (entry);
+ if (TREE_CODE (value) == CONST_DECL)
+ value = DECL_INITIAL (value);
+ if (wi::to_widest (value) == actual)
+ return true;
+ }
+
+ report_not_enum (location, fndecl, argno, actual, type);
+ return false;
+}
+
+/* Check that argument REL_ARGNO is suitable for indexing argument
+ REL_ARGNO - 1, in groups of GROUP_SIZE elements. REL_ARGNO counts
+ from the end of the predication arguments. */
+bool
+function_checker::require_immediate_lane_index (unsigned int rel_argno,
+ unsigned int group_size)
+{
+ unsigned int argno = m_base_arg + rel_argno;
+ if (!argument_exists_p (argno))
+ return true;
+
+ /* Get the type of the previous argument. tree_argument_type wants a
+ 1-based number, whereas ARGNO is 0-based. */
+ machine_mode mode = TYPE_MODE (type_argument_type (m_fntype, argno));
+ gcc_assert (VECTOR_MODE_P (mode));
+ unsigned int nlanes = 128 / (group_size * GET_MODE_UNIT_BITSIZE (mode));
+ return require_immediate_range (rel_argno, 0, nlanes - 1);
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression that
+ has one of the given values. */
+bool
+function_checker::require_immediate_one_of (unsigned int rel_argno,
+ HOST_WIDE_INT value0,
+ HOST_WIDE_INT value1,
+ HOST_WIDE_INT value2,
+ HOST_WIDE_INT value3)
+{
+ unsigned int argno = m_base_arg + rel_argno;
+ if (!argument_exists_p (argno))
+ return true;
+
+ HOST_WIDE_INT actual;
+ if (!require_immediate (argno, actual))
+ return false;
+
+ if (actual != value0
+ && actual != value1
+ && actual != value2
+ && actual != value3)
+ {
+ report_not_one_of (location, fndecl, argno, actual,
+ value0, value1, value2, value3);
+ return false;
+ }
+
+ return true;
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression in the
+ range [MIN, MAX]. REL_ARGNO counts from the end of the predication
+ arguments. */
+bool
+function_checker::require_immediate_range (unsigned int rel_argno,
+ HOST_WIDE_INT min,
+ HOST_WIDE_INT max)
+{
+ unsigned int argno = m_base_arg + rel_argno;
+ if (!argument_exists_p (argno))
+ return true;
+
+ /* Required because of the tree_to_uhwi -> HOST_WIDE_INT conversion
+ in require_immediate. */
+ gcc_assert (min >= 0 && min <= max);
+ HOST_WIDE_INT actual;
+ if (!require_immediate (argno, actual))
+ return false;
+
+ if (!IN_RANGE (actual, min, max))
+ {
+ report_out_of_range (location, fndecl, argno, actual, min, max);
+ return false;
+ }
+
+ return true;
+}
+
+/* Perform semantic checks on the call. Return true if the call is valid,
+ otherwise report a suitable error. */
+bool
+function_checker::check ()
+{
+ function_args_iterator iter;
+ tree type;
+ unsigned int i = 0;
+ FOREACH_FUNCTION_ARGS (m_fntype, type, iter)
+ {
+ if (type == void_type_node || i >= m_nargs)
+ break;
+
+ if (i >= m_base_arg
+ && TREE_CODE (type) == ENUMERAL_TYPE
+ && !require_immediate_enum (i - m_base_arg, type))
+ return false;
+
+ i += 1;
+ }
+
+ return shape->check (*this);
+}
+
+gimple_folder::gimple_folder (const function_instance &instance, tree fndecl,
+ gimple_stmt_iterator *gsi_in, gcall *call_in)
+ : function_call_info (gimple_location (call_in), instance, fndecl),
+ gsi (gsi_in), call (call_in), lhs (gimple_call_lhs (call_in))
+{
+}
+
+/* Convert predicate argument ARGNO so that it has the type appropriate for
+ an operation on VECTYPE. Add any new statements to STMTS. */
+tree
+gimple_folder::convert_pred (gimple_seq &stmts, tree vectype,
+ unsigned int argno)
+{
+ tree predtype = build_same_sized_truth_vector_type (vectype);
+ tree pred = gimple_call_arg (call, argno);
+ return gimple_build (&stmts, VIEW_CONVERT_EXPR, predtype, pred);
+}
+
+/* Return a pointer to the address in a contiguous load or store,
+ given that each memory vector has type VECTYPE. Add any new
+ statements to STMTS. */
+tree
+gimple_folder::fold_contiguous_base (gimple_seq &stmts, tree vectype)
+{
+ tree base = gimple_call_arg (call, 1);
+ if (mode_suffix_id == MODE_vnum)
+ {
+ tree offset = gimple_call_arg (call, 2);
+ offset = gimple_convert (&stmts, sizetype, offset);
+ offset = gimple_build (&stmts, MULT_EXPR, sizetype, offset,
+ TYPE_SIZE_UNIT (vectype));
+ base = gimple_build (&stmts, POINTER_PLUS_EXPR, TREE_TYPE (base),
+ base, offset);
+ }
+ return base;
+}
+
+/* Return the alignment and TBAA argument to an internal load or store
+ function like IFN_MASK_LOAD or IFN_MASK_STORE, given that it accesses
+ memory elements of type TYPE. */
+tree
+gimple_folder::load_store_cookie (tree type)
+{
+ return build_int_cst (build_pointer_type (type), TYPE_ALIGN_UNIT (type));
+}
+
+/* Fold the call to a PTRUE, taking the element size from type suffix 0. */
+gimple *
+gimple_folder::fold_to_ptrue ()
+{
+ tree svbool_type = TREE_TYPE (lhs);
+ tree bool_type = TREE_TYPE (svbool_type);
+ unsigned int element_bytes = type_suffix (0).element_bytes;
+
+ /* The return type is svbool_t for all type suffixes, thus for b8 we
+ want { 1, 1, 1, 1, ... }, for b16 we want { 1, 0, 1, 0, ... }, etc. */
+ tree_vector_builder builder (svbool_type, element_bytes, 1);
+ builder.quick_push (build_all_ones_cst (bool_type));
+ for (unsigned int i = 1; i < element_bytes; ++i)
+ builder.quick_push (build_zero_cst (bool_type));
+ return gimple_build_assign (lhs, builder.build ());
+}
+
+/* Fold the call to a PFALSE. */
+gimple *
+gimple_folder::fold_to_pfalse ()
+{
+ return gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
+}
+
+/* Fold an operation to a constant predicate in which the first VL
+ elements are set and the rest are clear. Take the element size
+ from type suffix 0. */
+gimple *
+gimple_folder::fold_to_vl_pred (unsigned int vl)
+{
+ tree vectype = TREE_TYPE (lhs);
+ tree element_type = TREE_TYPE (vectype);
+ tree minus_one = build_all_ones_cst (element_type);
+ tree zero = build_zero_cst (element_type);
+ unsigned int element_bytes = type_suffix (0).element_bytes;
+
+ /* Construct COUNT elements that contain the ptrue followed by
+ a repeating sequence of COUNT elements. */
+ unsigned int count = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vectype));
+ gcc_assert (vl * element_bytes <= count);
+ tree_vector_builder builder (vectype, count, 2);
+ for (unsigned int i = 0; i < count * 2; ++i)
+ {
+ bool bit = (i & (element_bytes - 1)) == 0 && i < vl * element_bytes;
+ builder.quick_push (bit ? minus_one : zero);
+ }
+ return gimple_build_assign (lhs, builder.build ());
+}
+
+/* Try to fold the call. Return the new statement on success and null
+ on failure. */
+gimple *
+gimple_folder::fold ()
+{
+ /* Don't fold anything when SVE is disabled; emit an error during
+ expansion instead. */
+ if (!TARGET_SVE)
+ return NULL;
+
+ /* Punt if the function has a return type and no result location is
+ provided. The attributes should allow target-independent code to
+ remove the calls if appropriate. */
+ if (!lhs && TREE_TYPE (gimple_call_fntype (call)) != void_type_node)
+ return NULL;
+
+ return base->fold (*this);
+}
+
+function_expander::function_expander (const function_instance &instance,
+ tree fndecl, tree call_expr_in,
+ rtx possible_target_in)
+ : function_call_info (EXPR_LOCATION (call_expr_in), instance, fndecl),
+ call_expr (call_expr_in), possible_target (possible_target_in)
+{
+}
+
+/* Return the handler of direct optab OP for type suffix SUFFIX_I. */
+insn_code
+function_expander::direct_optab_handler (optab op, unsigned int suffix_i)
+{
+ return ::direct_optab_handler (op, vector_mode (suffix_i));
+}
+
+/* Choose between signed and unsigned direct optabs SIGNED_OP and
+ UNSIGNED_OP based on the signedness of type suffix SUFFIX_I, then
+ pick the appropriate optab handler for the mode. Use MODE as the
+ mode if given, otherwise use the mode of type suffix SUFFIX_I. */
+insn_code
+function_expander::direct_optab_handler_for_sign (optab signed_op,
+ optab unsigned_op,
+ unsigned int suffix_i,
+ machine_mode mode)
+{
+ if (mode == VOIDmode)
+ mode = vector_mode (suffix_i);
+ optab op = type_suffix (suffix_i).unsigned_p ? unsigned_op : signed_op;
+ return ::direct_optab_handler (op, mode);
+}
+
+/* Return true if X overlaps any input. */
+bool
+function_expander::overlaps_input_p (rtx x)
+{
+ for (unsigned int i = 0; i < args.length (); ++i)
+ if (reg_overlap_mentioned_p (x, args[i]))
+ return true;
+ return false;
+}
+
+/* Return the base address for a contiguous load or store function.
+ MEM_MODE is the mode of the addressed memory. */
+rtx
+function_expander::get_contiguous_base (machine_mode mem_mode)
+{
+ rtx base = args[1];
+ if (mode_suffix_id == MODE_vnum)
+ {
+ /* Use the size of the memory mode for extending loads and truncating
+ stores. Use the size of a full vector for non-extending loads
+ and non-truncating stores (including svld[234] and svst[234]). */
+ poly_int64 size = ordered_min (GET_MODE_SIZE (mem_mode),
+ BYTES_PER_SVE_VECTOR);
+ rtx offset = gen_int_mode (size, Pmode);
+ offset = simplify_gen_binary (MULT, Pmode, args[2], offset);
+ base = simplify_gen_binary (PLUS, Pmode, base, offset);
+ }
+ return base;
+}
+
+/* For a function that does the equivalent of:
+
+ OUTPUT = COND ? FN (INPUTS) : FALLBACK;
+
+ return the value of FALLBACK.
+
+ MODE is the mode of OUTPUT. NOPS is the number of operands in INPUTS.
+ MERGE_ARGNO is the argument that provides FALLBACK for _m functions,
+ or DEFAULT_MERGE_ARGNO if we should apply the usual rules.
+
+ ARGNO is the caller's index into args. If the returned value is
+ argument 0 (as for unary _m operations), increment ARGNO past the
+ returned argument. */
+rtx
+function_expander::get_fallback_value (machine_mode mode, unsigned int nops,
+ unsigned int merge_argno,
+ unsigned int &argno)
+{
+ if (pred == PRED_z)
+ return CONST0_RTX (mode);
+
+ gcc_assert (pred == PRED_m || pred == PRED_x);
+ if (merge_argno == DEFAULT_MERGE_ARGNO)
+ merge_argno = nops == 1 && pred == PRED_m ? 0 : 1;
+
+ if (merge_argno == 0)
+ return args[argno++];
+
+ return args[merge_argno];
+}
+
+/* Return a REG rtx that can be used for the result of the function,
+ using the preferred target if suitable. */
+rtx
+function_expander::get_reg_target ()
+{
+ machine_mode target_mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
+ if (!possible_target || GET_MODE (possible_target) != target_mode)
+ possible_target = gen_reg_rtx (target_mode);
+ return possible_target;
+}
+
+/* As for get_reg_target, but make sure that the returned REG does not
+ overlap any inputs. */
+rtx
+function_expander::get_nonoverlapping_reg_target ()
+{
+ if (possible_target && overlaps_input_p (possible_target))
+ possible_target = NULL_RTX;
+ return get_reg_target ();
+}
+
+/* Add an output operand to the instruction we're building, which has
+ code ICODE. Bind the output to the preferred target rtx if possible. */
+void
+function_expander::add_output_operand (insn_code icode)
+{
+ unsigned int opno = m_ops.length ();
+ machine_mode mode = insn_data[icode].operand[opno].mode;
+ m_ops.safe_grow (opno + 1);
+ create_output_operand (&m_ops.last (), possible_target, mode);
+}
+
+/* Add an input operand to the instruction we're building, which has
+ code ICODE. Calculate the value of the operand as follows:
+
+ - If the operand is a vector and X is not, broadcast X to fill a
+ vector of the appropriate mode.
+
+ - Otherwise, if the operand is a predicate, coerce X to have the
+ mode that the instruction expects. In this case X is known to be
+ VNx16BImode (the mode of svbool_t).
+
+ - Otherwise use X directly. The expand machinery checks that X has
+ the right mode for the instruction. */
+void
+function_expander::add_input_operand (insn_code icode, rtx x)
+{
+ unsigned int opno = m_ops.length ();
+ const insn_operand_data &operand = insn_data[icode].operand[opno];
+ machine_mode mode = operand.mode;
+ if (mode == VOIDmode)
+ {
+ /* The only allowable use of VOIDmode is the wildcard
+ aarch64_any_register_operand, which is used to avoid
+ combinatorial explosion in the reinterpret patterns. */
+ gcc_assert (operand.predicate == aarch64_any_register_operand);
+ mode = GET_MODE (x);
+ }
+ else if (!VECTOR_MODE_P (GET_MODE (x)) && VECTOR_MODE_P (mode))
+ x = expand_vector_broadcast (mode, x);
+ else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+ {
+ gcc_assert (GET_MODE (x) == VNx16BImode);
+ x = gen_lowpart (mode, x);
+ }
+ m_ops.safe_grow (m_ops.length () + 1);
+ create_input_operand (&m_ops.last (), x, mode);
+}
+
+/* Add an integer operand with value X to the instruction. */
+void
+function_expander::add_integer_operand (HOST_WIDE_INT x)
+{
+ m_ops.safe_grow (m_ops.length () + 1);
+ create_integer_operand (&m_ops.last (), x);
+}
+
+/* Add a memory operand with mode MODE and address ADDR. */
+void
+function_expander::add_mem_operand (machine_mode mode, rtx addr)
+{
+ gcc_assert (VECTOR_MODE_P (mode));
+ rtx mem = gen_rtx_MEM (mode, memory_address (mode, addr));
+ /* The memory is only guaranteed to be element-aligned. */
+ set_mem_align (mem, GET_MODE_ALIGNMENT (GET_MODE_INNER (mode)));
+ add_fixed_operand (mem);
+}
+
+/* Add an address operand with value X. The static operand data says
+ what mode and form the address must have. */
+void
+function_expander::add_address_operand (rtx x)
+{
+ m_ops.safe_grow (m_ops.length () + 1);
+ create_address_operand (&m_ops.last (), x);
+}
+
+/* Add an operand that must be X. The only way of legitimizing an
+ invalid X is to reload the address of a MEM. */
+void
+function_expander::add_fixed_operand (rtx x)
+{
+ m_ops.safe_grow (m_ops.length () + 1);
+ create_fixed_operand (&m_ops.last (), x);
+}
+
+/* Generate instruction ICODE, given that its operands have already
+ been added to M_OPS. Return the value of the first operand. */
+rtx
+function_expander::generate_insn (insn_code icode)
+{
+ expand_insn (icode, m_ops.length (), m_ops.address ());
+ return function_returns_void_p () ? const0_rtx : m_ops[0].value;
+}
+
+/* Convert the arguments to a gather/scatter function into the
+ associated md operands. Argument ARGNO is the scalar or vector base and
+ argument ARGNO + 1 is the scalar or vector displacement (if applicable).
+ The md pattern expects:
+
+ - a scalar base
+ - a vector displacement
+ - a const_int that is 1 if the displacement is zero-extended from 32 bits
+ - a scaling multiplier (1 for bytes, 2 for .h indices, etc.). */
+void
+function_expander::prepare_gather_address_operands (unsigned int argno)
+{
+ machine_mode mem_mode = memory_vector_mode ();
+ tree vector_type = base_vector_type ();
+ units_index units = displacement_units ();
+ if (units == UNITS_none)
+ {
+ /* Vector base, no displacement. Convert to an integer zero base
+ and a vector byte offset. */
+ args.quick_insert (argno, const0_rtx);
+ units = UNITS_bytes;
+ }
+ else if (vector_type)
+ {
+ /* Vector base, scalar displacement. Convert to a scalar base and
+ a vector byte offset. */
+ std::swap (args[argno], args[argno + 1]);
+ if (units == UNITS_elements)
+ {
+ /* Convert the original scalar array index to a byte offset. */
+ rtx size = gen_int_mode (GET_MODE_UNIT_SIZE (mem_mode), DImode);
+ args[argno] = simplify_gen_binary (MULT, DImode, args[argno], size);
+ units = UNITS_bytes;
+ }
+ }
+ else
+ {
+ /* Scalar base, vector displacement. This is what the md pattern wants,
+ so we just need to make sure that the scalar base has DImode. */
+ if (Pmode == SImode)
+ args[argno] = simplify_gen_unary (ZERO_EXTEND, DImode,
+ args[argno], SImode);
+ vector_type = displacement_vector_type ();
+ }
+ tree scalar_displacement_type = TREE_TYPE (vector_type);
+
+ bool uxtw_p = (TYPE_PRECISION (scalar_displacement_type) < 64
+ && TYPE_UNSIGNED (scalar_displacement_type));
+ unsigned int scale = (units == UNITS_bytes
+ ? 1 : GET_MODE_UNIT_SIZE (mem_mode));
+
+ args.quick_insert (argno + 2, GEN_INT (uxtw_p));
+ args.quick_insert (argno + 3, GEN_INT (scale));
+}
+
+/* The final argument is an immediate svprfop value. Add two fake arguments
+ to represent the rw and locality operands of a PREFETCH rtx. */
+void
+function_expander::prepare_prefetch_operands ()
+{
+ unsigned int prfop = INTVAL (args.last ());
+ /* Bit 3 of the prfop selects stores over loads. */
+ args.quick_push (GEN_INT ((prfop & 8) != 0));
+ /* Bits 1 and 2 specify the locality; 0-based for svprfop but
+ 1-based for PREFETCH. */
+ args.quick_push (GEN_INT (((prfop >> 1) & 3) + 1));
+}
+
+/* Add a dummy argument to indicate whether predicate argument ARGNO
+ is all-true when interpreted in mode PRED_MODE. The hint goes
+ immediately after ARGNO. */
+void
+function_expander::add_ptrue_hint (unsigned int argno, machine_mode pred_mode)
+{
+ rtx pred = gen_lowpart (pred_mode, args[argno]);
+ int hint = (pred == CONSTM1_RTX (pred_mode)
+ ? SVE_KNOWN_PTRUE : SVE_MAYBE_NOT_PTRUE);
+ args.quick_insert (argno + 1, gen_int_mode (hint, SImode));
+}
+
+/* Rotate inputs args[START:END] one position to the left, so that
+ args[START] becomes args[END - 1]. */
+void
+function_expander::rotate_inputs_left (unsigned int start, unsigned int end)
+{
+ rtx new_last = args[start];
+ for (unsigned int i = start; i < end - 1; ++i)
+ args[i] = args[i + 1];
+ args[end - 1] = new_last;
+}
+
+/* Return true if the negation of argument ARGNO can be folded away,
+ replacing it with the negated value if so. MODE is the associated
+ vector mode, but the argument could be a single element. The main
+ case this handles is constant arguments. */
+bool
+function_expander::try_negating_argument (unsigned int argno,
+ machine_mode mode)
+{
+ rtx x = args[argno];
+ if (!VECTOR_MODE_P (GET_MODE (x)))
+ mode = GET_MODE_INNER (mode);
+
+ x = simplify_unary_operation (NEG, mode, x, mode);
+ if (!x)
+ return false;
+
+ args[argno] = x;
+ return true;
+}
+
+/* Implement the call using instruction ICODE, with a 1:1 mapping between
+ arguments and input operands. */
+rtx
+function_expander::use_exact_insn (insn_code icode)
+{
+ unsigned int nops = insn_data[icode].n_operands;
+ if (!function_returns_void_p ())
+ {
+ add_output_operand (icode);
+ nops -= 1;
+ }
+ for (unsigned int i = 0; i < nops; ++i)
+ add_input_operand (icode, args[i]);
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which does not use a
+ governing predicate. We must therefore drop the GP from an _x call. */
+rtx
+function_expander::use_unpred_insn (insn_code icode)
+{
+ /* We can't drop the predicate for _z and _m. */
+ gcc_assert (pred == PRED_x || pred == PRED_none);
+ /* Discount the output operand. */
+ unsigned int nops = insn_data[icode].n_operands - 1;
+ /* Drop the predicate argument in the case of _x predication. */
+ unsigned int bias = (pred == PRED_x ? 1 : 0);
+ unsigned int i = 0;
+
+ add_output_operand (icode);
+ for (; i < nops; ++i)
+ add_input_operand (icode, args[i + bias]);
+
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which is a predicated
+ operation that returns arbitrary values for inactive lanes. */
+rtx
+function_expander::use_pred_x_insn (insn_code icode)
+{
+ /* At present we never need to handle PRED_none, which would involve
+ creating a new predicate rather than using one supplied by the user. */
+ gcc_assert (pred == PRED_x);
+ /* Discount the output operand. */
+ unsigned int nops = args.length () - 1;
+
+ bool has_float_operand_p = FLOAT_MODE_P (insn_data[icode].operand[0].mode);
+
+ /* Add the normal operands. */
+ add_output_operand (icode);
+ add_input_operand (icode, args[0]);
+ for (unsigned int i = 0; i < nops; ++i)
+ {
+ add_input_operand (icode, args[i + 1]);
+ if (FLOAT_MODE_P (GET_MODE (args[i + 1])))
+ has_float_operand_p = true;
+ }
+
+ if (has_float_operand_p)
+ {
+ /* Add a flag that indicates whether unpredicated instructions
+ are allowed. */
+ rtx pred = m_ops[1].value;
+ if (flag_trapping_math && pred != CONST1_RTX (GET_MODE (pred)))
+ add_integer_operand (SVE_STRICT_GP);
+ else
+ add_integer_operand (SVE_RELAXED_GP);
+ }
+
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which does the equivalent of:
+
+ OUTPUT = COND ? FN (INPUTS) : FALLBACK;
+
+ The instruction operands are in the order above: OUTPUT, COND, INPUTS
+ and FALLBACK. MERGE_ARGNO is the argument that provides FALLBACK for _m
+ functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules. */
+rtx
+function_expander::use_cond_insn (insn_code icode, unsigned int merge_argno)
+{
+ /* At present we never need to handle PRED_none, which would involve
+ creating a new predicate rather than using one supplied by the user. */
+ gcc_assert (pred != PRED_none);
+ /* Discount the output, predicate and fallback value. */
+ unsigned int nops = insn_data[icode].n_operands - 3;
+ machine_mode mode = insn_data[icode].operand[0].mode;
+
+ unsigned int opno = 0;
+ rtx fallback_arg = get_fallback_value (mode, nops, merge_argno, opno);
+ rtx pred = args[opno++];
+
+ add_output_operand (icode);
+ add_input_operand (icode, pred);
+ for (unsigned int i = 0; i < nops; ++i)
+ add_input_operand (icode, args[opno + i]);
+ add_input_operand (icode, fallback_arg);
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which is a select-like
+ operation with the following operands:
+
+ 0: output
+ 1: true value
+ 2: false value
+ 3: predicate
+
+ MERGE_ARGNO is the argument that provides the "false" value for _m
+ functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules. */
+rtx
+function_expander::use_vcond_mask_insn (insn_code icode,
+ unsigned int merge_argno)
+{
+ machine_mode mode = vector_mode (0);
+
+ unsigned int opno = 0;
+ rtx false_arg = get_fallback_value (mode, 1, merge_argno, opno);
+ rtx pred_arg = args[opno++];
+ rtx true_arg = args[opno++];
+
+ add_output_operand (icode);
+ add_input_operand (icode, true_arg);
+ add_input_operand (icode, false_arg);
+ add_input_operand (icode, pred_arg);
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which loads memory operand 1
+ into register operand 0 under the control of predicate operand 2. */
+rtx
+function_expander::use_contiguous_load_insn (insn_code icode)
+{
+ machine_mode mem_mode = memory_vector_mode ();
+
+ add_output_operand (icode);
+ add_mem_operand (mem_mode, get_contiguous_base (mem_mode));
+ add_input_operand (icode, args[0]);
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which prefetches from
+ address operand 1 under the control of predicate operand 0.
+ Operands 2, 3 and 4 respectively specify the svprfop value,
+ the PREFETCH rw flag and the PREFETCH locality. */
+rtx
+function_expander::use_contiguous_prefetch_insn (insn_code icode)
+{
+ add_input_operand (icode, args[0]);
+ add_address_operand (get_contiguous_base (VNx16QImode));
+ for (unsigned int i = args.length () - 3; i < args.length (); ++i)
+ add_input_operand (icode, args[i]);
+ return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which stores register operand 1
+ into memory operand 0 under the control of predicate operand 2. */
+rtx
+function_expander::use_contiguous_store_insn (insn_code icode)
+{
+ machine_mode mem_mode = memory_vector_mode ();
+
+ add_mem_operand (mem_mode, get_contiguous_base (mem_mode));
+ add_input_operand (icode, args.last ());
+ add_input_operand (icode, args[0]);
+ return generate_insn (icode);
+}
+
+/* Implement the call using one of the following strategies, chosen in order:
+
+ (1) "aarch64_pred_<optab><mode>_z" for PRED_z predicate functions
+
+ (2) "aarch64_pred_<optab><mode>" for PRED_x functions
+
+ (3) a normal unpredicated optab for PRED_none and PRED_x functions,
+ dropping the predicate in the latter case
+
+ (4) "cond_<optab><mode>" otherwise
+
+ where <optab> corresponds to:
+
+ - CODE_FOR_SINT for signed integers
+ - CODE_FOR_UINT for unsigned integers
+ - UNSPEC_FOR_FP for floating-point values
+
+ MERGE_ARGNO is the argument that provides the values of inactive lanes for
+ _m functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules. */
+rtx
+function_expander::map_to_rtx_codes (rtx_code code_for_sint,
+ rtx_code code_for_uint,
+ int unspec_for_fp,
+ unsigned int merge_argno)
+{
+ machine_mode mode = vector_mode (0);
+ rtx_code code = (type_suffix (0).unsigned_p ? code_for_uint : code_for_sint);
+ insn_code icode;
+
+ /* Handle predicate logic operations, which always use _z predication. */
+ if (type_suffix (0).tclass == TYPE_bool)
+ {
+ gcc_assert (pred == PRED_z && code_for_uint == code_for_sint);
+ return use_exact_insn (code_for_aarch64_pred_z (code, mode));
+ }
+
+ /* First try using UNSPEC_PRED_X patterns for _x predication,
+ if available. */
+ if (pred == PRED_x)
+ {
+ if (type_suffix (0).integer_p)
+ icode = maybe_code_for_aarch64_pred (code, mode);
+ else
+ icode = maybe_code_for_aarch64_pred (unspec_for_fp, mode);
+ if (icode != CODE_FOR_nothing)
+ return use_pred_x_insn (icode);
+ }
+
+ /* Otherwise expand PRED_none and PRED_x operations without a predicate.
+ Floating-point operations conventionally use the signed rtx code. */
+ if (pred == PRED_none || pred == PRED_x)
+ return use_unpred_insn (direct_optab_handler (code_to_optab (code), 0));
+
+ /* Don't use cond_*_optabs here, since not all codes have one yet. */
+ if (type_suffix (0).integer_p)
+ icode = code_for_cond (code, mode);
+ else
+ icode = code_for_cond (unspec_for_fp, mode);
+ return use_cond_insn (icode, merge_argno);
+}
+
+/* Implement the call using one of the following strategies, chosen in order:
+
+ (1) "aarch64_pred_<optab><mode>" for PRED_x functions; this is a
+ predicated pattern
+
+ (2) "aarch64_sve_<optab><mode>" for PRED_none and PRED_x functions;
+ this is an unpredicated pattern
+
+ (3) "cond_<optab><mode>" otherwise
+
+ where <optab> corresponds to:
+
+ - UNSPEC_FOR_SINT for signed integers
+ - UNSPEC_FOR_UINT for unsigned integers
+ - UNSPEC_FOR_FP for floating-point values
+
+ MERGE_ARGNO is the argument that provides the values of inactive lanes for
+ _m functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules. */
+rtx
+function_expander::map_to_unspecs (int unspec_for_sint, int unspec_for_uint,
+ int unspec_for_fp, unsigned int merge_argno)
+{
+ machine_mode mode = vector_mode (0);
+ int unspec = (!type_suffix (0).integer_p ? unspec_for_fp
+ : type_suffix (0).unsigned_p ? unspec_for_uint
+ : unspec_for_sint);
+
+ if (pred == PRED_x)
+ {
+ insn_code icode = maybe_code_for_aarch64_pred (unspec, mode);
+ if (icode != CODE_FOR_nothing)
+ return use_pred_x_insn (icode);
+ }
+
+ if (pred == PRED_none || pred == PRED_x)
+ return use_unpred_insn (code_for_aarch64_sve (unspec, mode));
+
+ insn_code icode = code_for_cond (unspec, vector_mode (0));
+ return use_cond_insn (icode, merge_argno);
+}
+
+/* Implement the call using an @aarch64 instruction and the
+ instructions are parameterized by an rtx_code. CODE_FOR_SINT
+ is the rtx_code for signed integer operations, CODE_FOR_UINT
+ is the rtx_code for unsigned integer operations. */
+rtx
+function_expander::expand_signed_unpred_op (rtx_code code_for_sint,
+ rtx_code code_for_uint)
+{
+ insn_code icode;
+ if (type_suffix (0).unsigned_p)
+ icode = code_for_aarch64 (code_for_uint, code_for_uint, vector_mode (0));
+ else
+ icode = code_for_aarch64 (code_for_sint, code_for_sint, vector_mode (0));
+ return use_unpred_insn (icode);
+}
+
+/* Expand the call and return its lhs. */
+rtx
+function_expander::expand ()
+{
+ unsigned int nargs = call_expr_nargs (call_expr);
+ args.reserve (nargs);
+ for (unsigned int i = 0; i < nargs; ++i)
+ args.quick_push (expand_normal (CALL_EXPR_ARG (call_expr, i)));
+
+ return base->expand (*this);
+}
+
+/* Register the built-in SVE ABI types, such as __SVBool_t. */
+static void
+register_builtin_types ()
+{
+#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
+ scalar_types[VECTOR_TYPE_ ## ACLE_NAME] = SCALAR_TYPE;
+#include "aarch64-sve-builtins.def"
+
+ for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
+ {
+ tree eltype = scalar_types[i];
+ tree vectype;
+ if (eltype == boolean_type_node)
+ {
+ vectype = build_truth_vector_type (BYTES_PER_SVE_VECTOR,
+ BYTES_PER_SVE_VECTOR);
+ gcc_assert (TYPE_MODE (vectype) == VNx16BImode
+ && TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype)
+ && TYPE_ALIGN (vectype) == 16
+ && known_eq (wi::to_poly_offset (TYPE_SIZE (vectype)),
+ BYTES_PER_SVE_VECTOR));
+ }
+ else
+ {
+ unsigned int elbytes = tree_to_uhwi (TYPE_SIZE_UNIT (eltype));
+ poly_uint64 nunits = exact_div (BYTES_PER_SVE_VECTOR, elbytes);
+ vectype = build_vector_type (eltype, nunits);
+ gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype))
+ && TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype)
+ && TYPE_ALIGN (vectype) == 128
+ && known_eq (wi::to_poly_offset (TYPE_SIZE (vectype)),
+ BITS_PER_SVE_VECTOR));
+ }
+ vectype = build_distinct_type_copy (vectype);
+ SET_TYPE_STRUCTURAL_EQUALITY (vectype);
+ TYPE_ARTIFICIAL (vectype) = 1;
+ abi_vector_types[i] = vectype;
+ lang_hooks.types.register_builtin_type (vectype,
+ vector_types[i].abi_name);
+ }
+}
+
+/* Initialize all compiler built-ins related to SVE that should be
+ defined at start-up. */
+void
+init_builtins ()
+{
+ sve_switcher sve;
+ register_builtin_types ();
+}
+
+/* Register vector type TYPE under its arm_sve.h name. */
+static void
+register_vector_type (vector_type_index type)
+{
+ tree vectype = abi_vector_types[type];
+ tree id = get_identifier (vector_types[type].acle_name);
+ tree decl = build_decl (input_location, TYPE_DECL, id, vectype);
+ decl = lang_hooks.decls.pushdecl (decl);
+
+ /* Record the new ACLE type if pushdecl succeeded without error. Use
+ the ABI type otherwise, so that the type we record at least has the
+ right form, even if it doesn't have the right name. This should give
+ better error recovery behavior than installing error_mark_node or
+ installing an incorrect type. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype)
+ vectype = TREE_TYPE (decl);
+ acle_vector_types[0][type] = vectype;
+}
+
+/* Register the tuple type that contains NUM_VECTORS vectors of type TYPE. */
+static void
+register_tuple_type (unsigned int num_vectors, vector_type_index type)
+{
+ tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
+
+ /* The contents of the type are opaque, so we can define them in any
+ way that maps to the correct ABI type.
+
+ Here we choose to use the same layout as for arm_neon.h, but with
+ "__val" instead of "val":
+
+ struct svfooxN_t { svfoo_t __val[N]; };
+
+ (It wouldn't be possible to write that directly in C or C++ for
+ sizeless types, but that's not a problem for this function.)
+
+ Using arrays simplifies the handling of svget and svset for variable
+ arguments. */
+ tree vector_type = acle_vector_types[0][type];
+ tree array_type = build_array_type_nelts (vector_type, num_vectors);
+ gcc_assert (VECTOR_MODE_P (TYPE_MODE (array_type))
+ && TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type)
+ && TYPE_ALIGN (array_type) == 128);
+
+ tree field = build_decl (input_location, FIELD_DECL,
+ get_identifier ("__val"), array_type);
+ DECL_FIELD_CONTEXT (field) = tuple_type;
+ TYPE_FIELDS (tuple_type) = field;
+ layout_type (tuple_type);
+ gcc_assert (VECTOR_MODE_P (TYPE_MODE (tuple_type))
+ && TYPE_MODE_RAW (tuple_type) == TYPE_MODE (tuple_type)
+ && TYPE_ALIGN (tuple_type) == 128);
+
+ /* Work out the structure name. */
+ char buffer[sizeof ("svfloat64x4_t")];
+ const char *vector_type_name = vector_types[type].acle_name;
+ snprintf (buffer, sizeof (buffer), "%.*sx%d_t",
+ (int) strlen (vector_type_name) - 2, vector_type_name,
+ num_vectors);
+
+ tree decl = build_decl (input_location, TYPE_DECL,
+ get_identifier (buffer), tuple_type);
+ TYPE_NAME (tuple_type) = decl;
+ TYPE_STUB_DECL (tuple_type) = decl;
+ lang_hooks.decls.pushdecl (decl);
+ /* ??? Undo the effect of set_underlying_type for C. The C frontend
+ doesn't recognize DECL as a built-in because (as intended) the decl has
+ a real location instead of BUILTINS_LOCATION. The frontend therefore
+ treats the decl like a normal C "typedef struct foo foo;", expecting
+ the type for tag "struct foo" to have a dummy unnamed TYPE_DECL instead
+ of the named one we attached above. It then sets DECL_ORIGINAL_TYPE
+ on the supposedly unnamed decl, creating a circularity that upsets
+ dwarf2out.
+
+ We don't want to follow the normal C model and create "struct foo"
+ tags for tuple types since (a) the types are supposed to be opaque
+ and (b) they couldn't be defined as a real struct anyway. Treating
+ the TYPE_DECLs as "typedef struct foo foo;" without creating
+ "struct foo" would lead to confusing error messages. */
+ DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
+
+ acle_vector_types[num_vectors - 1][type] = tuple_type;
+}
+
+/* Register the svpattern enum. */
+static void
+register_svpattern ()
+{
+ auto_vec<string_int_pair, 32> values;
+#define PUSH(UPPER, LOWER, VALUE) \
+ values.quick_push (string_int_pair ("SV_" #UPPER, VALUE));
+ AARCH64_FOR_SVPATTERN (PUSH)
+#undef PUSH
+
+ acle_svpattern = lang_hooks.types.simulate_enum_decl (input_location,
+ "svpattern", values);
+}
+
+/* Register the svprfop enum. */
+static void
+register_svprfop ()
+{
+ auto_vec<string_int_pair, 16> values;
+#define PUSH(UPPER, LOWER, VALUE) \
+ values.quick_push (string_int_pair ("SV_" #UPPER, VALUE));
+ AARCH64_FOR_SVPRFOP (PUSH)
+#undef PUSH
+
+ acle_svprfop = lang_hooks.types.simulate_enum_decl (input_location,
+ "svprfop", values);
+}
+
+/* Implement #pragma GCC aarch64 "arm_sve.h". */
+void
+handle_arm_sve_h ()
+{
+ if (function_table)
+ {
+ error ("duplicate definition of %qs", "arm_sve.h");
+ return;
+ }
+
+ sve_switcher sve;
+
+ /* Define the vector and tuple types. */
+ for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i)
+ {
+ vector_type_index type = vector_type_index (type_i);
+ register_vector_type (type);
+ if (type != VECTOR_TYPE_svbool_t)
+ for (unsigned int count = 2; count <= MAX_TUPLE_SIZE; ++count)
+ register_tuple_type (count, type);
+ }
+
+ /* Define the enums. */
+ register_svpattern ();
+ register_svprfop ();
+
+ /* Define the functions. */
+ function_table = new hash_table<registered_function_hasher> (1023);
+ function_builder builder;
+ for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i)
+ builder.register_function_group (function_groups[i]);
+}
+
+/* Return the function decl with SVE function subcode CODE, or error_mark_node
+ if no such function exists. */
+tree
+builtin_decl (unsigned int code, bool)
+{
+ if (code >= vec_safe_length (registered_functions))
+ return error_mark_node;
+ return (*registered_functions)[code]->decl;
+}
+
+/* If we're implementing manual overloading, check whether the SVE
+ function with subcode CODE is overloaded, and if so attempt to
+ determine the corresponding non-overloaded function. The call
+ occurs at location LOCATION and has the arguments given by ARGLIST.
+
+ If the call is erroneous, report an appropriate error and return
+ error_mark_node. Otherwise, if the function is overloaded, return
+ the decl of the non-overloaded function. Return NULL_TREE otherwise,
+ indicating that the call should be processed in the normal way. */
+tree
+resolve_overloaded_builtin (location_t location, unsigned int code,
+ vec<tree, va_gc> *arglist)
+{
+ if (code >= vec_safe_length (registered_functions))
+ return NULL_TREE;
+
+ registered_function &rfn = *(*registered_functions)[code];
+ if (rfn.overloaded_p)
+ return function_resolver (location, rfn.instance, rfn.decl,
+ *arglist).resolve ();
+ return NULL_TREE;
+}
+
+/* Perform any semantic checks needed for a call to the SVE function
+ with subcode CODE, such as testing for integer constant expressions.
+ The call occurs at location LOCATION and has NARGS arguments,
+ given by ARGS. FNDECL is the original function decl, before
+ overload resolution.
+
+ Return true if the call is valid, otherwise report a suitable error. */
+bool
+check_builtin_call (location_t location, vec<location_t>, unsigned int code,
+ tree fndecl, unsigned int nargs, tree *args)
+{
+ const registered_function &rfn = *(*registered_functions)[code];
+ if (!check_required_extensions (location, rfn.decl, rfn.required_extensions))
+ return false;
+ return function_checker (location, rfn.instance, fndecl,
+ TREE_TYPE (rfn.decl), nargs, args).check ();
+}
+
+/* Attempt to fold STMT, given that it's a call to the SVE function
+ with subcode CODE. Return the new statement on success and null
+ on failure. Insert any other new statements at GSI. */
+gimple *
+gimple_fold_builtin (unsigned int code, gimple_stmt_iterator *gsi, gcall *stmt)
+{
+ registered_function &rfn = *(*registered_functions)[code];
+ return gimple_folder (rfn.instance, rfn.decl, gsi, stmt).fold ();
+}
+
+/* Expand a call to the SVE function with subcode CODE. EXP is the call
+ expression and TARGET is the preferred location for the result.
+ Return the value of the lhs. */
+rtx
+expand_builtin (unsigned int code, tree exp, rtx target)
+{
+ registered_function &rfn = *(*registered_functions)[code];
+ if (!check_required_extensions (EXPR_LOCATION (exp), rfn.decl,
+ rfn.required_extensions))
+ return target;
+ return function_expander (rfn.instance, rfn.decl, exp, target).expand ();
+}
+
+/* Return true if TYPE is the ABI-defined __SVBool_t type. */
+bool
+svbool_type_p (const_tree type)
+{
+ tree abi_type = abi_vector_types[VECTOR_TYPE_svbool_t];
+ return (type != error_mark_node
+ && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (abi_type));
+}
+
+/* If TYPE is a built-in type defined by the SVE ABI, return the mangled name,
+ otherwise return NULL. */
+const char *
+mangle_builtin_type (const_tree type)
+{
+ if (type == error_mark_node)
+ return NULL;
+
+ vector_type_index vtype = find_vector_type (type);
+ if (vtype != NUM_VECTOR_TYPES)
+ return vector_types[vtype].mangled_name;
+
+ return NULL;
+}
+
+/* If TYPE is one of the ABI-defined SVE vector types, or an ACLE-defined
+ tuple of them, return the number of vectors it contains. Return 0
+ otherwise. */
+unsigned int
+nvectors_if_data_type (const_tree type)
+{
+ if (type == error_mark_node)
+ return 0;
+
+ type = TYPE_MAIN_VARIANT (type);
+ if (VECTOR_TYPE_P (type))
+ {
+ vector_type_index type_id = find_vector_type (type);
+ if (type_id != VECTOR_TYPE_svbool_t && type_id != NUM_VECTOR_TYPES)
+ return 1;
+ }
+ else if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ for (unsigned int size_i = 1; size_i < MAX_TUPLE_SIZE; ++size_i)
+ for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i)
+ {
+ tree tuple_type = acle_vector_types[size_i][type_i];
+ if (tuple_type && type == TYPE_MAIN_VARIANT (tuple_type))
+ return size_i + 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Return true if TYPE is a built-in type defined by the SVE ABI. */
+bool
+builtin_type_p (const_tree type)
+{
+ return svbool_type_p (type) || nvectors_if_data_type (type) > 0;
+}
+
+}
+
+using namespace aarch64_sve;
+
+inline void
+gt_ggc_mx (function_instance *)
+{
+}
+
+inline void
+gt_pch_nx (function_instance *)
+{
+}
+
+inline void
+gt_pch_nx (function_instance *, void (*) (void *, void *), void *)
+{
+}
+
+#include "gt-aarch64-sve-builtins.h"
--- /dev/null
+/* Builtin lists for AArch64 SVE
+ Copyright (C) 2018-2019 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/>. */
+
+#ifndef DEF_SVE_MODE
+#define DEF_SVE_MODE(A, B, C, D)
+#endif
+
+#ifndef DEF_SVE_TYPE
+#define DEF_SVE_TYPE(A, B, C, D)
+#endif
+
+#ifndef DEF_SVE_TYPE_SUFFIX
+#define DEF_SVE_TYPE_SUFFIX(A, B, C, D, E)
+#endif
+
+#ifndef DEF_SVE_FUNCTION
+#define DEF_SVE_FUNCTION(A, B, C, D)
+#endif
+
+DEF_SVE_MODE (n, none, none, none)
+DEF_SVE_MODE (index, none, none, elements)
+DEF_SVE_MODE (offset, none, none, bytes)
+DEF_SVE_MODE (s32index, none, svint32_t, elements)
+DEF_SVE_MODE (s32offset, none, svint32_t, bytes)
+DEF_SVE_MODE (s64index, none, svint64_t, elements)
+DEF_SVE_MODE (s64offset, none, svint64_t, bytes)
+DEF_SVE_MODE (u32base, svuint32_t, none, none)
+DEF_SVE_MODE (u32base_index, svuint32_t, none, elements)
+DEF_SVE_MODE (u32base_offset, svuint32_t, none, bytes)
+DEF_SVE_MODE (u32base_s32index, svuint32_t, svint32_t, elements)
+DEF_SVE_MODE (u32base_s32offset, svuint32_t, svint32_t, bytes)
+DEF_SVE_MODE (u32base_u32index, svuint32_t, svuint32_t, elements)
+DEF_SVE_MODE (u32base_u32offset, svuint32_t, svuint32_t, bytes)
+DEF_SVE_MODE (u32index, none, svuint32_t, elements)
+DEF_SVE_MODE (u32offset, none, svuint32_t, bytes)
+DEF_SVE_MODE (u64base, svuint64_t, none, none)
+DEF_SVE_MODE (u64base_index, svuint64_t, none, elements)
+DEF_SVE_MODE (u64base_offset, svuint64_t, none, bytes)
+DEF_SVE_MODE (u64base_s64index, svuint64_t, svint64_t, elements)
+DEF_SVE_MODE (u64base_s64offset, svuint64_t, svint64_t, bytes)
+DEF_SVE_MODE (u64base_u64index, svuint64_t, svuint64_t, elements)
+DEF_SVE_MODE (u64base_u64offset, svuint64_t, svuint64_t, bytes)
+DEF_SVE_MODE (u64index, none, svuint64_t, elements)
+DEF_SVE_MODE (u64offset, none, svuint64_t, bytes)
+DEF_SVE_MODE (vnum, none, none, vectors)
+
+DEF_SVE_TYPE (svbool_t, 10, __SVBool_t, boolean_type_node)
+DEF_SVE_TYPE (svfloat16_t, 13, __SVFloat16_t, aarch64_fp16_type_node)
+DEF_SVE_TYPE (svfloat32_t, 13, __SVFloat32_t, float_type_node)
+DEF_SVE_TYPE (svfloat64_t, 13, __SVFloat64_t, double_type_node)
+DEF_SVE_TYPE (svint8_t, 10, __SVInt8_t, intQI_type_node)
+DEF_SVE_TYPE (svint16_t, 11, __SVInt16_t, intHI_type_node)
+DEF_SVE_TYPE (svint32_t, 11, __SVInt32_t, intSI_type_node)
+DEF_SVE_TYPE (svint64_t, 11, __SVInt64_t, intDI_type_node)
+DEF_SVE_TYPE (svuint8_t, 11, __SVUint8_t, unsigned_intQI_type_node)
+DEF_SVE_TYPE (svuint16_t, 12, __SVUint16_t, unsigned_intHI_type_node)
+DEF_SVE_TYPE (svuint32_t, 12, __SVUint32_t, unsigned_intSI_type_node)
+DEF_SVE_TYPE (svuint64_t, 12, __SVUint64_t, unsigned_intDI_type_node)
+
+DEF_SVE_TYPE_SUFFIX (b, svbool_t, bool, 8, VNx16BImode)
+DEF_SVE_TYPE_SUFFIX (b8, svbool_t, bool, 8, VNx16BImode)
+DEF_SVE_TYPE_SUFFIX (b16, svbool_t, bool, 16, VNx8BImode)
+DEF_SVE_TYPE_SUFFIX (b32, svbool_t, bool, 32, VNx4BImode)
+DEF_SVE_TYPE_SUFFIX (b64, svbool_t, bool, 64, VNx2BImode)
+DEF_SVE_TYPE_SUFFIX (f16, svfloat16_t, float, 16, VNx8HFmode)
+DEF_SVE_TYPE_SUFFIX (f32, svfloat32_t, float, 32, VNx4SFmode)
+DEF_SVE_TYPE_SUFFIX (f64, svfloat64_t, float, 64, VNx2DFmode)
+DEF_SVE_TYPE_SUFFIX (s8, svint8_t, signed, 8, VNx16QImode)
+DEF_SVE_TYPE_SUFFIX (s16, svint16_t, signed, 16, VNx8HImode)
+DEF_SVE_TYPE_SUFFIX (s32, svint32_t, signed, 32, VNx4SImode)
+DEF_SVE_TYPE_SUFFIX (s64, svint64_t, signed, 64, VNx2DImode)
+DEF_SVE_TYPE_SUFFIX (u8, svuint8_t, unsigned, 8, VNx16QImode)
+DEF_SVE_TYPE_SUFFIX (u16, svuint16_t, unsigned, 16, VNx8HImode)
+DEF_SVE_TYPE_SUFFIX (u32, svuint32_t, unsigned, 32, VNx4SImode)
+DEF_SVE_TYPE_SUFFIX (u64, svuint64_t, unsigned, 64, VNx2DImode)
+
+#include "aarch64-sve-builtins-base.def"
+
+#undef DEF_SVE_FUNCTION
+#undef DEF_SVE_TYPE_SUFFIX
+#undef DEF_SVE_TYPE
+#undef DEF_SVE_MODE
--- /dev/null
+/* ACLE support for AArch64 SVE
+ Copyright (C) 2018-2019 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/>. */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_H
+#define GCC_AARCH64_SVE_BUILTINS_H
+
+/* The full name of an SVE ACLE function is the concatenation of:
+
+ - the base name ("svadd", etc.)
+ - the "mode" suffix ("_n", "_index", etc.)
+ - the type suffixes ("_s32", "_b8", etc.)
+ - the predication suffix ("_x", "_z", etc.)
+
+ Each piece of information is individually useful, so we retain this
+ classification throughout:
+
+ - function_base represents the base name
+
+ - mode_suffix_index represents the mode suffix
+
+ - type_suffix_index represents individual type suffixes, while
+ type_suffix_pair represents a pair of them
+
+ - prediction_index extends the predication suffix with an additional
+ alternative: PRED_implicit for implicitly-predicated operations
+
+ In addition to its unique full name, a function may have a shorter
+ overloaded alias. This alias removes pieces of the suffixes that
+ can be inferred from the arguments, such as by shortening the mode
+ suffix or dropping some of the type suffixes. The base name and the
+ predication suffix stay the same.
+
+ The function_shape class describes what arguments a given function
+ takes and what its overloaded alias is called. In broad terms,
+ function_base describes how the underlying instruction behaves while
+ function_shape describes how that instruction has been presented at
+ the language level.
+
+ The static list of functions uses function_group to describe a group
+ of related functions. The function_builder class is responsible for
+ expanding this static description into a list of individual functions
+ and registering the associated built-in functions. function_instance
+ describes one of these individual functions in terms of the properties
+ described above.
+
+ The classes involved in compiling a function call are:
+
+ - function_resolver, which resolves an overloaded function call to a
+ specific function_instance and its associated function decl
+
+ - function_checker, which checks whether the values of the arguments
+ conform to the ACLE specification
+
+ - gimple_folder, which tries to fold a function call at the gimple level
+
+ - function_expander, which expands a function call into rtl instructions
+
+ function_resolver and function_checker operate at the language level
+ and so are associated with the function_shape. gimple_folder and
+ function_expander are concerned with the behavior of the function
+ and so are associated with the function_base.
+
+ Note that we've specifically chosen not to fold calls in the frontend,
+ since SVE intrinsics will hardly ever fold a useful language-level
+ constant. */
+namespace aarch64_sve
+{
+/* The maximum number of vectors in an ACLE tuple type. */
+const unsigned int MAX_TUPLE_SIZE = 4;
+
+/* Used to represent the default merge argument index for _m functions.
+ The actual index depends on how many arguments the function takes. */
+const unsigned int DEFAULT_MERGE_ARGNO = ~0U;
+
+/* Flags that describe what a function might do, in addition to reading
+ its arguments and returning a result. */
+const unsigned int CP_READ_FPCR = 1U << 0;
+const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
+const unsigned int CP_READ_MEMORY = 1U << 2;
+const unsigned int CP_PREFETCH_MEMORY = 1U << 3;
+const unsigned int CP_WRITE_MEMORY = 1U << 4;
+const unsigned int CP_READ_FFR = 1U << 5;
+const unsigned int CP_WRITE_FFR = 1U << 6;
+
+/* Enumerates the SVE predicate and (data) vector types, together called
+ "vector types" for brevity. */
+enum vector_type_index
+{
+#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
+ VECTOR_TYPE_ ## ACLE_NAME,
+#include "aarch64-sve-builtins.def"
+ NUM_VECTOR_TYPES
+};
+
+/* Classifies the available measurement units for an address displacement. */
+enum units_index
+{
+ UNITS_none,
+ UNITS_bytes,
+ UNITS_elements,
+ UNITS_vectors
+};
+
+/* Describes the various uses of a governing predicate. */
+enum predication_index
+{
+ /* No governing predicate is present. */
+ PRED_none,
+
+ /* A governing predicate is present but there is no predication suffix
+ associated with it. This is used when the result is neither a vector
+ nor a predicate, since the distinction between "zeroing" and "merging"
+ doesn't apply in that case. It is also used when a suffix would be
+ redundant (such as for loads and comparisons, which are inherently
+ zeroing operations). */
+ PRED_implicit,
+
+ /* Merging predication: copy inactive lanes from the first data argument
+ to the vector result. */
+ PRED_m,
+
+ /* "Don't care" predication: set inactive lanes of the vector result
+ to arbitrary values. */
+ PRED_x,
+
+ /* Zero predication: set inactive lanes of the vector result to zero. */
+ PRED_z,
+
+ NUM_PREDS
+};
+
+/* Classifies element types, based on type suffixes with the bit count
+ removed. */
+enum type_class_index
+{
+ TYPE_bool,
+ TYPE_float,
+ TYPE_signed,
+ TYPE_unsigned,
+ NUM_TYPE_CLASSES
+};
+
+/* Classifies an operation into "modes"; for example, to distinguish
+ vector-scalar operations from vector-vector operations, or to
+ distinguish between different addressing modes. This classification
+ accounts for the function suffixes that occur between the base name
+ and the first type suffix. */
+enum mode_suffix_index
+{
+#define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) MODE_##NAME,
+#include "aarch64-sve-builtins.def"
+ MODE_none
+};
+
+/* Enumerates the possible type suffixes. Each suffix is associated with
+ a vector type, but for predicates provides extra information about the
+ element size. */
+enum type_suffix_index
+{
+#define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
+ TYPE_SUFFIX_ ## NAME,
+#include "aarch64-sve-builtins.def"
+ NUM_TYPE_SUFFIXES
+};
+
+/* Combines two type suffixes. */
+typedef enum type_suffix_index type_suffix_pair[2];
+
+class function_base;
+class function_shape;
+
+/* Static information about a mode suffix. */
+struct mode_suffix_info
+{
+ /* The suffix string itself. */
+ const char *string;
+
+ /* The type of the vector base address, or NUM_VECTOR_TYPES if the
+ mode does not include a vector base address. */
+ vector_type_index base_vector_type;
+
+ /* The type of the vector displacement, or NUM_VECTOR_TYPES if the
+ mode does not include a vector displacement. (Note that scalar
+ displacements are always int64_t.) */
+ vector_type_index displacement_vector_type;
+
+ /* The units in which the vector or scalar displacement is measured,
+ or UNITS_none if the mode doesn't take a displacement. */
+ units_index displacement_units;
+};
+
+/* Static information about a type suffix. */
+struct type_suffix_info
+{
+ /* The suffix string itself. */
+ const char *string;
+
+ /* The associated ACLE vector or predicate type. */
+ vector_type_index vector_type : 8;
+
+ /* What kind of type the suffix represents. */
+ type_class_index tclass : 8;
+
+ /* The number of bits and bytes in an element. For predicates this
+ measures the associated data elements. */
+ unsigned int element_bits : 8;
+ unsigned int element_bytes : 8;
+
+ /* True if the suffix is for an integer type. */
+ unsigned int integer_p : 1;
+ /* True if the suffix is for an unsigned type. */
+ unsigned int unsigned_p : 1;
+ /* True if the suffix is for a floating-point type. */
+ unsigned int float_p : 1;
+ /* True if the suffix is for a boolean type. */
+ unsigned int bool_p : 1;
+ unsigned int spare : 12;
+
+ /* The associated vector or predicate mode. */
+ machine_mode vector_mode : 16;
+};
+
+/* Static information about a set of functions. */
+struct function_group_info
+{
+ /* The base name, as a string. */
+ const char *base_name;
+
+ /* Describes the behavior associated with the function base name. */
+ const function_base *const *base;
+
+ /* The shape of the functions, as described above the class definition.
+ It's possible to have entries with the same base name but different
+ shapes. */
+ const function_shape *const *shape;
+
+ /* A list of the available type suffixes, and of the available predication
+ types. The function supports every combination of the two.
+
+ The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
+ while the list of predication types is terminated by NUM_PREDS.
+ The list of type suffixes is lexicographically ordered based
+ on the index value. */
+ const type_suffix_pair *types;
+ const predication_index *preds;
+
+ /* The architecture extensions that the functions require, as a set of
+ AARCH64_FL_* flags. */
+ uint64_t required_extensions;
+};
+
+/* Describes a single fully-resolved function (i.e. one that has a
+ unique full name). */
+class GTY((user)) function_instance
+{
+public:
+ function_instance (const char *, const function_base *,
+ const function_shape *, mode_suffix_index,
+ const type_suffix_pair &, predication_index);
+
+ bool operator== (const function_instance &) const;
+ bool operator!= (const function_instance &) const;
+ hashval_t hash () const;
+
+ unsigned int call_properties () const;
+ bool reads_global_state_p () const;
+ bool modifies_global_state_p () const;
+ bool could_trap_p () const;
+
+ unsigned int vectors_per_tuple () const;
+ tree memory_scalar_type () const;
+ machine_mode memory_vector_mode () const;
+
+ const mode_suffix_info &mode_suffix () const;
+ tree base_vector_type () const;
+ tree displacement_vector_type () const;
+ units_index displacement_units () const;
+
+ const type_suffix_info &type_suffix (unsigned int) const;
+ tree scalar_type (unsigned int) const;
+ tree vector_type (unsigned int) const;
+ tree tuple_type (unsigned int) const;
+ unsigned int elements_per_vq (unsigned int i) const;
+ machine_mode vector_mode (unsigned int) const;
+ machine_mode gp_mode (unsigned int) const;
+
+ /* The properties of the function. (The explicit "enum"s are required
+ for gengtype.) */
+ const char *base_name;
+ const function_base *base;
+ const function_shape *shape;
+ enum mode_suffix_index mode_suffix_id;
+ type_suffix_pair type_suffix_ids;
+ enum predication_index pred;
+};
+
+class registered_function;
+
+/* A class for building and registering function decls. */
+class function_builder
+{
+public:
+ function_builder ();
+ ~function_builder ();
+
+ void add_unique_function (const function_instance &, tree,
+ vec<tree> &, uint64_t, bool);
+ void add_overloaded_function (const function_instance &, uint64_t);
+ void add_overloaded_functions (const function_group_info &,
+ mode_suffix_index);
+
+ void register_function_group (const function_group_info &);
+
+private:
+ void append_name (const char *);
+ char *finish_name ();
+
+ char *get_name (const function_instance &, bool);
+
+ tree get_attributes (const function_instance &);
+
+ registered_function &add_function (const function_instance &,
+ const char *, tree, tree, uint64_t, bool);
+
+ /* The function type to use for functions that are resolved by
+ function_resolver. */
+ tree m_overload_type;
+
+ /* True if we should create a separate decl for each instance of an
+ overloaded function, instead of using function_resolver. */
+ bool m_direct_overloads;
+
+ /* Used for building up function names. */
+ obstack m_string_obstack;
+
+ /* Maps all overloaded function names that we've registered so far
+ to their associated function_instances. */
+ hash_map<nofree_string_hash, registered_function *> m_overload_names;
+};
+
+/* A base class for handling calls to built-in functions. */
+class function_call_info : public function_instance
+{
+public:
+ function_call_info (location_t, const function_instance &, tree);
+
+ bool function_returns_void_p ();
+
+ /* The location of the call. */
+ location_t location;
+
+ /* The FUNCTION_DECL that is being called. */
+ tree fndecl;
+};
+
+/* A class for resolving an overloaded function call. */
+class function_resolver : public function_call_info
+{
+public:
+ enum { SAME_SIZE = 256, HALF_SIZE, QUARTER_SIZE };
+ static const type_class_index SAME_TYPE_CLASS = NUM_TYPE_CLASSES;
+
+ function_resolver (location_t, const function_instance &, tree,
+ vec<tree, va_gc> &);
+
+ tree get_vector_type (type_suffix_index);
+ const char *get_scalar_type_name (type_suffix_index);
+ tree get_argument_type (unsigned int);
+ bool scalar_argument_p (unsigned int);
+
+ tree report_no_such_form (type_suffix_index);
+ tree lookup_form (mode_suffix_index,
+ type_suffix_index = NUM_TYPE_SUFFIXES,
+ type_suffix_index = NUM_TYPE_SUFFIXES);
+ tree resolve_to (mode_suffix_index,
+ type_suffix_index = NUM_TYPE_SUFFIXES,
+ type_suffix_index = NUM_TYPE_SUFFIXES);
+
+ type_suffix_index infer_integer_scalar_type (unsigned int);
+ type_suffix_index infer_pointer_type (unsigned int, bool = false);
+ type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
+ type_suffix_index infer_vector_type (unsigned int);
+ type_suffix_index infer_integer_vector_type (unsigned int);
+ type_suffix_index infer_unsigned_vector_type (unsigned int);
+ type_suffix_index infer_sd_vector_type (unsigned int);
+ type_suffix_index infer_tuple_type (unsigned int);
+
+ bool require_vector_or_scalar_type (unsigned int);
+
+ bool require_vector_type (unsigned int, vector_type_index);
+ bool require_matching_vector_type (unsigned int, type_suffix_index);
+ bool require_derived_vector_type (unsigned int, unsigned int,
+ type_suffix_index,
+ type_class_index = SAME_TYPE_CLASS,
+ unsigned int = SAME_SIZE);
+
+ bool require_scalar_type (unsigned int, const char *);
+ bool require_pointer_type (unsigned int);
+ bool require_matching_integer_scalar_type (unsigned int, unsigned int,
+ type_suffix_index);
+ bool require_derived_scalar_type (unsigned int, type_class_index,
+ unsigned int = SAME_SIZE);
+ bool require_integer_immediate (unsigned int);
+
+ vector_type_index infer_vector_base_type (unsigned int);
+ vector_type_index infer_vector_displacement_type (unsigned int);
+
+ mode_suffix_index resolve_sv_displacement (unsigned int,
+ type_suffix_index, bool);
+ mode_suffix_index resolve_gather_address (unsigned int,
+ type_suffix_index, bool);
+ mode_suffix_index resolve_adr_address (unsigned int);
+
+ bool check_num_arguments (unsigned int);
+ bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
+ tree resolve_unary (type_class_index = SAME_TYPE_CLASS,
+ unsigned int = SAME_SIZE);
+ tree resolve_uniform (unsigned int, unsigned int = 0);
+ tree resolve_uniform_opt_n (unsigned int);
+ tree finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index,
+ type_class_index = SAME_TYPE_CLASS,
+ unsigned int = SAME_SIZE);
+
+ tree resolve ();
+
+private:
+ /* The arguments to the overloaded function. */
+ vec<tree, va_gc> &m_arglist;
+};
+
+/* A class for checking that the semantic constraints on a function call are
+ satisfied, such as arguments being integer constant expressions with
+ a particular range. The parent class's FNDECL is the decl that was
+ called in the original source, before overload resolution. */
+class function_checker : public function_call_info
+{
+public:
+ function_checker (location_t, const function_instance &, tree,
+ tree, unsigned int, tree *);
+
+ bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
+ HOST_WIDE_INT);
+ bool require_immediate_enum (unsigned int, tree);
+ bool require_immediate_lane_index (unsigned int, unsigned int = 1);
+ bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
+ HOST_WIDE_INT, HOST_WIDE_INT);
+ bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
+
+ bool check ();
+
+private:
+ bool argument_exists_p (unsigned int);
+
+ bool require_immediate (unsigned int, HOST_WIDE_INT &);
+
+ /* The type of the resolved function. */
+ tree m_fntype;
+
+ /* The arguments to the function. */
+ unsigned int m_nargs;
+ tree *m_args;
+
+ /* The first argument not associated with the function's predication
+ type. */
+ unsigned int m_base_arg;
+};
+
+/* A class for folding a gimple function call. */
+class gimple_folder : public function_call_info
+{
+public:
+ gimple_folder (const function_instance &, tree,
+ gimple_stmt_iterator *, gcall *);
+
+ tree convert_pred (gimple_seq &, tree, unsigned int);
+ tree fold_contiguous_base (gimple_seq &, tree);
+ tree load_store_cookie (tree);
+
+ gimple *fold_to_pfalse ();
+ gimple *fold_to_ptrue ();
+ gimple *fold_to_vl_pred (unsigned int);
+
+ gimple *fold ();
+
+ /* Where to insert extra statements that feed the final replacement. */
+ gimple_stmt_iterator *gsi;
+
+ /* The call we're folding. */
+ gcall *call;
+
+ /* The result of the call, or null if none. */
+ tree lhs;
+};
+
+/* A class for expanding a function call into RTL. */
+class function_expander : public function_call_info
+{
+public:
+ function_expander (const function_instance &, tree, tree, rtx);
+ rtx expand ();
+
+ insn_code direct_optab_handler (optab, unsigned int = 0);
+ insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
+ machine_mode = E_VOIDmode);
+
+ bool overlaps_input_p (rtx);
+
+ rtx get_contiguous_base (machine_mode);
+ rtx get_fallback_value (machine_mode, unsigned int,
+ unsigned int, unsigned int &);
+ rtx get_reg_target ();
+ rtx get_nonoverlapping_reg_target ();
+
+ void add_output_operand (insn_code);
+ void add_input_operand (insn_code, rtx);
+ void add_integer_operand (HOST_WIDE_INT);
+ void add_mem_operand (machine_mode, rtx);
+ void add_address_operand (rtx);
+ void add_fixed_operand (rtx);
+ rtx generate_insn (insn_code);
+
+ void prepare_gather_address_operands (unsigned int);
+ void prepare_prefetch_operands ();
+ void add_ptrue_hint (unsigned int, machine_mode);
+ void rotate_inputs_left (unsigned int, unsigned int);
+ bool try_negating_argument (unsigned int, machine_mode);
+
+ rtx use_exact_insn (insn_code);
+ rtx use_unpred_insn (insn_code);
+ rtx use_pred_x_insn (insn_code);
+ rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
+ rtx use_vcond_mask_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
+ rtx use_contiguous_load_insn (insn_code);
+ rtx use_contiguous_prefetch_insn (insn_code);
+ rtx use_contiguous_store_insn (insn_code);
+
+ rtx map_to_rtx_codes (rtx_code, rtx_code, int,
+ unsigned int = DEFAULT_MERGE_ARGNO);
+ rtx map_to_unspecs (int, int, int, unsigned int = DEFAULT_MERGE_ARGNO);
+ rtx expand_signed_unpred_op (rtx_code, rtx_code);
+
+ /* The function call expression. */
+ tree call_expr;
+
+ /* For functions that return a value, this is the preferred location
+ of that value. It could be null or could have a different mode
+ from the function return type. */
+ rtx possible_target;
+
+ /* The expanded arguments. */
+ auto_vec<rtx, 16> args;
+
+private:
+ /* Used to build up the operands to an instruction. */
+ auto_vec<expand_operand, 8> m_ops;
+};
+
+/* Provides information about a particular function base name, and handles
+ tasks related to the base name. */
+class function_base
+{
+public:
+ /* Return a set of CP_* flags that describe what the function might do,
+ in addition to reading its arguments and returning a result. */
+ virtual unsigned int call_properties (const function_instance &) const;
+
+ /* If the function operates on tuples of vectors, return the number
+ of vectors in the tuples, otherwise return 1. */
+ virtual unsigned int vectors_per_tuple () const { return 1; }
+
+ /* If the function addresses memory, return the type of a single
+ scalar memory element. */
+ virtual tree
+ memory_scalar_type (const function_instance &) const
+ {
+ gcc_unreachable ();
+ }
+
+ /* If the function addresses memory, return a vector mode whose
+ GET_MODE_NUNITS is the number of elements addressed and whose
+ GET_MODE_INNER is the mode of a single scalar memory element. */
+ virtual machine_mode
+ memory_vector_mode (const function_instance &) const
+ {
+ gcc_unreachable ();
+ }
+
+ /* Try to fold the given gimple call. Return the new gimple statement
+ on success, otherwise return null. */
+ virtual gimple *fold (gimple_folder &) const { return NULL; }
+
+ /* Expand the given call into rtl. Return the result of the function,
+ or an arbitrary value if the function doesn't return a result. */
+ virtual rtx expand (function_expander &) const = 0;
+};
+
+/* Classifies functions into "shapes". The idea is to take all the
+ type signatures for a set of functions, remove the governing predicate
+ (if any), and classify what's left based on:
+
+ - the number of arguments
+
+ - the process of determining the types in the signature from the mode
+ and type suffixes in the function name (including types that are not
+ affected by the suffixes)
+
+ - which arguments must be integer constant expressions, and what range
+ those arguments have
+
+ - the process for mapping overloaded names to "full" names. */
+class function_shape
+{
+public:
+ virtual bool explicit_type_suffix_p (unsigned int) const = 0;
+
+ /* Define all functions associated with the given group. */
+ virtual void build (function_builder &,
+ const function_group_info &) const = 0;
+
+ /* Try to resolve the overloaded call. Return the non-overloaded
+ function decl on success and error_mark_node on failure. */
+ virtual tree resolve (function_resolver &) const = 0;
+
+ /* Check whether the given call is semantically valid. Return true
+ if it is, otherwise report an error and return false. */
+ virtual bool check (function_checker &) const { return true; }
+};
+
+/* RAII class for enabling enough SVE features to define the built-in
+ types and implement the arm_sve.h pragma. */
+class sve_switcher
+{
+public:
+ sve_switcher ();
+ ~sve_switcher ();
+
+private:
+ unsigned long m_old_isa_flags;
+ bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
+};
+
+extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
+extern const mode_suffix_info mode_suffixes[MODE_none + 1];
+
+extern tree scalar_types[NUM_VECTOR_TYPES];
+extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+extern tree acle_svpattern;
+extern tree acle_svprfop;
+
+/* Return the ACLE type svbool_t. */
+inline tree
+get_svbool_t (void)
+{
+ return acle_vector_types[0][VECTOR_TYPE_svbool_t];
+}
+
+/* Try to find a mode with the given mode_suffix_info fields. Return the
+ mode on success or MODE_none on failure. */
+inline mode_suffix_index
+find_mode_suffix (vector_type_index base_vector_type,
+ vector_type_index displacement_vector_type,
+ units_index displacement_units)
+{
+ for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
+ {
+ const mode_suffix_info &mode = mode_suffixes[mode_i];
+ if (mode.base_vector_type == base_vector_type
+ && mode.displacement_vector_type == displacement_vector_type
+ && mode.displacement_units == displacement_units)
+ return mode_suffix_index (mode_i);
+ }
+ return MODE_none;
+}
+
+/* Return the type suffix associated with ELEMENT_BITS-bit elements of type
+ class TCLASS. */
+inline type_suffix_index
+find_type_suffix (type_class_index tclass, unsigned int element_bits)
+{
+ for (unsigned int i = 0; i < NUM_TYPE_SUFFIXES; ++i)
+ if (type_suffixes[i].tclass == tclass
+ && type_suffixes[i].element_bits == element_bits)
+ return type_suffix_index (i);
+ gcc_unreachable ();
+}
+
+/* Return the single field in tuple type TYPE. */
+inline tree
+tuple_type_field (tree type)
+{
+ for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ return field;
+ gcc_unreachable ();
+}
+
+inline function_instance::
+function_instance (const char *base_name_in,
+ const function_base *base_in,
+ const function_shape *shape_in,
+ mode_suffix_index mode_suffix_id_in,
+ const type_suffix_pair &type_suffix_ids_in,
+ predication_index pred_in)
+ : base_name (base_name_in), base (base_in), shape (shape_in),
+ mode_suffix_id (mode_suffix_id_in), pred (pred_in)
+{
+ memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
+}
+
+inline bool
+function_instance::operator== (const function_instance &other) const
+{
+ return (base == other.base
+ && shape == other.shape
+ && mode_suffix_id == other.mode_suffix_id
+ && pred == other.pred
+ && type_suffix_ids[0] == other.type_suffix_ids[0]
+ && type_suffix_ids[1] == other.type_suffix_ids[1]);
+}
+
+inline bool
+function_instance::operator!= (const function_instance &other) const
+{
+ return !operator== (other);
+}
+
+/* If the function operates on tuples of vectors, return the number
+ of vectors in the tuples, otherwise return 1. */
+inline unsigned int
+function_instance::vectors_per_tuple () const
+{
+ return base->vectors_per_tuple ();
+}
+
+/* If the function addresses memory, return the type of a single
+ scalar memory element. */
+inline tree
+function_instance::memory_scalar_type () const
+{
+ return base->memory_scalar_type (*this);
+}
+
+/* If the function addresses memory, return a vector mode whose
+ GET_MODE_NUNITS is the number of elements addressed and whose
+ GET_MODE_INNER is the mode of a single scalar memory element. */
+inline machine_mode
+function_instance::memory_vector_mode () const
+{
+ return base->memory_vector_mode (*this);
+}
+
+/* Return information about the function's mode suffix. */
+inline const mode_suffix_info &
+function_instance::mode_suffix () const
+{
+ return mode_suffixes[mode_suffix_id];
+}
+
+/* Return the type of the function's vector base address argument,
+ or null it doesn't have a vector base address. */
+inline tree
+function_instance::base_vector_type () const
+{
+ return acle_vector_types[0][mode_suffix ().base_vector_type];
+}
+
+/* Return the type of the function's vector index or offset argument,
+ or null if doesn't have a vector index or offset argument. */
+inline tree
+function_instance::displacement_vector_type () const
+{
+ return acle_vector_types[0][mode_suffix ().displacement_vector_type];
+}
+
+/* If the function takes a vector or scalar displacement, return the units
+ in which the displacement is measured, otherwise return UNITS_none. */
+inline units_index
+function_instance::displacement_units () const
+{
+ return mode_suffix ().displacement_units;
+}
+
+/* Return information about type suffix I. */
+inline const type_suffix_info &
+function_instance::type_suffix (unsigned int i) const
+{
+ return type_suffixes[type_suffix_ids[i]];
+}
+
+/* Return the scalar type associated with type suffix I. */
+inline tree
+function_instance::scalar_type (unsigned int i) const
+{
+ return scalar_types[type_suffix (i).vector_type];
+}
+
+/* Return the vector type associated with type suffix I. */
+inline tree
+function_instance::vector_type (unsigned int i) const
+{
+ return acle_vector_types[0][type_suffix (i).vector_type];
+}
+
+/* If the function operates on tuples of vectors, return the tuple type
+ associated with type suffix I, otherwise return the vector type associated
+ with type suffix I. */
+inline tree
+function_instance::tuple_type (unsigned int i) const
+{
+ unsigned int num_vectors = vectors_per_tuple ();
+ return acle_vector_types[num_vectors - 1][type_suffix (i).vector_type];
+}
+
+/* Return the number of elements of type suffix I that fit within a
+ 128-bit block. */
+inline unsigned int
+function_instance::elements_per_vq (unsigned int i) const
+{
+ return 128 / type_suffix (i).element_bits;
+}
+
+/* Return the vector or predicate mode associated with type suffix I. */
+inline machine_mode
+function_instance::vector_mode (unsigned int i) const
+{
+ return type_suffix (i).vector_mode;
+}
+
+/* Return the mode of the governing predicate to use when operating on
+ type suffix I. */
+inline machine_mode
+function_instance::gp_mode (unsigned int i) const
+{
+ return aarch64_sve_pred_mode (type_suffix (i).element_bytes).require ();
+}
+
+/* Return true if the function has no return value. */
+inline bool
+function_call_info::function_returns_void_p ()
+{
+ return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+}
+
+/* Default implementation of function::call_properties, with conservatively
+ correct behavior for floating-point instructions. */
+inline unsigned int
+function_base::call_properties (const function_instance &instance) const
+{
+ unsigned int flags = 0;
+ if (instance.type_suffix (0).float_p || instance.type_suffix (1).float_p)
+ flags |= CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
+ return flags;
+}
+
+}
+
+#endif
;; ---- Description of UNSPEC_PRED_Z
;; ---- Note on predicated integer arithemtic and UNSPEC_PRED_X
;; ---- Note on predicated FP arithmetic patterns and GP "strictness"
+;; ---- Note on FFR handling
;;
;; == Moves
;; ---- Moves of single vectors
;; ---- Moves of multiple vectors
;; ---- Moves of predicates
+;; ---- Moves relating to the FFR
;;
;; == Loads
;; ---- Normal contiguous loads
+;; ---- Extending contiguous loads
+;; ---- First-faulting contiguous loads
+;; ---- First-faulting extending contiguous loads
+;; ---- Non-temporal contiguous loads
;; ---- Normal gather loads
+;; ---- Extending gather loads
+;; ---- First-faulting gather loads
+;; ---- First-faulting extending gather loads
+;;
+;; == Prefetches
+;; ---- Contiguous prefetches
+;; ---- Gather prefetches
;;
;; == Stores
;; ---- Normal contiguous stores
+;; ---- Truncating contiguous stores
+;; ---- Non-temporal contiguous stores
;; ---- Normal scatter stores
+;; ---- Truncating scatter stores
;;
;; == Vector creation
;; ---- [INT,FP] Duplicate element
;; == Unary arithmetic
;; ---- [INT] General unary arithmetic corresponding to rtx codes
;; ---- [INT] General unary arithmetic corresponding to unspecs
+;; ---- [INT] Sign extension
;; ---- [INT] Zero extension
;; ---- [INT] Logical inverse
+;; ---- [FP<-INT] General unary arithmetic that maps to unspecs
;; ---- [FP] General unary arithmetic corresponding to unspecs
;; ---- [PRED] Inverse
;; ---- [INT] Subtraction
;; ---- [INT] Take address
;; ---- [INT] Absolute difference
+;; ---- [INT] Saturating addition and subtraction
;; ---- [INT] Highpart multiplication
;; ---- [INT] Division
;; ---- [INT] Binary logical operations
;; ---- [INT] Binary logical operations (inverted second input)
-;; ---- [INT] Shifts
+;; ---- [INT] Shifts (rounding towards -Inf)
;; ---- [INT] Shifts (rounding towards 0)
+;; ---- [FP<-INT] General binary arithmetic corresponding to unspecs
;; ---- [FP] General binary arithmetic corresponding to rtx codes
;; ---- [FP] General binary arithmetic corresponding to unspecs
;; ---- [FP] Addition
+;; ---- [FP] Complex addition
;; ---- [FP] Subtraction
;; ---- [FP] Absolute difference
;; ---- [FP] Multiplication
;; ---- [INT] Dot product
;; ---- [INT] Sum of absolute differences
;; ---- [FP] General ternary arithmetic corresponding to unspecs
+;; ---- [FP] Complex multiply-add
+;; ---- [FP] Trigonometric multiply-add
;;
;; == Comparisons and selects
;; ---- [INT,FP] Select based on predicates
;; ---- [INT] While tests
;; ---- [FP] Direct comparisons
;; ---- [FP] Absolute comparisons
+;; ---- [PRED] Select
;; ---- [PRED] Test bits
;;
;; == Reductions
;; ---- [FP<-FP] Unpacks
;; ---- [PRED<-PRED] Packs
;; ---- [PRED<-PRED] Unpacks
+;;
+;; == Vector partitioning
+;; ---- [PRED] Unary partitioning
+;; ---- [PRED] Binary partitioning
+;; ---- [PRED] Scalarization
+;;
+;; == Counting elements
+;; ---- [INT] Count elements in a pattern (scalar)
+;; ---- [INT] Increment by the number of elements in a pattern (scalar)
+;; ---- [INT] Increment by the number of elements in a pattern (vector)
+;; ---- [INT] Decrement by the number of elements in a pattern (scalar)
+;; ---- [INT] Decrement by the number of elements in a pattern (vector)
+;; ---- [INT] Count elements in a predicate (scalar)
+;; ---- [INT] Increment by the number of elements in a predicate (scalar)
+;; ---- [INT] Increment by the number of elements in a predicate (vector)
+;; ---- [INT] Decrement by the number of elements in a predicate (scalar)
+;; ---- [INT] Decrement by the number of elements in a predicate (vector)
;; =========================================================================
;; == General notes
;; - OP0 OP1 ... are the normal input operands to the operation.
;;
;; - MNEMONIC is the mnemonic of the associated SVE instruction.
+;;
+;; -------------------------------------------------------------------------
+;; ---- Note on FFR handling
+;; -------------------------------------------------------------------------
+;;
+;; Logically we want to divide FFR-related instructions into regions
+;; that contain exactly one of:
+;;
+;; - a single write to the FFR
+;; - any number of reads from the FFR (but only one read is likely)
+;; - any number of LDFF1 and LDNF1 instructions
+;;
+;; However, LDFF1 and LDNF1 instructions should otherwise behave like
+;; normal loads as far as possible. This means that they should be
+;; schedulable within a region in the same way that LD1 would be,
+;; and they should be deleted as dead if the result is unused. The loads
+;; should therefore not write to the FFR, since that would both serialize
+;; the loads with respect to each other and keep the loads live for any
+;; later RDFFR.
+;;
+;; We get around this by using a fake "FFR token" (FFRT) to help describe
+;; the dependencies. Writing to the FFRT starts a new "FFRT region",
+;; while using the FFRT keeps the instruction within its region.
+;; Specifically:
+;;
+;; - Writes start a new FFRT region as well as setting the FFR:
+;;
+;; W1: parallel (FFRT = <new value>, FFR = <actual FFR value>)
+;;
+;; - Loads use an LD1-like instruction that also uses the FFRT, so that the
+;; loads stay within the same FFRT region:
+;;
+;; L1: load data while using the FFRT
+;;
+;; In addition, any FFRT region that includes a load also has at least one
+;; instance of:
+;;
+;; L2: FFR = update(FFR, FFRT) [type == no_insn]
+;;
+;; to make it clear that the region both reads from and writes to the FFR.
+;;
+;; - Reads do the following:
+;;
+;; R1: FFRT = FFR [type == no_insn]
+;; R2: read from the FFRT
+;; R3: FFRT = update(FFRT) [type == no_insn]
+;;
+;; R1 and R3 both create new FFRT regions, so that previous LDFF1s and
+;; LDNF1s cannot move forwards across R1 and later LDFF1s and LDNF1s
+;; cannot move backwards across R3.
+;;
+;; This way, writes are only kept alive by later loads or reads,
+;; and write/read pairs fold normally. For two consecutive reads,
+;; the first R3 is made dead by the second R1, which in turn becomes
+;; redundant with the first R1. We then have:
+;;
+;; first R1: FFRT = FFR
+;; first read from the FFRT
+;; second read from the FFRT
+;; second R3: FFRT = update(FFRT)
+;;
+;; i.e. the two FFRT regions collapse into a single one with two
+;; independent reads.
+;;
+;; The model still prevents some valid optimizations though. For example,
+;; if all loads in an FFRT region are deleted as dead, nothing would remove
+;; the L2 instructions.
;; =========================================================================
;; == Moves
;; special predicate for operand 1 to reduce the number of patterns.
(define_insn_and_split "*aarch64_sve_reinterpret<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w")
- (unspec:SVE_ALL [(match_operand 1 "aarch64_any_register_operand" "0")]
+ (unspec:SVE_ALL [(match_operand 1 "aarch64_any_register_operand" "w")]
UNSPEC_REINTERPRET))]
"TARGET_SVE"
"#"
"&& reload_completed"
[(set (match_dup 0) (match_dup 1))]
{
- emit_note (NOTE_INSN_DELETED);
- DONE;
+ operands[1] = aarch64_replace_reg_mode (operands[1], <MODE>mode);
}
)
;; - LDR
;; - PFALSE
;; - PTRUE
+;; - PTRUES
;; - STR
;; -------------------------------------------------------------------------
* return aarch64_output_sve_mov_immediate (operands[1]);"
)
+;; Match PTRUES Pn.B when both the predicate and flags are useful.
+(define_insn_and_rewrite "*aarch64_sve_ptruevnx16bi_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 2)
+ (match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+ [(unspec:VNx16BI
+ [(match_operand:SI 4 "const_int_operand")
+ (match_operand:VNx16BI 5 "aarch64_simd_imm_zero")]
+ UNSPEC_PTRUE)])]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (match_dup 1))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_ptrues (operands[1]);
+ }
+ "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+ {
+ operands[2] = operands[3] = CONSTM1_RTX (VNx16BImode);
+ }
+)
+
+;; Match PTRUES Pn.[HSD] when both the predicate and flags are useful.
+(define_insn_and_rewrite "*aarch64_sve_ptrue<mode>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 2)
+ (match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (subreg:PRED_HSD
+ (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+ [(unspec:VNx16BI
+ [(match_operand:SI 4 "const_int_operand")
+ (match_operand:PRED_HSD 5 "aarch64_simd_imm_zero")]
+ UNSPEC_PTRUE)]) 0)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (match_dup 1))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_ptrues (operands[1]);
+ }
+ "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+ {
+ operands[2] = CONSTM1_RTX (VNx16BImode);
+ operands[3] = CONSTM1_RTX (<MODE>mode);
+ }
+)
+
+;; Match PTRUES Pn.B when only the flags result is useful (which is
+;; a way of testing VL).
+(define_insn_and_rewrite "*aarch64_sve_ptruevnx16bi_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 2)
+ (match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+ [(unspec:VNx16BI
+ [(match_operand:SI 4 "const_int_operand")
+ (match_operand:VNx16BI 5 "aarch64_simd_imm_zero")]
+ UNSPEC_PTRUE)])]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_ptrues (operands[1]);
+ }
+ "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+ {
+ operands[2] = operands[3] = CONSTM1_RTX (VNx16BImode);
+ }
+)
+
+;; Match PTRUES Pn.[HWD] when only the flags result is useful (which is
+;; a way of testing VL).
+(define_insn_and_rewrite "*aarch64_sve_ptrue<mode>_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 2)
+ (match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (subreg:PRED_HSD
+ (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+ [(unspec:VNx16BI
+ [(match_operand:SI 4 "const_int_operand")
+ (match_operand:PRED_HSD 5 "aarch64_simd_imm_zero")]
+ UNSPEC_PTRUE)]) 0)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_ptrues (operands[1]);
+ }
+ "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+ {
+ operands[2] = CONSTM1_RTX (VNx16BImode);
+ operands[3] = CONSTM1_RTX (<MODE>mode);
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Moves relating to the FFR
+;; -------------------------------------------------------------------------
+;; RDFFR
+;; RDFFRS
+;; SETFFR
+;; WRFFR
+;; -------------------------------------------------------------------------
+
+;; [W1 in the block comment above about FFR handling]
+;;
+;; Write to the FFR and start a new FFRT scheduling region.
+(define_insn "aarch64_wrffr"
+ [(set (reg:VNx16BI FFR_REGNUM)
+ (match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one" "Dm, Upa"))
+ (set (reg:VNx16BI FFRT_REGNUM)
+ (match_dup 0))]
+ "TARGET_SVE"
+ "@
+ setffr
+ wrffr\t%0.b"
+)
+
+;; [L2 in the block comment above about FFR handling]
+;;
+;; Introduce a read from and write to the FFR in the current FFRT region,
+;; so that the FFR value is live on entry to the region and so that the FFR
+;; value visibly changes within the region. This is used (possibly multiple
+;; times) in an FFRT region that includes LDFF1 or LDNF1 instructions.
+(define_insn "aarch64_update_ffr_for_load"
+ [(set (reg:VNx16BI FFR_REGNUM)
+ (unspec:VNx16BI [(reg:VNx16BI FFRT_REGNUM)
+ (reg:VNx16BI FFR_REGNUM)] UNSPEC_UPDATE_FFR))]
+ "TARGET_SVE"
+ ""
+ [(set_attr "type" "no_insn")]
+)
+
+;; [R1 in the block comment above about FFR handling]
+;;
+;; Notionally copy the FFR to the FFRT, so that the current FFR value
+;; can be read from there by the RDFFR instructions below. This acts
+;; as a scheduling barrier for earlier LDFF1 and LDNF1 instructions and
+;; creates a natural dependency with earlier writes.
+(define_insn "aarch64_copy_ffr_to_ffrt"
+ [(set (reg:VNx16BI FFRT_REGNUM)
+ (reg:VNx16BI FFR_REGNUM))]
+ "TARGET_SVE"
+ ""
+ [(set_attr "type" "no_insn")]
+)
+
+;; [R2 in the block comment above about FFR handling]
+;;
+;; Read the FFR via the FFRT.
+(define_insn "aarch64_rdffr"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (reg:VNx16BI FFRT_REGNUM))]
+ "TARGET_SVE"
+ "rdffr\t%0.b"
+)
+
+;; Likewise with zero predication.
+(define_insn "aarch64_rdffr_z"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (reg:VNx16BI FFRT_REGNUM)
+ (match_operand:VNx16BI 1 "register_operand" "Upa")))]
+ "TARGET_SVE"
+ "rdffr\t%0.b, %1/z"
+)
+
+;; Read the FFR to test for a fault, without using the predicate result.
+(define_insn "*aarch64_rdffr_z_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_dup 1)
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (and:VNx16BI
+ (reg:VNx16BI FFRT_REGNUM)
+ (match_dup 1))]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ "rdffrs\t%0.b, %1/z"
+)
+
+;; Same for unpredicated RDFFR when tested with a known PTRUE.
+(define_insn "*aarch64_rdffr_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_dup 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ "rdffrs\t%0.b, %1/z"
+)
+
+;; Read the FFR with zero predication and test the result.
+(define_insn "*aarch64_rdffr_z_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_dup 1)
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (and:VNx16BI
+ (reg:VNx16BI FFRT_REGNUM)
+ (match_dup 1))]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (and:VNx16BI
+ (reg:VNx16BI FFRT_REGNUM)
+ (match_dup 1)))]
+ "TARGET_SVE"
+ "rdffrs\t%0.b, %1/z"
+)
+
+;; Same for unpredicated RDFFR when tested with a known PTRUE.
+(define_insn "*aarch64_rdffr_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_dup 1)
+ (const_int SVE_KNOWN_PTRUE)
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (reg:VNx16BI FFRT_REGNUM))]
+ "TARGET_SVE"
+ "rdffrs\t%0.b, %1/z"
+)
+
+;; [R3 in the block comment above about FFR handling]
+;;
+;; Arbitrarily update the FFRT after a read from the FFR. This acts as
+;; a scheduling barrier for later LDFF1 and LDNF1 instructions.
+(define_insn "aarch64_update_ffrt"
+ [(set (reg:VNx16BI FFRT_REGNUM)
+ (unspec:VNx16BI [(reg:VNx16BI FFRT_REGNUM)] UNSPEC_UPDATE_FFRT))]
+ "TARGET_SVE"
+ ""
+ [(set_attr "type" "no_insn")]
+)
+
;; =========================================================================
;; == Loads
;; =========================================================================
"ld<vector_count><Vesize>\t%0, %2/z, %1"
)
+;; -------------------------------------------------------------------------
+;; ---- Extending contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; LD1B
+;; LD1H
+;; LD1SB
+;; LD1SH
+;; LD1SW
+;; LD1W
+;; -------------------------------------------------------------------------
+
+;; Predicated load and extend, with 8 elements per 128-bit block.
+(define_insn "@aarch64_load_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>"
+ [(set (match_operand:VNx8_WIDE 0 "register_operand" "=w")
+ (ANY_EXTEND:VNx8_WIDE
+ (unspec:VNx8_NARROW
+ [(match_operand:VNx8BI 2 "register_operand" "Upl")
+ (match_operand:VNx8_NARROW 1 "memory_operand" "m")]
+ UNSPEC_LD1_SVE)))]
+ "TARGET_SVE"
+ "ld1<ANY_EXTEND:s><VNx8_NARROW:Vesize>\t%0.<VNx8_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated load and extend, with 4 elements per 128-bit block.
+(define_insn "@aarch64_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+ [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w")
+ (ANY_EXTEND:VNx4_WIDE
+ (unspec:VNx4_NARROW
+ [(match_operand:VNx4BI 2 "register_operand" "Upl")
+ (match_operand:VNx4_NARROW 1 "memory_operand" "m")]
+ UNSPEC_LD1_SVE)))]
+ "TARGET_SVE"
+ "ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.<VNx4_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated load and extend, with 2 elements per 128-bit block.
+(define_insn "@aarch64_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 2 "register_operand" "Upl")
+ (match_operand:VNx2_NARROW 1 "memory_operand" "m")]
+ UNSPEC_LD1_SVE)))]
+ "TARGET_SVE"
+ "ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.<VNx2_WIDE:Vetype>, %2/z, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- First-faulting contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - LDFF1B
+;; - LDFF1D
+;; - LDFF1H
+;; - LDFF1W
+;; - LDNF1B
+;; - LDNF1D
+;; - LDNF1H
+;; - LDNF1W
+;; -------------------------------------------------------------------------
+
+;; Contiguous non-extending first-faulting or non-faulting loads.
+(define_insn "@aarch64_ld<fn>f1<mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+ (unspec:SVE_ALL
+ [(match_operand:<VPRED> 2 "register_operand" "Upl")
+ (match_operand:SVE_ALL 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+ (reg:VNx16BI FFRT_REGNUM)]
+ SVE_LDFF1_LDNF1))]
+ "TARGET_SVE"
+ "ld<fn>f1<Vesize>\t%0.<Vetype>, %2/z, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- First-faulting extending contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - LDFF1B
+;; - LDFF1H
+;; - LDFF1SB
+;; - LDFF1SH
+;; - LDFF1SW
+;; - LDFF1W
+;; - LDNF1B
+;; - LDNF1H
+;; - LDNF1SB
+;; - LDNF1SH
+;; - LDNF1SW
+;; - LDNF1W
+;; -------------------------------------------------------------------------
+
+;; Predicated first-faulting or non-faulting load and extend, with 8 elements
+;; per 128-bit block.
+(define_insn "@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>"
+ [(set (match_operand:VNx8_WIDE 0 "register_operand" "=w")
+ (ANY_EXTEND:VNx8_WIDE
+ (unspec:VNx8_NARROW
+ [(match_operand:VNx8BI 2 "register_operand" "Upl")
+ (match_operand:VNx8_NARROW 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+ (reg:VNx16BI FFRT_REGNUM)]
+ SVE_LDFF1_LDNF1)))]
+ "TARGET_SVE"
+ "ld<fn>f1<ANY_EXTEND:s><VNx8_NARROW:Vesize>\t%0.<VNx8_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated first-faulting or non-faulting load and extend, with 4 elements
+;; per 128-bit block.
+(define_insn "@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+ [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w")
+ (ANY_EXTEND:VNx4_WIDE
+ (unspec:VNx4_NARROW
+ [(match_operand:VNx4BI 2 "register_operand" "Upl")
+ (match_operand:VNx4_NARROW 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+ (reg:VNx16BI FFRT_REGNUM)]
+ SVE_LDFF1_LDNF1)))]
+ "TARGET_SVE"
+ "ld<fn>f1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.<VNx4_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated first-faulting or non-faulting load and extend, with 2 elements
+;; per 128-bit block.
+(define_insn "@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 2 "register_operand" "Upl")
+ (match_operand:VNx2_NARROW 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+ (reg:VNx16BI FFRT_REGNUM)]
+ SVE_LDFF1_LDNF1)))]
+ "TARGET_SVE"
+ "ld<fn>f1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.<VNx2_WIDE:Vetype>, %2/z, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Non-temporal contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - LDNT1B
+;; - LDNT1D
+;; - LDNT1H
+;; - LDNT1W
+;; -------------------------------------------------------------------------
+
+;; Predicated contiguous non-temporal load.
+(define_insn "@aarch64_ldnt1<mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+ (unspec:SVE_ALL
+ [(match_operand:<VPRED> 2 "register_operand" "Upl")
+ (match_operand:SVE_ALL 1 "memory_operand" "m")]
+ UNSPEC_LDNT1_SVE))]
+ "TARGET_SVE"
+ "ldnt1<Vesize>\t%0.<Vetype>, %2/z, %1"
+)
+
;; -------------------------------------------------------------------------
;; ---- Normal gather loads
;; -------------------------------------------------------------------------
[(set (match_operand:SVE_SD 0 "register_operand")
(unspec:SVE_SD
[(match_dup 5)
- (match_operand:DI 1 "aarch64_reg_or_zero")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<Vesize>")
(match_operand:<V_INT_EQUIV> 2 "register_operand")
(match_operand:DI 3 "const_int_operand")
(match_operand:DI 4 "aarch64_gather_scale_operand_<Vesize>")
;; Predicated gather loads for 32-bit elements. Operand 3 is true for
;; unsigned extension and false for signed extension.
(define_insn "mask_gather_load<mode>"
- [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w")
+ [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w, w")
(unspec:SVE_S
- [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
- (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
- (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w, w, w")
- (match_operand:DI 3 "const_int_operand" "i, Z, Ui1, Z, Ui1")
- (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
+ [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_w" "Z, vgw, rk, rk, rk, rk")
+ (match_operand:VNx4SI 2 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 3 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, Ui1, i, i")
(mem:BLK (scratch))]
UNSPEC_LD1_GATHER))]
"TARGET_SVE"
"@
ld1w\t%0.s, %5/z, [%2.s]
+ ld1w\t%0.s, %5/z, [%2.s, #%1]
ld1w\t%0.s, %5/z, [%1, %2.s, sxtw]
ld1w\t%0.s, %5/z, [%1, %2.s, uxtw]
ld1w\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
;; Predicated gather loads for 64-bit elements. The value of operand 3
;; doesn't matter in this case.
(define_insn "mask_gather_load<mode>"
- [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w")
+ [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w, w")
(unspec:SVE_D
- [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
- (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk")
- (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w")
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_d" "Z, vgd, rk, rk")
+ (match_operand:VNx2DI 2 "register_operand" "w, w, w, w")
(match_operand:DI 3 "const_int_operand")
- (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, Ui1, i")
(mem:BLK (scratch))]
UNSPEC_LD1_GATHER))]
"TARGET_SVE"
"@
ld1d\t%0.d, %5/z, [%2.d]
+ ld1d\t%0.d, %5/z, [%2.d, #%1]
ld1d\t%0.d, %5/z, [%1, %2.d]
ld1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
)
-;; =========================================================================
-;; == Stores
-;; =========================================================================
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn "*mask_gather_load<mode>_sxtw"
+ [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+ (unspec:SVE_D
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "register_operand" "rk, rk")
+ (unspec:VNx2DI
+ [(match_dup 5)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+ (mem:BLK (scratch))]
+ UNSPEC_LD1_GATHER))]
+ "TARGET_SVE"
+ "@
+ ld1d\t%0.d, %5/z, [%1, %2.d, sxtw]
+ ld1d\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*mask_gather_load<mode>_uxtw"
+ [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+ (unspec:SVE_D
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "register_operand" "rk, rk")
+ (and:VNx2DI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")
+ (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+ (mem:BLK (scratch))]
+ UNSPEC_LD1_GATHER))]
+ "TARGET_SVE"
+ "@
+ ld1d\t%0.d, %5/z, [%1, %2.d, uxtw]
+ ld1d\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+)
;; -------------------------------------------------------------------------
-;; ---- Normal contiguous stores
+;; ---- Extending gather loads
;; -------------------------------------------------------------------------
-;; Includes contiguous forms of:
-;; - ST1B
-;; - ST1D
-;; - ST1H
-;; - ST1W
-;; - ST2B
-;; - ST2D
-;; - ST2H
-;; - ST2W
-;; - ST3B
-;; - ST3D
-;; - ST3H
-;; - ST3W
-;; - ST4B
-;; - ST4D
-;; - ST4H
-;; - ST4W
+;; Includes gather forms of:
+;; - LD1B
+;; - LD1H
+;; - LD1SB
+;; - LD1SH
+;; - LD1SW
+;; - LD1W
;; -------------------------------------------------------------------------
-;; Predicated ST1.
-(define_insn "maskstore<mode><vpred>"
- [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
- (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
- (match_operand:SVE_ALL 1 "register_operand" "w")
- (match_dup 0)]
- UNSPEC_ST1_SVE))]
+;; Predicated extending gather loads for 32-bit elements. Operand 3 is
+;; true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_gather_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+ [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w, w, w, w, w, w")
+ (ANY_EXTEND:VNx4_WIDE
+ (unspec:VNx4_NARROW
+ [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx4_NARROW:Vesize>" "Z, vg<VNx4_NARROW:Vesize>, rk, rk, rk, rk")
+ (match_operand:VNx4_WIDE 2 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 3 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx4_NARROW:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+ (mem:BLK (scratch))]
+ UNSPEC_LD1_GATHER)))]
"TARGET_SVE"
- "st1<Vesize>\t%1.<Vetype>, %2, %0"
-)
-
-;; Unpredicated ST[234]. This is always a full update, so the dependence
-;; on the old value of the memory location (via (match_dup 0)) is redundant.
-;; There doesn't seem to be any obvious benefit to treating the all-true
-;; case differently though. In particular, it's very unlikely that we'll
-;; only find out during RTL that a store_lanes is dead.
-(define_expand "vec_store_lanes<mode><vsingle>"
- [(set (match_operand:SVE_STRUCT 0 "memory_operand")
- (unspec:SVE_STRUCT
- [(match_dup 2)
- (match_operand:SVE_STRUCT 1 "register_operand")
- (match_dup 0)]
- UNSPEC_STN))]
+ "@
+ ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s]
+ ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s, #%1]
+ ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw]
+ ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw]
+ ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+ ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
+)
+
+;; Predicated extending gather loads for 64-bit elements. The value of
+;; operand 3 doesn't matter in this case.
+(define_insn "@aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w, w, w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx2_NARROW:Vesize>" "Z, vg<VNx2_NARROW:Vesize>, rk, rk")
+ (match_operand:VNx2_WIDE 2 "register_operand" "w, w, w, w")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, Ui1, Ui1, i")
+ (mem:BLK (scratch))]
+ UNSPEC_LD1_GATHER)))]
+ "TARGET_SVE"
+ "@
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d]
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d, #%1]
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d]
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+ (unspec:VNx2DI
+ [(match_operand 6)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+ (mem:BLK (scratch))]
+ UNSPEC_LD1_GATHER)))]
"TARGET_SVE"
+ "@
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw]
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+ "&& !rtx_equal_p (operands[5], operands[6])"
{
- operands[2] = aarch64_ptrue_reg (<VPRED>mode);
+ operands[6] = copy_rtx (operands[5]);
}
)
-;; Predicated ST[234].
-(define_insn "vec_mask_store_lanes<mode><vsingle>"
- [(set (match_operand:SVE_STRUCT 0 "memory_operand" "+m")
- (unspec:SVE_STRUCT
- [(match_operand:<VPRED> 2 "register_operand" "Upl")
- (match_operand:SVE_STRUCT 1 "register_operand" "w")
- (match_dup 0)]
- UNSPEC_STN))]
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+ (and:VNx2DI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")
+ (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+ (mem:BLK (scratch))]
+ UNSPEC_LD1_GATHER)))]
"TARGET_SVE"
- "st<vector_count><Vesize>\t%1, %2, %0"
+ "@
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw]
+ ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
)
;; -------------------------------------------------------------------------
-;; ---- Normal scatter stores
+;; ---- First-faulting gather loads
;; -------------------------------------------------------------------------
-;; Includes scatter forms of:
-;; - ST1D
-;; - ST1W
+;; Includes gather forms of:
+;; - LDFF1D
+;; - LDFF1W
;; -------------------------------------------------------------------------
-;; Unpredicated scatter stores.
-(define_expand "scatter_store<mode>"
+;; Predicated first-faulting gather loads for 32-bit elements. Operand
+;; 3 is true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_ldff1_gather<mode>"
+ [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w, w")
+ (unspec:SVE_S
+ [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_w" "Z, vgw, rk, rk, rk, rk")
+ (match_operand:VNx4SI 2 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 3 "const_int_operand" "i, i, Z, Ui1, Z, Ui1")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, Ui1, i, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER))]
+ "TARGET_SVE"
+ "@
+ ldff1w\t%0.s, %5/z, [%2.s]
+ ldff1w\t%0.s, %5/z, [%2.s, #%1]
+ ldff1w\t%0.s, %5/z, [%1, %2.s, sxtw]
+ ldff1w\t%0.s, %5/z, [%1, %2.s, uxtw]
+ ldff1w\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+ ldff1w\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
+)
+
+;; Predicated first-faulting gather loads for 64-bit elements. The value
+;; of operand 3 doesn't matter in this case.
+(define_insn "@aarch64_ldff1_gather<mode>"
+ [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w, w")
+ (unspec:SVE_D
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_d" "Z, vgd, rk, rk")
+ (match_operand:VNx2DI 2 "register_operand" "w, w, w, w")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, Ui1, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER))]
+ "TARGET_SVE"
+ "@
+ ldff1d\t%0.d, %5/z, [%2.d]
+ ldff1d\t%0.d, %5/z, [%2.d, #%1]
+ ldff1d\t%0.d, %5/z, [%1, %2.d]
+ ldff1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_ldff1_gather<mode>_sxtw"
+ [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+ (unspec:SVE_D
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "register_operand" "rk, rk")
+ (unspec:VNx2DI
+ [(match_operand 6)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER))]
+ "TARGET_SVE"
+ "@
+ ldff1d\t%0.d, %5/z, [%1, %2.d, sxtw]
+ ldff1d\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+ "&& !rtx_equal_p (operands[5], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[5]);
+ }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_ldff1_gather<mode>_uxtw"
+ [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+ (unspec:SVE_D
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "register_operand" "rk, rk")
+ (and:VNx2DI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")
+ (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER))]
+ "TARGET_SVE"
+ "@
+ ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw]
+ ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- First-faulting extending gather loads
+;; -------------------------------------------------------------------------
+;; Includes gather forms of:
+;; - LDFF1B
+;; - LDFF1H
+;; - LDFF1SB
+;; - LDFF1SH
+;; - LDFF1SW
+;; - LDFF1W
+;; -------------------------------------------------------------------------
+
+;; Predicated extending first-faulting gather loads for 32-bit elements.
+;; Operand 3 is true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+ [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w, w, w, w, w, w")
+ (ANY_EXTEND:VNx4_WIDE
+ (unspec:VNx4_NARROW
+ [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx4_NARROW:Vesize>" "Z, vg<VNx4_NARROW:Vesize>, rk, rk, rk, rk")
+ (match_operand:VNx4_WIDE 2 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 3 "const_int_operand" "i, i, Z, Ui1, Z, Ui1")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx4_NARROW:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER)))]
+ "TARGET_SVE"
+ "@
+ ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s]
+ ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s, #%1]
+ ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw]
+ ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw]
+ ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+ ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
+)
+
+;; Predicated extending first-faulting gather loads for 64-bit elements.
+;; The value of operand 3 doesn't matter in this case.
+(define_insn "@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w, w, w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx2_NARROW:Vesize>" "Z, vg<VNx2_NARROW:Vesize>, rk, rk")
+ (match_operand:VNx2_WIDE 2 "register_operand" "w, w, w, w")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, Ui1, Ui1, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER)))]
+ "TARGET_SVE"
+ "@
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d]
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d, #%1]
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d]
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+ (unspec:VNx2DI
+ [(match_operand 6)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER)))]
+ "TARGET_SVE"
+ "@
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw]
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+ "&& !rtx_equal_p (operands[5], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[5]);
+ }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw"
+ [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+ (ANY_EXTEND:VNx2_WIDE
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+ (and:VNx2DI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")
+ (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+ (mem:BLK (scratch))
+ (reg:VNx16BI FFRT_REGNUM)]
+ UNSPEC_LDFF1_GATHER)))]
+ "TARGET_SVE"
+ "@
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw]
+ ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+)
+
+;; =========================================================================
+;; == Prefetches
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- Contiguous prefetches
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - PRFB
+;; - PRFD
+;; - PRFH
+;; - PRFW
+;; -------------------------------------------------------------------------
+
+;; Contiguous predicated prefetches. Operand 2 gives the real prefetch
+;; operation (as an svprfop), with operands 3 and 4 providing distilled
+;; information.
+(define_insn "@aarch64_sve_prefetch<mode>"
+ [(prefetch (unspec:DI
+ [(match_operand:<VPRED> 0 "register_operand" "Upl")
+ (match_operand:SVE_I 1 "aarch64_sve_prefetch_operand" "UP<Vesize>")
+ (match_operand:DI 2 "const_int_operand")]
+ UNSPEC_SVE_PREFETCH)
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand"))]
+ "TARGET_SVE"
+ {
+ operands[1] = gen_rtx_MEM (<MODE>mode, operands[1]);
+ return aarch64_output_sve_prefetch ("prf<Vesize>", operands[2], "%0, %1");
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Gather prefetches
+;; -------------------------------------------------------------------------
+;; Includes gather forms of:
+;; - PRFB
+;; - PRFD
+;; - PRFH
+;; - PRFW
+;; -------------------------------------------------------------------------
+
+;; Predicated gather prefetches for 32-bit bases and offsets. The operands
+;; are:
+;; 0: the governing predicate
+;; 1: the scalar component of the address
+;; 2: the vector component of the address
+;; 3: 1 for zero extension, 0 for sign extension
+;; 4: the scale multiplier
+;; 5: a vector zero that identifies the mode of data being accessed
+;; 6: the prefetch operator (an svprfop)
+;; 7: the normal RTL prefetch rw flag
+;; 8: the normal RTL prefetch locality value
+(define_insn "@aarch64_sve_gather_prefetch<SVE_I:mode><VNx4SI_ONLY:mode>"
+ [(prefetch (unspec:DI
+ [(match_operand:VNx4BI 0 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<SVE_I:Vesize>" "Z, vg<SVE_I:Vesize>, rk, rk, rk, rk")
+ (match_operand:VNx4SI_ONLY 2 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 3 "const_int_operand" "i, i, Z, Ui1, Z, Ui1")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+ (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+ (match_operand:DI 6 "const_int_operand")]
+ UNSPEC_SVE_PREFETCH_GATHER)
+ (match_operand:DI 7 "const_int_operand")
+ (match_operand:DI 8 "const_int_operand"))]
+ "TARGET_SVE"
+ {
+ static const char *const insns[][2] = {
+ "prf<SVE_I:Vesize>", "%0, [%2.s]",
+ "prf<SVE_I:Vesize>", "%0, [%2.s, #%1]",
+ "prfb", "%0, [%1, %2.s, sxtw]",
+ "prfb", "%0, [%1, %2.s, uxtw]",
+ "prf<SVE_I:Vesize>", "%0, [%1, %2.s, sxtw %p4]",
+ "prf<SVE_I:Vesize>", "%0, [%1, %2.s, uxtw %p4]"
+ };
+ const char *const *parts = insns[which_alternative];
+ return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+ }
+)
+
+;; Predicated gather prefetches for 64-bit elements. The value of operand 3
+;; doesn't matter in this case.
+(define_insn "@aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>"
+ [(prefetch (unspec:DI
+ [(match_operand:VNx2BI 0 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 1 "aarch64_sve_gather_offset_<SVE_I:Vesize>" "Z, vg<SVE_I:Vesize>, rk, rk")
+ (match_operand:VNx2DI_ONLY 2 "register_operand" "w, w, w, w")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, Ui1, Ui1, i")
+ (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+ (match_operand:DI 6 "const_int_operand")]
+ UNSPEC_SVE_PREFETCH_GATHER)
+ (match_operand:DI 7 "const_int_operand")
+ (match_operand:DI 8 "const_int_operand"))]
+ "TARGET_SVE"
+ {
+ static const char *const insns[][2] = {
+ "prf<SVE_I:Vesize>", "%0, [%2.d]",
+ "prf<SVE_I:Vesize>", "%0, [%2.d, #%1]",
+ "prfb", "%0, [%1, %2.d]",
+ "prf<SVE_I:Vesize>", "%0, [%1, %2.d, lsl %p4]"
+ };
+ const char *const *parts = insns[which_alternative];
+ return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+ }
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_sxtw"
+ [(prefetch (unspec:DI
+ [(match_operand:VNx2BI 0 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "register_operand" "rk, rk")
+ (unspec:VNx2DI_ONLY
+ [(match_operand 9)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, i")
+ (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+ (match_operand:DI 6 "const_int_operand")]
+ UNSPEC_SVE_PREFETCH_GATHER)
+ (match_operand:DI 7 "const_int_operand")
+ (match_operand:DI 8 "const_int_operand"))]
+ "TARGET_SVE"
+ {
+ static const char *const insns[][2] = {
+ "prfb", "%0, [%1, %2.d, sxtw]",
+ "prf<SVE_I:Vesize>", "%0, [%1, %2.d, sxtw %p4]"
+ };
+ const char *const *parts = insns[which_alternative];
+ return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+ }
+ "&& !rtx_equal_p (operands[0], operands[9])"
+ {
+ operands[9] = copy_rtx (operands[0]);
+ }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_uxtw"
+ [(prefetch (unspec:DI
+ [(match_operand:VNx2BI 0 "register_operand" "Upl, Upl")
+ (match_operand:DI 1 "register_operand" "rk, rk")
+ (and:VNx2DI_ONLY
+ (match_operand:VNx2DI 2 "register_operand" "w, w")
+ (match_operand:VNx2DI 9 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, i")
+ (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+ (match_operand:DI 6 "const_int_operand")]
+ UNSPEC_SVE_PREFETCH_GATHER)
+ (match_operand:DI 7 "const_int_operand")
+ (match_operand:DI 8 "const_int_operand"))]
+ "TARGET_SVE"
+ {
+ static const char *const insns[][2] = {
+ "prfb", "%0, [%1, %2.d, uxtw]",
+ "prf<SVE_I:Vesize>", "%0, [%1, %2.d, uxtw %p4]"
+ };
+ const char *const *parts = insns[which_alternative];
+ return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+ }
+)
+
+;; =========================================================================
+;; == Stores
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- Normal contiguous stores
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - ST1B
+;; - ST1D
+;; - ST1H
+;; - ST1W
+;; - ST2B
+;; - ST2D
+;; - ST2H
+;; - ST2W
+;; - ST3B
+;; - ST3D
+;; - ST3H
+;; - ST3W
+;; - ST4B
+;; - ST4D
+;; - ST4H
+;; - ST4W
+;; -------------------------------------------------------------------------
+
+;; Predicated ST1.
+(define_insn "maskstore<mode><vpred>"
+ [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
+ (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
+ (match_operand:SVE_ALL 1 "register_operand" "w")
+ (match_dup 0)]
+ UNSPEC_ST1_SVE))]
+ "TARGET_SVE"
+ "st1<Vesize>\t%1.<Vetype>, %2, %0"
+)
+
+;; Unpredicated ST[234]. This is always a full update, so the dependence
+;; on the old value of the memory location (via (match_dup 0)) is redundant.
+;; There doesn't seem to be any obvious benefit to treating the all-true
+;; case differently though. In particular, it's very unlikely that we'll
+;; only find out during RTL that a store_lanes is dead.
+(define_expand "vec_store_lanes<mode><vsingle>"
+ [(set (match_operand:SVE_STRUCT 0 "memory_operand")
+ (unspec:SVE_STRUCT
+ [(match_dup 2)
+ (match_operand:SVE_STRUCT 1 "register_operand")
+ (match_dup 0)]
+ UNSPEC_STN))]
+ "TARGET_SVE"
+ {
+ operands[2] = aarch64_ptrue_reg (<VPRED>mode);
+ }
+)
+
+;; Predicated ST[234].
+(define_insn "vec_mask_store_lanes<mode><vsingle>"
+ [(set (match_operand:SVE_STRUCT 0 "memory_operand" "+m")
+ (unspec:SVE_STRUCT
+ [(match_operand:<VPRED> 2 "register_operand" "Upl")
+ (match_operand:SVE_STRUCT 1 "register_operand" "w")
+ (match_dup 0)]
+ UNSPEC_STN))]
+ "TARGET_SVE"
+ "st<vector_count><Vesize>\t%1, %2, %0"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Truncating contiguous stores
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - ST1B
+;; - ST1H
+;; - ST1W
+;; -------------------------------------------------------------------------
+
+;; Predicated truncate and store, with 8 elements per 128-bit block.
+(define_insn "@aarch64_store_trunc<VNx8_NARROW:mode><VNx8_WIDE:mode>"
+ [(set (match_operand:VNx8_NARROW 0 "memory_operand" "+m")
+ (unspec:VNx8_NARROW
+ [(match_operand:VNx8BI 2 "register_operand" "Upl")
+ (truncate:VNx8_NARROW
+ (match_operand:VNx8_WIDE 1 "register_operand" "w"))
+ (match_dup 0)]
+ UNSPEC_ST1_SVE))]
+ "TARGET_SVE"
+ "st1<VNx8_NARROW:Vesize>\t%1.<VNx8_WIDE:Vetype>, %2, %0"
+)
+
+;; Predicated truncate and store, with 4 elements per 128-bit block.
+(define_insn "@aarch64_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>"
+ [(set (match_operand:VNx4_NARROW 0 "memory_operand" "+m")
+ (unspec:VNx4_NARROW
+ [(match_operand:VNx4BI 2 "register_operand" "Upl")
+ (truncate:VNx4_NARROW
+ (match_operand:VNx4_WIDE 1 "register_operand" "w"))
+ (match_dup 0)]
+ UNSPEC_ST1_SVE))]
+ "TARGET_SVE"
+ "st1<VNx4_NARROW:Vesize>\t%1.<VNx4_WIDE:Vetype>, %2, %0"
+)
+
+;; Predicated truncate and store, with 2 elements per 128-bit block.
+(define_insn "@aarch64_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>"
+ [(set (match_operand:VNx2_NARROW 0 "memory_operand" "+m")
+ (unspec:VNx2_NARROW
+ [(match_operand:VNx2BI 2 "register_operand" "Upl")
+ (truncate:VNx2_NARROW
+ (match_operand:VNx2_WIDE 1 "register_operand" "w"))
+ (match_dup 0)]
+ UNSPEC_ST1_SVE))]
+ "TARGET_SVE"
+ "st1<VNx2_NARROW:Vesize>\t%1.<VNx2_WIDE:Vetype>, %2, %0"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Non-temporal contiguous stores
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - STNT1B
+;; - STNT1D
+;; - STNT1H
+;; - STNT1W
+;; -------------------------------------------------------------------------
+
+(define_insn "@aarch64_stnt1<mode>"
+ [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
+ (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
+ (match_operand:SVE_ALL 1 "register_operand" "w")
+ (match_dup 0)]
+ UNSPEC_STNT1_SVE))]
+ "TARGET_SVE"
+ "stnt1<Vesize>\t%1.<Vetype>, %2, %0"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Normal scatter stores
+;; -------------------------------------------------------------------------
+;; Includes scatter forms of:
+;; - ST1D
+;; - ST1W
+;; -------------------------------------------------------------------------
+
+;; Unpredicated scatter stores.
+(define_expand "scatter_store<mode>"
[(set (mem:BLK (scratch))
(unspec:BLK
[(match_dup 5)
- (match_operand:DI 0 "aarch64_reg_or_zero")
+ (match_operand:DI 0 "aarch64_sve_gather_offset_<Vesize>")
(match_operand:<V_INT_EQUIV> 1 "register_operand")
(match_operand:DI 2 "const_int_operand")
(match_operand:DI 3 "aarch64_gather_scale_operand_<Vesize>")
(define_insn "mask_scatter_store<mode>"
[(set (mem:BLK (scratch))
(unspec:BLK
- [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
- (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
- (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w, w, w")
- (match_operand:DI 2 "const_int_operand" "i, Z, Ui1, Z, Ui1")
- (match_operand:DI 3 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
- (match_operand:SVE_S 4 "register_operand" "w, w, w, w, w")]
+ [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 0 "aarch64_sve_gather_offset_w" "Z, vgw, rk, rk, rk, rk")
+ (match_operand:VNx4SI 1 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 2 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, Ui1, i, i")
+ (match_operand:SVE_S 4 "register_operand" "w, w, w, w, w, w")]
UNSPEC_ST1_SCATTER))]
"TARGET_SVE"
"@
st1w\t%4.s, %5, [%1.s]
+ st1w\t%4.s, %5, [%1.s, #%0]
st1w\t%4.s, %5, [%0, %1.s, sxtw]
st1w\t%4.s, %5, [%0, %1.s, uxtw]
st1w\t%4.s, %5, [%0, %1.s, sxtw %p3]
(define_insn "mask_scatter_store<mode>"
[(set (mem:BLK (scratch))
(unspec:BLK
- [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
- (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk")
- (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w")
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 0 "aarch64_sve_gather_offset_d" "Z, vgd, rk, rk")
+ (match_operand:VNx2DI 1 "register_operand" "w, w, w, w")
(match_operand:DI 2 "const_int_operand")
- (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
- (match_operand:SVE_D 4 "register_operand" "w, w, w")]
+ (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, Ui1, Ui1, i")
+ (match_operand:SVE_D 4 "register_operand" "w, w, w, w")]
UNSPEC_ST1_SCATTER))]
"TARGET_SVE"
"@
st1d\t%4.d, %5, [%1.d]
+ st1d\t%4.d, %5, [%1.d, #%0]
st1d\t%4.d, %5, [%0, %1.d]
st1d\t%4.d, %5, [%0, %1.d, lsl %p3]"
)
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*mask_scatter_store<mode>_sxtw"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 0 "register_operand" "rk, rk")
+ (unspec:VNx2DI
+ [(match_operand 6)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 1 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, i")
+ (match_operand:SVE_D 4 "register_operand" "w, w")]
+ UNSPEC_ST1_SCATTER))]
+ "TARGET_SVE"
+ "@
+ st1d\t%4.d, %5, [%0, %1.d, sxtw]
+ st1d\t%4.d, %5, [%0, %1.d, sxtw %p3]"
+ "&& !rtx_equal_p (operands[5], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[5]);
+ }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*mask_scatter_store<mode>_uxtw"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 0 "aarch64_reg_or_zero" "rk, rk")
+ (and:VNx2DI
+ (match_operand:VNx2DI 1 "register_operand" "w, w")
+ (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, i")
+ (match_operand:SVE_D 4 "register_operand" "w, w")]
+ UNSPEC_ST1_SCATTER))]
+ "TARGET_SVE"
+ "@
+ st1d\t%4.d, %5, [%0, %1.d, uxtw]
+ st1d\t%4.d, %5, [%0, %1.d, uxtw %p3]"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Truncating scatter stores
+;; -------------------------------------------------------------------------
+;; Includes scatter forms of:
+;; - ST1B
+;; - ST1H
+;; - ST1W
+;; -------------------------------------------------------------------------
+
+;; Predicated truncating scatter stores for 32-bit elements. Operand 2 is
+;; true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_scatter_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK
+ [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:DI 0 "aarch64_sve_gather_offset_<VNx4_NARROW:Vesize>" "Z, vg<VNx4_NARROW:Vesize>, rk, rk, rk, rk")
+ (match_operand:VNx4SI 1 "register_operand" "w, w, w, w, w, w")
+ (match_operand:DI 2 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx4_NARROW:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+ (truncate:VNx4_NARROW
+ (match_operand:VNx4_WIDE 4 "register_operand" "w, w, w, w, w, w"))]
+ UNSPEC_ST1_SCATTER))]
+ "TARGET_SVE"
+ "@
+ st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%1.s]
+ st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%1.s, #%0]
+ st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, sxtw]
+ st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, uxtw]
+ st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, sxtw %p3]
+ st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, uxtw %p3]"
+)
+
+;; Predicated truncating scatter stores for 64-bit elements. The value of
+;; operand 2 doesn't matter in this case.
+(define_insn "@aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+ (match_operand:DI 0 "aarch64_sve_gather_offset_<VNx2_NARROW:Vesize>" "Z, vg<VNx2_NARROW:Vesize>, rk, rk")
+ (match_operand:VNx2DI 1 "register_operand" "w, w, w, w")
+ (match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, Ui1, Ui1, i")
+ (truncate:VNx2_NARROW
+ (match_operand:VNx2_WIDE 4 "register_operand" "w, w, w, w"))]
+ UNSPEC_ST1_SCATTER))]
+ "TARGET_SVE"
+ "@
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%1.d]
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%1.d, #%0]
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d]
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, lsl %p3]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_sxtw"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 0 "register_operand" "rk, rk")
+ (unspec:VNx2DI
+ [(match_operand 6)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 1 "register_operand" "w, w")))]
+ UNSPEC_PRED_X)
+ (match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+ (truncate:VNx2_NARROW
+ (match_operand:VNx2_WIDE 4 "register_operand" "w, w"))]
+ UNSPEC_ST1_SCATTER))]
+ "TARGET_SVE"
+ "@
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, sxtw]
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, sxtw %p3]"
+ "&& !rtx_equal_p (operands[5], operands[6])"
+ {
+ operands[6] = copy_rtx (operands[5]);
+ }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_uxtw"
+ [(set (mem:BLK (scratch))
+ (unspec:BLK
+ [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+ (match_operand:DI 0 "aarch64_reg_or_zero" "rk, rk")
+ (and:VNx2DI
+ (match_operand:VNx2DI 1 "register_operand" "w, w")
+ (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+ (match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+ (truncate:VNx2_NARROW
+ (match_operand:VNx2_WIDE 4 "register_operand" "w, w"))]
+ UNSPEC_ST1_SCATTER))]
+ "TARGET_SVE"
+ "@
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, uxtw]
+ st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, uxtw %p3]"
+)
+
;; =========================================================================
;; == Vector creation
;; =========================================================================
;; ---- [INT,FP] Duplicate element
;; -------------------------------------------------------------------------
;; Includes:
+;; - DUP
;; - MOV
;; - LD1RB
;; - LD1RD
;; duplicate the input and do a compare with zero.
(define_expand "vec_duplicate<mode>"
[(set (match_operand:PRED_ALL 0 "register_operand")
- (vec_duplicate:PRED_ALL (match_operand 1 "register_operand")))]
+ (vec_duplicate:PRED_ALL (match_operand:QI 1 "register_operand")))]
"TARGET_SVE"
{
rtx tmp = gen_reg_rtx (DImode);
;; ---- [INT,FP] Extract active element
;; -------------------------------------------------------------------------
;; Includes:
+;; - LASTA
;; - LASTB
;; -------------------------------------------------------------------------
;; Extract the last active element of operand 1 into operand 0.
;; If no elements are active, extract the last inactive element instead.
-(define_insn "extract_last_<mode>"
- [(set (match_operand:<VEL> 0 "register_operand" "=r, w")
+(define_insn "@extract_<last_op>_<mode>"
+ [(set (match_operand:<VEL> 0 "register_operand" "=?r, w")
(unspec:<VEL>
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(match_operand:SVE_ALL 2 "register_operand" "w, w")]
- UNSPEC_LASTB))]
+ LAST))]
"TARGET_SVE"
"@
- lastb\t%<vwcore>0, %1, %2.<Vetype>
- lastb\t%<Vetype>0, %1, %2.<Vetype>"
+ last<ab>\t%<vwcore>0, %1, %2.<Vetype>
+ last<ab>\t%<Vetype>0, %1, %2.<Vetype>"
)
;; -------------------------------------------------------------------------
)
;; Integer unary arithmetic predicated with a PTRUE.
-(define_insn "*<optab><mode>2"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl")
"<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
)
-;; Predicated integer unary arithmetic, merging with the first input.
-(define_insn "*cond_<optab><mode>_2"
- [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
+;; Predicated integer unary arithmetic with merging.
+(define_expand "@cond_<optab><mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand")
+ (SVE_INT_UNARY:SVE_I
+ (match_operand:SVE_I 2 "register_operand"))
+ (match_operand:SVE_I 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
+;; Predicated integer unary arithmetic, merging with the first input.
+(define_insn "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(SVE_INT_UNARY:SVE_I
;; ---- [INT] General unary arithmetic corresponding to unspecs
;; -------------------------------------------------------------------------
;; Includes
+;; - RBIT
;; - REVB
;; - REVH
;; - REVW
"<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
)
+;; Predicated integer unary operations with merging.
+(define_insn "@cond_<optab><mode>"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w, ?&w")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
+ (unspec:SVE_I
+ [(match_operand:SVE_I 2 "register_operand" "w, w, w")]
+ SVE_INT_UNARY)
+ (match_operand:SVE_I 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <elem_bits> >= <min_elem_bits>"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+ movprfx\t%0, %3\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Sign extension
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - SXTB
+;; - SXTH
+;; - SXTW
+;; -------------------------------------------------------------------------
+
+;; Predicated SXT[BHW].
+(define_insn "@aarch64_pred_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>"
+ [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
+ (unspec:SVE_HSDI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (sign_extend:SVE_HSDI
+ (truncate:SVE_PARTIAL
+ (match_operand:SVE_HSDI 2 "register_operand" "w")))]
+ UNSPEC_PRED_X))]
+ "TARGET_SVE && (~<narrower_mask> & <self_mask>) == 0"
+ "sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
+)
+
+;; Predicated SXT[BHW] with merging.
+(define_insn "@aarch64_cond_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>"
+ [(set (match_operand:SVE_HSDI 0 "register_operand" "=w, ?&w, ?&w")
+ (unspec:SVE_HSDI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
+ (sign_extend:SVE_HSDI
+ (truncate:SVE_PARTIAL
+ (match_operand:SVE_HSDI 2 "register_operand" "w, w, w")))
+ (match_operand:SVE_HSDI 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && (~<narrower_mask> & <self_mask>) == 0"
+ "@
+ sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+ movprfx\t%0.<SVE_HSDI:Vetype>, %1/z, %2.<SVE_HSDI:Vetype>\;sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+ movprfx\t%0, %3\;sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
+ [(set_attr "movprfx" "*,yes,yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [INT] Zero extension
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; ---- [INT] Logical inverse
;; -------------------------------------------------------------------------
+;; Includes:
+;; - CNOT
+;; -------------------------------------------------------------------------
;; Predicated logical inverse.
+(define_expand "@aarch64_pred_cnot<mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (eq:<VPRED>
+ (match_operand:SVE_I 3 "register_operand")
+ (match_dup 4))]
+ UNSPEC_PRED_Z)
+ (match_dup 5)
+ (match_dup 4)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ {
+ operands[4] = CONST0_RTX (<MODE>mode);
+ operands[5] = CONST1_RTX (<MODE>mode);
+ }
+)
+
(define_insn "*cnot<mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w")
(unspec:SVE_I
"cnot\t%0.<Vetype>, %1/m, %2.<Vetype>"
)
+;; Predicated logical inverse with merging.
+(define_expand "@cond_cnot<mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_I
+ [(unspec:<VPRED>
+ [(match_dup 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (eq:<VPRED>
+ (match_operand:SVE_I 2 "register_operand")
+ (match_dup 5))]
+ UNSPEC_PRED_Z)
+ (match_dup 6)
+ (match_dup 5)]
+ UNSPEC_SEL)
+ (match_operand:SVE_I 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ {
+ operands[4] = CONSTM1_RTX (<VPRED>mode);
+ operands[5] = CONST0_RTX (<MODE>mode);
+ operands[6] = CONST1_RTX (<MODE>mode);
+ }
+)
+
;; Predicated logical inverse, merging with the first input.
(define_insn_and_rewrite "*cond_cnot<mode>_2"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
[(set_attr "movprfx" "*,yes,yes")]
)
+;; -------------------------------------------------------------------------
+;; ---- [FP<-INT] General unary arithmetic that maps to unspecs
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FEXPA
+;; -------------------------------------------------------------------------
+
+;; Unpredicated unary operations that take an integer and return a float.
+(define_insn "@aarch64_sve_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w")
+ (unspec:SVE_F [(match_operand:<V_INT_EQUIV> 1 "register_operand" "w")]
+ SVE_FP_UNARY_INT))]
+ "TARGET_SVE"
+ "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP] General unary arithmetic corresponding to unspecs
;; -------------------------------------------------------------------------
;; Includes:
;; - FABS
;; - FNEG
+;; - FRECPE
+;; - FRECPX
;; - FRINTA
;; - FRINTI
;; - FRINTM
;; - FRINTP
;; - FRINTX
;; - FRINTZ
+;; - FRSQRT
;; - FSQRT
;; -------------------------------------------------------------------------
+;; Unpredicated floating-point unary operations.
+(define_insn "@aarch64_sve_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w")
+ (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")]
+ SVE_FP_UNARY))]
+ "TARGET_SVE"
+ "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
+)
+
;; Unpredicated floating-point unary operations.
(define_expand "<optab><mode>2"
[(set (match_operand:SVE_F 0 "register_operand")
)
;; Predicated floating-point unary operations.
-(define_insn "*<optab><mode>2"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_F 0 "register_operand" "=w")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand" "Upl")
"<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
)
+;; Predicated floating-point unary arithmetic with merging.
+(define_expand "@cond_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_F 2 "register_operand")]
+ SVE_COND_FP_UNARY)
+ (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
;; Predicated floating-point unary arithmetic, merging with the first input.
(define_insn_and_rewrite "*cond_<optab><mode>_2"
[(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
;; and third alternatives, but using Upa or X isn't likely to gain much
;; and would make the instruction seem less uniform to the register
;; allocator.
-(define_insn_and_split "*<optab><mode>3"
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w, ?&w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
;; - ADR
;; -------------------------------------------------------------------------
-;; Unshifted ADR, with the offset being zero-extended from the low 32 bits.
-(define_insn "*aarch64_adr_uxtw"
+;; An unshifted and unscaled ADR. This is functionally equivalent to an ADD,
+;; but the svadrb intrinsics should preserve the user's choice.
+(define_insn "@aarch64_adr<mode>"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
+ (unspec:SVE_SDI
+ [(match_operand:SVE_SDI 1 "register_operand" "w")
+ (match_operand:SVE_SDI 2 "register_operand" "w")]
+ UNSPEC_ADR))]
+ "TARGET_SVE"
+ "adr\t%0.<Vetype>, [%1.<Vetype>, %2.<Vetype>]"
+)
+
+;; Same, but with the offset being sign-extended from the low 32 bits.
+(define_insn_and_rewrite "*aarch64_adr_sxtw"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w")
+ (unspec:VNx2DI
+ [(match_operand:VNx2DI 1 "register_operand" "w")
+ (unspec:VNx2DI
+ [(match_operand 3)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w")))]
+ UNSPEC_PRED_X)]
+ UNSPEC_ADR))]
+ "TARGET_SVE"
+ "adr\t%0.d, [%1.d, %2.d, sxtw]"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (VNx2BImode);
+ }
+)
+
+;; Same, but with the offset being zero-extended from the low 32 bits.
+(define_insn "*aarch64_adr_uxtw_unspec"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w")
+ (unspec:VNx2DI
+ [(match_operand:VNx2DI 1 "register_operand" "w")
+ (and:VNx2DI
+ (match_operand:VNx2DI 2 "register_operand" "w")
+ (match_operand:VNx2DI 3 "aarch64_sve_uxtw_immediate"))]
+ UNSPEC_ADR))]
+ "TARGET_SVE"
+ "adr\t%0.d, [%1.d, %2.d, uxtw]"
+)
+
+;; Same, matching as a PLUS rather than unspec.
+(define_insn "*aarch64_adr_uxtw_and"
[(set (match_operand:VNx2DI 0 "register_operand" "=w")
(plus:VNx2DI
(and:VNx2DI
)
;; ADR with a nonzero shift.
+(define_expand "@aarch64_adr<mode>_shift"
+ [(set (match_operand:SVE_SDI 0 "register_operand")
+ (plus:SVE_SDI
+ (unspec:SVE_SDI
+ [(match_dup 4)
+ (ashift:SVE_SDI
+ (match_operand:SVE_SDI 2 "register_operand")
+ (match_operand:SVE_SDI 3 "const_1_to_3_operand"))]
+ UNSPEC_PRED_X)
+ (match_operand:SVE_SDI 1 "register_operand")))]
+ "TARGET_SVE"
+ {
+ operands[4] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
(define_insn_and_rewrite "*aarch64_adr<mode>_shift"
[(set (match_operand:SVE_SDI 0 "register_operand" "=w")
(plus:SVE_SDI
}
)
+;; Same, but with the index being sign-extended from the low 32 bits.
+(define_insn_and_rewrite "*aarch64_adr_shift_sxtw"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w")
+ (plus:VNx2DI
+ (unspec:VNx2DI
+ [(match_operand 4)
+ (ashift:VNx2DI
+ (unspec:VNx2DI
+ [(match_operand 5)
+ (sign_extend:VNx2DI
+ (truncate:VNx2SI
+ (match_operand:VNx2DI 2 "register_operand" "w")))]
+ UNSPEC_PRED_X)
+ (match_operand:VNx2DI 3 "const_1_to_3_operand"))]
+ UNSPEC_PRED_X)
+ (match_operand:VNx2DI 1 "register_operand" "w")))]
+ "TARGET_SVE"
+ "adr\t%0.d, [%1.d, %2.d, sxtw %3]"
+ "&& (!CONSTANT_P (operands[4]) || !CONSTANT_P (operands[5]))"
+ {
+ operands[5] = operands[4] = CONSTM1_RTX (VNx2BImode);
+ }
+)
+
;; Same, but with the index being zero-extended from the low 32 bits.
(define_insn_and_rewrite "*aarch64_adr_shift_uxtw"
[(set (match_operand:VNx2DI 0 "register_operand" "=w")
"TARGET_SVE"
{
rtx pred = aarch64_ptrue_reg (<VPRED>mode);
- emit_insn (gen_aarch64_<su>abd<mode>_3 (operands[0], pred, operands[1],
- operands[2]));
+ emit_insn (gen_aarch64_pred_<su>abd<mode> (operands[0], pred, operands[1],
+ operands[2]));
DONE;
}
)
;; Predicated integer absolute difference.
-(define_insn "aarch64_<su>abd<mode>_3"
+(define_insn "@aarch64_pred_<su>abd<mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
[(set_attr "movprfx" "*,yes")]
)
+(define_expand "@aarch64_cond_<su>abd<mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand")
+ (minus:SVE_I
+ (unspec:SVE_I
+ [(match_dup 1)
+ (USMAX:SVE_I
+ (match_operand:SVE_I 2 "register_operand")
+ (match_operand:SVE_I 3 "register_operand"))]
+ UNSPEC_PRED_X)
+ (unspec:SVE_I
+ [(match_dup 1)
+ (<max_opp>:SVE_I
+ (match_dup 2)
+ (match_dup 3))]
+ UNSPEC_PRED_X))
+ (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+{
+ if (rtx_equal_p (operands[3], operands[4]))
+ std::swap (operands[2], operands[3]);
+})
+
;; Predicated integer absolute difference, merging with the first input.
(define_insn_and_rewrite "*aarch64_cond_<su>abd<mode>_2"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
[(set_attr "movprfx" "yes")]
)
+;; -------------------------------------------------------------------------
+;; ---- [INT] Saturating addition and subtraction
+;; -------------------------------------------------------------------------
+;; - SQADD
+;; - SQSUB
+;; - UQADD
+;; - UQSUB
+;; -------------------------------------------------------------------------
+
+;; Unpredicated saturating signed addition and subtraction.
+(define_insn "@aarch64_<su_optab><optab><mode>"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w, ?&w, w")
+ (SBINQOPS:SVE_I
+ (match_operand:SVE_I 1 "register_operand" "0, 0, w, w, w")
+ (match_operand:SVE_I 2 "aarch64_sve_sqadd_operand" "vsQ, vsS, vsQ, vsS, w")))]
+ "TARGET_SVE"
+ "@
+ <binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+ <binqops_op_rev>\t%0.<Vetype>, %0.<Vetype>, #%N2
+ movprfx\t%0, %1\;<binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+ movprfx\t%0, %1\;<binqops_op_rev>\t%0.<Vetype>, %0.<Vetype>, #%N2
+ <binqops_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+ [(set_attr "movprfx" "*,*,yes,yes,*")]
+)
+
+;; Unpredicated saturating unsigned addition and subtraction.
+(define_insn "@aarch64_<su_optab><optab><mode>"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w, w")
+ (UBINQOPS:SVE_I
+ (match_operand:SVE_I 1 "register_operand" "0, w, w")
+ (match_operand:SVE_I 2 "aarch64_sve_arith_operand" "vsa, vsa, w")))]
+ "TARGET_SVE"
+ "@
+ <binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+ movprfx\t%0, %1\;<binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+ <binqops_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+ [(set_attr "movprfx" "*,yes,*")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [INT] Highpart multiplication
;; -------------------------------------------------------------------------
)
;; Predicated highpart multiplication.
-(define_insn "*<su>mul<mode>3_highpart"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
[(set_attr "movprfx" "*,yes")]
)
+;; Predicated highpart multiplications with merging.
+(define_expand "@cond_<optab><mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:SVE_I 2 "register_operand")
+ (match_operand:SVE_I 3 "register_operand")]
+ MUL_HIGHPART)
+ (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+{
+ /* Only target code is aware of these operations, so we don't need
+ to handle the fully-general case. */
+ gcc_assert (rtx_equal_p (operands[2], operands[4])
+ || CONSTANT_P (operands[4]));
+})
+
+;; Predicated highpart multiplications, merging with the first input.
+(define_insn "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_I
+ [(match_operand:SVE_I 2 "register_operand" "0, w")
+ (match_operand:SVE_I 3 "register_operand" "w, w")]
+ MUL_HIGHPART)
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,yes")])
+
+;; Predicated highpart multiplications, merging with zero.
+(define_insn "*cond_<optab><mode>_z"
+ [(set (match_operand:SVE_I 0 "register_operand" "=&w, &w")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_I
+ [(match_operand:SVE_I 2 "register_operand" "%0, w")
+ (match_operand:SVE_I 3 "register_operand" "w, w")]
+ MUL_HIGHPART)
+ (match_operand:SVE_I 4 "aarch64_simd_imm_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "yes")])
+
;; -------------------------------------------------------------------------
;; ---- [INT] Division
;; -------------------------------------------------------------------------
)
;; Integer division predicated with a PTRUE.
-(define_insn "*<optab><mode>3"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_SDI 0 "register_operand" "=w, w, ?&w")
(unspec:SVE_SDI
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
)
;; Predicated integer division with merging.
-(define_expand "cond_<optab><mode>"
+(define_expand "@cond_<optab><mode>"
[(set (match_operand:SVE_SDI 0 "register_operand")
(unspec:SVE_SDI
[(match_operand:<VPRED> 1 "register_operand")
;; - BIC
;; -------------------------------------------------------------------------
+;; Unpredicated BIC.
+(define_expand "@aarch64_bic<mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (and:SVE_I
+ (unspec:SVE_I
+ [(match_dup 3)
+ (not:SVE_I (match_operand:SVE_I 2 "register_operand"))]
+ UNSPEC_PRED_X)
+ (match_operand:SVE_I 1 "register_operand")))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+;; Predicated BIC.
(define_insn_and_rewrite "*bic<mode>3"
[(set (match_operand:SVE_I 0 "register_operand" "=w")
(and:SVE_I
}
)
+;; Predicated BIC with merging.
+(define_expand "@cond_bic<mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand")
+ (and:SVE_I
+ (not:SVE_I (match_operand:SVE_I 3 "register_operand"))
+ (match_operand:SVE_I 2 "register_operand"))
+ (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
;; Predicated integer BIC, merging with the first input.
(define_insn "*cond_bic<mode>_2"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
)
;; -------------------------------------------------------------------------
-;; ---- [INT] Shifts
+;; ---- [INT] Shifts (rounding towards -Inf)
;; -------------------------------------------------------------------------
;; Includes:
;; - ASR
+;; - ASRR
;; - LSL
+;; - LSLR
;; - LSR
+;; - LSRR
;; -------------------------------------------------------------------------
;; Unpredicated shift by a scalar, which expands into one of the vector
;; the predicate for the first alternative, but using Upa or X isn't
;; likely to gain much and would make the instruction seem less uniform
;; to the register allocator.
-(define_insn_and_split "*v<optab><mode>3"
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w, w, w, ?&w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
[(set_attr "movprfx" "yes")]
)
-;; -------------------------------------------------------------------------
-;; ---- [INT] Shifts (rounding towards 0)
-;; -------------------------------------------------------------------------
-;; Includes:
-;; - ASRD
-;; -------------------------------------------------------------------------
+;; Unpredicated shifts of narrow elements by 64-bit amounts.
+(define_insn "@aarch64_sve_<sve_int_op><mode>"
+ [(set (match_operand:SVE_BHSI 0 "register_operand" "=w")
+ (unspec:SVE_BHSI
+ [(match_operand:SVE_BHSI 1 "register_operand" "w")
+ (match_operand:VNx2DI 2 "register_operand" "w")]
+ SVE_SHIFT_WIDE))]
+ "TARGET_SVE"
+ "<sve_int_op>\t%0.<Vetype>, %1.<Vetype>, %2.d"
+)
-;; Unpredicated arithmetic right shift for division by power-of-2.
-(define_expand "sdiv_pow2<mode>3"
- [(set (match_operand:SVE_I 0 "register_operand")
- (unspec:SVE_I
- [(match_dup 3)
- (unspec:SVE_I
- [(match_operand:SVE_I 1 "register_operand")
- (match_operand 2 "aarch64_simd_rshift_imm")]
- UNSPEC_ASRD)]
- UNSPEC_PRED_X))]
+;; Merging predicated shifts of narrow elements by 64-bit amounts.
+(define_expand "@cond_<sve_int_op><mode>"
+ [(set (match_operand:SVE_BHSI 0 "register_operand")
+ (unspec:SVE_BHSI
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_BHSI
+ [(match_operand:SVE_BHSI 2 "register_operand")
+ (match_operand:VNx2DI 3 "register_operand")]
+ SVE_SHIFT_WIDE)
+ (match_operand:SVE_BHSI 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
"TARGET_SVE"
- {
- operands[3] = aarch64_ptrue_reg (<VPRED>mode);
- }
)
-;; Predicated ASRD with PTRUE.
-(define_insn "*sdiv_pow2<mode>3"
+;; Predicated shifts of narrow elements by 64-bit amounts, merging with
+;; the first input.
+(define_insn "*cond_<sve_int_op><mode>_m"
+ [(set (match_operand:SVE_BHSI 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_BHSI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_BHSI
+ [(match_operand:SVE_BHSI 2 "register_operand" "0, w")
+ (match_operand:VNx2DI 3 "register_operand" "w, w")]
+ SVE_SHIFT_WIDE)
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
+ movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d"
+ [(set_attr "movprfx" "*, yes")])
+
+;; Predicated shifts of narrow elements by 64-bit amounts, merging with zero.
+(define_insn "*cond_<sve_int_op><mode>_z"
+ [(set (match_operand:SVE_BHSI 0 "register_operand" "=&w, &w")
+ (unspec:SVE_BHSI
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_BHSI
+ [(match_operand:SVE_BHSI 2 "register_operand" "0, w")
+ (match_operand:VNx2DI 3 "register_operand" "w, w")]
+ SVE_SHIFT_WIDE)
+ (match_operand:SVE_BHSI 4 "aarch64_simd_imm_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d"
+ [(set_attr "movprfx" "yes")])
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Shifts (rounding towards 0)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - ASRD
+;; -------------------------------------------------------------------------
+
+;; Unpredicated ASRD.
+(define_expand "sdiv_pow2<mode>3"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_dup 3)
+ (unspec:SVE_I
+ [(match_operand:SVE_I 1 "register_operand")
+ (match_operand 2 "aarch64_simd_rshift_imm")]
+ UNSPEC_ASRD)
+ (match_dup 1)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ {
+ operands[3] = aarch64_ptrue_reg (<VPRED>mode);
+ }
+)
+
+;; Predicated ASRD with merging.
+(define_expand "@cond_asrd<mode>"
+ [(set (match_operand:SVE_I 0 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_I
+ [(match_operand:SVE_I 2 "register_operand")
+ (match_operand:SVE_I 3 "aarch64_simd_rshift_imm")]
+ UNSPEC_ASRD)
+ (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
+;; Predicated ASRD, merging with the first input.
+(define_insn "*cond_asrd<mode>_2"
[(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
(unspec:SVE_I
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(unspec:SVE_I
[(match_operand:SVE_I 2 "register_operand" "0, w")
- (match_operand 3 "aarch64_simd_rshift_imm")]
- UNSPEC_ASRD)]
- UNSPEC_PRED_X))]
+ (match_operand:SVE_I 3 "aarch64_simd_rshift_imm")]
+ UNSPEC_ASRD)
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
+ movprfx\t%0, %2\;asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+ [(set_attr "movprfx" "*,yes")])
+
+;; Predicated ASRD, merging with zero.
+(define_insn "*cond_asrd<mode>_z"
+ [(set (match_operand:SVE_I 0 "register_operand" "=w")
+ (unspec:SVE_I
+ [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (unspec:SVE_I
+ [(match_operand:SVE_I 2 "register_operand" "w")
+ (match_operand:SVE_I 3 "aarch64_simd_rshift_imm")]
+ UNSPEC_ASRD)
+ (match_operand:SVE_I 4 "aarch64_simd_imm_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+ [(set_attr "movprfx" "yes")])
+
+;; -------------------------------------------------------------------------
+;; ---- [FP<-INT] General binary arithmetic corresponding to unspecs
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FSCALE
+;; - FTSMUL
+;; - FTSSEL
+;; -------------------------------------------------------------------------
+
+;; Unpredicated floating-point binary operations that take an integer as
+;; their second operand.
+(define_insn "@aarch64_sve_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w")
+ (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")
+ (match_operand:<V_INT_EQUIV> 2 "register_operand" "w")]
+ SVE_FP_BINARY_INT))]
+ "TARGET_SVE"
+ "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+)
+
+;; Predicated floating-point binary operations that take an integer
+;; as their second operand.
+(define_insn "@aarch64_pred_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "0, w")
+ (match_operand:<V_INT_EQUIV> 3 "register_operand" "w, w")]
+ SVE_COND_FP_BINARY_INT))]
+ "TARGET_SVE"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated floating-point binary operations with merging, taking an
+;; integer as their second operand.
+(define_expand "@cond_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_F 2 "register_operand")
+ (match_operand:<V_INT_EQUIV> 3 "register_operand")]
+ SVE_COND_FP_BINARY_INT)
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
"TARGET_SVE"
+)
+
+;; Predicated floating-point binary operations that take an integer as their
+;; second operand, with inactive lanes coming from the first operand.
+(define_insn_and_rewrite "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "0, w")
+ (match_operand:<V_INT_EQUIV> 3 "register_operand" "w, w")]
+ SVE_COND_FP_BINARY_INT)
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE && aarch64_sve_pred_dominates_p (&operands[4], operands[1])"
"@
- asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
- movprfx\t%0, %2\;asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+ <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+ "&& !rtx_equal_p (operands[1], operands[4])"
+ {
+ operands[4] = copy_rtx (operands[1]);
+ }
[(set_attr "movprfx" "*,yes")]
)
+;; Predicated floating-point binary operations that take an integer as
+;; their second operand, with the values of inactive lanes being distinct
+;; from the other inputs.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+ [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand 5)
+ (match_operand:SI 6 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "0, w, w, w")
+ (match_operand:<V_INT_EQUIV> 3 "register_operand" "w, w, w, w")]
+ SVE_COND_FP_BINARY_INT)
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, Dz, 0, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE
+ && !rtx_equal_p (operands[2], operands[4])
+ && aarch64_sve_pred_dominates_p (&operands[5], operands[1])"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ #"
+ "&& 1"
+ {
+ if (reload_completed
+ && register_operand (operands[4], <MODE>mode)
+ && !rtx_equal_p (operands[0], operands[4]))
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+ operands[4], operands[1]));
+ operands[4] = operands[2] = operands[0];
+ }
+ else if (!rtx_equal_p (operands[1], operands[5]))
+ operands[5] = copy_rtx (operands[1]);
+ else
+ FAIL;
+ }
+ [(set_attr "movprfx" "yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP] General binary arithmetic corresponding to rtx codes
;; -------------------------------------------------------------------------
;; - FADD (constant forms handled in the "Addition" section)
;; - FDIV
;; - FDIVR
+;; - FMAX
;; - FMAXNM (including #0.0 and #1.0)
+;; - FMIN
;; - FMINNM (including #0.0 and #1.0)
;; - FMUL (including #0.5 and #2.0)
+;; - FMULX
+;; - FRECPS
+;; - FRSQRTS
;; - FSUB (constant forms handled in the "Addition" section)
;; - FSUBR (constant forms handled in the "Subtraction" section)
;; -------------------------------------------------------------------------
;; Unpredicated floating-point binary operations.
+(define_insn "@aarch64_sve_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w")
+ (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")
+ (match_operand:SVE_F 2 "register_operand" "w")]
+ SVE_FP_BINARY))]
+ "TARGET_SVE"
+ "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+)
+
+;; Unpredicated floating-point binary operations that need to be predicated
+;; for SVE.
(define_expand "<optab><mode>3"
[(set (match_operand:SVE_F 0 "register_operand")
(unspec:SVE_F
)
;; Predicated floating-point binary operations that have no immediate forms.
-(define_insn "*<optab><mode>3"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
)
;; Predicated floating-point operations with merging.
-(define_expand "cond_<optab><mode>"
+(define_expand "@cond_<optab><mode>"
[(set (match_operand:SVE_F 0 "register_operand")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand")
;; -------------------------------------------------------------------------
;; Predicated floating-point addition.
-(define_insn_and_split "*add<mode>3"
- [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, ?&w, ?&w")
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, w, ?&w, ?&w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
- (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, i, Z, i, i")
- (match_operand:SVE_F 2 "register_operand" "%0, 0, w, w, w")
- (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, w, vsA, vsN")]
- UNSPEC_COND_FADD))]
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, i, Z, Ui1, i, i, Ui1")
+ (match_operand:SVE_F 2 "register_operand" "%0, 0, w, 0, w, w, w")
+ (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, w, w, vsA, vsN, w")]
+ SVE_COND_FP_ADD))]
"TARGET_SVE"
"@
fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
#
+ fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
movprfx\t%0, %2\;fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
- movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3"
+ movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
+ movprfx\t%0, %2\;fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
; Split the unpredicated form after reload, so that we don't have
; the unnecessary PTRUE.
"&& reload_completed
- && register_operand (operands[3], <MODE>mode)"
+ && register_operand (operands[3], <MODE>mode)
+ && INTVAL (operands[4]) == SVE_RELAXED_GP"
[(set (match_dup 0) (plus:SVE_F (match_dup 2) (match_dup 3)))]
""
- [(set_attr "movprfx" "*,*,*,yes,yes")]
+ [(set_attr "movprfx" "*,*,*,*,yes,yes,yes")]
)
;; Predicated floating-point addition of a constant, merging with the
;; Register merging forms are handled through SVE_COND_FP_BINARY.
+;; -------------------------------------------------------------------------
+;; ---- [FP] Complex addition
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FCADD
+;; -------------------------------------------------------------------------
+
+;; Predicated FCADD.
+(define_insn "@aarch64_pred_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "0, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w")]
+ SVE_COND_FCADD))]
+ "TARGET_SVE"
+ "@
+ fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0, %2\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCADD with merging.
+(define_expand "@cond_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_F 2 "register_operand")
+ (match_operand:SVE_F 3 "register_operand")]
+ SVE_COND_FCADD)
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
+;; Predicated FCADD, merging with the first input.
+(define_insn_and_rewrite "*cond_<optab><mode>_2"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "0, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w")]
+ SVE_COND_FCADD)
+ (match_dup 2)]
+ UNSPEC_SEL))]
+ "TARGET_SVE && aarch64_sve_pred_dominates_p (&operands[4], operands[1])"
+ "@
+ fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0, %2\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>"
+ "&& !rtx_equal_p (operands[1], operands[4])"
+ {
+ operands[4] = copy_rtx (operands[1]);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCADD, merging with an independent value.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+ [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand 5)
+ (match_operand:SI 6 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "w, 0, w, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w, w, w")]
+ SVE_COND_FCADD)
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, Dz, 0, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE
+ && !rtx_equal_p (operands[2], operands[4])
+ && aarch64_sve_pred_dominates_p (&operands[5], operands[1])"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+ #"
+ "&& 1"
+ {
+ if (reload_completed
+ && register_operand (operands[4], <MODE>mode)
+ && !rtx_equal_p (operands[0], operands[4]))
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+ operands[4], operands[1]));
+ operands[4] = operands[2] = operands[0];
+ }
+ else if (!rtx_equal_p (operands[1], operands[5]))
+ operands[5] = copy_rtx (operands[1]);
+ else
+ FAIL;
+ }
+ [(set_attr "movprfx" "yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP] Subtraction
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Predicated floating-point subtraction.
-(define_insn_and_split "*sub<mode>3"
- [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, w, ?&w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
- (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, i")
- (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand" "vsA, w, vsA")
- (match_operand:SVE_F 3 "register_operand" "0, w, 0")]
- UNSPEC_COND_FSUB))]
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+ (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, Ui1, Ui1, i, Ui1")
+ (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand" "vsA, w, 0, w, vsA, w")
+ (match_operand:SVE_F 3 "register_operand" "0, w, w, 0, w, w")]
+ SVE_COND_FP_SUB))]
"TARGET_SVE"
"@
fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
#
- movprfx\t%0, %3\;fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2"
+ fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+ movprfx\t%0, %3\;fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
+ movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
; Split the unpredicated form after reload, so that we don't have
; the unnecessary PTRUE.
"&& reload_completed
- && register_operand (operands[2], <MODE>mode)"
+ && register_operand (operands[2], <MODE>mode)
+ && INTVAL (operands[4]) == SVE_RELAXED_GP"
[(set (match_dup 0) (minus:SVE_F (match_dup 2) (match_dup 3)))]
""
- [(set_attr "movprfx" "*,*,yes")]
+ [(set_attr "movprfx" "*,*,*,*,yes,yes")]
)
;; Predicated floating-point subtraction from a constant, merging with the
;; -------------------------------------------------------------------------
;; Predicated floating-point absolute difference.
-(define_insn_and_rewrite "*fabd<mode>3"
+(define_expand "@aarch64_pred_abd<mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (match_dup 4)
+ (match_operand:SVE_F 2 "register_operand")
+ (match_operand:SVE_F 3 "register_operand")]
+ UNSPEC_COND_FSUB)]
+ UNSPEC_COND_FABS))]
+ "TARGET_SVE"
+)
+
+;; Predicated floating-point absolute difference.
+(define_insn_and_rewrite "*aarch64_pred_abd<mode>"
[(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
[(set_attr "movprfx" "*,yes")]
)
-;; Predicated floating-point absolute difference, merging with the first
-;; input.
-(define_insn_and_rewrite "*aarch64_cond_abd<mode>_2"
- [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+(define_expand "@aarch64_cond_abd<mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_F 2 "register_operand")
+ (match_operand:SVE_F 3 "register_operand")]
+ UNSPEC_COND_FSUB)]
+ UNSPEC_COND_FABS)
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+{
+ if (rtx_equal_p (operands[3], operands[4]))
+ std::swap (operands[2], operands[3]);
+})
+
+;; Predicated floating-point absolute difference, merging with the first
+;; input.
+(define_insn_and_rewrite "*aarch64_cond_abd<mode>_2"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
(unspec:SVE_F
[(match_operand 4)
(match_operand:SI 5 "aarch64_sve_gp_strictness")
;; -------------------------------------------------------------------------
;; Predicated floating-point multiplication.
-(define_insn_and_split "*mul<mode>3"
- [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, ?&w, ?&w")
(unspec:SVE_F
- [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
- (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, i")
- (match_operand:SVE_F 2 "register_operand" "%0, w, 0")
- (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand" "vsM, w, vsM")]
- UNSPEC_COND_FMUL))]
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
+ (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, Ui1, i, Ui1")
+ (match_operand:SVE_F 2 "register_operand" "%0, w, 0, w, w")
+ (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand" "vsM, w, w, vsM, w")]
+ SVE_COND_FP_MUL))]
"TARGET_SVE"
"@
fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
#
- movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+ fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
+ movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
; Split the unpredicated form after reload, so that we don't have
; the unnecessary PTRUE.
"&& reload_completed
- && register_operand (operands[3], <MODE>mode)"
+ && register_operand (operands[3], <MODE>mode)
+ && INTVAL (operands[4]) == SVE_RELAXED_GP"
[(set (match_dup 0) (mult:SVE_F (match_dup 2) (match_dup 3)))]
""
- [(set_attr "movprfx" "*,*,yes")]
+ [(set_attr "movprfx" "*,*,*,yes,yes")]
)
;; Merging forms are handled through SVE_COND_FP_BINARY and
;; SVE_COND_FP_BINARY_I1.
+;; Unpredicated multiplication by selected lanes.
+(define_insn "@aarch64_mul_lane_<mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w")
+ (mult:SVE_F
+ (unspec:SVE_F
+ [(match_operand:SVE_F 2 "register_operand" "<sve_lane_con>")
+ (match_operand:SI 3 "const_int_operand")]
+ UNSPEC_SVE_LANE_SELECT)
+ (match_operand:SVE_F 1 "register_operand" "w")))]
+ "TARGET_SVE"
+ "fmul\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]"
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP] Binary logical operations
;; -------------------------------------------------------------------------
;; ---- [FP] Maximum and minimum
;; -------------------------------------------------------------------------
;; Includes:
+;; - FMAX
;; - FMAXNM
+;; - FMIN
;; - FMINNM
;; -------------------------------------------------------------------------
)
;; Predicated floating-point maximum/minimum.
-(define_insn "*<optab><mode>3"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w, ?&w")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
(match_operand:SI 4 "aarch64_sve_gp_strictness")
(match_operand:SVE_F 2 "register_operand" "%0, 0, w, w")
(match_operand:SVE_F 3 "aarch64_sve_float_maxmin_operand" "vsB, w, vsB, w")]
- SVE_COND_FP_MAXMIN_PUBLIC))]
+ SVE_COND_FP_MAXMIN))]
"TARGET_SVE"
"@
<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
"<logical>s\t%0.b, %1/z, %2.b, %3.b"
)
+;; Same with just the flags result.
+(define_insn "*<optab><mode>3_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (and:PRED_ALL
+ (LOGICAL:PRED_ALL
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")
+ (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+ (match_dup 4))]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ "<logical>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
;; -------------------------------------------------------------------------
;; ---- [PRED] Binary logical operations (inverted second input)
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Predicated predicate BIC and ORN.
-(define_insn "*<nlogical><mode>3"
+(define_insn "aarch64_pred_<nlogical><mode>_z"
[(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
(and:PRED_ALL
(NLOGICAL:PRED_ALL
"<nlogical>\t%0.b, %1/z, %2.b, %3.b"
)
+;; Same, but set the flags as a side-effect.
+(define_insn "*<nlogical><mode>3_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (and:PRED_ALL
+ (NLOGICAL:PRED_ALL
+ (not:PRED_ALL
+ (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+ (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+ (match_dup 4))]
+ UNSPEC_PTEST))
+ (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (and:PRED_ALL (NLOGICAL:PRED_ALL
+ (not:PRED_ALL (match_dup 3))
+ (match_dup 2))
+ (match_dup 4)))]
+ "TARGET_SVE"
+ "<nlogical>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
+;; Same with just the flags result.
+(define_insn "*<nlogical><mode>3_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (and:PRED_ALL
+ (NLOGICAL:PRED_ALL
+ (not:PRED_ALL
+ (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+ (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+ (match_dup 4))]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ "<nlogical>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
;; -------------------------------------------------------------------------
;; ---- [PRED] Binary logical operations (inverted result)
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Predicated predicate NAND and NOR.
-(define_insn "*<logical_nn><mode>3"
+(define_insn "aarch64_pred_<logical_nn><mode>_z"
[(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
(and:PRED_ALL
(NLOGICAL:PRED_ALL
"<logical_nn>\t%0.b, %1/z, %2.b, %3.b"
)
+;; Same, but set the flags as a side-effect.
+(define_insn "*<logical_nn><mode>3_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (and:PRED_ALL
+ (NLOGICAL:PRED_ALL
+ (not:PRED_ALL
+ (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+ (not:PRED_ALL
+ (match_operand:PRED_ALL 3 "register_operand" "Upa")))
+ (match_dup 4))]
+ UNSPEC_PTEST))
+ (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (and:PRED_ALL (NLOGICAL:PRED_ALL
+ (not:PRED_ALL (match_dup 2))
+ (not:PRED_ALL (match_dup 3)))
+ (match_dup 4)))]
+ "TARGET_SVE"
+ "<logical_nn>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
+;; Same with just the flags result.
+(define_insn "*<logical_nn><mode>3_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (and:PRED_ALL
+ (NLOGICAL:PRED_ALL
+ (not:PRED_ALL
+ (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+ (not:PRED_ALL
+ (match_operand:PRED_ALL 3 "register_operand" "Upa")))
+ (match_dup 4))]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ "<logical_nn>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
;; =========================================================================
;; == Ternary arithmetic
;; =========================================================================
)
;; Predicated integer addition of product.
-(define_insn "*fma<mode>4"
+(define_insn "@aarch64_pred_fma<mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
(plus:SVE_I
(unspec:SVE_I
)
;; Predicated integer subtraction of product.
-(define_insn "*fnma<mode>3"
+(define_insn "@aarch64_pred_fnma<mode>"
[(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
(minus:SVE_I
(match_operand:SVE_I 4 "register_operand" "w, 0, w")
[(set_attr "movprfx" "*,yes")]
)
+;; Four-element integer dot-product by selected lanes with accumulation.
+(define_insn "@aarch64_<sur>dot_prod_lane<vsi2qi>"
+ [(set (match_operand:SVE_SDI 0 "register_operand" "=w, ?&w")
+ (plus:SVE_SDI
+ (unspec:SVE_SDI
+ [(match_operand:<VSI2QI> 1 "register_operand" "w, w")
+ (unspec:<VSI2QI>
+ [(match_operand:<VSI2QI> 2 "register_operand" "<sve_lane_con>, <sve_lane_con>")
+ (match_operand:SI 3 "const_int_operand")]
+ UNSPEC_SVE_LANE_SELECT)]
+ DOTPROD)
+ (match_operand:SVE_SDI 4 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ "@
+ <sur>dot\\t%0.<Vetype>, %1.<Vetype_fourth>, %2.<Vetype_fourth>[%3]
+ movprfx\t%0, %4\;<sur>dot\\t%0.<Vetype>, %1.<Vetype_fourth>, %2.<Vetype_fourth>[%3]"
+ [(set_attr "movprfx" "*,yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [INT] Sum of absolute differences
;; -------------------------------------------------------------------------
)
;; Predicated floating-point ternary operations.
-(define_insn "*<optab><mode>4"
+(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
)
;; Predicated floating-point ternary operations with merging.
-(define_expand "cond_<optab><mode>"
+(define_expand "@cond_<optab><mode>"
[(set (match_operand:SVE_F 0 "register_operand")
(unspec:SVE_F
[(match_operand:<VPRED> 1 "register_operand")
[(set_attr "movprfx" "yes")]
)
+;; Unpredicated FMLA and FMLS by selected lanes. It doesn't seem worth using
+;; (fma ...) since target-independent code won't understand the indexing.
+(define_insn "@aarch64_<optab>_lane_<mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:SVE_F 1 "register_operand" "w, w")
+ (unspec:SVE_F
+ [(match_operand:SVE_F 2 "register_operand" "<sve_lane_con>, <sve_lane_con>")
+ (match_operand:SI 3 "const_int_operand")]
+ UNSPEC_SVE_LANE_SELECT)
+ (match_operand:SVE_F 4 "register_operand" "0, w")]
+ SVE_FP_TERNARY_LANE))]
+ "TARGET_SVE"
+ "@
+ <sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]
+ movprfx\t%0, %4\;<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] Complex multiply-add
+;; -------------------------------------------------------------------------
+;; Includes merging patterns for:
+;; - FCMLA
+;; -------------------------------------------------------------------------
+
+;; Predicated FCMLA.
+(define_insn "@aarch64_pred_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (match_operand:SI 5 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "w, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w")
+ (match_operand:SVE_F 4 "register_operand" "0, w")]
+ SVE_COND_FCMLA))]
+ "TARGET_SVE"
+ "@
+ fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCMLA with merging.
+(define_expand "@cond_<optab><mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_F 2 "register_operand")
+ (match_operand:SVE_F 3 "register_operand")
+ (match_operand:SVE_F 4 "register_operand")]
+ SVE_COND_FCMLA)
+ (match_operand:SVE_F 5 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
+;; Predicated FCMLA, merging with the third input.
+(define_insn_and_rewrite "*cond_<optab><mode>_4"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand 5)
+ (match_operand:SI 6 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "w, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w")
+ (match_operand:SVE_F 4 "register_operand" "0, w")]
+ SVE_COND_FCMLA)
+ (match_dup 4)]
+ UNSPEC_SEL))]
+ "TARGET_SVE && aarch64_sve_pred_dominates_p (&operands[5], operands[1])"
+ "@
+ fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>"
+ "&& !rtx_equal_p (operands[1], operands[5])"
+ {
+ operands[5] = copy_rtx (operands[1]);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCMLA, merging with an independent value.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+ [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, ?&w")
+ (unspec:SVE_F
+ [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
+ (unspec:SVE_F
+ [(match_operand 6)
+ (match_operand:SI 7 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_F 2 "register_operand" "w, w, w, w")
+ (match_operand:SVE_F 3 "register_operand" "w, w, w, w")
+ (match_operand:SVE_F 4 "register_operand" "w, 0, w, w")]
+ SVE_COND_FCMLA)
+ (match_operand:SVE_F 5 "aarch64_simd_reg_or_zero" "Dz, Dz, 0, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE
+ && !rtx_equal_p (operands[4], operands[5])
+ && aarch64_sve_pred_dominates_p (&operands[6], operands[1])"
+ "@
+ movprfx\t%0.<Vetype>, %1/z, %4.<Vetype>\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+ movprfx\t%0.<Vetype>, %1/m, %4.<Vetype>\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+ #"
+ "&& 1"
+ {
+ if (reload_completed
+ && register_operand (operands[5], <MODE>mode)
+ && !rtx_equal_p (operands[0], operands[5]))
+ {
+ emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[4],
+ operands[5], operands[1]));
+ operands[5] = operands[4] = operands[0];
+ }
+ else if (!rtx_equal_p (operands[1], operands[6]))
+ operands[6] = copy_rtx (operands[1]);
+ else
+ FAIL;
+ }
+ [(set_attr "movprfx" "yes")]
+)
+
+;; Unpredicated FCMLA with indexing.
+(define_insn "@aarch64_<optab>_lane_<mode>"
+ [(set (match_operand:SVE_HSF 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_HSF
+ [(match_operand:SVE_HSF 1 "register_operand" "w, w")
+ (unspec:SVE_HSF
+ [(match_operand:SVE_HSF 2 "register_operand" "<sve_lane_pair_con>, <sve_lane_pair_con>")
+ (match_operand:SI 3 "const_int_operand")]
+ UNSPEC_SVE_LANE_SELECT)
+ (match_operand:SVE_HSF 4 "register_operand" "0, w")]
+ FCMLA))]
+ "TARGET_SVE"
+ "@
+ fcmla\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3], #<rot>
+ movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3], #<rot>"
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] Trigonometric multiply-add
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FTMAD
+;; -------------------------------------------------------------------------
+
+(define_insn "@aarch64_sve_tmad<mode>"
+ [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "0, w")
+ (match_operand:SVE_F 2 "register_operand" "w, w")
+ (match_operand:DI 3 "const_int_operand")]
+ UNSPEC_FTMAD))]
+ "TARGET_SVE"
+ "@
+ ftmad\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #%3
+ movprfx\t%0, %1\;ftmad\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #%3"
+ [(set_attr "movprfx" "*,yes")]
+)
+
;; =========================================================================
;; == Comparisons and selects
;; =========================================================================
;; the latter of which can be a zero constant or a variable. Treat duplicates
;; of GPRs as being more expensive than duplicates of FPRs, since they
;; involve a cross-file move.
-(define_insn "*aarch64_sel_dup<mode>"
+(define_insn "@aarch64_sel_dup<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=?w, w, ??w, ?&w, ??&w, ?&w")
(unspec:SVE_ALL
[(match_operand:<VPRED> 3 "register_operand" "Upa, Upa, Upl, Upl, Upl, Upl")
;; -------------------------------------------------------------------------
;; ---- [INT] Comparisons
;; -------------------------------------------------------------------------
-;; Includes merging patterns for:
+;; Includes:
;; - CMPEQ
;; - CMPGE
;; - CMPGT
(clobber (reg:CC_NZC CC_REGNUM))])]
)
-;; -------------------------------------------------------------------------
-;; ---- [INT] While tests
-;; -------------------------------------------------------------------------
-;; Includes:
-;; - WHILELO
-;; -------------------------------------------------------------------------
-
-;; Set element I of the result if operand1 + J < operand2 for all J in [0, I],
-;; with the comparison being unsigned.
-(define_insn "@while_ult<GPI:mode><PRED_ALL:mode>"
- [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
- (unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
- (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
- UNSPEC_WHILE_LO))
+;; Predicated integer wide comparisons.
+(define_insn "@aarch64_pred_cmp<cmp_op><mode>_wide"
+ [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+ (unspec:<VPRED>
+ [(match_operand:VNx16BI 1 "register_operand" "Upl")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:SVE_BHSI 3 "register_operand" "w")
+ (match_operand:VNx2DI 4 "register_operand" "w")]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z))
(clobber (reg:CC_NZC CC_REGNUM))]
"TARGET_SVE"
- "whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+ "cmp<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.d"
)
-;; WHILELO sets the flags in the same way as a PTEST with a PTRUE GP.
-;; Handle the case in which both results are useful. The GP operands
-;; to the PTEST aren't needed, so we allow them to be anything.
-(define_insn_and_rewrite "*while_ult<GPI:mode><PRED_ALL:mode>_cc"
+;; Predicated integer wide comparisons in which both the flag and
+;; predicate results are interesting.
+(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide_cc"
[(set (reg:CC_NZC CC_REGNUM)
(unspec:CC_NZC
- [(match_operand 3)
+ [(match_operand:VNx16BI 1 "register_operand" "Upl")
(match_operand 4)
- (const_int SVE_KNOWN_PTRUE)
- (unspec:PRED_ALL
- [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
- (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
- UNSPEC_WHILE_LO)]
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:VNx16BI 6 "register_operand" "Upl")
+ (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:SVE_BHSI 2 "register_operand" "w")
+ (match_operand:VNx2DI 3 "register_operand" "w")]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z)]
UNSPEC_PTEST))
- (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
- (unspec:PRED_ALL [(match_dup 1)
- (match_dup 2)]
- UNSPEC_WHILE_LO))]
- "TARGET_SVE"
- "whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
- ;; Force the compiler to drop the unused predicate operand, so that we
- ;; don't have an unnecessary PTRUE.
- "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
- {
- operands[3] = CONSTM1_RTX (VNx16BImode);
- operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
- }
-)
-
+ (set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+ (unspec:<VPRED>
+ [(match_dup 6)
+ (match_dup 7)
+ (unspec:<VPRED>
+ [(match_dup 2)
+ (match_dup 3)]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z))]
+ "TARGET_SVE
+ && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+ "cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.d"
+)
+
+;; Predicated integer wide comparisons in which only the flags result
+;; is interesting.
+(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upl")
+ (match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:VNx16BI 6 "register_operand" "Upl")
+ (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+ (unspec:<VPRED>
+ [(match_operand:SVE_BHSI 2 "register_operand" "w")
+ (match_operand:VNx2DI 3 "register_operand" "w")]
+ SVE_COND_INT_CMP_WIDE)]
+ UNSPEC_PRED_Z)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:<VPRED> 0 "=Upa"))]
+ "TARGET_SVE
+ && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+ "cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.d"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] While tests
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - WHILELE
+;; - WHILELO
+;; - WHILELS
+;; - WHILELT
+;; -------------------------------------------------------------------------
+
+;; Set element I of the result if (cmp (plus operand1 J) operand2) is
+;; true for all J in [0, I].
+(define_insn "@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>"
+ [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+ SVE_WHILE))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE"
+ "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+)
+
+;; The WHILE instructions set the flags in the same way as a PTEST with
+;; a PTRUE GP. Handle the case in which both results are useful. The GP
+;; operands to the PTEST aren't needed, so we allow them to be anything.
+(define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 3)
+ (match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (unspec:PRED_ALL
+ [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+ SVE_WHILE)]
+ UNSPEC_PTEST))
+ (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (unspec:PRED_ALL [(match_dup 1)
+ (match_dup 2)]
+ SVE_WHILE))]
+ "TARGET_SVE"
+ "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+ ;; Force the compiler to drop the unused predicate operand, so that we
+ ;; don't have an unnecessary PTRUE.
+ "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+ {
+ operands[3] = CONSTM1_RTX (VNx16BImode);
+ operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+;; Same, but handle the case in which only the flags result is useful.
+(define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand 3)
+ (match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (unspec:PRED_ALL
+ [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+ (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+ SVE_WHILE)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:PRED_ALL 0 "=Upa"))]
+ "TARGET_SVE"
+ "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+ ;; Force the compiler to drop the unused predicate operand, so that we
+ ;; don't have an unnecessary PTRUE.
+ "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+ {
+ operands[3] = CONSTM1_RTX (VNx16BImode);
+ operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP] Direct comparisons
;; -------------------------------------------------------------------------
)
;; Predicated floating-point comparisons.
-(define_insn "*fcm<cmp_op><mode>"
+(define_insn "@aarch64_pred_fcm<cmp_op><mode>"
[(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
(unspec:<VPRED>
[(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
- (match_operand:SI 4 "aarch64_sve_ptrue_flag")
- (match_operand:SVE_F 2 "register_operand" "w, w")
- (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w")]
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:SVE_F 3 "register_operand" "w, w")
+ (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, w")]
SVE_COND_FP_CMP_I0))]
"TARGET_SVE"
"@
- fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
- fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+ fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, #0.0
+ fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
)
;; Same for unordered comparisons.
-(define_insn "*fcmuo<mode>"
+(define_insn "@aarch64_pred_fcmuo<mode>"
[(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
(unspec:<VPRED>
[(match_operand:<VPRED> 1 "register_operand" "Upl")
- (match_operand:SI 4 "aarch64_sve_ptrue_flag")
- (match_operand:SVE_F 2 "register_operand" "w")
- (match_operand:SVE_F 3 "register_operand" "w")]
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:SVE_F 3 "register_operand" "w")
+ (match_operand:SVE_F 4 "register_operand" "w")]
UNSPEC_COND_FCMUO))]
"TARGET_SVE"
- "fcmuo\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+ "fcmuo\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
)
;; Floating-point comparisons predicated on a PTRUE, with the results ANDed
;; -------------------------------------------------------------------------
;; Predicated floating-point absolute comparisons.
+(define_expand "@aarch64_pred_fac<cmp_op><mode>"
+ [(set (match_operand:<VPRED> 0 "register_operand")
+ (unspec:<VPRED>
+ [(match_operand:<VPRED> 1 "register_operand")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (match_dup 2)
+ (match_operand:SVE_F 3 "register_operand")]
+ UNSPEC_COND_FABS)
+ (unspec:SVE_F
+ [(match_dup 1)
+ (match_dup 2)
+ (match_operand:SVE_F 4 "register_operand")]
+ UNSPEC_COND_FABS)]
+ SVE_COND_FP_ABS_CMP))]
+ "TARGET_SVE"
+)
+
(define_insn_and_rewrite "*aarch64_pred_fac<cmp_op><mode>"
[(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
(unspec:<VPRED>
}
)
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Select
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - SEL
+;; -------------------------------------------------------------------------
+
+(define_insn "@vcond_mask_<mode><mode>"
+ [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (ior:PRED_ALL
+ (and:PRED_ALL
+ (match_operand:PRED_ALL 3 "register_operand" "Upa")
+ (match_operand:PRED_ALL 1 "register_operand" "Upa"))
+ (and:PRED_ALL
+ (not (match_dup 3))
+ (match_operand:PRED_ALL 2 "register_operand" "Upa"))))]
+ "TARGET_SVE"
+ "sel\t%0.b, %3, %1.b, %2.b"
+)
+
;; -------------------------------------------------------------------------
;; ---- [PRED] Test bits
;; -------------------------------------------------------------------------
;; ---- [INT,FP] Conditional reductions
;; -------------------------------------------------------------------------
;; Includes:
+;; - CLASTA
;; - CLASTB
;; -------------------------------------------------------------------------
;; Set operand 0 to the last active element in operand 3, or to tied
;; operand 1 if no elements are active.
-(define_insn "fold_extract_last_<mode>"
+(define_insn "@fold_extract_<last_op>_<mode>"
[(set (match_operand:<VEL> 0 "register_operand" "=?r, w")
(unspec:<VEL>
[(match_operand:<VEL> 1 "register_operand" "0, 0")
(match_operand:<VPRED> 2 "register_operand" "Upl, Upl")
(match_operand:SVE_ALL 3 "register_operand" "w, w")]
- UNSPEC_CLASTB))]
+ CLAST))]
+ "TARGET_SVE"
+ "@
+ clast<ab>\t%<vwcore>0, %2, %<vwcore>0, %3.<Vetype>
+ clast<ab>\t%<Vetype>0, %2, %<Vetype>0, %3.<Vetype>"
+)
+
+(define_insn "@aarch64_fold_extract_vector_<last_op>_<mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_ALL
+ [(match_operand:SVE_ALL 1 "register_operand" "0, w")
+ (match_operand:<VPRED> 2 "register_operand" "Upl, Upl")
+ (match_operand:SVE_ALL 3 "register_operand" "w, w")]
+ CLAST))]
"TARGET_SVE"
"@
- clastb\t%<vwcore>0, %2, %<vwcore>0, %3.<Vetype>
- clastb\t%<Vetype>0, %2, %<Vetype>0, %3.<Vetype>"
+ clast<ab>\t%0.<Vetype>, %2, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %1\;clast<ab>\t%0.<Vetype>, %2, %0.<Vetype>, %3.<Vetype>"
)
;; -------------------------------------------------------------------------
;; - ANDV
;; - EORV
;; - ORV
+;; - SADDV
;; - SMAXV
;; - SMINV
;; - UADDV
;; Unpredicated integer add reduction.
(define_expand "reduc_plus_scal_<mode>"
- [(set (match_operand:<VEL> 0 "register_operand")
- (unspec:<VEL> [(match_dup 2)
- (match_operand:SVE_I 1 "register_operand")]
- UNSPEC_ADDV))]
+ [(match_operand:<VEL> 0 "register_operand")
+ (match_operand:SVE_I 1 "register_operand")]
"TARGET_SVE"
{
- operands[2] = aarch64_ptrue_reg (<VPRED>mode);
+ rtx pred = aarch64_ptrue_reg (<VPRED>mode);
+ rtx tmp = <VEL>mode == DImode ? operands[0] : gen_reg_rtx (DImode);
+ emit_insn (gen_aarch64_pred_reduc_uadd_<mode> (tmp, pred, operands[1]));
+ if (tmp != operands[0])
+ emit_move_insn (operands[0], gen_lowpart (<VEL>mode, tmp));
+ DONE;
}
)
;; Predicated integer add reduction. The result is always 64-bits.
-(define_insn "*reduc_plus_scal_<mode>"
- [(set (match_operand:<VEL> 0 "register_operand" "=w")
- (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
- (match_operand:SVE_I 2 "register_operand" "w")]
- UNSPEC_ADDV))]
- "TARGET_SVE"
- "uaddv\t%d0, %1, %2.<Vetype>"
+(define_insn "@aarch64_pred_reduc_<optab>_<mode>"
+ [(set (match_operand:DI 0 "register_operand" "=w")
+ (unspec:DI [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (match_operand:SVE_I 2 "register_operand" "w")]
+ SVE_INT_ADDV))]
+ "TARGET_SVE && <max_elem_bits> >= <elem_bits>"
+ "<su>addv\t%d0, %1, %2.<Vetype>"
)
;; Unpredicated integer reductions.
)
;; Predicated integer reductions.
-(define_insn "*reduc_<optab>_scal_<mode>"
+(define_insn "@aarch64_pred_reduc_<optab>_<mode>"
[(set (match_operand:<VEL> 0 "register_operand" "=w")
(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
(match_operand:SVE_I 2 "register_operand" "w")]
)
;; Predicated floating-point tree reductions.
-(define_insn "*reduc_<optab>_scal_<mode>"
+(define_insn "@aarch64_pred_reduc_<optab>_<mode>"
[(set (match_operand:<VEL> 0 "register_operand" "=w")
(unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
(match_operand:SVE_F 2 "register_operand" "w")]
}
)
-(define_insn "*aarch64_sve_tbl<mode>"
+(define_insn "@aarch64_sve_tbl<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w")
(unspec:SVE_ALL
[(match_operand:SVE_ALL 1 "register_operand" "w")
;; ---- [INT,FP] Special-purpose unary permutes
;; -------------------------------------------------------------------------
;; Includes:
+;; - COMPACT
;; - DUP
;; - REV
;; -------------------------------------------------------------------------
+;; Compact active elements and pad with zeros.
+(define_insn "@aarch64_sve_compact<mode>"
+ [(set (match_operand:SVE_SD 0 "register_operand" "=w")
+ (unspec:SVE_SD [(match_operand:<VPRED> 1 "register_operand" "Upl")
+ (match_operand:SVE_SD 2 "register_operand" "w")]
+ UNSPEC_SVE_COMPACT))]
+ "TARGET_SVE"
+ "compact\t%0.<Vetype>, %1, %2.<Vetype>"
+)
+
;; Duplicate one element of a vector.
-(define_insn "*aarch64_sve_dup_lane<mode>"
+(define_insn "@aarch64_sve_dup_lane<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w")
(vec_duplicate:SVE_ALL
(vec_select:<VEL>
"dup\t%0.<Vetype>, %1.<Vetype>[%2]"
)
+;; Use DUP.Q to duplicate a 128-bit segment of a register.
+;;
+;; The vec_select:<V128> sets memory lane number N of the V128 to lane
+;; number op2 + N of op1. (We don't need to distinguish between memory
+;; and architectural register lane numbering for op1 or op0, since the
+;; two numbering schemes are the same for SVE.)
+;;
+;; The vec_duplicate:SVE_ALL then copies memory lane number N of the
+;; V128 (and thus lane number op2 + N of op1) to lane numbers N + I * STEP
+;; of op0. We therefore get the correct result for both endiannesses.
+;;
+;; The wrinkle is that for big-endian V128 registers, memory lane numbering
+;; is in the opposite order to architectural register lane numbering.
+;; Thus if we were to do this operation via a V128 temporary register,
+;; the vec_select and vec_duplicate would both involve a reverse operation
+;; for big-endian targets. In this fused pattern the two reverses cancel
+;; each other out.
+(define_insn "@aarch64_sve_dupq_lane<mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+ (vec_duplicate:SVE_ALL
+ (vec_select:<V128>
+ (match_operand:SVE_ALL 1 "register_operand" "w")
+ (match_operand 2 "ascending_int_parallel"))))]
+ "TARGET_SVE
+ && (INTVAL (XVECEXP (operands[2], 0, 0))
+ * GET_MODE_SIZE (<VEL>mode)) % 16 == 0
+ && IN_RANGE (INTVAL (XVECEXP (operands[2], 0, 0))
+ * GET_MODE_SIZE (<VEL>mode), 0, 63)"
+ {
+ unsigned int byte = (INTVAL (XVECEXP (operands[2], 0, 0))
+ * GET_MODE_SIZE (<VEL>mode));
+ operands[2] = gen_int_mode (byte / 16, DImode);
+ return "dup\t%0.q, %1.q[%2]";
+ }
+)
+
;; Reverse the order of elements within a full vector.
(define_insn "@aarch64_sve_rev<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w")
;; ---- [INT,FP] Special-purpose binary permutes
;; -------------------------------------------------------------------------
;; Includes:
+;; - SPLICE
;; - TRN1
;; - TRN2
;; - UZP1
;; - ZIP2
;; -------------------------------------------------------------------------
+;; Like EXT, but start at the first active element.
+(define_insn "@aarch64_sve_splice<mode>"
+ [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
+ (unspec:SVE_ALL [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+ (match_operand:SVE_ALL 2 "register_operand" "0, w")
+ (match_operand:SVE_ALL 3 "register_operand" "w, w")]
+ UNSPEC_SVE_SPLICE))]
+ "TARGET_SVE"
+ "@
+ splice\t%0.<Vetype>, %1, %0.<Vetype>, %3.<Vetype>
+ movprfx\t%0, %2\;splice\t%0.<Vetype>, %1, %0.<Vetype>, %3.<Vetype>"
+ [(set_attr "movprfx" "*, yes")]
+)
+
;; Permutes that take half the elements from one vector and half the
;; elements from the other.
-(define_insn "aarch64_sve_<perm_insn><mode>"
+(define_insn "@aarch64_sve_<perm_insn><mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w")
(unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")
(match_operand:SVE_ALL 2 "register_operand" "w")]
;; Concatenate two vectors and extract a subvector. Note that the
;; immediate (third) operand is the lane index not the byte index.
-(define_insn "*aarch64_sve_ext<mode>"
+(define_insn "@aarch64_sve_ext<mode>"
[(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
(unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "0, w")
(match_operand:SVE_ALL 2 "register_operand" "w, w")
}
)
-(define_insn "aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>"
+(define_insn "@aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>"
[(set (match_operand:<VWIDE> 0 "register_operand" "=w")
(unspec:<VWIDE> [(match_operand:SVE_BHSI 1 "register_operand" "w")]
UNPACK))]
)
;; Predicated float-to-integer conversion, either to the same width or wider.
-(define_insn "*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
+(define_insn "@aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
[(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
(unspec:SVE_HSDI
[(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
)
;; Predicated narrowing float-to-integer conversion.
-(define_insn "*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+(define_insn "@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
[(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w")
(unspec:VNx4SI_ONLY
[(match_operand:VNx2BI 1 "register_operand" "Upl")
;; Predicated float-to-integer conversion with merging, either to the same
;; width or wider.
-;;
+(define_expand "@cond_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
+ [(set (match_operand:SVE_HSDI 0 "register_operand")
+ (unspec:SVE_HSDI
+ [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand")
+ (unspec:SVE_HSDI
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_F 2 "register_operand")]
+ SVE_COND_FCVTI)
+ (match_operand:SVE_HSDI 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+)
+
;; The first alternative doesn't need the earlyclobber, but the only case
;; it would help is the uninteresting one in which operands 2 and 3 are
;; the same register (despite having different modes). Making all the
[(set_attr "movprfx" "*,yes,yes")]
)
+;; Predicated narrowing float-to-integer conversion with merging.
+(define_expand "@cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+ [(set (match_operand:VNx4SI_ONLY 0 "register_operand")
+ (unspec:VNx4SI_ONLY
+ [(match_operand:VNx2BI 1 "register_operand")
+ (unspec:VNx4SI_ONLY
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:VNx2DF_ONLY 2 "register_operand")]
+ SVE_COND_FCVTI)
+ (match_operand:VNx4SI_ONLY 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
+(define_insn "*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+ [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=&w, &w, ?&w")
+ (unspec:VNx4SI_ONLY
+ [(match_operand:VNx2BI 1 "register_operand" "Upl, Upl, Upl")
+ (unspec:VNx4SI_ONLY
+ [(match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (match_operand:VNx2DF_ONLY 2 "register_operand" "w, w, w")]
+ SVE_COND_FCVTI)
+ (match_operand:VNx4SI_ONLY 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+ movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+ movprfx\t%0, %3\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>"
+ [(set_attr "movprfx" "*,yes,yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [INT<-FP] Packs
;; -------------------------------------------------------------------------
;; Predicated integer-to-float conversion, either to the same width or
;; narrower.
-(define_insn "*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
+(define_insn "@aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
[(set (match_operand:SVE_F 0 "register_operand" "=w")
(unspec:SVE_F
[(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
)
;; Predicated widening integer-to-float conversion.
-(define_insn "aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+(define_insn "@aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
[(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w")
(unspec:VNx2DF_ONLY
[(match_operand:VNx2BI 1 "register_operand" "Upl")
;; Predicated integer-to-float conversion with merging, either to the same
;; width or narrower.
-;;
+(define_expand "@cond_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
+ [(set (match_operand:SVE_F 0 "register_operand")
+ (unspec:SVE_F
+ [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand")
+ (unspec:SVE_F
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_HSDI 2 "register_operand")]
+ SVE_COND_ICVTF)
+ (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+)
+
;; The first alternative doesn't need the earlyclobber, but the only case
;; it would help is the uninteresting one in which operands 2 and 3 are
;; the same register (despite having different modes). Making all the
[(set_attr "movprfx" "*,yes,yes")]
)
+;; Predicated widening integer-to-float conversion with merging.
+(define_expand "@cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+ [(set (match_operand:VNx2DF_ONLY 0 "register_operand")
+ (unspec:VNx2DF_ONLY
+ [(match_operand:VNx2BI 1 "register_operand")
+ (unspec:VNx2DF_ONLY
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:VNx4SI_ONLY 2 "register_operand")]
+ SVE_COND_ICVTF)
+ (match_operand:VNx2DF_ONLY 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
+(define_insn "*cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+ [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w, ?&w, ?&w")
+ (unspec:VNx2DF_ONLY
+ [(match_operand:VNx2BI 1 "register_operand" "Upl, Upl, Upl")
+ (unspec:VNx2DF_ONLY
+ [(match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (match_operand:VNx4SI_ONLY 2 "register_operand" "w, w, w")]
+ SVE_COND_ICVTF)
+ (match_operand:VNx2DF_ONLY 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+ "@
+ <su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
+ movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
+ movprfx\t%0, %3\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>"
+ [(set_attr "movprfx" "*,yes,yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP<-INT] Packs
;; -------------------------------------------------------------------------
)
;; Predicated float-to-float truncation.
-(define_insn "*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
+(define_insn "@aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
[(set (match_operand:SVE_HSF 0 "register_operand" "=w")
(unspec:SVE_HSF
[(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
"fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>"
)
+;; Predicated float-to-float truncation with merging.
+(define_expand "@cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
+ [(set (match_operand:SVE_HSF 0 "register_operand")
+ (unspec:SVE_HSF
+ [(match_operand:<SVE_SDF:VPRED> 1 "register_operand")
+ (unspec:SVE_HSF
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_SDF 2 "register_operand")]
+ SVE_COND_FCVT)
+ (match_operand:SVE_HSF 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+)
+
+(define_insn "*cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
+ [(set (match_operand:SVE_HSF 0 "register_operand" "=w, ?&w, ?&w")
+ (unspec:SVE_HSF
+ [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl, Upl, Upl")
+ (unspec:SVE_HSF
+ [(match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_SDF 2 "register_operand" "w, w, w")]
+ SVE_COND_FCVT)
+ (match_operand:SVE_HSF 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+ "@
+ fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+ movprfx\t%0.<SVE_SDF:Vetype>, %1/z, %2.<SVE_SDF:Vetype>\;fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+ movprfx\t%0, %3\;fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>"
+ [(set_attr "movprfx" "*,yes,yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [FP<-FP] Unpacks
;; -------------------------------------------------------------------------
)
;; Predicated float-to-float extension.
-(define_insn "aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+(define_insn "@aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
[(set (match_operand:SVE_SDF 0 "register_operand" "=w")
(unspec:SVE_SDF
[(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
"fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>"
)
+;; Predicated float-to-float extension with merging.
+(define_expand "@cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+ [(set (match_operand:SVE_SDF 0 "register_operand")
+ (unspec:SVE_SDF
+ [(match_operand:<SVE_SDF:VPRED> 1 "register_operand")
+ (unspec:SVE_SDF
+ [(match_dup 1)
+ (const_int SVE_STRICT_GP)
+ (match_operand:SVE_HSF 2 "register_operand")]
+ SVE_COND_FCVT)
+ (match_operand:SVE_SDF 3 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+)
+
+(define_insn "*cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+ [(set (match_operand:SVE_SDF 0 "register_operand" "=w, ?&w, ?&w")
+ (unspec:SVE_SDF
+ [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl, Upl, Upl")
+ (unspec:SVE_SDF
+ [(match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_gp_strictness")
+ (match_operand:SVE_HSF 2 "register_operand" "w, w, w")]
+ SVE_COND_FCVT)
+ (match_operand:SVE_SDF 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+ UNSPEC_SEL))]
+ "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+ "@
+ fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>
+ movprfx\t%0.<SVE_SDF:Vetype>, %1/z, %2.<SVE_SDF:Vetype>\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>
+ movprfx\t%0, %3\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>"
+ [(set_attr "movprfx" "*,yes,yes")]
+)
+
;; -------------------------------------------------------------------------
;; ---- [PRED<-PRED] Packs
;; -------------------------------------------------------------------------
}
)
-(define_insn "aarch64_sve_punpk<perm_hilo>_<mode>"
+(define_insn "@aarch64_sve_punpk<perm_hilo>_<mode>"
[(set (match_operand:<VWIDE> 0 "register_operand" "=Upa")
(unspec:<VWIDE> [(match_operand:PRED_BHS 1 "register_operand" "Upa")]
UNPACK_UNSIGNED))]
"TARGET_SVE"
"punpk<perm_hilo>\t%0.h, %1.b"
)
+
+;; =========================================================================
+;; == Vector partitioning
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Unary partitioning
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - BRKA
+;; - BRKAS
+;; - BRKB
+;; - BRKBS
+;; -------------------------------------------------------------------------
+
+;; Note that unlike most other instructions that have both merging and
+;; zeroing forms, these instructions don't operate elementwise and so
+;; don't fit the IFN_COND model.
+(define_insn "@aarch64_brk<brk_op>"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa, Upa")
+ (unspec:VNx16BI
+ [(match_operand:VNx16BI 1 "register_operand" "Upa, Upa")
+ (match_operand:VNx16BI 2 "register_operand" "Upa, Upa")
+ (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero" "Dz, 0")]
+ SVE_BRK_UNARY))]
+ "TARGET_SVE"
+ "@
+ brk<brk_op>\t%0.b, %1/z, %2.b
+ brk<brk_op>\t%0.b, %1/m, %2.b"
+)
+
+;; Same, but also producing a flags result.
+(define_insn "*aarch64_brk<brk_op>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa, Upa")
+ (match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+ (unspec:VNx16BI
+ [(match_dup 1)
+ (match_operand:VNx16BI 2 "register_operand" "Upa, Upa")
+ (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero" "Dz, 0")]
+ SVE_BRK_UNARY)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa, Upa")
+ (unspec:VNx16BI
+ [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ SVE_BRK_UNARY))]
+ "TARGET_SVE"
+ "@
+ brk<brk_op>s\t%0.b, %1/z, %2.b
+ brk<brk_op>s\t%0.b, %1/m, %2.b"
+)
+
+;; Same, but with only the flags result being interesting.
+(define_insn "*aarch64_brk<brk_op>_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa, Upa")
+ (match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+ (unspec:VNx16BI
+ [(match_dup 1)
+ (match_operand:VNx16BI 2 "register_operand" "Upa, Upa")
+ (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero" "Dz, 0")]
+ SVE_BRK_UNARY)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa, Upa"))]
+ "TARGET_SVE"
+ "@
+ brk<brk_op>s\t%0.b, %1/z, %2.b
+ brk<brk_op>s\t%0.b, %1/m, %2.b"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Binary partitioning
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - BRKN
+;; - BRKNS
+;; - BRKPA
+;; - BRKPAS
+;; - BRKPB
+;; - BRKPBS
+;; -------------------------------------------------------------------------
+
+;; Binary BRKs (BRKN, BRKPA, BRKPB).
+(define_insn "@aarch64_brk<brk_op>"
+ [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (unspec:VNx16BI
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand:VNx16BI 2 "register_operand" "Upa")
+ (match_operand:VNx16BI 3 "register_operand" "<brk_reg_con>")]
+ SVE_BRK_BINARY))]
+ "TARGET_SVE"
+ "brk<brk_op>\t%0.b, %1/z, %2.b, %<brk_reg_opno>.b"
+)
+
+;; Same, but also producing a flags result.
+(define_insn "*aarch64_brk<brk_op>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+ (unspec:VNx16BI
+ [(match_dup 1)
+ (match_operand:VNx16BI 2 "register_operand" "Upa")
+ (match_operand:VNx16BI 3 "register_operand" "<brk_reg_con>")]
+ SVE_BRK_BINARY)]
+ UNSPEC_PTEST))
+ (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+ (unspec:VNx16BI
+ [(match_dup 1)
+ (match_dup 2)
+ (match_dup 3)]
+ SVE_BRK_BINARY))]
+ "TARGET_SVE"
+ "brk<brk_op>s\t%0.b, %1/z, %2.b, %<brk_reg_opno>.b"
+)
+
+;; Same, but with only the flags result being interesting.
+(define_insn "*aarch64_brk<brk_op>_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_dup 1)
+ (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+ (unspec:VNx16BI
+ [(match_dup 1)
+ (match_operand:VNx16BI 2 "register_operand" "Upa")
+ (match_operand:VNx16BI 3 "register_operand" "<brk_reg_con>")]
+ SVE_BRK_BINARY)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+ "TARGET_SVE"
+ "brk<brk_op>s\t%0.b, %1/z, %2.b, %<brk_reg_opno>.b"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Scalarization
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - PFIRST
+;; - PNEXT
+;; -------------------------------------------------------------------------
+
+(define_insn "@aarch64_sve_<sve_pred_op><mode>"
+ [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (unspec:PRED_ALL
+ [(match_operand:PRED_ALL 1 "register_operand" "Upa")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_ALL 3 "register_operand" "0")]
+ SVE_PITER))
+ (clobber (reg:CC_NZC CC_REGNUM))]
+ "TARGET_SVE && <max_elem_bits> >= <elem_bits>"
+ "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+)
+
+;; Same, but also producing a flags result.
+(define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_cc"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 2)
+ (match_operand:SI 3 "aarch64_sve_ptrue_flag")
+ (unspec:PRED_ALL
+ [(match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_ALL 6 "register_operand" "0")]
+ SVE_PITER)]
+ UNSPEC_PTEST))
+ (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+ (unspec:PRED_ALL
+ [(match_dup 4)
+ (match_dup 5)
+ (match_dup 6)]
+ SVE_PITER))]
+ "TARGET_SVE
+ && <max_elem_bits> >= <elem_bits>
+ && aarch64_sve_same_pred_for_ptest_p (&operands[2], &operands[4])"
+ "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+ "&& !rtx_equal_p (operands[2], operands[4])"
+ {
+ operands[4] = operands[2];
+ operands[5] = operands[3];
+ }
+)
+
+;; Same, but with only the flags result being interesting.
+(define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_ptest"
+ [(set (reg:CC_NZC CC_REGNUM)
+ (unspec:CC_NZC
+ [(match_operand:VNx16BI 1 "register_operand" "Upa")
+ (match_operand 2)
+ (match_operand:SI 3 "aarch64_sve_ptrue_flag")
+ (unspec:PRED_ALL
+ [(match_operand 4)
+ (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_ALL 6 "register_operand" "0")]
+ SVE_PITER)]
+ UNSPEC_PTEST))
+ (clobber (match_scratch:PRED_ALL 0 "=Upa"))]
+ "TARGET_SVE
+ && <max_elem_bits> >= <elem_bits>
+ && aarch64_sve_same_pred_for_ptest_p (&operands[2], &operands[4])"
+ "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+ "&& !rtx_equal_p (operands[2], operands[4])"
+ {
+ operands[4] = operands[2];
+ operands[5] = operands[3];
+ }
+)
+
+;; =========================================================================
+;; == Counting elements
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Count elements in a pattern (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - CNTB
+;; - CNTD
+;; - CNTH
+;; - CNTW
+;; -------------------------------------------------------------------------
+
+;; Count the number of elements in an svpattern. Operand 1 is the pattern,
+;; operand 2 is the number of elements that fit in a 128-bit block, and
+;; operand 3 is a multiplier in the range [1, 16].
+;;
+;; Note that this pattern isn't used for SV_ALL (but would work for that too).
+(define_insn "aarch64_sve_cnt_pat"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (unspec:SI [(match_operand:DI 1 "const_int_operand")
+ (match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_cnt_pat_immediate ("cnt", "%x0", operands + 1);
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a pattern (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INC
+;; - SQINC
+;; - UQINC
+;; -------------------------------------------------------------------------
+
+;; Increment a DImode register by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ANY_PLUS:DI (zero_extend:DI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT))
+ (match_operand:DI_ONLY 1 "register_operand" "0")))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%x0",
+ operands + 2);
+ }
+)
+
+;; Increment an SImode register by the number of elements in an svpattern
+;; using modular arithmetic. See aarch64_sve_cnt_pat for the counting
+;; behavior.
+(define_insn "*aarch64_sve_incsi_pat"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)
+ (match_operand:SI 1 "register_operand" "0")))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_cnt_pat_immediate ("inc", "%x0", operands + 2);
+ }
+)
+
+;; Increment an SImode register by the number of elements in an svpattern
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (<paired_extend>:DI
+ (SAT_PLUS:SI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)
+ (match_operand:SI_ONLY 1 "register_operand" "0"))))]
+ "TARGET_SVE"
+ {
+ const char *registers = (<CODE> == SS_PLUS ? "%x0, %w0" : "%w0");
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", registers,
+ operands + 2);
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a pattern (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INC
+;; - SQINC
+;; - UQINC
+;; -------------------------------------------------------------------------
+
+;; Increment a vector of DIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+ (ANY_PLUS:VNx2DI
+ (vec_duplicate:VNx2DI
+ (zero_extend:DI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)))
+ (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ {
+ if (which_alternative == 1)
+ output_asm_insn ("movprfx\t%0, %1", operands);
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+ operands + 2);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of SIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+ (ANY_PLUS:VNx4SI
+ (vec_duplicate:VNx4SI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT))
+ (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ {
+ if (which_alternative == 1)
+ output_asm_insn ("movprfx\t%0, %1", operands);
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+ operands + 2);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of HIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_expand "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx8HI 0 "register_operand")
+ (ANY_PLUS:VNx8HI
+ (vec_duplicate:VNx8HI
+ (truncate:HI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)))
+ (match_operand:VNx8HI_ONLY 1 "register_operand")))]
+ "TARGET_SVE"
+)
+
+(define_insn "*aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+ (ANY_PLUS:VNx8HI
+ (vec_duplicate:VNx8HI
+ (match_operator:HI 5 "subreg_lowpart_operator"
+ [(unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)]))
+ (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ {
+ if (which_alternative == 1)
+ output_asm_insn ("movprfx\t%0, %1", operands);
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+ operands + 2);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a pattern (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DEC
+;; - SQDEC
+;; - UQDEC
+;; -------------------------------------------------------------------------
+
+;; Decrement a DImode register by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ANY_MINUS:DI (match_operand:DI_ONLY 1 "register_operand" "0")
+ (zero_extend:DI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT))))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%x0",
+ operands + 2);
+ }
+)
+
+;; Decrement an SImode register by the number of elements in an svpattern
+;; using modular arithmetic. See aarch64_sve_cnt_pat for the counting
+;; behavior.
+(define_insn "*aarch64_sve_decsi_pat"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "0")
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)))]
+ "TARGET_SVE"
+ {
+ return aarch64_output_sve_cnt_pat_immediate ("dec", "%x0", operands + 2);
+ }
+)
+
+;; Decrement an SImode register by the number of elements in an svpattern
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (<paired_extend>:DI
+ (SAT_MINUS:SI
+ (match_operand:SI_ONLY 1 "register_operand" "0")
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT))))]
+ "TARGET_SVE"
+ {
+ const char *registers = (<CODE> == SS_MINUS ? "%x0, %w0" : "%w0");
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", registers,
+ operands + 2);
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a pattern (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DEC
+;; - SQDEC
+;; - UQDEC
+;; -------------------------------------------------------------------------
+
+;; Decrement a vector of DIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+ (ANY_MINUS:VNx2DI
+ (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")
+ (vec_duplicate:VNx2DI
+ (zero_extend:DI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)))))]
+ "TARGET_SVE"
+ {
+ if (which_alternative == 1)
+ output_asm_insn ("movprfx\t%0, %1", operands);
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+ operands + 2);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of SIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+ (ANY_MINUS:VNx4SI
+ (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")
+ (vec_duplicate:VNx4SI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT))))]
+ "TARGET_SVE"
+ {
+ if (which_alternative == 1)
+ output_asm_insn ("movprfx\t%0, %1", operands);
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+ operands + 2);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of HIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_expand "@aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx8HI 0 "register_operand")
+ (ANY_MINUS:VNx8HI
+ (match_operand:VNx8HI_ONLY 1 "register_operand")
+ (vec_duplicate:VNx8HI
+ (truncate:HI
+ (unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)))))]
+ "TARGET_SVE"
+)
+
+(define_insn "*aarch64_sve_<inc_dec><mode>_pat"
+ [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+ (ANY_MINUS:VNx8HI
+ (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")
+ (vec_duplicate:VNx8HI
+ (match_operator:HI 5 "subreg_lowpart_operator"
+ [(unspec:SI [(match_operand:DI 2 "const_int_operand")
+ (match_operand:DI 3 "const_int_operand")
+ (match_operand:DI 4 "const_int_operand")]
+ UNSPEC_SVE_CNT_PAT)]))))]
+ "TARGET_SVE"
+ {
+ if (which_alternative == 1)
+ output_asm_insn ("movprfx\t%0, %1", operands);
+ return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+ operands + 2);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Count elements in a predicate (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - CNTP
+;; -------------------------------------------------------------------------
+
+;; Count the number of set bits in a predicate. Operand 3 is true if
+;; operand 1 is known to be all-true.
+(define_insn "@aarch64_pred_cntp<mode>"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI
+ (unspec:SI [(match_operand:PRED_ALL 1 "register_operand" "Upl")
+ (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+ (match_operand:PRED_ALL 3 "register_operand" "Upa")]
+ UNSPEC_CNTP)))]
+ "TARGET_SVE"
+ "cntp\t%x0, %1, %3.<Vetype>")
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a predicate (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INCP
+;; - SQINCP
+;; - UQINCP
+;; -------------------------------------------------------------------------
+
+;; Increment a DImode register by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand")
+ (ANY_PLUS:DI
+ (zero_extend:DI
+ (unspec:SI [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand")]
+ UNSPEC_CNTP))
+ (match_operand:DI_ONLY 1 "register_operand")))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ANY_PLUS:DI
+ (zero_extend:DI
+ (unspec:SI [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+ UNSPEC_CNTP))
+ (match_operand:DI_ONLY 1 "register_operand" "0")))]
+ "TARGET_SVE"
+ "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+;; Increment an SImode register by the number of set bits in a predicate
+;; using modular arithmetic. See aarch64_sve_cntp for a description of
+;; the operands.
+(define_insn_and_rewrite "*aarch64_incsi<mode>_cntp"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI
+ (unspec:SI [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+ UNSPEC_CNTP)
+ (match_operand:SI 1 "register_operand" "0")))]
+ "TARGET_SVE"
+ "incp\t%x0, %2.<Vetype>"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<MODE>mode);
+ }
+)
+
+;; Increment an SImode register by the number of set bits in a predicate
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand")
+ (<paired_extend>:DI
+ (SAT_PLUS:SI
+ (unspec:SI [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand")]
+ UNSPEC_CNTP)
+ (match_operand:SI_ONLY 1 "register_operand"))))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (<paired_extend>:DI
+ (SAT_PLUS:SI
+ (unspec:SI [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+ UNSPEC_CNTP)
+ (match_operand:SI_ONLY 1 "register_operand" "0"))))]
+ "TARGET_SVE"
+ {
+ if (<CODE> == SS_PLUS)
+ return "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>, %w0";
+ else
+ return "<inc_dec>p\t%w0, %2.<PRED_ALL:Vetype>";
+ }
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a predicate (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INCP
+;; - SQINCP
+;; - UQINCP
+;; -------------------------------------------------------------------------
+
+;; Increment a vector of DIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx2DI 0 "register_operand")
+ (ANY_PLUS:VNx2DI
+ (vec_duplicate:VNx2DI
+ (zero_extend:DI
+ (unspec:SI
+ [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand")]
+ UNSPEC_CNTP)))
+ (match_operand:VNx2DI_ONLY 1 "register_operand")))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+ (ANY_PLUS:VNx2DI
+ (vec_duplicate:VNx2DI
+ (zero_extend:DI
+ (unspec:SI
+ [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+ UNSPEC_CNTP)))
+ (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ "@
+ <inc_dec>p\t%0.d, %2
+ movprfx\t%0, %1\;<inc_dec>p\t%0.d, %2"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of SIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx4SI 0 "register_operand")
+ (ANY_PLUS:VNx4SI
+ (vec_duplicate:VNx4SI
+ (unspec:SI
+ [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand")]
+ UNSPEC_CNTP))
+ (match_operand:VNx4SI_ONLY 1 "register_operand")))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+ (ANY_PLUS:VNx4SI
+ (vec_duplicate:VNx4SI
+ (unspec:SI
+ [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+ UNSPEC_CNTP))
+ (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ "@
+ <inc_dec>p\t%0.s, %2
+ movprfx\t%0, %1\;<inc_dec>p\t%0.s, %2"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of HIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx8HI 0 "register_operand")
+ (ANY_PLUS:VNx8HI
+ (vec_duplicate:VNx8HI
+ (truncate:HI
+ (unspec:SI
+ [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand")]
+ UNSPEC_CNTP)))
+ (match_operand:VNx8HI_ONLY 1 "register_operand")))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+ (ANY_PLUS:VNx8HI
+ (vec_duplicate:VNx8HI
+ (match_operator:HI 3 "subreg_lowpart_operator"
+ [(unspec:SI
+ [(match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+ UNSPEC_CNTP)]))
+ (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")))]
+ "TARGET_SVE"
+ "@
+ <inc_dec>p\t%0.h, %2
+ movprfx\t%0, %1\;<inc_dec>p\t%0.h, %2"
+ "&& !CONSTANT_P (operands[4])"
+ {
+ operands[4] = CONSTM1_RTX (<VPRED>mode);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a predicate (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DECP
+;; - SQDECP
+;; - UQDECP
+;; -------------------------------------------------------------------------
+
+;; Decrement a DImode register by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand")
+ (ANY_MINUS:DI
+ (match_operand:DI_ONLY 1 "register_operand")
+ (zero_extend:DI
+ (unspec:SI [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand")]
+ UNSPEC_CNTP))))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ANY_MINUS:DI
+ (match_operand:DI_ONLY 1 "register_operand" "0")
+ (zero_extend:DI
+ (unspec:SI [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+ UNSPEC_CNTP))))]
+ "TARGET_SVE"
+ "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+;; Decrement an SImode register by the number of set bits in a predicate
+;; using modular arithmetic. See aarch64_sve_cntp for a description of the
+;; operands.
+(define_insn_and_rewrite "*aarch64_decsi<mode>_cntp"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI
+ (match_operand:SI 1 "register_operand" "0")
+ (unspec:SI [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+ UNSPEC_CNTP)))]
+ "TARGET_SVE"
+ "decp\t%x0, %2.<Vetype>"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<MODE>mode);
+ }
+)
+
+;; Decrement an SImode register by the number of set bits in a predicate
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand")
+ (<paired_extend>:DI
+ (SAT_MINUS:SI
+ (match_operand:SI_ONLY 1 "register_operand")
+ (unspec:SI [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand")]
+ UNSPEC_CNTP))))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (<paired_extend>:DI
+ (SAT_MINUS:SI
+ (match_operand:SI_ONLY 1 "register_operand" "0")
+ (unspec:SI [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+ UNSPEC_CNTP))))]
+ "TARGET_SVE"
+ {
+ if (<CODE> == SS_MINUS)
+ return "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>, %w0";
+ else
+ return "<inc_dec>p\t%w0, %2.<PRED_ALL:Vetype>";
+ }
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+ }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a predicate (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DECP
+;; - SQDECP
+;; - UQDECP
+;; -------------------------------------------------------------------------
+
+;; Decrement a vector of DIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx2DI 0 "register_operand")
+ (ANY_MINUS:VNx2DI
+ (match_operand:VNx2DI_ONLY 1 "register_operand")
+ (vec_duplicate:VNx2DI
+ (zero_extend:DI
+ (unspec:SI
+ [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand")]
+ UNSPEC_CNTP)))))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+ (ANY_MINUS:VNx2DI
+ (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")
+ (vec_duplicate:VNx2DI
+ (zero_extend:DI
+ (unspec:SI
+ [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+ UNSPEC_CNTP)))))]
+ "TARGET_SVE"
+ "@
+ <inc_dec>p\t%0.d, %2
+ movprfx\t%0, %1\;<inc_dec>p\t%0.d, %2"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of SIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx4SI 0 "register_operand")
+ (ANY_MINUS:VNx4SI
+ (match_operand:VNx4SI_ONLY 1 "register_operand")
+ (vec_duplicate:VNx4SI
+ (unspec:SI
+ [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand")]
+ UNSPEC_CNTP))))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+ (ANY_MINUS:VNx4SI
+ (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")
+ (vec_duplicate:VNx4SI
+ (unspec:SI
+ [(match_operand 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+ UNSPEC_CNTP))))]
+ "TARGET_SVE"
+ "@
+ <inc_dec>p\t%0.s, %2
+ movprfx\t%0, %1\;<inc_dec>p\t%0.s, %2"
+ "&& !CONSTANT_P (operands[3])"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of HIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx8HI 0 "register_operand")
+ (ANY_MINUS:VNx8HI
+ (match_operand:VNx8HI_ONLY 1 "register_operand")
+ (vec_duplicate:VNx8HI
+ (truncate:HI
+ (unspec:SI
+ [(match_dup 3)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand")]
+ UNSPEC_CNTP)))))]
+ "TARGET_SVE"
+ {
+ operands[3] = CONSTM1_RTX (<VPRED>mode);
+ }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+ [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+ (ANY_MINUS:VNx8HI
+ (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")
+ (vec_duplicate:VNx8HI
+ (match_operator:HI 3 "subreg_lowpart_operator"
+ [(unspec:SI
+ [(match_operand 4)
+ (const_int SVE_KNOWN_PTRUE)
+ (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+ UNSPEC_CNTP)]))))]
+ "TARGET_SVE"
+ "@
+ <inc_dec>p\t%0.h, %2
+ movprfx\t%0, %1\;<inc_dec>p\t%0.h, %2"
+ "&& !CONSTANT_P (operands[4])"
+ {
+ operands[4] = CONSTM1_RTX (<VPRED>mode);
+ }
+ [(set_attr "movprfx" "*,yes")]
+)
/* Return the SVE vector mode that has NUNITS elements of mode INNER_MODE. */
-static opt_machine_mode
+opt_machine_mode
aarch64_sve_data_mode (scalar_mode inner_mode, poly_uint64 nunits)
{
enum mode_class mclass = (is_a <scalar_float_mode> (inner_mode)
Unlike mode_for_int_vector, this can handle the case in which
MODE is a predicate (and thus has a different total size). */
-static machine_mode
+machine_mode
aarch64_sve_int_mode (machine_mode mode)
{
scalar_int_mode int_mode = aarch64_sve_element_int_mode (mode);
return mask & -mask;
}
+/* If VNx16BImode rtx X is a canonical PTRUE for a predicate mode,
+ return that predicate mode, otherwise return opt_machine_mode (). */
+
+opt_machine_mode
+aarch64_ptrue_all_mode (rtx x)
+{
+ gcc_assert (GET_MODE (x) == VNx16BImode);
+ if (GET_CODE (x) != CONST_VECTOR
+ || !CONST_VECTOR_DUPLICATE_P (x)
+ || !CONST_INT_P (CONST_VECTOR_ENCODED_ELT (x, 0))
+ || INTVAL (CONST_VECTOR_ENCODED_ELT (x, 0)) == 0)
+ return opt_machine_mode ();
+
+ unsigned int nelts = const_vector_encoded_nelts (x);
+ for (unsigned int i = 1; i < nelts; ++i)
+ if (CONST_VECTOR_ENCODED_ELT (x, i) != const0_rtx)
+ return opt_machine_mode ();
+
+ return aarch64_sve_pred_mode (nelts);
+}
+
/* BUILDER is a predicate constant of mode VNx16BI. Consider the value
that the constant would have with predicate element size ELT_SIZE
(ignoring the upper bits in each element) and return:
the corresponding SVE predicate mode. Use TARGET for the result
if it's nonnull and convenient. */
-static rtx
+rtx
aarch64_convert_sve_data_to_pred (rtx target, machine_mode mode, rtx src)
{
machine_mode src_mode = GET_MODE (src);
src, CONST0_RTX (src_mode));
}
+/* Return the assembly token for svprfop value PRFOP. */
+
+static const char *
+svprfop_token (enum aarch64_svprfop prfop)
+{
+ switch (prfop)
+ {
+#define CASE(UPPER, LOWER, VALUE) case AARCH64_SV_##UPPER: return #LOWER;
+ AARCH64_FOR_SVPRFOP (CASE)
+#undef CASE
+ case AARCH64_NUM_SVPRFOPS:
+ break;
+ }
+ gcc_unreachable ();
+}
+
+/* Return the assembly string for an SVE prefetch operation with
+ mnemonic MNEMONIC, given that PRFOP_RTX is the prefetch operation
+ and that SUFFIX is the format for the remaining operands. */
+
+char *
+aarch64_output_sve_prefetch (const char *mnemonic, rtx prfop_rtx,
+ const char *suffix)
+{
+ static char buffer[128];
+ aarch64_svprfop prfop = (aarch64_svprfop) INTVAL (prfop_rtx);
+ unsigned int written = snprintf (buffer, sizeof (buffer), "%s\t%s, %s",
+ mnemonic, svprfop_token (prfop), suffix);
+ gcc_assert (written < sizeof (buffer));
+ return buffer;
+}
+
+/* Check whether we can calculate the number of elements in PATTERN
+ at compile time, given that there are NELTS_PER_VQ elements per
+ 128-bit block. Return the value if so, otherwise return -1. */
+
+HOST_WIDE_INT
+aarch64_fold_sve_cnt_pat (aarch64_svpattern pattern, unsigned int nelts_per_vq)
+{
+ unsigned int vl, const_vg;
+ if (pattern >= AARCH64_SV_VL1 && pattern <= AARCH64_SV_VL8)
+ vl = 1 + (pattern - AARCH64_SV_VL1);
+ else if (pattern >= AARCH64_SV_VL16 && pattern <= AARCH64_SV_VL256)
+ vl = 16 << (pattern - AARCH64_SV_VL16);
+ else if (aarch64_sve_vg.is_constant (&const_vg))
+ {
+ /* There are two vector granules per quadword. */
+ unsigned int nelts = (const_vg / 2) * nelts_per_vq;
+ switch (pattern)
+ {
+ case AARCH64_SV_POW2: return 1 << floor_log2 (nelts);
+ case AARCH64_SV_MUL4: return nelts & -4;
+ case AARCH64_SV_MUL3: return (nelts / 3) * 3;
+ case AARCH64_SV_ALL: return nelts;
+ default: gcc_unreachable ();
+ }
+ }
+ else
+ return -1;
+
+ /* There are two vector granules per quadword. */
+ poly_uint64 nelts_all = exact_div (aarch64_sve_vg, 2) * nelts_per_vq;
+ if (known_le (vl, nelts_all))
+ return vl;
+
+ /* Requesting more elements than are available results in a PFALSE. */
+ if (known_gt (vl, nelts_all))
+ return 0;
+
+ return -1;
+}
+
/* Return true if we can move VALUE into a register using a single
CNT[BHWD] instruction. */
value.coeffs[1], 0);
}
+/* Return the asm string for an instruction with a CNT-like vector size
+ operand (a vector pattern followed by a multiplier in the range [1, 16]).
+ PREFIX is the mnemonic without the size suffix and OPERANDS is the
+ first part of the operands template (the part that comes before the
+ vector size itself). CNT_PAT[0..2] are the operands of the
+ UNSPEC_SVE_CNT_PAT; see aarch64_sve_cnt_pat for details. */
+
+char *
+aarch64_output_sve_cnt_pat_immediate (const char *prefix,
+ const char *operands, rtx *cnt_pat)
+{
+ aarch64_svpattern pattern = (aarch64_svpattern) INTVAL (cnt_pat[0]);
+ unsigned int nelts_per_vq = INTVAL (cnt_pat[1]);
+ unsigned int factor = INTVAL (cnt_pat[2]) * nelts_per_vq;
+ return aarch64_output_sve_cnt_immediate (prefix, operands, pattern,
+ factor, nelts_per_vq);
+}
+
/* Return true if we can add X using a single SVE INC or DEC instruction. */
bool
{
rtx limit = force_reg (DImode, gen_int_mode (vl, DImode));
target = aarch64_target_reg (target, mode);
- emit_insn (gen_while_ult (DImode, mode, target, const0_rtx, limit));
+ emit_insn (gen_while (UNSPEC_WHILE_LO, DImode, mode,
+ target, const0_rtx, limit));
return target;
}
attributes. Unlike gen_lowpart, this doesn't care whether the
mode change is valid. */
-static rtx
+rtx
aarch64_replace_reg_mode (rtx x, machine_mode mode)
{
if (GET_MODE (x) == mode)
aarch64_init_builtins ()
{
aarch64_general_init_builtins ();
+ aarch64_sve::init_builtins ();
}
/* Implement TARGET_FOLD_BUILTIN. */
{
case AARCH64_BUILTIN_GENERAL:
return aarch64_general_fold_builtin (subcode, type, nargs, args);
+
+ case AARCH64_BUILTIN_SVE:
+ return NULL_TREE;
}
gcc_unreachable ();
}
case AARCH64_BUILTIN_GENERAL:
new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt);
break;
+
+ case AARCH64_BUILTIN_SVE:
+ new_stmt = aarch64_sve::gimple_fold_builtin (subcode, gsi, stmt);
+ break;
}
if (!new_stmt)
{
case AARCH64_BUILTIN_GENERAL:
return aarch64_general_expand_builtin (subcode, exp, target, ignore);
+
+ case AARCH64_BUILTIN_SVE:
+ return aarch64_sve::expand_builtin (subcode, exp, target);
}
gcc_unreachable ();
}
{
case AARCH64_BUILTIN_GENERAL:
return aarch64_general_builtin_decl (subcode, initialize_p);
+
+ case AARCH64_BUILTIN_SVE:
+ return aarch64_sve::builtin_decl (subcode, initialize_p);
}
gcc_unreachable ();
}
{
case AARCH64_BUILTIN_GENERAL:
return aarch64_general_builtin_rsqrt (subcode);
+
+ case AARCH64_BUILTIN_SVE:
+ return NULL_TREE;
}
gcc_unreachable ();
}
/* Mangle AArch64-specific internal types. TYPE_NAME is non-NULL_TREE for
builtin types. */
if (TYPE_NAME (type) != NULL)
- return aarch64_general_mangle_builtin_type (type);
+ {
+ const char *res;
+ if ((res = aarch64_general_mangle_builtin_type (type))
+ || (res = aarch64_sve::mangle_builtin_type (type)))
+ return res;
+ }
/* Use the default mangling. */
return NULL;
return IN_RANGE (val, 0, 0xff00);
}
+/* Return true if X is a valid immediate for the SVE SQADD and SQSUB
+ instructions. Negate X first if NEGATE_P is true. */
+
+bool
+aarch64_sve_sqadd_sqsub_immediate_p (rtx x, bool negate_p)
+{
+ rtx elt;
+
+ if (!const_vec_duplicate_p (x, &elt)
+ || !CONST_INT_P (elt))
+ return false;
+
+ if (!aarch64_sve_arith_immediate_p (x, negate_p))
+ return false;
+
+ /* After the optional negation, the immediate must be nonnegative.
+ E.g. a saturating add of -127 must be done via SQSUB Zn.B, Zn.B, #127
+ instead of SQADD Zn.B, Zn.B, #129. */
+ return negate_p == (INTVAL (elt) < 0);
+}
+
/* Return true if X is a valid immediate operand for an SVE logical
instruction such as AND. */
return false;
}
+/* Return true if X is an UNSPEC_PTRUE constant of the form:
+
+ (const (unspec [PATTERN ZERO] UNSPEC_PTRUE))
+
+ where PATTERN is the svpattern as a CONST_INT and where ZERO
+ is a zero constant of the required PTRUE mode (which can have
+ fewer elements than X's mode, if zero bits are significant).
+
+ If so, and if INFO is nonnull, describe the immediate in INFO. */
+bool
+aarch64_sve_ptrue_svpattern_p (rtx x, struct simd_immediate_info *info)
+{
+ if (GET_CODE (x) != CONST)
+ return false;
+
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_PTRUE)
+ return false;
+
+ if (info)
+ {
+ aarch64_svpattern pattern
+ = (aarch64_svpattern) INTVAL (XVECEXP (x, 0, 0));
+ machine_mode pred_mode = GET_MODE (XVECEXP (x, 0, 1));
+ scalar_int_mode int_mode = aarch64_sve_element_int_mode (pred_mode);
+ *info = simd_immediate_info (int_mode, pattern);
+ }
+ return true;
+}
+
/* Return true if X is a valid SVE predicate. If INFO is nonnull, use
it to describe valid immediates. */
static bool
aarch64_sve_pred_valid_immediate (rtx x, simd_immediate_info *info)
{
+ if (aarch64_sve_ptrue_svpattern_p (x, info))
+ return true;
+
if (x == CONST0_RTX (GET_MODE (x)))
{
if (info)
return false;
}
+/* Return true if OP is a valid MEM operand for an SVE LDFF1 instruction. */
+bool
+aarch64_sve_ldff1_operand_p (rtx op)
+{
+ if (!MEM_P (op))
+ return false;
+
+ struct aarch64_address_info addr;
+ if (!aarch64_classify_address (&addr, XEXP (op, 0), GET_MODE (op), false))
+ return false;
+
+ if (addr.type == ADDRESS_REG_IMM)
+ return known_eq (addr.const_offset, 0);
+
+ return addr.type == ADDRESS_REG_REG;
+}
+
+/* Return true if OP is a valid MEM operand for an SVE LDNF1 instruction. */
+bool
+aarch64_sve_ldnf1_operand_p (rtx op)
+{
+ struct aarch64_address_info addr;
+
+ return (MEM_P (op)
+ && aarch64_classify_address (&addr, XEXP (op, 0),
+ GET_MODE (op), false)
+ && addr.type == ADDRESS_REG_IMM);
+}
+
/* Return true if OP is a valid MEM operand for an SVE LDR instruction.
The conditions for STR are the same. */
bool
&& addr.type == ADDRESS_REG_IMM);
}
+/* Return true if OP is a valid address for an SVE PRF[BHWD] instruction,
+ addressing memory of mode MODE. */
+bool
+aarch64_sve_prefetch_operand_p (rtx op, machine_mode mode)
+{
+ struct aarch64_address_info addr;
+ if (!aarch64_classify_address (&addr, op, mode, false))
+ return false;
+
+ if (addr.type == ADDRESS_REG_IMM)
+ return known_eq (addr.const_offset, 0);
+
+ return addr.type == ADDRESS_REG_REG;
+}
+
/* Return true if OP is a valid MEM operand for an SVE_STRUCT mode.
We need to be able to access the individual pieces, so the range
is different from LD[234] and ST[234]. */
return templ;
}
+/* Return the asm template for a PTRUES. CONST_UNSPEC is the
+ aarch64_sve_ptrue_svpattern_immediate that describes the predicate
+ pattern. */
+
+char *
+aarch64_output_sve_ptrues (rtx const_unspec)
+{
+ static char templ[40];
+
+ struct simd_immediate_info info;
+ bool is_valid = aarch64_simd_valid_immediate (const_unspec, &info);
+ gcc_assert (is_valid && info.insn == simd_immediate_info::PTRUE);
+
+ char element_char = sizetochar (GET_MODE_BITSIZE (info.elt_mode));
+ snprintf (templ, sizeof (templ), "ptrues\t%%0.%c, %s", element_char,
+ svpattern_token (info.u.pattern));
+ return templ;
+}
+
/* Split operands into moves from op[1] + op[2] into op[0]. */
void
UNSPEC_XPACLRI
UNSPEC_LD1_SVE
UNSPEC_ST1_SVE
+ UNSPEC_LDNT1_SVE
+ UNSPEC_STNT1_SVE
UNSPEC_LD1RQ
UNSPEC_LD1_GATHER
+ UNSPEC_LDFF1_GATHER
UNSPEC_ST1_SCATTER
UNSPEC_PRED_X
UNSPEC_PRED_Z
UNSPEC_PTEST
+ UNSPEC_PTRUE
UNSPEC_UNPACKSHI
UNSPEC_UNPACKUHI
UNSPEC_UNPACKSLO
UNSPEC_UNPACKULO
UNSPEC_PACK
+ UNSPEC_WHILE_LE
UNSPEC_WHILE_LO
+ UNSPEC_WHILE_LS
+ UNSPEC_WHILE_LT
UNSPEC_LDN
UNSPEC_STN
UNSPEC_INSR
+ UNSPEC_CLASTA
UNSPEC_CLASTB
UNSPEC_FADDA
UNSPEC_REV_SUBREG
UNSPEC_SPECULATION_TRACKER
UNSPEC_COPYSIGN
UNSPEC_TTEST ; Represent transaction test.
+ UNSPEC_UPDATE_FFR
+ UNSPEC_UPDATE_FFRT
+ UNSPEC_RDFFR
+ UNSPEC_WRFFR
+ ;; Represents an SVE-style lane index, in which the indexing applies
+ ;; within the containing 128-bit block.
+ UNSPEC_SVE_LANE_SELECT
+ UNSPEC_SVE_CNT_PAT
+ UNSPEC_SVE_PREFETCH
+ UNSPEC_SVE_PREFETCH_GATHER
+ UNSPEC_SVE_COMPACT
+ UNSPEC_SVE_SPLICE
])
(define_c_enum "unspecv" [
--- /dev/null
+/* AArch64 SVE intrinsics include file.
+ Copyright (C) 2018-2019 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _ARM_SVE_H_
+#define _ARM_SVE_H_
+
+#include <stdint.h>
+
+typedef __fp16 float16_t;
+typedef float float32_t;
+typedef double float64_t;
+
+#pragma GCC aarch64 "arm_sve.h"
+
+#endif
true,
ADDR_QUERY_LDP_STP_N)")))
+(define_address_constraint "UPb"
+ "@internal
+ An address valid for SVE PRFB instructions."
+ (match_test "aarch64_sve_prefetch_operand_p (op, VNx16QImode)"))
+
+(define_address_constraint "UPd"
+ "@internal
+ An address valid for SVE PRFD instructions."
+ (match_test "aarch64_sve_prefetch_operand_p (op, VNx2DImode)"))
+
+(define_address_constraint "UPh"
+ "@internal
+ An address valid for SVE PRFH instructions."
+ (match_test "aarch64_sve_prefetch_operand_p (op, VNx8HImode)"))
+
+(define_address_constraint "UPw"
+ "@internal
+ An address valid for SVE PRFW instructions."
+ (match_test "aarch64_sve_prefetch_operand_p (op, VNx4SImode)"))
+
+(define_memory_constraint "Utf"
+ "@internal
+ An address valid for SVE LDFF1 instructions."
+ (and (match_code "mem")
+ (match_test "aarch64_sve_ldff1_operand_p (op)")))
+
+(define_memory_constraint "Utn"
+ "@internal
+ An address valid for SVE LDNF1 instructions."
+ (and (match_code "mem")
+ (match_test "aarch64_sve_ldnf1_operand_p (op)")))
+
(define_memory_constraint "Utr"
"@internal
An address valid for SVE LDR and STR instructions (as distinct from
An address valid for a prefetch instruction."
(match_test "aarch64_address_valid_for_prefetch_p (op, true)"))
+(define_constraint "vgb"
+ "@internal
+ A constraint that matches an immediate offset valid for SVE LD1B
+ gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_b"))
+
+(define_constraint "vgd"
+ "@internal
+ A constraint that matches an immediate offset valid for SVE LD1D
+ gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_d"))
+
+(define_constraint "vgh"
+ "@internal
+ A constraint that matches an immediate offset valid for SVE LD1H
+ gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_h"))
+
+(define_constraint "vgw"
+ "@internal
+ A constraint that matches an immediate offset valid for SVE LD1W
+ gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_w"))
+
(define_constraint "vsa"
"@internal
A constraint that matches an immediate operand valid for SVE
is valid for SVE SUB instructions."
(match_operand 0 "aarch64_sve_sub_arith_immediate"))
+(define_constraint "vsQ"
+ "@internal
+ Like vsa, but additionally check that the immediate is nonnegative
+ when interpreted as a signed value."
+ (match_operand 0 "aarch64_sve_qadd_immediate"))
+
+(define_constraint "vsS"
+ "@internal
+ Like vsn, but additionally check that the immediate is negative
+ when interpreted as a signed value."
+ (match_operand 0 "aarch64_sve_qsub_immediate"))
+
(define_constraint "vsl"
"@internal
A constraint that matches an immediate operand valid for SVE logical
;; Iterator for QI and HI modes
(define_mode_iterator SHORT [QI HI])
+;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator SI_ONLY [SI])
+(define_mode_iterator DI_ONLY [DI])
+
;; Iterator for all integer modes (up to 64-bit)
(define_mode_iterator ALLI [QI HI SI DI])
VNx8HF VNx4SF VNx2DF])
;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator VNx8HI_ONLY [VNx8HI])
(define_mode_iterator VNx4SI_ONLY [VNx4SI])
+(define_mode_iterator VNx2DI_ONLY [VNx2DI])
(define_mode_iterator VNx2DF_ONLY [VNx2DF])
;; All SVE vector structure modes.
;; All SVE floating-point vector modes.
(define_mode_iterator SVE_F [VNx8HF VNx4SF VNx2DF])
+;; All partial SVE modes.
+(define_mode_iterator SVE_PARTIAL [VNx2QI
+ VNx4QI VNx2HI
+ VNx8QI VNx4HI VNx2SI])
+
+;; Modes involved in extending or truncating SVE data, for 8 elements per
+;; 128-bit block.
+(define_mode_iterator VNx8_NARROW [VNx8QI])
+(define_mode_iterator VNx8_WIDE [VNx8HI])
+
+;; ...same for 4 elements per 128-bit block.
+(define_mode_iterator VNx4_NARROW [VNx4QI VNx4HI])
+(define_mode_iterator VNx4_WIDE [VNx4SI])
+
+;; ...same for 2 elements per 128-bit block.
+(define_mode_iterator VNx2_NARROW [VNx2QI VNx2HI VNx2SI])
+(define_mode_iterator VNx2_WIDE [VNx2DI])
+
;; All SVE predicate modes.
(define_mode_iterator PRED_ALL [VNx16BI VNx8BI VNx4BI VNx2BI])
;; SVE predicate modes that control 8-bit, 16-bit or 32-bit elements.
(define_mode_iterator PRED_BHS [VNx16BI VNx8BI VNx4BI])
+;; SVE predicate modes that control 16-bit, 32-bit or 64-bit elements.
+(define_mode_iterator PRED_HSD [VNx8BI VNx4BI VNx2BI])
+
;; ------------------------------------------------------------------
;; Unspec enumerations for Advance SIMD. These could well go into
;; aarch64.md but for their use in int_iterators here.
UNSPEC_FMLSL ; Used in aarch64-simd.md.
UNSPEC_FMLAL2 ; Used in aarch64-simd.md.
UNSPEC_FMLSL2 ; Used in aarch64-simd.md.
+ UNSPEC_ADR ; Used in aarch64-sve.md.
UNSPEC_SEL ; Used in aarch64-sve.md.
+ UNSPEC_BRKA ; Used in aarch64-sve.md.
+ UNSPEC_BRKB ; Used in aarch64-sve.md.
+ UNSPEC_BRKN ; Used in aarch64-sve.md.
+ UNSPEC_BRKPA ; Used in aarch64-sve.md.
+ UNSPEC_BRKPB ; Used in aarch64-sve.md.
+ UNSPEC_PFIRST ; Used in aarch64-sve.md.
+ UNSPEC_PNEXT ; Used in aarch64-sve.md.
+ UNSPEC_CNTP ; Used in aarch64-sve.md.
+ UNSPEC_SADDV ; Used in aarch64-sve.md.
+ UNSPEC_UADDV ; Used in aarch64-sve.md.
UNSPEC_ANDV ; Used in aarch64-sve.md.
UNSPEC_IORV ; Used in aarch64-sve.md.
UNSPEC_XORV ; Used in aarch64-sve.md.
UNSPEC_REVW ; Used in aarch64-sve.md.
UNSPEC_SMUL_HIGHPART ; Used in aarch64-sve.md.
UNSPEC_UMUL_HIGHPART ; Used in aarch64-sve.md.
+ UNSPEC_FMLA ; Used in aarch64-sve.md.
+ UNSPEC_FMLS ; Used in aarch64-sve.md.
+ UNSPEC_FEXPA ; Used in aarch64-sve.md.
+ UNSPEC_FTMAD ; Used in aarch64-sve.md.
+ UNSPEC_FTSMUL ; Used in aarch64-sve.md.
+ UNSPEC_FTSSEL ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPEQ_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPGE_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPGT_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPHI_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPHS_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPLE_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPLO_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPLS_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPLT_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_COND_CMPNE_WIDE ; Used in aarch64-sve.md.
UNSPEC_COND_FABS ; Used in aarch64-sve.md.
UNSPEC_COND_FADD ; Used in aarch64-sve.md.
+ UNSPEC_COND_FCADD90 ; Used in aarch64-sve.md.
+ UNSPEC_COND_FCADD270 ; Used in aarch64-sve.md.
UNSPEC_COND_FCMEQ ; Used in aarch64-sve.md.
UNSPEC_COND_FCMGE ; Used in aarch64-sve.md.
UNSPEC_COND_FCMGT ; Used in aarch64-sve.md.
+ UNSPEC_COND_FCMLA ; Used in aarch64-sve.md.
+ UNSPEC_COND_FCMLA90 ; Used in aarch64-sve.md.
+ UNSPEC_COND_FCMLA180 ; Used in aarch64-sve.md.
+ UNSPEC_COND_FCMLA270 ; Used in aarch64-sve.md.
UNSPEC_COND_FCMLE ; Used in aarch64-sve.md.
UNSPEC_COND_FCMLT ; Used in aarch64-sve.md.
UNSPEC_COND_FCMNE ; Used in aarch64-sve.md.
UNSPEC_COND_FCVTZS ; Used in aarch64-sve.md.
UNSPEC_COND_FCVTZU ; Used in aarch64-sve.md.
UNSPEC_COND_FDIV ; Used in aarch64-sve.md.
+ UNSPEC_COND_FMAX ; Used in aarch64-sve.md.
UNSPEC_COND_FMAXNM ; Used in aarch64-sve.md.
+ UNSPEC_COND_FMIN ; Used in aarch64-sve.md.
UNSPEC_COND_FMINNM ; Used in aarch64-sve.md.
UNSPEC_COND_FMLA ; Used in aarch64-sve.md.
UNSPEC_COND_FMLS ; Used in aarch64-sve.md.
UNSPEC_COND_FMUL ; Used in aarch64-sve.md.
+ UNSPEC_COND_FMULX ; Used in aarch64-sve.md.
UNSPEC_COND_FNEG ; Used in aarch64-sve.md.
UNSPEC_COND_FNMLA ; Used in aarch64-sve.md.
UNSPEC_COND_FNMLS ; Used in aarch64-sve.md.
+ UNSPEC_COND_FRECPX ; Used in aarch64-sve.md.
UNSPEC_COND_FRINTA ; Used in aarch64-sve.md.
UNSPEC_COND_FRINTI ; Used in aarch64-sve.md.
UNSPEC_COND_FRINTM ; Used in aarch64-sve.md.
UNSPEC_COND_FRINTP ; Used in aarch64-sve.md.
UNSPEC_COND_FRINTX ; Used in aarch64-sve.md.
UNSPEC_COND_FRINTZ ; Used in aarch64-sve.md.
+ UNSPEC_COND_FSCALE ; Used in aarch64-sve.md.
UNSPEC_COND_FSQRT ; Used in aarch64-sve.md.
UNSPEC_COND_FSUB ; Used in aarch64-sve.md.
UNSPEC_COND_SCVTF ; Used in aarch64-sve.md.
UNSPEC_COND_UCVTF ; Used in aarch64-sve.md.
+ UNSPEC_LASTA ; Used in aarch64-sve.md.
UNSPEC_LASTB ; Used in aarch64-sve.md.
+ UNSPEC_ASHIFT_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_ASHIFTRT_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_LSHIFTRT_WIDE ; Used in aarch64-sve.md.
+ UNSPEC_LDFF1 ; Used in aarch64-sve.md.
+ UNSPEC_LDNF1 ; Used in aarch64-sve.md.
UNSPEC_FCADD90 ; Used in aarch64-simd.md.
UNSPEC_FCADD270 ; Used in aarch64-simd.md.
UNSPEC_FCMLA ; Used in aarch64-simd.md.
(define_mode_attr Vetype_fourth [(VNx4SI "b") (VNx2DI "h")])
;; Equivalent of "size" for a vector element.
-(define_mode_attr Vesize [(VNx16QI "b")
- (VNx8HI "h") (VNx8HF "h")
- (VNx4SI "w") (VNx4SF "w")
+(define_mode_attr Vesize [(VNx16QI "b") (VNx8QI "b")
+ (VNx4QI "b") (VNx2QI "b")
+ (VNx8HI "h") (VNx4HI "h")
+ (VNx2HI "h") (VNx8HF "h")
+ (VNx4SI "w") (VNx2SI "w") (VNx4SF "w")
(VNx2DI "d") (VNx2DF "d")
(VNx32QI "b") (VNx48QI "b") (VNx64QI "b")
(VNx16HI "h") (VNx24HI "h") (VNx32HI "h")
(define_mode_attr data_bytes [(VNx16BI "1") (VNx8BI "2")
(VNx4BI "4") (VNx2BI "8")])
+;; Two-nybble mask for partial vector modes: nunits, byte size.
+(define_mode_attr self_mask [(VNx8QI "0x81")
+ (VNx4QI "0x41")
+ (VNx2QI "0x21")
+ (VNx4HI "0x42")
+ (VNx2HI "0x22")
+ (VNx2SI "0x24")])
+
+;; For full vector modes, the mask of narrower modes, encoded as above.
+(define_mode_attr narrower_mask [(VNx8HI "0x81")
+ (VNx4SI "0x43")
+ (VNx2DI "0x27")])
+
+;; The constraint to use for an SVE [SU]DOT, FMUL, FMLA or FMLS lane index.
+(define_mode_attr sve_lane_con [(VNx4SI "y") (VNx2DI "x")
+ (VNx8HF "y") (VNx4SF "y") (VNx2DF "x")])
+
+;; The constraint to use for an SVE FCMLA lane index.
+(define_mode_attr sve_lane_pair_con [(VNx8HF "y") (VNx4SF "x")])
+
;; -------------------------------------------------------------------
;; Code Iterators
;; -------------------------------------------------------------------
;; Code iterator for signed variants of vector saturating binary ops.
(define_code_iterator SBINQOPS [ss_plus ss_minus])
+;; Code iterator for unsigned variants of vector saturating binary ops.
+(define_code_iterator UBINQOPS [us_plus us_minus])
+
+;; Modular and saturating addition.
+(define_code_iterator ANY_PLUS [plus ss_plus us_plus])
+
+;; Saturating addition.
+(define_code_iterator SAT_PLUS [ss_plus us_plus])
+
+;; Modular and saturating subtraction.
+(define_code_iterator ANY_MINUS [minus ss_minus us_minus])
+
+;; Saturating subtraction.
+(define_code_iterator SAT_MINUS [ss_minus us_minus])
+
;; Comparison operators for <F>CM.
(define_code_iterator COMPARISONS [lt le eq ge gt])
(smax "s") (umax "u")
(smin "s") (umin "u")])
+;; "s" for signed ops, empty for unsigned ones.
+(define_code_attr s [(sign_extend "s") (zero_extend "")])
+
+;; Map signed/unsigned ops to the corresponding extension.
+(define_code_attr paired_extend [(ss_plus "sign_extend")
+ (us_plus "zero_extend")
+ (ss_minus "sign_extend")
+ (us_minus "zero_extend")])
+
;; Whether a shift is left or right.
(define_code_attr lr [(ashift "l") (ashiftrt "r") (lshiftrt "r")])
(ior "register_operand")
(xor "register_operand")])
+(define_code_attr inc_dec [(minus "dec") (ss_minus "sqdec") (us_minus "uqdec")
+ (plus "inc") (ss_plus "sqinc") (us_plus "uqinc")])
+
;; -------------------------------------------------------------------
;; Int Iterators.
;; -------------------------------------------------------------------
(define_int_iterator FMAXMINV [UNSPEC_FMAXV UNSPEC_FMINV
UNSPEC_FMAXNMV UNSPEC_FMINNMV])
+(define_int_iterator SVE_INT_ADDV [UNSPEC_SADDV UNSPEC_UADDV])
+
(define_int_iterator LOGICALF [UNSPEC_ANDF UNSPEC_IORF UNSPEC_XORF])
(define_int_iterator HADDSUB [UNSPEC_SHADD UNSPEC_UHADD
(define_int_iterator MUL_HIGHPART [UNSPEC_SMUL_HIGHPART UNSPEC_UMUL_HIGHPART])
-(define_int_iterator SVE_INT_UNARY [UNSPEC_REVB UNSPEC_REVH UNSPEC_REVW])
+(define_int_iterator CLAST [UNSPEC_CLASTA UNSPEC_CLASTB])
+
+(define_int_iterator LAST [UNSPEC_LASTA UNSPEC_LASTB])
+
+(define_int_iterator SVE_INT_UNARY [UNSPEC_RBIT UNSPEC_REVB
+ UNSPEC_REVH UNSPEC_REVW])
+
+(define_int_iterator SVE_FP_UNARY [UNSPEC_FRECPE UNSPEC_RSQRTE])
+
+(define_int_iterator SVE_FP_UNARY_INT [UNSPEC_FEXPA])
+
+(define_int_iterator SVE_FP_BINARY [UNSPEC_FRECPS UNSPEC_RSQRTS])
+
+(define_int_iterator SVE_FP_BINARY_INT [UNSPEC_FTSMUL UNSPEC_FTSSEL])
(define_int_iterator SVE_INT_REDUCTION [UNSPEC_ANDV
UNSPEC_IORV
(define_int_iterator SVE_COND_FP_UNARY [UNSPEC_COND_FABS
UNSPEC_COND_FNEG
+ UNSPEC_COND_FRECPX
UNSPEC_COND_FRINTA
UNSPEC_COND_FRINTI
UNSPEC_COND_FRINTM
(define_int_iterator SVE_COND_FP_BINARY [UNSPEC_COND_FADD
UNSPEC_COND_FDIV
+ UNSPEC_COND_FMAX
UNSPEC_COND_FMAXNM
+ UNSPEC_COND_FMIN
UNSPEC_COND_FMINNM
UNSPEC_COND_FMUL
+ UNSPEC_COND_FMULX
UNSPEC_COND_FSUB])
-(define_int_iterator SVE_COND_FP_BINARY_I1 [UNSPEC_COND_FMAXNM
+(define_int_iterator SVE_COND_FP_BINARY_INT [UNSPEC_COND_FSCALE])
+
+(define_int_iterator SVE_COND_FP_ADD [UNSPEC_COND_FADD])
+(define_int_iterator SVE_COND_FP_SUB [UNSPEC_COND_FSUB])
+(define_int_iterator SVE_COND_FP_MUL [UNSPEC_COND_FMUL])
+
+(define_int_iterator SVE_COND_FP_BINARY_I1 [UNSPEC_COND_FMAX
+ UNSPEC_COND_FMAXNM
+ UNSPEC_COND_FMIN
UNSPEC_COND_FMINNM
UNSPEC_COND_FMUL])
-(define_int_iterator SVE_COND_FP_BINARY_REG [UNSPEC_COND_FDIV])
+(define_int_iterator SVE_COND_FP_BINARY_REG [UNSPEC_COND_FDIV
+ UNSPEC_COND_FMULX])
+
+(define_int_iterator SVE_COND_FCADD [UNSPEC_COND_FCADD90
+ UNSPEC_COND_FCADD270])
+
+(define_int_iterator SVE_COND_FP_MAXMIN [UNSPEC_COND_FMAX
+ UNSPEC_COND_FMAXNM
+ UNSPEC_COND_FMIN
+ UNSPEC_COND_FMINNM])
;; Floating-point max/min operations that correspond to optabs,
;; as opposed to those that are internal to the port.
UNSPEC_COND_FNMLA
UNSPEC_COND_FNMLS])
+(define_int_iterator SVE_COND_FCMLA [UNSPEC_COND_FCMLA
+ UNSPEC_COND_FCMLA90
+ UNSPEC_COND_FCMLA180
+ UNSPEC_COND_FCMLA270])
+
+(define_int_iterator SVE_COND_INT_CMP_WIDE [UNSPEC_COND_CMPEQ_WIDE
+ UNSPEC_COND_CMPGE_WIDE
+ UNSPEC_COND_CMPGT_WIDE
+ UNSPEC_COND_CMPHI_WIDE
+ UNSPEC_COND_CMPHS_WIDE
+ UNSPEC_COND_CMPLE_WIDE
+ UNSPEC_COND_CMPLO_WIDE
+ UNSPEC_COND_CMPLS_WIDE
+ UNSPEC_COND_CMPLT_WIDE
+ UNSPEC_COND_CMPNE_WIDE])
+
;; SVE FP comparisons that accept #0.0.
(define_int_iterator SVE_COND_FP_CMP_I0 [UNSPEC_COND_FCMEQ
UNSPEC_COND_FCMGE
UNSPEC_COND_FCMLE
UNSPEC_COND_FCMLT])
+(define_int_iterator SVE_FP_TERNARY_LANE [UNSPEC_FMLA UNSPEC_FMLS])
+
+(define_int_iterator SVE_CFP_TERNARY_LANE [UNSPEC_FCMLA UNSPEC_FCMLA90
+ UNSPEC_FCMLA180 UNSPEC_FCMLA270])
+
+(define_int_iterator SVE_WHILE [UNSPEC_WHILE_LE UNSPEC_WHILE_LO
+ UNSPEC_WHILE_LS UNSPEC_WHILE_LT])
+
+(define_int_iterator SVE_SHIFT_WIDE [UNSPEC_ASHIFT_WIDE
+ UNSPEC_ASHIFTRT_WIDE
+ UNSPEC_LSHIFTRT_WIDE])
+
+(define_int_iterator SVE_LDFF1_LDNF1 [UNSPEC_LDFF1 UNSPEC_LDNF1])
+
(define_int_iterator FCADD [UNSPEC_FCADD90
UNSPEC_FCADD270])
(define_int_iterator FRINTNZX [UNSPEC_FRINT32Z UNSPEC_FRINT32X
UNSPEC_FRINT64Z UNSPEC_FRINT64X])
+(define_int_iterator SVE_BRK_UNARY [UNSPEC_BRKA UNSPEC_BRKB])
+
+(define_int_iterator SVE_BRK_BINARY [UNSPEC_BRKN UNSPEC_BRKPA UNSPEC_BRKPB])
+
+(define_int_iterator SVE_PITER [UNSPEC_PFIRST UNSPEC_PNEXT])
+
;; Iterators for atomic operations.
(define_int_iterator ATOMIC_LDOP
(define_int_attr optab [(UNSPEC_ANDF "and")
(UNSPEC_IORF "ior")
(UNSPEC_XORF "xor")
+ (UNSPEC_SADDV "sadd")
+ (UNSPEC_UADDV "uadd")
(UNSPEC_ANDV "and")
(UNSPEC_IORV "ior")
(UNSPEC_XORV "xor")
+ (UNSPEC_FRECPE "frecpe")
+ (UNSPEC_FRECPS "frecps")
+ (UNSPEC_RSQRTE "frsqrte")
+ (UNSPEC_RSQRTS "frsqrts")
+ (UNSPEC_RBIT "rbit")
(UNSPEC_REVB "revb")
(UNSPEC_REVH "revh")
(UNSPEC_REVW "revw")
(UNSPEC_FMAXV "smax_nan")
(UNSPEC_FMINNMV "smin")
(UNSPEC_FMINV "smin_nan")
+ (UNSPEC_SMUL_HIGHPART "smulh")
+ (UNSPEC_UMUL_HIGHPART "umulh")
+ (UNSPEC_FMLA "fma")
+ (UNSPEC_FMLS "fnma")
+ (UNSPEC_FCMLA "fcmla")
+ (UNSPEC_FCMLA90 "fcmla90")
+ (UNSPEC_FCMLA180 "fcmla180")
+ (UNSPEC_FCMLA270 "fcmla270")
+ (UNSPEC_FEXPA "fexpa")
+ (UNSPEC_FTSMUL "ftsmul")
+ (UNSPEC_FTSSEL "ftssel")
(UNSPEC_COND_FABS "abs")
(UNSPEC_COND_FADD "add")
+ (UNSPEC_COND_FCADD90 "cadd90")
+ (UNSPEC_COND_FCADD270 "cadd270")
+ (UNSPEC_COND_FCMLA "fcmla")
+ (UNSPEC_COND_FCMLA90 "fcmla90")
+ (UNSPEC_COND_FCMLA180 "fcmla180")
+ (UNSPEC_COND_FCMLA270 "fcmla270")
(UNSPEC_COND_FCVT "fcvt")
(UNSPEC_COND_FCVTZS "fix_trunc")
(UNSPEC_COND_FCVTZU "fixuns_trunc")
(UNSPEC_COND_FDIV "div")
+ (UNSPEC_COND_FMAX "smax_nan")
(UNSPEC_COND_FMAXNM "smax")
+ (UNSPEC_COND_FMIN "smin_nan")
(UNSPEC_COND_FMINNM "smin")
(UNSPEC_COND_FMLA "fma")
(UNSPEC_COND_FMLS "fnma")
(UNSPEC_COND_FMUL "mul")
+ (UNSPEC_COND_FMULX "mulx")
(UNSPEC_COND_FNEG "neg")
(UNSPEC_COND_FNMLA "fnms")
(UNSPEC_COND_FNMLS "fms")
+ (UNSPEC_COND_FRECPX "frecpx")
(UNSPEC_COND_FRINTA "round")
(UNSPEC_COND_FRINTI "nearbyint")
(UNSPEC_COND_FRINTM "floor")
(UNSPEC_COND_FRINTP "ceil")
(UNSPEC_COND_FRINTX "rint")
(UNSPEC_COND_FRINTZ "btrunc")
+ (UNSPEC_COND_FSCALE "fscale")
(UNSPEC_COND_FSQRT "sqrt")
(UNSPEC_COND_FSUB "sub")
(UNSPEC_COND_SCVTF "float")
(UNSPEC_FMINV "smin_nan")
(UNSPEC_FMAXNM "fmax")
(UNSPEC_FMINNM "fmin")
+ (UNSPEC_COND_FMAX "fmax_nan")
(UNSPEC_COND_FMAXNM "fmax")
+ (UNSPEC_COND_FMIN "fmin_nan")
(UNSPEC_COND_FMINNM "fmin")])
(define_int_attr maxmin_uns_op [(UNSPEC_UMAXV "umax")
(UNSPEC_FMAXNM "fmaxnm")
(UNSPEC_FMINNM "fminnm")])
+(define_code_attr binqops_op [(ss_plus "sqadd")
+ (us_plus "uqadd")
+ (ss_minus "sqsub")
+ (us_minus "uqsub")])
+
+(define_code_attr binqops_op_rev [(ss_plus "sqsub")
+ (ss_minus "sqadd")])
+
;; The SVE logical instruction that implements an unspec.
(define_int_attr logicalf_op [(UNSPEC_ANDF "and")
(UNSPEC_IORF "orr")
(UNSPEC_XORF "eor")])
+(define_int_attr last_op [(UNSPEC_CLASTA "after_last")
+ (UNSPEC_CLASTB "last")
+ (UNSPEC_LASTA "after_last")
+ (UNSPEC_LASTB "last")])
+
;; "s" for signed operations and "u" for unsigned ones.
-(define_int_attr su [(UNSPEC_UNPACKSHI "s")
+(define_int_attr su [(UNSPEC_SADDV "s")
+ (UNSPEC_UADDV "u")
+ (UNSPEC_UNPACKSHI "s")
(UNSPEC_UNPACKUHI "u")
(UNSPEC_UNPACKSLO "s")
(UNSPEC_UNPACKULO "u")
(define_int_attr bt [(UNSPEC_SMULLB "b") (UNSPEC_UMULLB "b")
(UNSPEC_SMULLT "t") (UNSPEC_UMULLT "t")])
+(define_int_attr fn [(UNSPEC_LDFF1 "f") (UNSPEC_LDNF1 "n")])
+
+(define_int_attr ab [(UNSPEC_CLASTA "a") (UNSPEC_CLASTB "b")
+ (UNSPEC_LASTA "a") (UNSPEC_LASTB "b")])
+
(define_int_attr addsub [(UNSPEC_SHADD "add")
(UNSPEC_UHADD "add")
(UNSPEC_SRHADD "add")
(UNSPEC_FRINT64Z "frint64z") (UNSPEC_FRINT64X "frint64x")])
;; The condition associated with an UNSPEC_COND_<xx>.
-(define_int_attr cmp_op [(UNSPEC_COND_FCMEQ "eq")
+(define_int_attr cmp_op [(UNSPEC_COND_CMPEQ_WIDE "eq")
+ (UNSPEC_COND_CMPGE_WIDE "ge")
+ (UNSPEC_COND_CMPGT_WIDE "gt")
+ (UNSPEC_COND_CMPHI_WIDE "hi")
+ (UNSPEC_COND_CMPHS_WIDE "hs")
+ (UNSPEC_COND_CMPLE_WIDE "le")
+ (UNSPEC_COND_CMPLO_WIDE "lo")
+ (UNSPEC_COND_CMPLS_WIDE "ls")
+ (UNSPEC_COND_CMPLT_WIDE "lt")
+ (UNSPEC_COND_CMPNE_WIDE "ne")
+ (UNSPEC_COND_FCMEQ "eq")
(UNSPEC_COND_FCMGE "ge")
(UNSPEC_COND_FCMGT "gt")
(UNSPEC_COND_FCMLE "le")
(UNSPEC_COND_FCMLT "lt")
(UNSPEC_COND_FCMNE "ne")
- (UNSPEC_COND_FCMUO "uo")])
+ (UNSPEC_WHILE_LE "le")
+ (UNSPEC_WHILE_LO "lo")
+ (UNSPEC_WHILE_LS "ls")
+ (UNSPEC_WHILE_LT "lt")])
+
+(define_int_attr while_optab_cmp [(UNSPEC_WHILE_LE "le")
+ (UNSPEC_WHILE_LO "ult")
+ (UNSPEC_WHILE_LS "ule")
+ (UNSPEC_WHILE_LT "lt")])
+
+(define_int_attr brk_op [(UNSPEC_BRKA "a") (UNSPEC_BRKB "b")
+ (UNSPEC_BRKN "n")
+ (UNSPEC_BRKPA "pa") (UNSPEC_BRKPB "pb")])
+
+(define_int_attr sve_pred_op [(UNSPEC_PFIRST "pfirst") (UNSPEC_PNEXT "pnext")])
(define_int_attr sve_int_op [(UNSPEC_ANDV "andv")
(UNSPEC_IORV "orv")
(UNSPEC_UMINV "uminv")
(UNSPEC_SMAXV "smaxv")
(UNSPEC_SMINV "sminv")
+ (UNSPEC_SMUL_HIGHPART "smulh")
+ (UNSPEC_UMUL_HIGHPART "umulh")
+ (UNSPEC_ASHIFT_WIDE "lsl")
+ (UNSPEC_ASHIFTRT_WIDE "asr")
+ (UNSPEC_LSHIFTRT_WIDE "lsr")
+ (UNSPEC_RBIT "rbit")
(UNSPEC_REVB "revb")
(UNSPEC_REVH "revh")
(UNSPEC_REVW "revw")])
-(define_int_attr sve_fp_op [(UNSPEC_FADDV "faddv")
+(define_int_attr sve_fp_op [(UNSPEC_FRECPE "frecpe")
+ (UNSPEC_FRECPS "frecps")
+ (UNSPEC_RSQRTE "frsqrte")
+ (UNSPEC_RSQRTS "frsqrts")
+ (UNSPEC_FADDV "faddv")
(UNSPEC_FMAXNMV "fmaxnmv")
(UNSPEC_FMAXV "fmaxv")
(UNSPEC_FMINNMV "fminnmv")
(UNSPEC_FMINV "fminv")
+ (UNSPEC_FMLA "fmla")
+ (UNSPEC_FMLS "fmls")
+ (UNSPEC_FEXPA "fexpa")
+ (UNSPEC_FTSMUL "ftsmul")
+ (UNSPEC_FTSSEL "ftssel")
(UNSPEC_COND_FABS "fabs")
(UNSPEC_COND_FADD "fadd")
(UNSPEC_COND_FDIV "fdiv")
+ (UNSPEC_COND_FMAX "fmax")
(UNSPEC_COND_FMAXNM "fmaxnm")
+ (UNSPEC_COND_FMIN "fmin")
(UNSPEC_COND_FMINNM "fminnm")
(UNSPEC_COND_FMUL "fmul")
+ (UNSPEC_COND_FMULX "fmulx")
(UNSPEC_COND_FNEG "fneg")
+ (UNSPEC_COND_FRECPX "frecpx")
(UNSPEC_COND_FRINTA "frinta")
(UNSPEC_COND_FRINTI "frinti")
(UNSPEC_COND_FRINTM "frintm")
(UNSPEC_COND_FRINTP "frintp")
(UNSPEC_COND_FRINTX "frintx")
(UNSPEC_COND_FRINTZ "frintz")
+ (UNSPEC_COND_FSCALE "fscale")
(UNSPEC_COND_FSQRT "fsqrt")
(UNSPEC_COND_FSUB "fsub")])
(define_int_attr sve_fp_op_rev [(UNSPEC_COND_FADD "fadd")
(UNSPEC_COND_FDIV "fdivr")
+ (UNSPEC_COND_FMAX "fmax")
(UNSPEC_COND_FMAXNM "fmaxnm")
+ (UNSPEC_COND_FMIN "fmin")
(UNSPEC_COND_FMINNM "fminnm")
(UNSPEC_COND_FMUL "fmul")
+ (UNSPEC_COND_FMULX "fmulx")
(UNSPEC_COND_FSUB "fsubr")])
(define_int_attr rot [(UNSPEC_FCADD90 "90")
(UNSPEC_FCMLA "0")
(UNSPEC_FCMLA90 "90")
(UNSPEC_FCMLA180 "180")
- (UNSPEC_FCMLA270 "270")])
+ (UNSPEC_FCMLA270 "270")
+ (UNSPEC_COND_FCADD90 "90")
+ (UNSPEC_COND_FCADD270 "270")
+ (UNSPEC_COND_FCMLA "0")
+ (UNSPEC_COND_FCMLA90 "90")
+ (UNSPEC_COND_FCMLA180 "180")
+ (UNSPEC_COND_FCMLA270 "270")])
(define_int_attr sve_fmla_op [(UNSPEC_COND_FMLA "fmla")
(UNSPEC_COND_FMLS "fmls")
(UNSPEC_COND_FNMLA "fnmad")
(UNSPEC_COND_FNMLS "fnmsb")])
+;; The register constraint to use for the final operand in a binary BRK.
+(define_int_attr brk_reg_con [(UNSPEC_BRKN "0")
+ (UNSPEC_BRKPA "Upa") (UNSPEC_BRKPB "Upa")])
+
+;; The register number to print for the above.
+(define_int_attr brk_reg_opno [(UNSPEC_BRKN "0")
+ (UNSPEC_BRKPA "3") (UNSPEC_BRKPB "3")])
+
;; The predicate to use for the first input operand in a floating-point
;; <optab><mode>3 pattern.
(define_int_attr sve_pred_fp_rhs1_operand
[(UNSPEC_COND_FADD "register_operand")
(UNSPEC_COND_FDIV "register_operand")
+ (UNSPEC_COND_FMAX "register_operand")
(UNSPEC_COND_FMAXNM "register_operand")
+ (UNSPEC_COND_FMIN "register_operand")
(UNSPEC_COND_FMINNM "register_operand")
(UNSPEC_COND_FMUL "register_operand")
+ (UNSPEC_COND_FMULX "register_operand")
(UNSPEC_COND_FSUB "aarch64_sve_float_arith_operand")])
;; The predicate to use for the second input operand in a floating-point
(define_int_attr sve_pred_fp_rhs2_operand
[(UNSPEC_COND_FADD "aarch64_sve_float_arith_with_sub_operand")
(UNSPEC_COND_FDIV "register_operand")
+ (UNSPEC_COND_FMAX "aarch64_sve_float_maxmin_operand")
(UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_operand")
+ (UNSPEC_COND_FMIN "aarch64_sve_float_maxmin_operand")
(UNSPEC_COND_FMINNM "aarch64_sve_float_maxmin_operand")
(UNSPEC_COND_FMUL "aarch64_sve_float_mul_operand")
+ (UNSPEC_COND_FMULX "register_operand")
(UNSPEC_COND_FSUB "register_operand")])
;; Likewise for immediates only.
(define_int_attr sve_pred_fp_rhs2_immediate
- [(UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_immediate")
+ [(UNSPEC_COND_FMAX "aarch64_sve_float_maxmin_immediate")
+ (UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_immediate")
+ (UNSPEC_COND_FMIN "aarch64_sve_float_maxmin_immediate")
(UNSPEC_COND_FMINNM "aarch64_sve_float_maxmin_immediate")
(UNSPEC_COND_FMUL "aarch64_sve_float_mul_immediate")])
+;; The maximum number of element bits that an instruction can handle.
+(define_int_attr max_elem_bits [(UNSPEC_UADDV "64") (UNSPEC_SADDV "32")
+ (UNSPEC_PFIRST "8") (UNSPEC_PNEXT "64")])
+
;; The minimum number of element bits that an instruction can handle.
-(define_int_attr min_elem_bits [(UNSPEC_REVB "16")
+(define_int_attr min_elem_bits [(UNSPEC_RBIT "8")
+ (UNSPEC_REVB "16")
(UNSPEC_REVH "32")
(UNSPEC_REVW "64")])
return CONST_INT_P (op) && IN_RANGE (INTVAL (op), 1, 3);
})
-(define_special_predicate "subreg_lowpart_operator"
- (and (match_code "subreg")
- (match_test "subreg_lowpart_p (op)")))
+(define_predicate "subreg_lowpart_operator"
+ (ior (match_code "truncate")
+ (and (match_code "subreg")
+ (match_test "subreg_lowpart_p (op)"))))
(define_predicate "aarch64_ccmp_immediate"
(and (match_code "const_int")
return aarch64_stepped_int_parallel_p (op, -1);
})
+(define_predicate "ascending_int_parallel"
+ (match_code "parallel")
+{
+ return aarch64_stepped_int_parallel_p (op, 1);
+})
+
(define_special_predicate "aarch64_simd_lshift_imm"
(match_code "const,const_vector")
{
(match_test "op == const0_rtx")
(match_operand 0 "aarch64_simd_or_scalar_imm_zero"))))
+(define_predicate "aarch64_simd_reg_or_minus_one"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_simd_imm_minus_one")))
+
(define_predicate "aarch64_simd_struct_operand"
(and (match_code "mem")
(match_test "TARGET_SIMD && aarch64_simd_mem_operand_p (op)")))
(and (match_code "mem")
(match_test "aarch64_sve_ld1rq_operand_p (op)")))
+(define_predicate "aarch64_sve_ldff1_operand"
+ (and (match_code "mem")
+ (match_test "aarch64_sve_ldff1_operand_p (op)")))
+
+(define_predicate "aarch64_sve_ldnf1_operand"
+ (and (match_code "mem")
+ (match_test "aarch64_sve_ldnf1_operand_p (op)")))
+
;; Like memory_operand, but restricted to addresses that are valid for
;; SVE LDR and STR instructions.
(define_predicate "aarch64_sve_ldr_operand"
(and (match_code "mem")
(match_test "aarch64_sve_ldr_operand_p (op)")))
+(define_special_predicate "aarch64_sve_prefetch_operand"
+ (and (match_code "reg, plus")
+ (match_test "aarch64_sve_prefetch_operand_p (op, mode)")))
+
(define_predicate "aarch64_sve_nonimmediate_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_sve_ldr_operand")))
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_sve_ld1r_operand")))
+(define_predicate "aarch64_sve_ptrue_svpattern_immediate"
+ (and (match_code "const")
+ (match_test "aarch64_sve_ptrue_svpattern_p (op, NULL)")))
+
(define_predicate "aarch64_sve_arith_immediate"
(and (match_code "const,const_vector")
(match_test "aarch64_sve_arith_immediate_p (op, false)")))
(and (match_code "const,const_vector")
(match_test "aarch64_sve_arith_immediate_p (op, true)")))
+(define_predicate "aarch64_sve_qadd_immediate"
+ (and (match_code "const,const_vector")
+ (match_test "aarch64_sve_sqadd_sqsub_immediate_p (op, false)")))
+
+(define_predicate "aarch64_sve_qsub_immediate"
+ (and (match_code "const,const_vector")
+ (match_test "aarch64_sve_sqadd_sqsub_immediate_p (op, true)")))
+
(define_predicate "aarch64_sve_vector_inc_dec_immediate"
(and (match_code "const,const_vector")
(match_test "aarch64_sve_vector_inc_dec_immediate_p (op)")))
+(define_predicate "aarch64_sve_gather_immediate_b"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
+
+(define_predicate "aarch64_sve_gather_immediate_h"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 62)")
+ (match_test "(INTVAL (op) & 1) == 0")))
+
+(define_predicate "aarch64_sve_gather_immediate_w"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 124)")
+ (match_test "(INTVAL (op) & 3) == 0")))
+
+(define_predicate "aarch64_sve_gather_immediate_d"
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (INTVAL (op), 0, 248)")
+ (match_test "(INTVAL (op) & 7) == 0")))
+
(define_predicate "aarch64_sve_uxtb_immediate"
(and (match_code "const_vector")
(match_test "GET_MODE_UNIT_BITSIZE (GET_MODE (op)) > 8")
(match_operand 0 "aarch64_sve_sub_arith_immediate")
(match_operand 0 "aarch64_sve_vector_inc_dec_immediate")))
+(define_predicate "aarch64_sve_sqadd_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_sve_qadd_immediate")
+ (match_operand 0 "aarch64_sve_qsub_immediate")))
+
(define_predicate "aarch64_sve_pred_and_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_sve_uxt_immediate")))
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_sve_logical_immediate")))
+(define_predicate "aarch64_sve_gather_offset_b"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_sve_gather_immediate_b")))
+
+(define_predicate "aarch64_sve_gather_offset_h"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_sve_gather_immediate_h")))
+
+(define_predicate "aarch64_sve_gather_offset_w"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_sve_gather_immediate_w")))
+
+(define_predicate "aarch64_sve_gather_offset_d"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "aarch64_sve_gather_immediate_d")))
+
(define_predicate "aarch64_sve_lshift_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "aarch64_simd_lshift_imm")))
(ior (match_test "INTVAL (op) == SVE_RELAXED_GP")
(match_test "INTVAL (op) == SVE_STRICT_GP"))))
+(define_predicate "aarch64_gather_scale_operand_b"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 1")))
+
+(define_predicate "aarch64_gather_scale_operand_h"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 1 || INTVAL (op) == 2")))
+
(define_predicate "aarch64_gather_scale_operand_w"
(and (match_code "const_int")
(match_test "INTVAL (op) == 1 || INTVAL (op) == 4")))
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/aarch64/aarch64-builtins.c
+aarch64-sve-builtins.o: $(srcdir)/config/aarch64/aarch64-sve-builtins.cc \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins.def \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+ $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) \
+ $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+ gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \
+ stor-layout.h $(REG_H) alias.h gimple-fold.h langhooks.h \
+ stringpool.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-base.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins.cc
+
+aarch64-sve-builtins-shapes.o: \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.cc \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+ $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.cc
+
+aarch64-sve-builtins-base.o: \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-base.cc \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+ $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) \
+ $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+ gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \
+ rtx-vector-builder.h vec-perm-indices.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-base.h \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-functions.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/aarch64/aarch64-sve-builtins-base.cc
+
aarch64-builtin-iterators.h: $(srcdir)/config/aarch64/geniterators.sh \
$(srcdir)/config/aarch64/iterators.md
$(SHELL) $(srcdir)/config/aarch64/geniterators.sh \
+2019-10-29 Richard Sandiford <richard.sandiford@arm.com>
+ Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
+ Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * g++.target/aarch64/sve/acle/aarch64-sve-acle.exp: New file.
+ * g++.target/aarch64/sve/acle/general-c++: New test directory.
+ * gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp: New file.
+ * gcc.target/aarch64/sve/acle/general: New test directory.
+ * gcc.target/aarch64/sve/acle/general-c: Likewise.
+
2019-10-29 Richard Biener <rguenther@suse.de>
PR tree-optimization/92241
--- /dev/null
+# Specific regression driver for AArch64 SVE.
+# Copyright (C) 2009-2019 Free Software Foundation, Inc.
+# Contributed by ARM Ltd.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AArch64 target.
+if {![istarget aarch64*-*-*] } {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+ set DEFAULT_CXXFLAGS " -pedantic-errors -Wno-long-long"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Force SVE if we're not testing it already.
+if { [check_effective_target_aarch64_sve] } {
+ set sve_flags ""
+} else {
+ set sve_flags "-march=armv8.2-a+sve"
+}
+
+# Main loop.
+set gcc_subdir [string replace $subdir 0 2 gcc]
+set files [glob -nocomplain \
+ "$srcdir/$gcc_subdir/general/*.c" \
+ "$srcdir/$subdir/general-c++/*.\[cC\]"]
+dg-runtest [lsort $files] "$sve_flags" $DEFAULT_CXXFLAGS
+
+# All done.
+dg-finish
--- /dev/null
+/* { dg-do compile } */
+
+#include "add_1.h"
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t x, svint8_t y)
+{
+ return svadd_u8_x (pg, x, y); /* { dg-error "cannot convert 'svint8_t' to 'svuint8_t'" } */
+}
--- /dev/null
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "initializing argument 3" } */
--- /dev/null
+/* { dg-do compile } */
+
+#include "add_2.h"
+
+void
+f1 (svbool_t pg, svuint8_t x, svint8_t y)
+{
+ svadd_x (pg, x); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svuint8_t&\)'} } */
+ svadd_x (pg, x, x, x); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svuint8_t&, svuint8_t&, svuint8_t&\)'} } */
+ svadd_x (x, x, x); /* { dg-error {no matching function for call to 'svadd_x\(svuint8_t&, svuint8_t&, svuint8_t&\)'} } */
+ svadd_x (pg, pg, pg); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svbool_t&, svbool_t&\)'} } */
+ svadd_x (pg, 1, x); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, int, svuint8_t&\)'} } */
+ svadd_x (pg, x, y); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svuint8_t&, svint8_t&\)'} } */
+}
--- /dev/null
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h"
+/* { dg-message {note: candidate: 'svfloat16_t svadd_x\(svbool_t, svfloat16_t, svfloat16_t\)'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *candidate expects 3 arguments, 2 provided} "" { target *-*-* } 3 } */
+/* { dg-message {note: *candidate expects 3 arguments, 4 provided} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 1 from 'svuint8_t' to 'svbool_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svbool_t' to 'svfloat16_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'int' to 'svfloat16_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svuint8_t' to 'svfloat16_t'} "" { target *-*-* } 3 } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fnon-call-exceptions" } */
+
+#include <arm_sve.h>
+
+svint8_t
+foo (svbool_t pg, svint8_t a, svint8_t b)
+{
+ try
+ {
+ a = svadd_m (pg, a, b);
+ }
+ catch (...)
+ {
+ a = b;
+ }
+ return a;
+}
+
+/* { dg-final { scan-tree-dump-not {__cxa_begin_catch} "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_add (uint64_t a, uint64_t b) { return a + b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+ svint32_t s32, svint64_t s64, int x)
+{
+ const int one = 1;
+ u8 = svasrd_x (pg, u8, 1); /* { dg-error {no matching function for call to 'svasrd_x\(svbool_t&, svuint8_t&, [^)]*\)'} } */
+ s8 = svasrd_x (pg, s8, x); /* { dg-error "argument 3 of 'svasrd_x' must be an integer constant expression" } */
+ s8 = svasrd_x (pg, s8, one);
+ s8 = svasrd_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_x (pg, s8, 1.0);
+ s8 = svasrd_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_x (pg, s8, 1);
+ s8 = svasrd_x (pg, s8, 1 + 1);
+ s8 = svasrd_x (pg, s8, const_add (1, 1));
+ s8 = svasrd_x (pg, s8, add (1, 1)); /* { dg-error "argument 3 of 'svasrd_x' must be an integer constant expression" } */
+ s8 = svasrd_x (pg, s8, 8);
+ s8 = svasrd_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_x (pg, s8, (uint64_t (1) << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s16 = svasrd_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+ s16 = svasrd_x (pg, s16, 1);
+ s16 = svasrd_x (pg, s16, 16);
+ s16 = svasrd_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+ s32 = svasrd_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+ s32 = svasrd_x (pg, s32, 1);
+ s32 = svasrd_x (pg, s32, 32);
+ s32 = svasrd_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+ s64 = svasrd_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+ s64 = svasrd_x (pg, s64, 1);
+ s64 = svasrd_x (pg, s64, 64);
+ s64 = svasrd_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_add (uint64_t a, uint64_t b) { return a + b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+void
+f1 (svbool_t pg, svint8_t s8, svint16_t s16, svint32_t s32, svint64_t s64,
+ int x)
+{
+ const int one = 1;
+ s8 = svasrd_n_s8_x (pg, s8, x); /* { dg-error "argument 3 of 'svasrd_n_s8_x' must be an integer constant expression" } */
+ s8 = svasrd_n_s8_x (pg, s8, one);
+ s8 = svasrd_n_s8_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_n_s8_x (pg, s8, 1.0);
+ s8 = svasrd_n_s8_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_n_s8_x (pg, s8, 1);
+ s8 = svasrd_n_s8_x (pg, s8, 1 + 1);
+ s8 = svasrd_n_s8_x (pg, s8, const_add (1, 1));
+ s8 = svasrd_n_s8_x (pg, s8, add (1, 1)); /* { dg-error "argument 3 of 'svasrd_n_s8_x' must be an integer constant expression" } */
+ s8 = svasrd_n_s8_x (pg, s8, 8);
+ s8 = svasrd_n_s8_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_n_s8_x (pg, s8, (uint64_t (1) << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s16 = svasrd_n_s16_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+ s16 = svasrd_n_s16_x (pg, s16, 1);
+ s16 = svasrd_n_s16_x (pg, s16, 16);
+ s16 = svasrd_n_s16_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+ s32 = svasrd_n_s32_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+ s32 = svasrd_n_s32_x (pg, s32, 1);
+ s32 = svasrd_n_s32_x (pg, s32, 32);
+ s32 = svasrd_n_s32_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+ s64 = svasrd_n_s64_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+ s64 = svasrd_n_s64_x (pg, s64, 1);
+ s64 = svasrd_n_s64_x (pg, s64, 64);
+ s64 = svasrd_n_s64_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_add (uint64_t a, uint64_t b) { return a + b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+template<uint64_t N, typename T>
+T shift (svbool_t pg, T v) { return svasrd_x (pg, v, N); }
+/* { dg-error {no matching function for call to 'svasrd_x\(svbool_t&,} "" { target *-*-* } .-1 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} "" { target *-*-* } .-2 } */
+/* { dg-error {passing 9 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} "" { target *-*-* } .-3 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} "" { target *-*-* } .-4 } */
+/* { dg-error {passing 17 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} "" { target *-*-* } .-5 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} "" { target *-*-* } .-6 } */
+/* { dg-error {passing 33 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} "" { target *-*-* } .-7 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} "" { target *-*-* } .-8 } */
+/* { dg-error {passing 65 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} "" { target *-*-* } .-9 } */
+
+template<typename T>
+T shift1 (svbool_t pg, T v, uint64_t n) { return svasrd_x (pg, v, n); }
+
+template<typename T>
+T shift2 (svbool_t pg, T v, uint64_t n) { return svasrd_x (pg, v, n); }
+/* { dg-error {argument 3 of 'svasrd_x' must be an integer constant expression} "" { target *-*-* } .-1 } */
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+ svint32_t s32, svint64_t s64)
+{
+ u8 = shift <1> (pg, u8);
+ s8 = shift <0> (pg, s8);
+ s8 = shift <1> (pg, s8);
+ s8 = shift <8> (pg, s8);
+ s8 = shift <9> (pg, s8);
+ s16 = shift <0> (pg, s16);
+ s16 = shift <1> (pg, s16);
+ s16 = shift <16> (pg, s16);
+ s16 = shift <17> (pg, s16);
+ s32 = shift <0> (pg, s32);
+ s32 = shift <1> (pg, s32);
+ s32 = shift <32> (pg, s32);
+ s32 = shift <33> (pg, s32);
+ s64 = shift <0> (pg, s64);
+ s64 = shift <1> (pg, s64);
+ s64 = shift <64> (pg, s64);
+ s64 = shift <65> (pg, s64);
+
+ s8 = shift2 (pg, s8, 1);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+test (svpattern pat, int i)
+{
+ svcntb_pat (pat); /* { dg-error "argument 1 of 'svcntb_pat' must be an integer constant expression" } */
+ svcntb_pat (i); /* { dg-error "invalid conversion from 'int' to 'svpattern'" } */
+ /* { dg-error "argument 1 of 'svcntb_pat' must be an integer constant expression" "" { target *-*-* } .-1 } */
+ svcntb_pat ((svpattern) -1); /* { dg-error "passing 4294967295 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 0);
+ svcntb_pat ((svpattern) 1);
+ svcntb_pat ((svpattern) 2);
+ svcntb_pat ((svpattern) 3);
+ svcntb_pat ((svpattern) 4);
+ svcntb_pat ((svpattern) 5);
+ svcntb_pat ((svpattern) 6);
+ svcntb_pat ((svpattern) 7);
+ svcntb_pat ((svpattern) 8);
+ svcntb_pat ((svpattern) 9);
+ svcntb_pat ((svpattern) 10);
+ svcntb_pat ((svpattern) 11);
+ svcntb_pat ((svpattern) 12);
+ svcntb_pat ((svpattern) 13);
+ svcntb_pat ((svpattern) 14); /* { dg-error "passing 14 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 15); /* { dg-error "passing 15 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 16); /* { dg-error "passing 16 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 17); /* { dg-error "passing 17 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 18); /* { dg-error "passing 18 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 19); /* { dg-error "passing 19 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 20); /* { dg-error "passing 20 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 21); /* { dg-error "passing 21 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 22); /* { dg-error "passing 22 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 23); /* { dg-error "passing 23 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 24); /* { dg-error "passing 24 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 25); /* { dg-error "passing 25 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 26); /* { dg-error "passing 26 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 27); /* { dg-error "passing 27 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 28); /* { dg-error "passing 28 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+ svcntb_pat ((svpattern) 29);
+ svcntb_pat ((svpattern) 30);
+ svcntb_pat ((svpattern) 31);
+ svcntb_pat ((svpattern) 32); /* { dg-error "passing 32 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+template<typename T>
+struct S
+{
+ S(T);
+ operator T() const;
+ void *base;
+};
+
+void f(svbool_t pg, const S<svuint8_t> &u8a, const S<svuint8_t> &u8b,
+ const S<svint8_t> &s8a)
+{
+ svadd_x(pg, u8a, u8b);
+ svadd_x(pg, u8a, 1);
+ svadd_x(pg, s8a, u8b); // { dg-error "no matching function for call" }
+ svadd_x(pg, s8a, 1);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+ svuint8x2_t u8x2)
+{
+ *ptr = svcreate2 (u8); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&\)'} } */
+ *ptr = svcreate2 (u8, u8, u8); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&, svuint8_t\&, svuint8_t\&\)'} } */
+ *ptr = svcreate2 (u8x2, u8x2); /* { dg-error {no matching function for call to 'svcreate2\(svuint8x2_t\&, svuint8x2_t\&\)'} } */
+ *ptr = svcreate2 (u8, f64); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&, svfloat64_t\&\)'} } */
+ *ptr = svcreate2 (u8, pg); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&, svbool_t\&\)'} } */
+ *ptr = svcreate2 (u8, u8);
+ *ptr = svcreate2 (f64, f64); /* { dg-error {cannot convert 'svfloat64x2_t' to 'svuint8x2_t' in assignment} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+ svuint8x2_t u8x2)
+{
+ *ptr = svcreate2_u8 (u8); /* { dg-error {too few arguments to function '[^']*'} } */
+ *ptr = svcreate2_u8 (u8, u8, u8); /* { dg-error {too many arguments to function '[^']*'} } */
+ *ptr = svcreate2_u8 (u8x2, u8x2); /* { dg-error {cannot convert 'svuint8x2_t' to 'svuint8_t'} } */
+ *ptr = svcreate2_u8 (u8, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svuint8_t'} } */
+ *ptr = svcreate2_u8 (pg, u8); /* { dg-error {cannot convert 'svbool_t' to 'svuint8_t'} } */
+ *ptr = svcreate2_u8 (u8, u8);
+ *ptr = svcreate2_f64 (f64, f64); /* { dg-error {cannot convert 'svfloat64x2_t' to 'svuint8x2_t' in assignment} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+ svfloat16x3_t f16x3)
+{
+ *ptr = svcreate3 (f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&\)'} } */
+ *ptr = svcreate3 (f16, f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svfloat16_t\&\)'} } */
+ *ptr = svcreate3 (f16, f16, f16, f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svfloat16_t\&, svfloat16_t\&, svfloat16_t\&\)'} } */
+ *ptr = svcreate3 (f16x3, f16x3, f16x3); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16x3_t\&, svfloat16x3_t\&, svfloat16x3_t\&\)'} } */
+ *ptr = svcreate3 (f16, f16, f64); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svfloat16_t\&, svfloat64_t\&\)'} } */
+ *ptr = svcreate3 (f16, pg, f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svbool_t\&, svfloat16_t\&\)'} } */
+ *ptr = svcreate3 (f16, f16, f16);
+ *ptr = svcreate3 (f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x3_t' to 'svfloat16x3_t' in assignment} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+ svfloat16x3_t f16x3)
+{
+ *ptr = svcreate3_f16 (f16); /* { dg-error {too few arguments to function '[^']*'} } */
+ *ptr = svcreate3_f16 (f16, f16); /* { dg-error {too few arguments to function '[^']*'} } */
+ *ptr = svcreate3_f16 (f16, f16, f16, f16); /* { dg-error {too many arguments to function '[^']*'} } */
+ *ptr = svcreate3_f16 (f16x3, f16x3, f16x3); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svfloat16_t'} } */
+ *ptr = svcreate3_f16 (f16, f16, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svfloat16_t'} } */
+ *ptr = svcreate3_f16 (f16, pg, f16); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16_t'} } */
+ *ptr = svcreate3_f16 (f16, f16, f16);
+ *ptr = svcreate3_f64 (f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x3_t' to 'svfloat16x3_t' in assignment} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+ svint32x4_t s32x4)
+{
+ *ptr = svcreate4 (s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&\)'} } */
+ *ptr = svcreate4 (s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&\)'} } */
+ *ptr = svcreate4 (s32, s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&, svint32_t\&\)'} } */
+ *ptr = svcreate4 (s32, s32, s32, s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&, svint32_t\&, svint32_t\&, svint32_t\&\)'} } */
+ *ptr = svcreate4 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {no matching function for call to 'svcreate4\(svint32x4_t\&, svint32x4_t\&, svint32x4_t\&, svint32x4_t\&\)'} } */
+ *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&, svint32_t\&, svfloat64_t\&\)'} } */
+ *ptr = svcreate4 (s32, pg, s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svbool_t\&, svint32_t\&, svint32_t\&\)'} } */
+ *ptr = svcreate4 (s32, s32, s32, s32);
+ *ptr = svcreate4 (f64, f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x4_t' to 'svint32x4_t' in assignment} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+ svint32x4_t s32x4)
+{
+ *ptr = svcreate4_s32 (s32); /* { dg-error {too few arguments to function '[^']*'} } */
+ *ptr = svcreate4_s32 (s32, s32); /* { dg-error {too few arguments to function '[^']*'} } */
+ *ptr = svcreate4_s32 (s32, s32, s32); /* { dg-error {too few arguments to function '[^']*'} } */
+ *ptr = svcreate4_s32 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function '[^']*'} } */
+ *ptr = svcreate4_s32 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {cannot convert 'svint32x4_t' to 'svint32_t'} } */
+ *ptr = svcreate4_s32 (s32, s32, s32, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svint32_t'} } */
+ *ptr = svcreate4_s32 (s32, pg, s32, s32); /* { dg-error {cannot convert 'svbool_t' to 'svint32_t'} } */
+ *ptr = svcreate4_s32 (s32, s32, s32, s32);
+ *ptr = svcreate4_f64 (f64, f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x4_t' to 'svint32x4_t' in assignment} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include "dot_1.h"
+
+svuint32_t
+f1 (svuint32_t x, svint8_t y, svuint8_t z)
+{
+ return svdot_u32 (x, y, z); /* { dg-error "cannot convert 'svint8_t' to 'svuint8_t'" } */
+}
--- /dev/null
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "initializing argument 2" } */
--- /dev/null
+/* { dg-do compile } */
+
+#include "dot_2.h"
+
+void
+f1 (svuint32_t x, svint8_t y, svuint8_t z)
+{
+ svdot (x, y); /* { dg-error {no matching function for call to 'svdot\(svuint32_t&, svint8_t&\)'} } */
+ svdot (x, x, x); /* { dg-error {no matching function for call to 'svdot\(svuint32_t&, svuint32_t&, svuint32_t&\)'} } */
+ svdot (1, z, z); /* { dg-error {no matching function for call to 'svdot\(int, svuint8_t&, svuint8_t&\)'} } */
+ svdot (x, y, z); /* { dg-error {no matching function for call to 'svdot\(svuint32_t&, svint8_t&, svuint8_t&\)'} } */
+}
--- /dev/null
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h"
+/* { dg-message {note: candidate: 'svuint32_t svdot\(svuint32_t, svuint8_t, svuint8_t\)'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *candidate expects 3 arguments, 2 provided} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svuint32_t' to 'svuint8_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 1 from 'int' to 'svuint32_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svint8_t' to 'svuint8_t'} "" { target *-*-* } 3 } */
--- /dev/null
+/* { dg-do compile } */
+
+int svadd_n_u8_x; /* { dg-message "note: previous declaration 'int svadd_n_u8_x'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint8_t svadd_n_u8_x\(svbool_t, svuint8_t, [^)\n]*\)' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+int svadd_n_u8_x = 1; /* { dg-message "note: previous declaration 'int svadd_n_u8_x'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint8_t svadd_n_u8_x\(svbool_t, svuint8_t, [^)\n]*\)' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+/* Although not supported, there's nothing to stop the user overloading
+ the sv* functions. */
+extern __SVInt8_t svadd_u8_x (__SVBool_t, __SVInt8_t, __SVInt8_t);
+
+#pragma GCC aarch64 "arm_sve.h"
--- /dev/null
+/* { dg-do compile } */
+
+/* Although somewhat suspect, this isn't actively wrong, and doesn't need
+ to be diagnosed. Any attempt to call the function before including
+ arm_sve.h will lead to a link failure. (Same for taking its address,
+ etc.) */
+extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t);
+
+#pragma GCC aarch64 "arm_sve.h"
--- /dev/null
+/* { dg-do compile } */
+
+__SVUint8_t
+svadd_u8_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
+{
+ return x;
+}
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svuint8_t
+f (svbool_t pg, svuint8_t x, svuint8_t y)
+{
+ return svadd_u8_x (pg, x, y);
+}
--- /dev/null
+/* { dg-do compile } */
+
+typedef int svadd_u8_x; /* { dg-message "note: previous declaration 'typedef int svadd_u8_x'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint8_t svadd_u8_x\(svbool_t, svuint8_t, svuint8_t\)' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+__SVUint8_t
+svadd_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
+{
+ return x;
+}
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svuint8_t
+f (svbool_t pg, svuint8_t x, svuint8_t y)
+{
+ return svadd_x (pg, x, y);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8 = svget2 (u8x2); /* { dg-error {no matching function for call to 'svget2\(svuint8x2_t\&\)'} } */
+ u8 = svget2 (u8x2, 1, 2); /* { dg-error {no matching function for call to 'svget2\(svuint8x2_t\&, int, int\)'} } */
+ u8 = svget2 (u8, 0); /* { dg-error {no matching function for call to 'svget2\(svuint8_t\&, int\)'} } */
+ u8 = svget2 (u8x3, 0); /* { dg-error {no matching function for call to 'svget2\(svuint8x3_t\&, int\)'} } */
+ u8 = svget2 (pg, 0); /* { dg-error {no matching function for call to 'svget2\(svbool_t\&, int\)'} } */
+ u8 = svget2 (u8x2, x); /* { dg-error "argument 2 of 'svget2' must be an integer constant expression" } */
+ u8 = svget2 (u8x2, 0);
+ f64 = svget2 (u8x2, 0); /* { dg-error "cannot convert 'svuint8_t' to 'svfloat64_t' in assignment" } */
+ u8 = svget2 (u8x2, 1);
+ u8 = svget2 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, one);
+ u8 = svget2 (u8x2, 3 - 2);
+ u8 = svget2 (u8x2, 1.0);
+ u8 = svget2 (u8x2, const_sub (5, 4));
+ u8 = svget2 (u8x2, const_sub (6, 4)); /* { dg-error {passing 2 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, add (0, 0)); /* { dg-error "argument 2 of 'svget2' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8 = svget2_u8 (u8x2); /* { dg-error {too few arguments to function '[^']*'} } */
+ u8 = svget2_u8 (u8x2, 1, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+ u8 = svget2_u8 (u8, 0); /* { dg-error {cannot convert 'svuint8_t' to 'svuint8x2_t'} } */
+ u8 = svget2_u8 (u8x3, 0); /* { dg-error {cannot convert 'svuint8x3_t' to 'svuint8x2_t'} } */
+ u8 = svget2_u8 (pg, 0); /* { dg-error {cannot convert 'svbool_t' to 'svuint8x2_t'} } */
+ u8 = svget2_u8 (u8x2, x); /* { dg-error "argument 2 of 'svget2_u8' must be an integer constant expression" } */
+ u8 = svget2_u8 (u8x2, 0);
+ f64 = svget2_u8 (u8x2, 0); /* { dg-error "cannot convert 'svuint8_t' to 'svfloat64_t' in assignment" } */
+ u8 = svget2_u8 (u8x2, 1);
+ u8 = svget2_u8 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, one);
+ u8 = svget2_u8 (u8x2, 3 - 2);
+ u8 = svget2_u8 (u8x2, 1.0);
+ u8 = svget2_u8 (u8x2, const_sub (5, 4));
+ u8 = svget2_u8 (u8x2, const_sub (6, 4)); /* { dg-error {passing 2 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, add (0, 0)); /* { dg-error "argument 2 of 'svget2_u8' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+ int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16 = svget3 (f16x3); /* { dg-error {no matching function for call to 'svget3\(svfloat16x3_t\&\)'} } */
+ f16 = svget3 (f16x3, 1, 2); /* { dg-error {no matching function for call to 'svget3\(svfloat16x3_t\&, int, int\)'} } */
+ f16 = svget3 (f16, 0); /* { dg-error {no matching function for call to 'svget3\(svfloat16_t\&, int\)'} } */
+ f16 = svget3 (f16x4, 0); /* { dg-error {no matching function for call to 'svget3\(svfloat16x4_t\&, int\)'} } */
+ f16 = svget3 (pg, 0); /* { dg-error {no matching function for call to 'svget3\(svbool_t\&, int\)'} } */
+ f16 = svget3 (f16x3, x); /* { dg-error "argument 2 of 'svget3' must be an integer constant expression" } */
+ f16 = svget3 (f16x3, 0);
+ f64 = svget3 (f16x3, 0); /* { dg-error "cannot convert 'svfloat16_t' to 'svfloat64_t' in assignment" } */
+ f16 = svget3 (f16x3, 1);
+ f16 = svget3 (f16x3, 2);
+ f16 = svget3 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, one);
+ f16 = svget3 (f16x3, 3 - 2);
+ f16 = svget3 (f16x3, 1.0);
+ f16 = svget3 (f16x3, const_sub (5, 4));
+ f16 = svget3 (f16x3, const_sub (6, 4));
+ f16 = svget3 (f16x3, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, add (0, 0)); /* { dg-error "argument 2 of 'svget3' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+ int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16 = svget3_f16 (f16x3); /* { dg-error {too few arguments to function '[^']*'} } */
+ f16 = svget3_f16 (f16x3, 1, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+ f16 = svget3_f16 (f16, 0); /* { dg-error {cannot convert 'svfloat16_t' to 'svfloat16x3_t'} } */
+ f16 = svget3_f16 (f16x4, 0); /* { dg-error {cannot convert 'svfloat16x4_t' to 'svfloat16x3_t'} } */
+ f16 = svget3_f16 (pg, 0); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16x3_t'} } */
+ f16 = svget3_f16 (f16x3, x); /* { dg-error "argument 2 of 'svget3_f16' must be an integer constant expression" } */
+ f16 = svget3_f16 (f16x3, 0);
+ f64 = svget3_f16 (f16x3, 0); /* { dg-error "cannot convert 'svfloat16_t' to 'svfloat64_t' in assignment" } */
+ f16 = svget3_f16 (f16x3, 1);
+ f16 = svget3_f16 (f16x3, 2);
+ f16 = svget3_f16 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, one);
+ f16 = svget3_f16 (f16x3, 3 - 2);
+ f16 = svget3_f16 (f16x3, 1.0);
+ f16 = svget3_f16 (f16x3, const_sub (5, 4));
+ f16 = svget3_f16 (f16x3, const_sub (6, 4));
+ f16 = svget3_f16 (f16x3, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, add (0, 0)); /* { dg-error "argument 2 of 'svget3_f16' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32 = svget4 (s32x4); /* { dg-error {no matching function for call to 'svget4\(svint32x4_t\&\)'} } */
+ s32 = svget4 (s32x4, 1, 2); /* { dg-error {no matching function for call to 'svget4\(svint32x4_t\&, int, int\)'} } */
+ s32 = svget4 (s32, 0); /* { dg-error {no matching function for call to 'svget4\(svint32_t\&, int\)'} } */
+ s32 = svget4 (s32x2, 0); /* { dg-error {no matching function for call to 'svget4\(svint32x2_t\&, int\)'} } */
+ s32 = svget4 (pg, 0); /* { dg-error {no matching function for call to 'svget4\(svbool_t\&, int\)'} } */
+ s32 = svget4 (s32x4, x); /* { dg-error "argument 2 of 'svget4' must be an integer constant expression" } */
+ s32 = svget4 (s32x4, 0);
+ f64 = svget4 (s32x4, 0); /* { dg-error "cannot convert 'svint32_t' to 'svfloat64_t' in assignment" } */
+ s32 = svget4 (s32x4, 1);
+ s32 = svget4 (s32x4, 2);
+ s32 = svget4 (s32x4, 3);
+ s32 = svget4 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, one);
+ s32 = svget4 (s32x4, 3 - 2);
+ s32 = svget4 (s32x4, 1.0);
+ s32 = svget4 (s32x4, const_sub (5, 4));
+ s32 = svget4 (s32x4, const_sub (6, 4));
+ s32 = svget4 (s32x4, const_sub (7, 4));
+ s32 = svget4 (s32x4, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, add (0, 0)); /* { dg-error "argument 2 of 'svget4' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32 = svget4_s32 (s32x4); /* { dg-error {too few arguments to function '[^']*'} } */
+ s32 = svget4_s32 (s32x4, 1, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+ s32 = svget4_s32 (s32, 0); /* { dg-error {cannot convert 'svint32_t' to 'svint32x4_t'} } */
+ s32 = svget4_s32 (s32x2, 0); /* { dg-error {cannot convert 'svint32x2_t' to 'svint32x4_t'} } */
+ s32 = svget4_s32 (pg, 0); /* { dg-error {cannot convert 'svbool_t' to 'svint32x4_t'} } */
+ s32 = svget4_s32 (s32x4, x); /* { dg-error "argument 2 of 'svget4_s32' must be an integer constant expression" } */
+ s32 = svget4_s32 (s32x4, 0);
+ f64 = svget4_s32 (s32x4, 0); /* { dg-error "cannot convert 'svint32_t' to 'svfloat64_t' in assignment" } */
+ s32 = svget4_s32 (s32x4, 1);
+ s32 = svget4_s32 (s32x4, 2);
+ s32 = svget4_s32 (s32x4, 3);
+ s32 = svget4_s32 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, one);
+ s32 = svget4_s32 (s32x4, 3 - 2);
+ s32 = svget4_s32 (s32x4, 1.0);
+ s32 = svget4_s32 (s32x4, const_sub (5, 4));
+ s32 = svget4_s32 (s32x4, const_sub (6, 4));
+ s32 = svget4_s32 (s32x4, const_sub (7, 4));
+ s32 = svget4_s32 (s32x4, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, add (0, 0)); /* { dg-error "argument 2 of 'svget4_s32' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t x, svint8_t w, svuint64_t y)
+{
+ svlsl_wide_u8_x (pg, x, x); /* { dg-error "cannot convert 'svuint8_t' to 'svuint64_t'" } */
+ svlsl_wide_u8_x (pg, x); /* { dg-error {too few arguments to function 'svuint8_t svlsl_wide_u8_x\(svbool_t, svuint8_t, svuint64_t\)'} } */
+ svlsl_wide_u8_x (pg, x, y, x); /* { dg-error {too many arguments to function 'svuint8_t svlsl_wide_u8_x\(svbool_t, svuint8_t, svuint64_t\)'} } */
+ return svlsl_wide_s8_x (pg, w, y); /* { dg-error {cannot convert 'svint8_t' to 'svuint8_t' in return} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f1 (svbool_t pg, svuint8_t x, svuint64_t y)
+{
+ svlsl_wide_x (pg, x); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint8_t&\)'} } */
+ svlsl_wide_x (pg, x, x, x, x); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint8_t&, svuint8_t&, svuint8_t&, svuint8_t&\)'} } */
+ svlsl_wide_x (x, x, y); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svuint8_t&, svuint8_t&, svuint64_t&\)'} } */
+ svlsl_wide_x (pg, 1, y); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, int, svuint64_t&\)'} } */
+ svlsl_wide_x (pg, x, x); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint8_t&, svuint8_t&\)'} } */
+ svlsl_wide_x (pg, y, y); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint64_t&, svuint64_t&\)'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void f1(svbool_t) {}
+void f2(svint8_t) {}
+void f3(svint16_t) {}
+void f4(svint32_t) {}
+void f5(svint64_t) {}
+void f6(svuint8_t) {}
+void f7(svuint16_t) {}
+void f8(svuint32_t) {}
+void f9(svuint64_t) {}
+void f10(svfloat16_t) {}
+void f11(svfloat32_t) {}
+void f12(svfloat64_t) {}
+
+/* { dg-final { scan-assembler "_Z2f110__SVBool_t:" } } */
+/* { dg-final { scan-assembler "_Z2f210__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f311__SVInt16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f411__SVInt32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f511__SVInt64_t:" } } */
+/* { dg-final { scan-assembler "_Z2f611__SVUint8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f712__SVUint16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f812__SVUint32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f912__SVUint64_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1013__SVFloat16_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1113__SVFloat32_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1213__SVFloat64_t:" } } */
--- /dev/null
+/* { dg-do compile } */
+
+void f1(__SVBool_t) {}
+void f2(__SVInt8_t) {}
+void f3(__SVInt16_t) {}
+void f4(__SVInt32_t) {}
+void f5(__SVInt64_t) {}
+void f6(__SVUint8_t) {}
+void f7(__SVUint16_t) {}
+void f8(__SVUint32_t) {}
+void f9(__SVUint64_t) {}
+void f10(__SVFloat16_t) {}
+void f11(__SVFloat32_t) {}
+void f12(__SVFloat64_t) {}
+
+/* { dg-final { scan-assembler "_Z2f110__SVBool_t:" } } */
+/* { dg-final { scan-assembler "_Z2f210__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f311__SVInt16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f411__SVInt32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f511__SVInt64_t:" } } */
+/* { dg-final { scan-assembler "_Z2f611__SVUint8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f712__SVUint16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f812__SVUint32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f912__SVUint64_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1013__SVFloat16_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1113__SVFloat32_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1213__SVFloat64_t:" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-msve-vector-bits=256" } */
+
+#include <arm_sve.h>
+
+typedef __SVInt8_t t1;
+typedef svint8_t t2;
+/* Distinct from svint8_t, but compatible with it. */
+typedef int8_t t3 __attribute__((vector_size(32)));
+
+void f1(t1) {}
+void f2(t2) {}
+void f3(t3) {}
+void f4(t1 &a, t2 &b, t3 &c) { a = b = c; }
+
+/* { dg-final { scan-assembler "_Z2f110__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f210__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f3Dv32_a:" } } */
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void f1(svint8x2_t) {}
+void f2(svint16x2_t) {}
+void f3(svint32x2_t) {}
+void f4(svint64x2_t) {}
+void f5(svuint8x2_t) {}
+void f6(svuint16x2_t) {}
+void f7(svuint32x2_t) {}
+void f8(svuint64x2_t) {}
+void f9(svfloat16x2_t) {}
+void f10(svfloat32x2_t) {}
+void f11(svfloat64x2_t) {}
+
+void g1(svint8x3_t) {}
+void g2(svint16x3_t) {}
+void g3(svint32x3_t) {}
+void g4(svint64x3_t) {}
+void g5(svuint8x3_t) {}
+void g6(svuint16x3_t) {}
+void g7(svuint32x3_t) {}
+void g8(svuint64x3_t) {}
+void g9(svfloat16x3_t) {}
+void g10(svfloat32x3_t) {}
+void g11(svfloat64x3_t) {}
+
+void h1(svint8x4_t) {}
+void h2(svint16x4_t) {}
+void h3(svint32x4_t) {}
+void h4(svint64x4_t) {}
+void h5(svuint8x4_t) {}
+void h6(svuint16x4_t) {}
+void h7(svuint32x4_t) {}
+void h8(svuint64x4_t) {}
+void h9(svfloat16x4_t) {}
+void h10(svfloat32x4_t) {}
+void h11(svfloat64x4_t) {}
+
+/* { dg-final { scan-assembler "_Z2f110svint8x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f211svint16x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f311svint32x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f411svint64x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f511svuint8x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f612svuint16x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f712svuint32x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f812svuint64x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f913svfloat16x2_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1013svfloat32x2_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1113svfloat64x2_t:" } } */
+
+/* { dg-final { scan-assembler "_Z2g110svint8x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g211svint16x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g311svint32x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g411svint64x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g511svuint8x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g612svuint16x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g712svuint32x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g812svuint64x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g913svfloat16x3_t:" } } */
+/* { dg-final { scan-assembler "_Z3g1013svfloat32x3_t:" } } */
+/* { dg-final { scan-assembler "_Z3g1113svfloat64x3_t:" } } */
+
+/* { dg-final { scan-assembler "_Z2h110svint8x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h211svint16x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h311svint32x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h411svint64x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h511svuint8x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h612svuint16x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h712svuint32x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h812svuint64x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h913svfloat16x4_t:" } } */
+/* { dg-final { scan-assembler "_Z3h1013svfloat32x4_t:" } } */
+/* { dg-final { scan-assembler "_Z3h1113svfloat64x4_t:" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+ svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8x2 = svset2 (u8x2); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&\)'} } */
+ u8x2 = svset2 (u8x2, 1); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int\)'} } */
+ u8x2 = svset2 (u8x2, 1, u8, 2); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svuint8_t\&, int\)'} } */
+ u8x2 = svset2 (u8, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svuint8_t\&, int, svuint8_t\&\)'} } */
+ u8x2 = svset2 (s8x2, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svint8x2_t\&, int, svuint8_t\&\)'} } */
+ u8x2 = svset2 (u8x3, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svuint8x3_t\&, int, svuint8_t\&\)'} } */
+ u8x2 = svset2 (pg, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svbool_t\&, int, svuint8_t\&\)'} } */
+ u8x2 = svset2 (u8x2, 0, f64); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svfloat64_t\&\)'} } */
+ u8x2 = svset2 (u8x2, 0, u8x2); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svuint8x2_t\&\)'} } */
+ u8x2 = svset2 (u8x2, 0, pg); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svbool_t\&\)'} } */
+ u8x2 = svset2 (u8x2, x, u8); /* { dg-error "argument 2 of 'svset2' must be an integer constant expression" } */
+ u8x2 = svset2 (u8x2, 0, u8);
+ s8x2 = svset2 (u8x2, 0, u8); /* { dg-error {cannot convert 'svuint8x2_t' to 'svint8x2_t' in assignment} } */
+ u8x2 = svset2 (u8x2, 1, u8);
+ u8x2 = svset2 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, one, u8);
+ u8x2 = svset2 (u8x2, 3 - 2, u8);
+ u8x2 = svset2 (u8x2, 1.0, u8);
+ u8x2 = svset2 (u8x2, const_sub (5, 4), u8);
+ u8x2 = svset2 (u8x2, const_sub (6, 4), u8); /* { dg-error {passing 2 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, const_sub (7, 4), u8); /* { dg-error {passing 3 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, const_sub (8, 4), u8); /* { dg-error {passing 4 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, add (0, 0), u8); /* { dg-error "argument 2 of 'svset2' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+ svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8x2 = svset2_u8 (u8x2); /* { dg-error {too few arguments to function '[^']*'} } */
+ u8x2 = svset2_u8 (u8x2, 1); /* { dg-error {too few arguments to function '[^']*'} } */
+ u8x2 = svset2_u8 (u8x2, 1, u8, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+ u8x2 = svset2_u8 (u8, 0, u8); /* { dg-error {cannot convert 'svuint8_t' to 'svuint8x2_t'} } */
+ u8x2 = svset2_u8 (s8x2, 0, u8); /* { dg-error {cannot convert 'svint8x2_t' to 'svuint8x2_t'} } */
+ u8x2 = svset2_u8 (u8x3, 0, u8); /* { dg-error {cannot convert 'svuint8x3_t' to 'svuint8x2_t'} } */
+ u8x2 = svset2_u8 (pg, 0, u8); /* { dg-error {cannot convert 'svbool_t' to 'svuint8x2_t'} } */
+ u8x2 = svset2_u8 (u8x2, 0, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svuint8_t'} } */
+ u8x2 = svset2_u8 (u8x2, 0, u8x2); /* { dg-error {cannot convert 'svuint8x2_t' to 'svuint8_t'} } */
+ u8x2 = svset2_u8 (u8x2, 0, pg); /* { dg-error {cannot convert 'svbool_t' to 'svuint8_t'} } */
+ u8x2 = svset2_u8 (u8x2, x, u8); /* { dg-error "argument 2 of 'svset2_u8' must be an integer constant expression" } */
+ u8x2 = svset2_u8 (u8x2, 0, u8);
+ s8x2 = svset2_u8 (u8x2, 0, u8); /* { dg-error {cannot convert 'svuint8x2_t' to 'svint8x2_t' in assignment} } */
+ u8x2 = svset2_u8 (u8x2, 1, u8);
+ u8x2 = svset2_u8 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, one, u8);
+ u8x2 = svset2_u8 (u8x2, 3 - 2, u8);
+ u8x2 = svset2_u8 (u8x2, 1.0, u8);
+ u8x2 = svset2_u8 (u8x2, const_sub (5, 4), u8);
+ u8x2 = svset2_u8 (u8x2, const_sub (6, 4), u8); /* { dg-error {passing 2 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, const_sub (7, 4), u8); /* { dg-error {passing 3 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, const_sub (8, 4), u8); /* { dg-error {passing 4 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, add (0, 0), u8); /* { dg-error "argument 2 of 'svset2_u8' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svuint16x3_t u16x3,
+ svfloat16x4_t f16x4, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16x3 = svset3 (f16x3); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&\)'} } */
+ f16x3 = svset3 (f16x3, 1); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int\)'} } */
+ f16x3 = svset3 (f16x3, 1, f16, 2); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svfloat16_t\&, int\)'} } */
+ f16x3 = svset3 (f16, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svfloat16_t\&, int, svfloat16_t\&\)'} } */
+ f16x3 = svset3 (u16x3, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svuint16x3_t\&, int, svfloat16_t\&\)'} } */
+ f16x3 = svset3 (f16x4, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svfloat16x4_t\&, int, svfloat16_t\&\)'} } */
+ f16x3 = svset3 (pg, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svbool_t\&, int, svfloat16_t\&\)'} } */
+ f16x3 = svset3 (f16x3, 0, f64); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svfloat64_t\&\)'} } */
+ f16x3 = svset3 (f16x3, 0, f16x3); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svfloat16x3_t\&\)'} } */
+ f16x3 = svset3 (f16x3, 0, pg); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svbool_t\&\)'} } */
+ f16x3 = svset3 (f16x3, x, f16); /* { dg-error "argument 2 of 'svset3' must be an integer constant expression" } */
+ f16x3 = svset3 (f16x3, 0, f16);
+ u16x3 = svset3 (f16x3, 0, f16); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svuint16x3_t' in assignment} } */
+ f16x3 = svset3 (f16x3, 1, f16);
+ f16x3 = svset3 (f16x3, 2, f16);
+ f16x3 = svset3 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, one, f16);
+ f16x3 = svset3 (f16x3, 3 - 2, f16);
+ f16x3 = svset3 (f16x3, 1.0, f16);
+ f16x3 = svset3 (f16x3, const_sub (5, 4), f16);
+ f16x3 = svset3 (f16x3, const_sub (6, 4), f16);
+ f16x3 = svset3 (f16x3, const_sub (7, 4), f16); /* { dg-error {passing 3 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, const_sub (8, 4), f16); /* { dg-error {passing 4 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, add (0, 0), f16); /* { dg-error "argument 2 of 'svset3' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svuint16x3_t u16x3,
+ svfloat16x4_t f16x4, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16x3 = svset3_f16 (f16x3); /* { dg-error {too few arguments to function '[^']*'} } */
+ f16x3 = svset3_f16 (f16x3, 1); /* { dg-error {too few arguments to function '[^']*'} } */
+ f16x3 = svset3_f16 (f16x3, 1, f16, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+ f16x3 = svset3_f16 (f16, 0, f16); /* { dg-error {cannot convert 'svfloat16_t' to 'svfloat16x3_t'} } */
+ f16x3 = svset3_f16 (u16x3, 0, f16); /* { dg-error {cannot convert 'svuint16x3_t' to 'svfloat16x3_t'} } */
+ f16x3 = svset3_f16 (f16x4, 0, f16); /* { dg-error {cannot convert 'svfloat16x4_t' to 'svfloat16x3_t'} } */
+ f16x3 = svset3_f16 (pg, 0, f16); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16x3_t'} } */
+ f16x3 = svset3_f16 (f16x3, 0, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svfloat16_t'} } */
+ f16x3 = svset3_f16 (f16x3, 0, f16x3); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svfloat16_t'} } */
+ f16x3 = svset3_f16 (f16x3, 0, pg); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16_t'} } */
+ f16x3 = svset3_f16 (f16x3, x, f16); /* { dg-error "argument 2 of 'svset3_f16' must be an integer constant expression" } */
+ f16x3 = svset3_f16 (f16x3, 0, f16);
+ u16x3 = svset3_f16 (f16x3, 0, f16); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svuint16x3_t' in assignment} } */
+ f16x3 = svset3_f16 (f16x3, 1, f16);
+ f16x3 = svset3_f16 (f16x3, 2, f16);
+ f16x3 = svset3_f16 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, one, f16);
+ f16x3 = svset3_f16 (f16x3, 3 - 2, f16);
+ f16x3 = svset3_f16 (f16x3, 1.0, f16);
+ f16x3 = svset3_f16 (f16x3, const_sub (5, 4), f16);
+ f16x3 = svset3_f16 (f16x3, const_sub (6, 4), f16);
+ f16x3 = svset3_f16 (f16x3, const_sub (7, 4), f16); /* { dg-error {passing 3 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, const_sub (8, 4), f16); /* { dg-error {passing 4 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, add (0, 0), f16); /* { dg-error "argument 2 of 'svset3_f16' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+ svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32x4 = svset4 (s32x4); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&\)'} } */
+ s32x4 = svset4 (s32x4, 1); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int\)'} } */
+ s32x4 = svset4 (s32x4, 1, s32, 2); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svint32_t\&, int\)'} } */
+ s32x4 = svset4 (s32, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svint32_t\&, int, svint32_t\&\)'} } */
+ s32x4 = svset4 (f32x4, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svfloat32x4_t\&, int, svint32_t\&\)'} } */
+ s32x4 = svset4 (s32x2, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svint32x2_t\&, int, svint32_t\&\)'} } */
+ s32x4 = svset4 (pg, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svbool_t\&, int, svint32_t\&\)'} } */
+ s32x4 = svset4 (s32x4, 0, f64); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svfloat64_t\&\)'} } */
+ s32x4 = svset4 (s32x4, 0, s32x4); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svint32x4_t\&\)'} } */
+ s32x4 = svset4 (s32x4, 0, pg); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svbool_t\&\)'} } */
+ s32x4 = svset4 (s32x4, x, s32); /* { dg-error "argument 2 of 'svset4' must be an integer constant expression" } */
+ s32x4 = svset4 (s32x4, 0, s32);
+ f32x4 = svset4 (s32x4, 0, s32); /* { dg-error {cannot convert 'svint32x4_t' to 'svfloat32x4_t' in assignment} } */
+ s32x4 = svset4 (s32x4, 1, s32);
+ s32x4 = svset4 (s32x4, 2, s32);
+ s32x4 = svset4 (s32x4, 3, s32);
+ s32x4 = svset4 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, one, s32);
+ s32x4 = svset4 (s32x4, 3 - 2, s32);
+ s32x4 = svset4 (s32x4, 1.0, s32);
+ s32x4 = svset4 (s32x4, const_sub (5, 4), s32);
+ s32x4 = svset4 (s32x4, const_sub (6, 4), s32);
+ s32x4 = svset4 (s32x4, const_sub (7, 4), s32);
+ s32x4 = svset4 (s32x4, const_sub (8, 4), s32); /* { dg-error {passing 4 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, add (0, 0), s32); /* { dg-error "argument 2 of 'svset4' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+ svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32x4 = svset4_s32 (s32x4); /* { dg-error {too few arguments to function '[^']*'} } */
+ s32x4 = svset4_s32 (s32x4, 1); /* { dg-error {too few arguments to function '[^']*'} } */
+ s32x4 = svset4_s32 (s32x4, 1, s32, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+ s32x4 = svset4_s32 (s32, 0, s32); /* { dg-error {cannot convert 'svint32_t' to 'svint32x4_t'} } */
+ s32x4 = svset4_s32 (f32x4, 0, s32); /* { dg-error {cannot convert 'svfloat32x4_t' to 'svint32x4_t'} } */
+ s32x4 = svset4_s32 (s32x2, 0, s32); /* { dg-error {cannot convert 'svint32x2_t' to 'svint32x4_t'} } */
+ s32x4 = svset4_s32 (pg, 0, s32); /* { dg-error {cannot convert 'svbool_t' to 'svint32x4_t'} } */
+ s32x4 = svset4_s32 (s32x4, 0, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svint32_t'} } */
+ s32x4 = svset4_s32 (s32x4, 0, s32x4); /* { dg-error {cannot convert 'svint32x4_t' to 'svint32_t'} } */
+ s32x4 = svset4_s32 (s32x4, 0, pg); /* { dg-error {cannot convert 'svbool_t' to 'svint32_t'} } */
+ s32x4 = svset4_s32 (s32x4, x, s32); /* { dg-error "argument 2 of 'svset4_s32' must be an integer constant expression" } */
+ s32x4 = svset4_s32 (s32x4, 0, s32);
+ f32x4 = svset4_s32 (s32x4, 0, s32); /* { dg-error {cannot convert 'svint32x4_t' to 'svfloat32x4_t' in assignment} } */
+ s32x4 = svset4_s32 (s32x4, 1, s32);
+ s32x4 = svset4_s32 (s32x4, 2, s32);
+ s32x4 = svset4_s32 (s32x4, 3, s32);
+ s32x4 = svset4_s32 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, one, s32);
+ s32x4 = svset4_s32 (s32x4, 3 - 2, s32);
+ s32x4 = svset4_s32 (s32x4, 1.0, s32);
+ s32x4 = svset4_s32 (s32x4, const_sub (5, 4), s32);
+ s32x4 = svset4_s32 (s32x4, const_sub (6, 4), s32);
+ s32x4 = svset4_s32 (s32x4, const_sub (7, 4), s32);
+ s32x4 = svset4_s32 (s32x4, const_sub (8, 4), s32); /* { dg-error {passing 4 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, add (0, 0), s32); /* { dg-error "argument 2 of 'svset4_s32' must be an integer constant expression" } */
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+
+int svbool_t; /* { dg-message "note: previous declaration 'int svbool_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef [^'\n]* svbool_t' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef int svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
--- /dev/null
+/* { dg-do compile } */
+
+struct svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
+
+svint8_t f (svint8x2_t x) { return x.__val[0]; } /* { dg-error {'x' has incomplete type} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef struct svint8x2_t svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
+
+svint8_t f (svint8x2_t x) { return x.__val[0]; } /* { dg-error {'x' has incomplete type} } */
--- /dev/null
+/* { dg-do compile } */
+
+struct svint8x2_t {};
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
--- /dev/null
+/* { dg-do compile } */
+
+enum svpattern { FOO }; /* { dg-message "note: previous definition here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "multiple definition of 'enum svpattern'" } */
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+enum svpattern { FOO }; /* { dg-error "multiple definition of 'enum svpattern'" } */
+enum foo { SV_ALL }; /* { dg-error "'SV_ALL' conflicts with a previous declaration" } */
+typedef int SV_POW2; /* { dg-error "'typedef int SV_POW2' redeclared as different kind of entity" } */
+int SV_VL3; /* { dg-error "'int SV_VL3' redeclared as different kind of entity" } */
--- /dev/null
+/* { dg-do compile } */
+
+struct svpattern { int x; };
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "'svpattern' referred to as enum" } */
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+struct svpattern { int x; }; /* { dg-error "'svpattern' referred to as 'struct'" } */
--- /dev/null
+/* { dg-do compile } */
+
+int svpattern; /* OK in C. */
+
+#pragma GCC aarch64 "arm_sve.h"
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+int svpattern; /* OK in C. */
--- /dev/null
+/* { dg-do compile } */
+
+int svint8_t; /* { dg-message "note: previous declaration 'int svint8_t" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef [^'\n]* svint8_t' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+enum foo { SV_VL4 };
+typedef int SV_POW2;
+int SV_ALL;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "'SV_VL4' conflicts with a previous declaration" } */
+/* { dg-error "'SV_POW2' redeclared as different kind of entity" "" { target *-*-* } .-1 } */
+/* { dg-error "'SV_ALL' redeclared as different kind of entity" "" { target *-*-* } .-2 } */
--- /dev/null
+/* { dg-do compile } */
+
+int svuint16_t; /* { dg-message "note: previous declaration 'int svuint16_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef [^'\n]* svuint16_t' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+int svfloat32_t; /* { dg-message "note: previous declaration 'int svfloat32_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef [^'\n]* svfloat32_t' redeclared as different kind of entity} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef int svbool_t; /* { dg-message "note: previous declaration as 'typedef int svbool_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration '[^'\n]* svbool_t'} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef __SVBool_t svbool_t;
+
+#pragma GCC aarch64 "arm_sve.h"
+
--- /dev/null
+/* { dg-do compile } */
+
+int svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef struct svint8x2_t svint8x2_t' redeclared as different kind of entity} } */
+
+void f (struct svint8x2_t) {} /* { dg-error {incomplete type} } */
+void g () { int &x = svint8x2_t; }
--- /dev/null
+/* { dg-do compile } */
+
+struct svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
+
+void f (svint8x2_t) {} /* { dg-error {incomplete type} } */
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+int svint8x2_t; /* { dg-error {'int svint8x2_t' redeclared as different kind of entity} } */
+
+void f (struct svint8x2_t) {} /* { dg-error {using typedef-name 'svint8x2_t' after 'struct'} } */
+void g () { int &x = svint8x2_t; } /* { dg-error {expected primary-expression before ';' token} } */
--- /dev/null
+// { dg-do compile }
+
+#include <arm_sve.h>
+
+enum foo { A, B };
+
+void
+test (int8_t s8, int16_t s16, int32_t s32, int64_t s64,
+ uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64,
+ bool b, foo e, int *ptr, float f32, svbool_t pg,
+ svint32_t vec)
+{
+ svwhilele_b8 (s32); // { dg-error {no matching function for call to 'svwhilele_b8\(int32_t&\)'} }
+ svwhilele_b8 (s32, s32, s32); // { dg-error {no matching function for call to 'svwhilele_b8\(int32_t&, int32_t&, int32_t&\)'} }
+
+ svwhilele_b8 (b, b);
+ svwhilele_b8 (e, e);
+ svwhilele_b8 (s8, s8);
+ svwhilele_b8 (u8, u8);
+ svwhilele_b8 (s16, s16);
+ svwhilele_b8 (u16, u16);
+ svwhilele_b8 (ptr, ptr); // { dg-error {no matching function for call to 'svwhilele_b8\(int\*&, int\*&\)'} }
+ // { dg-error {invalid conversion from 'int\*' to '[^']*'} "" { target *-*-* } .-1 }
+ svwhilele_b8 (f32, f32); // { dg-error {call of overloaded 'svwhilele_b8\(float&, float&\)' is ambiguous} }
+ svwhilele_b8 (pg, pg); // { dg-error {no matching function for call to 'svwhilele_b8\(svbool_t&, svbool_t&\)'} }
+ svwhilele_b8 (vec, vec); // { dg-error {no matching function for call to 'svwhilele_b8\(svint32_t&, svint32_t&\)'} }
+
+ svwhilele_b8 (s32, b);
+ svwhilele_b8 (s32, e);
+ svwhilele_b8 (s32, s8);
+ svwhilele_b8 (s32, u8);
+ svwhilele_b8 (s32, s16);
+ svwhilele_b8 (s32, u16);
+
+ svwhilele_b8 (u32, b); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, bool&\)' is ambiguous} }
+ svwhilele_b8 (u32, e); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, foo&\)' is ambiguous} }
+ svwhilele_b8 (u32, s8); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int8_t&\)' is ambiguous} }
+ svwhilele_b8 (u32, u8); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, uint8_t&\)' is ambiguous} }
+ svwhilele_b8 (u32, s16); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int16_t&\)' is ambiguous} }
+ svwhilele_b8 (u32, u16); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, uint16_t&\)' is ambiguous} }
+
+ svwhilele_b8 (s32, s32);
+ svwhilele_b8 (s32, u32); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, uint32_t&\)' is ambiguous} }
+ svwhilele_b8 (s32, s64); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, int64_t&\)' is ambiguous} }
+ svwhilele_b8 (s32, u64); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, uint64_t&\)' is ambiguous} }
+
+ svwhilele_b8 (u32, s32); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int32_t&\)' is ambiguous} }
+ svwhilele_b8 (u32, u32);
+ svwhilele_b8 (u32, s64); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int64_t&\)' is ambiguous} }
+ svwhilele_b8 (u32, u64); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, uint64_t&\)' is ambiguous} }
+
+ svwhilele_b8 (s64, s32); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, int32_t&\)' is ambiguous} }
+ svwhilele_b8 (s64, u32); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, uint32_t&\)' is ambiguous} }
+ svwhilele_b8 (s64, s64);
+ svwhilele_b8 (s64, u64); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, uint64_t&\)' is ambiguous} }
+
+ svwhilele_b8 (u64, s32); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, int32_t&\)' is ambiguous} }
+ svwhilele_b8 (u64, u32); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, uint32_t&\)' is ambiguous} }
+ svwhilele_b8 (u64, s64); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, int64_t&\)' is ambiguous} }
+ svwhilele_b8 (u64, u64);
+
+ svwhilele_b8 (0, s32);
+ svwhilele_b8 (0, u32); // { dg-error {call of overloaded 'svwhilele_b8\(int, uint32_t&\)' is ambiguous} }
+ svwhilele_b8 (0, s64); // { dg-error {call of overloaded 'svwhilele_b8\(int, int64_t&\)' is ambiguous} }
+ svwhilele_b8 (0, u64); // { dg-error {call of overloaded 'svwhilele_b8\(int, uint64_t&\)' is ambiguous} }
+
+ svwhilele_b8 (s32, 0);
+ svwhilele_b8 (u32, 0); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int\)' is ambiguous} }
+ svwhilele_b8 (s64, 0); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, int\)' is ambiguous} }
+ svwhilele_b8 (u64, 0); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, int\)' is ambiguous} }
+
+ svwhilele_b8 (0U, s32); // { dg-error {call of overloaded 'svwhilele_b8\(unsigned int, int32_t&\)' is ambiguous} }
+ svwhilele_b8 (0U, u32);
+ svwhilele_b8 (0U, s64); // { dg-error {call of overloaded 'svwhilele_b8\(unsigned int, int64_t&\)' is ambiguous} }
+ svwhilele_b8 (0U, u64); // { dg-error {call of overloaded 'svwhilele_b8\(unsigned int, uint64_t&\)' is ambiguous} }
+
+ svwhilele_b8 (s32, 0U); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, unsigned int\)' is ambiguous} }
+ svwhilele_b8 (u32, 0U);
+ svwhilele_b8 (s64, 0U); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, unsigned int\)' is ambiguous} }
+ svwhilele_b8 (u64, 0U); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, unsigned int\)' is ambiguous} }
+}
--- /dev/null
+# Specific regression driver for AArch64 SVE.
+# Copyright (C) 2009-2019 Free Software Foundation, Inc.
+# Contributed by ARM Ltd.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AArch64 target.
+if {![istarget aarch64*-*-*] } {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Force SVE if we're not testing it already.
+if { [check_effective_target_aarch64_sve] } {
+ set sve_flags ""
+} else {
+ set sve_flags "-march=armv8.2-a+sve"
+}
+
+# Main loop.
+# FIXME: This should include general/*.c too, but leave that until the
+# C frontend allows initialization of SVE vectors.
+set files [glob -nocomplain $srcdir/$subdir/general-c/*.c]
+dg-runtest [lsort $files] "$sve_flags" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, uint32_t *u32_ptr, svuint8_t u8, svuint16_t u16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+ svadrh_index (u32); /* { dg-error {too few arguments to function 'svadrh_index'} } */
+ svadrh_index (u32, u32, u32); /* { dg-error {too many arguments to function 'svadrh_index'} } */
+ svadrh_index (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrh_index', which expects an SVE vector type} } */
+ svadrh_index (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrh_index', which expects an SVE vector type} } */
+ svadrh_index (u16, u16); /* { dg-error {passing 'svuint16_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svadrh_index (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svadrh_index (f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svadrh_index (pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+ svadrh_index (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrh_index', which expects an SVE vector type} } */
+ svadrh_index (u32, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svadrh_index', which expects a vector of 32-bit or 64-bit integers} } */
+ svadrh_index (u32, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svadrh_index', which expects a vector of 32-bit or 64-bit integers} } */
+ svadrh_index (u32, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+
+ svadrh_index (u32, s32);
+ svadrh_index (u32, u32);
+ svadrh_index (u32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+ svadrh_index (u32, s64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an index of type 'svint64_t'} } */
+ svadrh_index (u32, u64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an index of type 'svuint64_t'} } */
+ svadrh_index (u32, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+
+ svadrh_index (u64, s32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an index of type 'svint32_t'} } */
+ svadrh_index (u64, u32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an index of type 'svuint32_t'} } */
+ svadrh_index (u64, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+ svadrh_index (u64, s64);
+ svadrh_index (u64, u64);
+ svadrh_index (u64, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, uint32_t *u32_ptr, svuint8_t u8, svuint16_t u16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+ svadrb_offset (u32); /* { dg-error {too few arguments to function 'svadrb_offset'} } */
+ svadrb_offset (u32, u32, u32); /* { dg-error {too many arguments to function 'svadrb_offset'} } */
+ svadrb_offset (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrb_offset', which expects an SVE vector type} } */
+ svadrb_offset (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrb_offset', which expects an SVE vector type} } */
+ svadrb_offset (u16, u16); /* { dg-error {passing 'svuint16_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svadrb_offset (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svadrb_offset (f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svadrb_offset (pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+ svadrb_offset (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrb_offset', which expects an SVE vector type} } */
+ svadrb_offset (u32, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svadrb_offset', which expects a vector of 32-bit or 64-bit integers} } */
+ svadrb_offset (u32, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svadrb_offset', which expects a vector of 32-bit or 64-bit integers} } */
+ svadrb_offset (u32, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+
+ svadrb_offset (u32, s32);
+ svadrb_offset (u32, u32);
+ svadrb_offset (u32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+ svadrb_offset (u32, s64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an offset of type 'svint64_t'} } */
+ svadrb_offset (u32, u64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an offset of type 'svuint64_t'} } */
+ svadrb_offset (u32, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+
+ svadrb_offset (u64, s32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an offset of type 'svint32_t'} } */
+ svadrb_offset (u64, u32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an offset of type 'svuint32_t'} } */
+ svadrb_offset (u64, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+ svadrb_offset (u64, s64);
+ svadrb_offset (u64, u64);
+ svadrb_offset (u64, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint16_t s16)
+{
+ svzip1 (pg); /* { dg-error {too few arguments to function 'svzip1'} } */
+ svzip1 (pg, u8, u8); /* { dg-error {too many arguments to function 'svzip1'} } */
+ svzip1 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svzip1', but previous arguments had type 'svbool_t'} } */
+ svzip1 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+ svzip1 (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+ svzip1 (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svzip1', which expects an SVE vector type} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svint16_t s16, svuint16_t u16,
+ svfloat32_t f32, svint32_t s32, svuint32_t u32)
+{
+ svscale_x (pg, f16); /* { dg-error {too few arguments to function 'svscale_x'} } */
+ svscale_x (pg, f16, s16, s16); /* { dg-error {too many arguments to function 'svscale_x'} } */
+ svscale_x (s32, f16, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svscale_x', which expects 'svbool_t'} } */
+ svscale_x (1, f16, s32); /* { dg-error {passing 'int' to argument 1 of 'svscale_x', which expects 'svbool_t'} } */
+ svscale_x (pg, pg, s16); /* { dg-error {'svscale_x' has no form that takes 'svbool_t' arguments} } */
+ svscale_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svscale_x', which expects an SVE vector type} } */
+ svscale_x (pg, f16, s16);
+ svscale_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, f16, s32); /* { dg-error {arguments 2 and 3 of 'svscale_x' must have the same element size, but the values passed here have type 'svfloat16_t' and 'svint32_t' respectively} } */
+ svscale_x (pg, f16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, f16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, f16, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, f16, 0);
+ svscale_x (pg, s16, s16); /* { dg-error {'svscale_x' has no form that takes 'svint16_t' arguments} } */
+ svscale_x (pg, s16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, s16, s32); /* { dg-error {'svscale_x' has no form that takes 'svint16_t' arguments} } */
+ svscale_x (pg, s16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+ svscale_x (pg, u16, s16); /* { dg-error {'svscale_x' has no form that takes 'svuint16_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+ svint32_t s32, int i)
+{
+ svmul_lane (f32, f32); /* { dg-error {too few arguments to function 'svmul_lane'} } */
+ svmul_lane (f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svmul_lane'} } */
+ svmul_lane (pg, pg, 0); /* { dg-error {'svmul_lane' has no form that takes 'svbool_t' arguments} } */
+ svmul_lane (s32, s32, 0); /* { dg-error {'svmul_lane' has no form that takes 'svint32_t' arguments} } */
+ svmul_lane (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmul_lane', which expects an SVE vector type} } */
+ svmul_lane (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmul_lane', which expects an SVE vector type} } */
+ svmul_lane (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmul_lane', but previous arguments had type 'svfloat32_t'} } */
+ svmul_lane (f32, f32, s32); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+ svmul_lane (f32, f32, i); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+
+ svmul_lane (f16, f16, 0);
+ svmul_lane (f16, f16, 7);
+ svmul_lane (f16, f16, 8); /* { dg-error {passing 8 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 7\]} } */
+ svmul_lane (f16, f16, -1); /* { dg-error {passing -1 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 7\]} } */
+
+ svmul_lane (f32, f32, 0);
+ svmul_lane (f32, f32, 3);
+ svmul_lane (f32, f32, 4); /* { dg-error {passing 4 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 3\]} } */
+ svmul_lane (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 3\]} } */
+
+ svmul_lane (f64, f64, 0);
+ svmul_lane (f64, f64, 1);
+ svmul_lane (f64, f64, 2); /* { dg-error {passing 2 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 1\]} } */
+ svmul_lane (f64, f64, -1); /* { dg-error {passing -1 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 1\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svfloat16_t f16, int i, float f)
+{
+ svinsr (u8); /* { dg-error {too few arguments to function 'svinsr'} } */
+ svinsr (u8, 0, 0); /* { dg-error {too many arguments to function 'svinsr'} } */
+ svinsr (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svinsr', which expects an SVE vector type} } */
+ svinsr (u8, 0);
+ svinsr (u8, -1);
+ svinsr (u8, i);
+ svinsr (u8, f);
+ svinsr (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svinsr', which expects a scalar element} } */
+ svinsr (pg, 0); /* { dg-error {'svinsr' has no form that takes 'svbool_t' arguments} } */
+ svinsr (f16, f);
+ svinsr (f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svinsr', which expects a scalar element} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8)
+{
+ svadd_u8_x (pg, u8, s8); /* { dg-error {incompatible type for argument 3 of 'svadd_u8_x'} } */
+ svadd_u8_x (pg, u8); /* { dg-error {too few arguments to function 'svadd_u8_x'} } */
+ svadd_u8_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svadd_u8_x'} } */
+ return svadd_s8_x (pg, s8, s8); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+ svadd_x (pg, u8); /* { dg-error {too few arguments to function 'svadd_x'} } */
+ svadd_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svadd_x'} } */
+ svadd_x (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svadd_x', which expects 'svbool_t'} } */
+ svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+ svadd_x (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svadd_x', which expects an SVE vector type} } */
+ svadd_x (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+ svadd_x (pg, u8, u8);
+ svadd_x (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+ svadd_x (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+ svadd_x (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+ svadd_x (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+ svadd_x (pg, u8, 0);
+
+ svadd_x (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svfloat16_t'} } */
+ svadd_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svfloat16_t'} } */
+ svadd_x (pg, f16, f16);
+ svadd_x (pg, f16, 1);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+ svand_z (pg, u8); /* { dg-error {too few arguments to function 'svand_z'} } */
+ svand_z (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svand_z'} } */
+ svand_z (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svand_z', which expects 'svbool_t'} } */
+ svand_z (pg, pg, pg);
+ svand_z (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svand_z', which expects an SVE vector type} } */
+ svand_z (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+ svand_z (pg, u8, u8);
+ svand_z (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+ svand_z (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+ svand_z (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+ svand_z (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+ svand_z (pg, u8, 0);
+
+ svand_z (pg, pg, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svbool_t'} } */
+ svand_z (pg, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svand_z', but its 'svbool_t' form does not accept scalars} } */
+
+ svand_z (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svfloat16_t'} } */
+ svand_z (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svfloat16_t'} } */
+ svand_z (pg, f16, f16); /* { dg-error {'svand_z' has no form that takes 'svfloat16_t' arguments} } */
+ svand_z (pg, f16, 1); /* { dg-error {'svand_z' has no form that takes 'svfloat16_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+{
+ svcadd_x (pg, f32, f32); /* { dg-error {too few arguments to function 'svcadd_x'} } */
+ svcadd_x (pg, f32, f32, 90, 90); /* { dg-error {too many arguments to function 'svcadd_x'} } */
+ svcadd_x (f32, f32, f32, 90); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcadd_x', which expects 'svbool_t'} } */
+ svcadd_x (pg, pg, pg, 90); /* { dg-error {'svcadd_x' has no form that takes 'svbool_t' arguments} } */
+ svcadd_x (pg, s32, s32, 90); /* { dg-error {'svcadd_x' has no form that takes 'svint32_t' arguments} } */
+ svcadd_x (pg, 1, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcadd_x', which expects an SVE vector type} } */
+ svcadd_x (pg, f32, 1, 90); /* { dg-error {passing 'int' to argument 3 of 'svcadd_x', which expects an SVE vector type} } */
+ svcadd_x (pg, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcadd_x', but previous arguments had type 'svfloat32_t'} } */
+ svcadd_x (pg, f32, f32, s32); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+ svcadd_x (pg, f32, f32, i); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+ svcadd_x (pg, f32, f32, -90); /* { dg-error {passing -90 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+ svcadd_x (pg, f32, f32, 0); /* { dg-error {passing 0 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+ svcadd_x (pg, f32, f32, 1); /* { dg-error {passing 1 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+ svcadd_x (pg, f32, f32, 90);
+ svcadd_x (pg, f32, f32, 180); /* { dg-error {passing 180 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+ svcadd_x (pg, f32, f32, 270);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, int i, float f)
+{
+ svdupq_lane (u8); /* { dg-error {too few arguments to function 'svdupq_lane'} } */
+ svdupq_lane (u8, 0, 0); /* { dg-error {too many arguments to function 'svdupq_lane'} } */
+ svdupq_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdupq_lane', which expects an SVE vector type} } */
+ svdupq_lane (u8, 0);
+ svdupq_lane (u8, -1);
+ svdupq_lane (u8, i);
+ svdupq_lane (u8, f);
+ svdupq_lane (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svdupq_lane', which expects 'uint64_t'} } */
+ svdupq_lane (pg, 0); /* { dg-error {'svdupq_lane' has no form that takes 'svbool_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint64_t u64)
+{
+ svlsl_wide_u8_x (pg, u8, u8); /* { dg-error {incompatible type for argument 3 of 'svlsl_wide_u8_x'} } */
+ svlsl_wide_u8_x (pg, u8); /* { dg-error {too few arguments to function 'svlsl_wide_u8_x'} } */
+ svlsl_wide_u8_x (pg, u8, u64, u8); /* { dg-error {too many arguments to function 'svlsl_wide_u8_x'} } */
+ return svlsl_wide_s8_x (pg, s8, u64); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svuint64_t u64)
+{
+ svlsl_wide_x (pg, u8); /* { dg-error {too few arguments to function 'svlsl_wide_x'} } */
+ svlsl_wide_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svlsl_wide_x'} } */
+ svlsl_wide_x (u8, u8, u64); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svlsl_wide_x', which expects 'svbool_t'} } */
+ svlsl_wide_x (pg, 1, u64); /* { dg-error {passing 'int' to argument 2 of 'svlsl_wide_x', which expects an SVE vector type} } */
+ svlsl_wide_x (pg, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svlsl_wide_x', which expects 'svuint64_t'} } */
+ svlsl_wide_x (pg, u64, u64); /* { dg-error {'svlsl_wide_x' has no form that takes 'svuint64_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+ svfloat16_t f16)
+{
+ svtbl (u8); /* { dg-error {too few arguments to function 'svtbl'} } */
+ svtbl (u8, u8, u8); /* { dg-error {too many arguments to function 'svtbl'} } */
+ svtbl (pg, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (pg, u8); /* { dg-error {'svtbl' has no form that takes 'svbool_t' arguments} } */
+
+ svtbl (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svtbl', which expects an SVE vector type} } */
+ svtbl (u8, u8);
+ svtbl (u8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (u8, u16); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svuint8_t' and 'svuint16_t' respectively} } */
+ svtbl (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+ svtbl (s8, u8);
+ svtbl (s8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (s8, u16); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svint8_t' and 'svuint16_t' respectively} } */
+ svtbl (s8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (s8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+ svtbl (u16, u8); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svuint16_t' and 'svuint8_t' respectively} } */
+ svtbl (u16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (u16, u16);
+ svtbl (u16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (u16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+ svtbl (s16, u8); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svint16_t' and 'svuint8_t' respectively} } */
+ svtbl (s16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (s16, u16);
+ svtbl (s16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (s16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+ svtbl (f16, u8); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svfloat16_t' and 'svuint8_t' respectively} } */
+ svtbl (f16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (f16, u16);
+ svtbl (f16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+ svtbl (f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, int i, float f)
+{
+ svdup_lane (u8); /* { dg-error {too few arguments to function 'svdup_lane'} } */
+ svdup_lane (u8, 0, 0); /* { dg-error {too many arguments to function 'svdup_lane'} } */
+ svdup_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdup_lane', which expects an SVE vector type} } */
+ svdup_lane (u8, 0);
+ svdup_lane (u8, -1);
+ svdup_lane (u8, i);
+ svdup_lane (u8, f);
+ svdup_lane (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svdup_lane', which expects a scalar integer} } */
+ svdup_lane (pg, 0); /* { dg-error {'svdup_lane' has no form that takes 'svbool_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svint16_t s16, svuint16_t u16,
+ svfloat32_t f32, svint32_t s32, svuint32_t u32)
+{
+ svlsl_x (pg, s16); /* { dg-error {too few arguments to function 'svlsl_x'} } */
+ svlsl_x (pg, s16, u16, u16); /* { dg-error {too many arguments to function 'svlsl_x'} } */
+ svlsl_x (s32, s32, u32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svlsl_x', which expects 'svbool_t'} } */
+ svlsl_x (1, s32, u32); /* { dg-error {passing 'int' to argument 1 of 'svlsl_x', which expects 'svbool_t'} } */
+ svlsl_x (pg, pg, u16); /* { dg-error {'svlsl_x' has no form that takes 'svbool_t' arguments} } */
+ svlsl_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svlsl_x', which expects an SVE vector type} } */
+ svlsl_x (pg, s16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, s16, u16);
+ svlsl_x (pg, s16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, s16, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, s16, u32); /* { dg-error {arguments 2 and 3 of 'svlsl_x' must have the same element size, but the values passed here have type 'svint16_t' and 'svuint32_t' respectively} } */
+ svlsl_x (pg, s16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, s16, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, s16, 0);
+ svlsl_x (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, f16, u16); /* { dg-error {'svlsl_x' has no form that takes 'svfloat16_t' arguments} } */
+ svlsl_x (pg, f16, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+ svlsl_x (pg, f16, u32); /* { dg-error {'svlsl_x' has no form that takes 'svfloat16_t' arguments} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint32_t s32, svint64_t s64, int i)
+{
+ svclasta (pg, 1); /* { dg-error {too few arguments to function 'svclasta'} } */
+ svclasta (pg, 1, s32, 1); /* { dg-error {too many arguments to function 'svclasta'} } */
+ svclasta (1, 1, s32); /* { dg-error {passing 'int' to argument 1 of 'svclasta', which expects 'svbool_t'} } */
+ svclasta (pg, 1, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE vector type} } */
+ svclasta (pg, 1, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+ svclasta (pg, i, s32);
+ svclasta (pg, s32, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE vector type} } */
+ svclasta (pg, s32, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svclasta', but previous arguments had type 'svint32_t'} } */
+ svclasta (pg, pg, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+ svcmpeq (pg, u8); /* { dg-error {too few arguments to function 'svcmpeq'} } */
+ svcmpeq (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svcmpeq'} } */
+ svcmpeq (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcmpeq', which expects 'svbool_t'} } */
+ svcmpeq (pg, pg, pg); /* { dg-error {'svcmpeq' has no form that takes 'svbool_t' arguments} } */
+ svcmpeq (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq', which expects an SVE vector type} } */
+ svcmpeq (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+ svcmpeq (pg, u8, u8);
+ svcmpeq (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+ svcmpeq (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+ svcmpeq (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+ svcmpeq (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+ svcmpeq (pg, u8, 0);
+
+ svcmpeq (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svfloat16_t'} } */
+ svcmpeq (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svfloat16_t'} } */
+ svcmpeq (pg, f16, f16);
+ svcmpeq (pg, f16, 1);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+#include <stdbool.h>
+
+enum signed_enum { SA = -1, SB };
+enum unsigned_enum { UA, UB };
+
+void
+test (int8_t s8, int16_t s16, int32_t s32, int64_t s64,
+ uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64,
+ bool b, enum signed_enum se, enum unsigned_enum ue,
+ int *ptr, float f32, svbool_t pg, svint32_t vec)
+{
+ svwhilele_b8 (s32); /* { dg-error {too few arguments to function 'svwhilele_b8'} } */
+ svwhilele_b8 (s32, s32, s32); /* { dg-error {too many arguments to function 'svwhilele_b8'} } */
+
+ svwhilele_b8 (b, b);
+ svwhilele_b8 (se, se);
+ svwhilele_b8 (ue, ue);
+ svwhilele_b8 (s8, s8);
+ svwhilele_b8 (u8, u8);
+ svwhilele_b8 (s16, s16);
+ svwhilele_b8 (u16, u16);
+ svwhilele_b8 (ptr, ptr); /* { dg-error {passing 'int \*' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+ svwhilele_b8 (f32, f32); /* { dg-error {passing 'float' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+ svwhilele_b8 (pg, pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+ svwhilele_b8 (vec, vec); /* { dg-error {passing 'svint32_t' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+
+ svwhilele_b8 (s32, b);
+ svwhilele_b8 (s32, se);
+ svwhilele_b8 (s32, ue); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (s32, s8);
+ svwhilele_b8 (s32, u8);
+ svwhilele_b8 (s32, s16);
+ svwhilele_b8 (s32, u16);
+
+ svwhilele_b8 (u32, b); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u32, se); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u32, ue);
+ svwhilele_b8 (u32, s8); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u32, u8); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u32, s16); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u32, u16); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+
+ svwhilele_b8 (s32, s32);
+ svwhilele_b8 (s32, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (s32, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'int64_t'} } */
+ svwhilele_b8 (s32, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint64_t'} } */
+
+ svwhilele_b8 (u32, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u32, u32);
+ svwhilele_b8 (u32, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int64_t'} } */
+ svwhilele_b8 (u32, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'uint64_t'} } */
+
+ svwhilele_b8 (s64, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (s64, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (s64, s64);
+ svwhilele_b8 (s64, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'uint64_t'} } */
+
+ svwhilele_b8 (u64, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u64, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (u64, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'int64_t'} } */
+ svwhilele_b8 (u64, u64);
+
+ svwhilele_b8 (0, s32);
+ svwhilele_b8 (0, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (0, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'int64_t'} } */
+ svwhilele_b8 (0, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint64_t'} } */
+
+ svwhilele_b8 (s32, 0);
+ svwhilele_b8 (u32, 0); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (s64, 0); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (u64, 0); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'int32_t'} } */
+
+ svwhilele_b8 (0U, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+ svwhilele_b8 (0U, u32);
+ svwhilele_b8 (0U, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int64_t'} } */
+ svwhilele_b8 (0U, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'uint64_t'} } */
+
+ svwhilele_b8 (s32, 0U); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (u32, 0U);
+ svwhilele_b8 (s64, 0U); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'uint32_t'} } */
+ svwhilele_b8 (u64, 0U); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'uint32_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint64_t s64, svuint64_t u64,
+ svfloat32_t f32, svfloat64_t f64, unsigned int x)
+{
+ svcmpeq_wide (pg, s8); /* { dg-error {too few arguments to function 'svcmpeq_wide'} } */
+ svcmpeq_wide (pg, s8, s64, s8); /* { dg-error {too many arguments to function 'svcmpeq_wide'} } */
+ svcmpeq_wide (s8, s8, s64); /* { dg-error {passing 'svint8_t' to argument 1 of 'svcmpeq_wide', which expects 'svbool_t'} } */
+ svcmpeq_wide (pg, 0, s64); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq_wide', which expects an SVE vector type} } */
+ svcmpeq_wide (pg, s8, 0);
+ svcmpeq_wide (pg, s8, x);
+ svcmpeq_wide (pg, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+ svcmpeq_wide (pg, s8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+ svcmpeq_wide (pg, s8, s64);
+ svcmpeq_wide (pg, s8, u64); /* { dg-error {arguments 2 and 3 of 'svcmpeq_wide' must have the same signedness, but the values passed here have type 'svint8_t' and 'svuint64_t' respectively} } */
+ svcmpeq_wide (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+ svcmpeq_wide (pg, u8, u64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svuint8_t' arguments} } */
+ svcmpeq_wide (pg, s64, s64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svint64_t' arguments} } */
+ svcmpeq_wide (pg, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+ svcmpeq_wide (pg, f32, f64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svfloat32_t' arguments} } */
+ svcmpeq_wide (pg, f64, f64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svfloat64_t' arguments} } */
+ svcmpeq_wide (pg, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (enum svpattern pat, int i)
+{
+ svcntb_pat (pat); /* { dg-error {argument 1 of 'svcntb_pat' must be an integer constant expression} } */
+ svcntb_pat (i); /* { dg-error {argument 1 of 'svcntb_pat' must be an integer constant expression} } */
+ svcntb_pat ((enum svpattern) -1); /* { dg-error {passing 4294967295 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 0);
+ svcntb_pat ((enum svpattern) 1);
+ svcntb_pat ((enum svpattern) 2);
+ svcntb_pat ((enum svpattern) 3);
+ svcntb_pat ((enum svpattern) 4);
+ svcntb_pat ((enum svpattern) 5);
+ svcntb_pat ((enum svpattern) 6);
+ svcntb_pat ((enum svpattern) 7);
+ svcntb_pat ((enum svpattern) 8);
+ svcntb_pat ((enum svpattern) 9);
+ svcntb_pat ((enum svpattern) 10);
+ svcntb_pat ((enum svpattern) 11);
+ svcntb_pat ((enum svpattern) 12);
+ svcntb_pat ((enum svpattern) 13);
+ svcntb_pat ((enum svpattern) 14); /* { dg-error {passing 14 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 15); /* { dg-error {passing 15 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 16); /* { dg-error {passing 16 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 17); /* { dg-error {passing 17 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 18); /* { dg-error {passing 18 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 19); /* { dg-error {passing 19 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 20); /* { dg-error {passing 20 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 21); /* { dg-error {passing 21 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 22); /* { dg-error {passing 22 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 23); /* { dg-error {passing 23 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 24); /* { dg-error {passing 24 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 25); /* { dg-error {passing 25 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 26); /* { dg-error {passing 26 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 27); /* { dg-error {passing 27 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 28); /* { dg-error {passing 28 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+ svcntb_pat ((enum svpattern) 29);
+ svcntb_pat ((enum svpattern) 30);
+ svcntb_pat ((enum svpattern) 31);
+ svcntb_pat ((enum svpattern) 32); /* { dg-error {passing 32 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint32_t u32, svuint32x2_t u32x2)
+{
+ svlen (); /* { dg-error {too few arguments to function 'svlen'} } */
+ svlen (u32, u32); /* { dg-error {too many arguments to function 'svlen'} } */
+ svlen (0); /* { dg-error {passing 'int' to argument 1 of 'svlen', which expects an SVE vector type} } */
+ svlen (pg); /* { dg-error {'svlen' has no form that takes 'svbool_t' arguments} } */
+ svlen (u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 1 of 'svlen', which expects a single SVE vector rather than a tuple} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+ svuint8x2_t u8x2, int x)
+{
+ *ptr = svcreate2 (u8); /* { dg-error {too few arguments to function 'svcreate2'} } */
+ *ptr = svcreate2 (u8, u8, u8); /* { dg-error {too many arguments to function 'svcreate2'} } */
+ *ptr = svcreate2 (u8x2, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 1 of 'svcreate2', which expects a single SVE vector rather than a tuple} } */
+ *ptr = svcreate2 (u8, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+ *ptr = svcreate2 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+ *ptr = svcreate2 (u8, x); /* { dg-error {passing 'int' to argument 2 of 'svcreate2', which expects an SVE vector type} } */
+ *ptr = svcreate2 (x, u8); /* { dg-error {passing 'int' to argument 1 of 'svcreate2', which expects an SVE vector type} } */
+ *ptr = svcreate2 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svcreate2', but previous arguments had type 'svbool_t'} } */
+ *ptr = svcreate2 (pg, pg); /* { dg-error {'svcreate2' has no form that takes 'svbool_t' arguments} } */
+ *ptr = svcreate2 (u8, u8);
+ *ptr = svcreate2 (f64, f64); /* { dg-error {incompatible types when assigning to type 'svuint8x2_t' from type 'svfloat64x2_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+ svuint8x2_t u8x2, int x)
+{
+ *ptr = svcreate2_u8 (u8); /* { dg-error {too few arguments to function 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (u8, u8, u8); /* { dg-error {too many arguments to function 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (u8x2, u8x2); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+ /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} "" { target *-*-* } .-1 } */
+ *ptr = svcreate2_u8 (u8, f64); /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (u8, pg); /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (u8, x); /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (x, u8); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (pg, u8); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+ *ptr = svcreate2_u8 (pg, pg); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+ /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} "" { target *-*-* } .-1 } */
+ *ptr = svcreate2_u8 (u8, u8);
+ *ptr = svcreate2_f64 (f64, f64); /* { dg-error {incompatible types when assigning to type 'svuint8x2_t' from type 'svfloat64x2_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+ svfloat16x3_t f16x3, int x)
+{
+ *ptr = svcreate3 (f16); /* { dg-error {too few arguments to function 'svcreate3'} } */
+ *ptr = svcreate3 (f16, f16); /* { dg-error {too few arguments to function 'svcreate3'} } */
+ *ptr = svcreate3 (f16, f16, f16, f16); /* { dg-error {too many arguments to function 'svcreate3'} } */
+ *ptr = svcreate3 (f16x3, f16x3, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 1 of 'svcreate3', which expects a single SVE vector rather than a tuple} } */
+ *ptr = svcreate3 (f16, f16, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+ *ptr = svcreate3 (f16, pg, f16); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+ *ptr = svcreate3 (f16, x, f16); /* { dg-error {passing 'int' to argument 2 of 'svcreate3', which expects an SVE vector type} } */
+ *ptr = svcreate3 (x, f16, f16); /* { dg-error {passing 'int' to argument 1 of 'svcreate3', which expects an SVE vector type} } */
+ *ptr = svcreate3 (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svcreate3', but previous arguments had type 'svbool_t'} } */
+ *ptr = svcreate3 (pg, pg, pg); /* { dg-error {'svcreate3' has no form that takes 'svbool_t' arguments} } */
+ *ptr = svcreate3 (f16, f16, f16);
+ *ptr = svcreate3 (f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svfloat16x3_t' from type 'svfloat64x3_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+ svfloat16x3_t f16x3, int x)
+{
+ *ptr = svcreate3_f16 (f16); /* { dg-error {too few arguments to function 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (f16, f16); /* { dg-error {too few arguments to function 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (f16, f16, f16, f16); /* { dg-error {too many arguments to function 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (f16x3, f16x3, f16x3); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+ /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} "" { target *-*-* } .-1 } */
+ /* { dg-error {incompatible type for argument 3 of 'svcreate3_f16'} "" { target *-*-* } .-2 } */
+ *ptr = svcreate3_f16 (f16, f16, f64); /* { dg-error {incompatible type for argument 3 of 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (f16, pg, f16); /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (f16, x, f16); /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (x, f16, f16); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (pg, f16, f16); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+ *ptr = svcreate3_f16 (pg, pg, pg); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+ /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} "" { target *-*-* } .-1 } */
+ /* { dg-error {incompatible type for argument 3 of 'svcreate3_f16'} "" { target *-*-* } .-2 } */
+ *ptr = svcreate3_f16 (f16, f16, f16);
+ *ptr = svcreate3_f64 (f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svfloat16x3_t' from type 'svfloat64x3_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+ svint32x4_t s32x4, int x)
+{
+ *ptr = svcreate4 (s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+ *ptr = svcreate4 (s32, s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+ *ptr = svcreate4 (s32, s32, s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+ *ptr = svcreate4 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function 'svcreate4'} } */
+ *ptr = svcreate4 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 1 of 'svcreate4', which expects a single SVE vector rather than a tuple} } */
+ *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+ *ptr = svcreate4 (s32, s32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+ *ptr = svcreate4 (s32, x, s32, s32); /* { dg-error {passing 'int' to argument 2 of 'svcreate4', which expects an SVE vector type} } */
+ *ptr = svcreate4 (x, s32, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svcreate4', which expects an SVE vector type} } */
+ *ptr = svcreate4 (pg, s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcreate4', but previous arguments had type 'svbool_t'} } */
+ *ptr = svcreate4 (pg, pg, pg, pg); /* { dg-error {'svcreate4' has no form that takes 'svbool_t' arguments} } */
+ *ptr = svcreate4 (s32, s32, s32, s32);
+ *ptr = svcreate4 (f64, f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svint32x4_t' from type 'svfloat64x4_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+ svint32x4_t s32x4, int x)
+{
+ *ptr = svcreate4_s32 (s32); /* { dg-error {too few arguments to function 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (s32, s32); /* { dg-error {too few arguments to function 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (s32, s32, s32); /* { dg-error {too few arguments to function 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+ /* { dg-error {incompatible type for argument 2 of 'svcreate4_s32'} "" { target *-*-* } .-1 } */
+ /* { dg-error {incompatible type for argument 3 of 'svcreate4_s32'} "" { target *-*-* } .-2 } */
+ /* { dg-error {incompatible type for argument 4 of 'svcreate4_s32'} "" { target *-*-* } .-3 } */
+ *ptr = svcreate4_s32 (s32, s32, s32, f64); /* { dg-error {incompatible type for argument 4 of 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (s32, s32, pg, s32); /* { dg-error {incompatible type for argument 3 of 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (s32, x, s32, s32); /* { dg-error {incompatible type for argument 2 of 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (x, s32, s32, s32); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (pg, s32, s32, s32); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+ *ptr = svcreate4_s32 (pg, pg, pg, pg); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+ /* { dg-error {incompatible type for argument 2 of 'svcreate4_s32'} "" { target *-*-* } .-1 } */
+ /* { dg-error {incompatible type for argument 3 of 'svcreate4_s32'} "" { target *-*-* } .-2 } */
+ /* { dg-error {incompatible type for argument 4 of 'svcreate4_s32'} "" { target *-*-* } .-3 } */
+ *ptr = svcreate4_s32 (s32, s32, s32, s32);
+ *ptr = svcreate4_f64 (f64, f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svint32x4_t' from type 'svfloat64x4_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ svfloat16_t f16, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, int i)
+{
+ svext (pg, pg, 0); /* { dg-error {'svext' has no form that takes 'svbool_t' arguments} } */
+ svext (s8, s8, i); /* { dg-error {argument 3 of 'svext' must be an integer constant expression} } */
+
+ svext (s8, s8, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+ svext (s8, s8, 0);
+ svext (s8, s8, 255);
+ svext (s8, s8, 256); /* { dg-error {passing 256 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+
+ svext (u8, u8, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+ svext (u8, u8, 0);
+ svext (u8, u8, 255);
+ svext (u8, u8, 256); /* { dg-error {passing 256 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+
+ svext (s16, s16, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+ svext (s16, s16, 0);
+ svext (s16, s16, 127);
+ svext (s16, s16, 128); /* { dg-error {passing 128 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+
+ svext (u16, u16, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+ svext (u16, u16, 0);
+ svext (u16, u16, 127);
+ svext (u16, u16, 128); /* { dg-error {passing 128 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+
+ svext (f16, f16, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+ svext (f16, f16, 0);
+ svext (f16, f16, 127);
+ svext (f16, f16, 128); /* { dg-error {passing 128 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+
+ svext (s32, s32, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+ svext (s32, s32, 0);
+ svext (s32, s32, 63);
+ svext (s32, s32, 64); /* { dg-error {passing 64 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+
+ svext (u32, u32, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+ svext (u32, u32, 0);
+ svext (u32, u32, 63);
+ svext (u32, u32, 64); /* { dg-error {passing 64 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+
+ svext (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+ svext (f32, f32, 0);
+ svext (f32, f32, 63);
+ svext (f32, f32, 64); /* { dg-error {passing 64 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+
+ svext (s64, s64, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+ svext (s64, s64, 0);
+ svext (s64, s64, 31);
+ svext (s64, s64, 32); /* { dg-error {passing 32 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+
+ svext (u64, u64, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+ svext (u64, u64, 0);
+ svext (u64, u64, 31);
+ svext (u64, u64, 32); /* { dg-error {passing 32 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+
+ svext (f64, f64, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+ svext (f64, f64, 0);
+ svext (f64, f64, 31);
+ svext (f64, f64, 32); /* { dg-error {passing 32 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, int i, float f, double d, void *ptr, svfloat32_t f32,
+ svint32_t i32)
+{
+ svadda (pg, f); /* { dg-error {too few arguments to function 'svadda'} } */
+ svadda (pg, f, f32, f32); /* { dg-error {too many arguments to function 'svadda'} } */
+ svadda (f32, f, f32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadda', which expects 'svbool_t'} } */
+ svadda (pg, i, f32);
+ svadda (pg, f, f32);
+ svadda (pg, d, f32);
+ svadda (pg, ptr, f32); /* { dg-error {incompatible type for argument 2 of 'svadda_f32'} } */
+ svadda (pg, pg, f32); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadda', which expects a scalar element} } */
+ svadda (pg, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadda', which expects a scalar element} } */
+ svadda (pg, f, f); /* { dg-error {passing 'float' to argument 3 of 'svadda', which expects an SVE vector type} } */
+ svadda (pg, i, i32); /* { dg-error {'svadda' has no form that takes 'svint32_t' arguments} } */
+ svadda (pg, i, i); /* { dg-error {passing 'int' to argument 3 of 'svadda', which expects an SVE vector type} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+int svadd_n_u8_x; /* { dg-message "note: previous declaration of 'svadd_n_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svadd_n_u8_x' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+int svadd_n_u8_x = 1; /* { dg-message "note: previous definition of 'svadd_n_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svadd_n_u8_x' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+extern __SVInt8_t svadd_u8_x (__SVBool_t, __SVInt8_t, __SVInt8_t); /* { dg-message "note: previous declaration of 'svadd_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting types for 'svadd_u8_x'} } */
--- /dev/null
+/* { dg-do compile } */
+
+/* Although somewhat suspect, this isn't actively wrong, and doesn't need
+ to be diagnosed. Any attempt to call the function before including
+ arm_sve.h will lead to a link failure. (Same for taking its address,
+ etc.) */
+extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t);
+
+#pragma GCC aarch64 "arm_sve.h"
--- /dev/null
+/* { dg-do compile } */
+
+/* There's no requirement to diagnose this. In particular, arm_sve.h
+ is allowed to use macros to implement the functions, and defining
+ a macro that matches an existing symbol would not be diagnosed.
+
+ At the moment this works like other built-ins in the sense that the
+ explicit definition "wins". This isn't supported behavior though. */
+__SVUint8_t
+svadd_u8_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
+{
+ return x;
+}
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svuint8_t
+f (svbool_t pg, svuint8_t x, svuint8_t y)
+{
+ return svadd_u8_x (pg, x, y);
+}
--- /dev/null
+/* { dg-do compile } */
+
+typedef int svadd_u8_x; /* { dg-message "note: previous declaration of 'svadd_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svadd_u8_x' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8 = svget2 (u8x2); /* { dg-error {too few arguments to function 'svget2'} } */
+ u8 = svget2 (u8x2, 1, 2); /* { dg-error {too many arguments to function 'svget2'} } */
+ u8 = svget2 (u8, 0); /* { dg-error {passing single vector 'svuint8_t' to argument 1 of 'svget2', which expects a tuple of 2 vectors} } */
+ u8 = svget2 (u8x3, 0); /* { dg-error {passing 'svuint8x3_t' to argument 1 of 'svget2', which expects a tuple of 2 vectors} } */
+ u8 = svget2 (pg, 0); /* { dg-error {passing 'svbool_t' to argument 1 of 'svget2', which expects a tuple of 2 vectors} } */
+ u8 = svget2 (u8x2, x); /* { dg-error {argument 2 of 'svget2' must be an integer constant expression} } */
+ u8 = svget2 (u8x2, 0);
+ f64 = svget2 (u8x2, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8_t'} } */
+ u8 = svget2 (u8x2, 1);
+ u8 = svget2 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2 (u8x2, one); /* { dg-error {argument 2 of 'svget2' must be an integer constant expression} } */
+ u8 = svget2 (u8x2, 3 - 2);
+ u8 = svget2 (u8x2, 1.0);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+ svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8 = svget2_u8 (u8x2); /* { dg-error {too few arguments to function 'svget2_u8'} } */
+ u8 = svget2_u8 (u8x2, 1, 2); /* { dg-error {too many arguments to function 'svget2_u8'} } */
+ u8 = svget2_u8 (u8, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+ u8 = svget2_u8 (s8x2, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+ u8 = svget2_u8 (u8x3, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+ u8 = svget2_u8 (pg, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+ u8 = svget2_u8 (u8x2, x); /* { dg-error {argument 2 of 'svget2_u8' must be an integer constant expression} } */
+ u8 = svget2_u8 (u8x2, 0);
+ f64 = svget2_u8 (u8x2, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8_t'} } */
+ u8 = svget2_u8 (u8x2, 1);
+ u8 = svget2_u8 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+ u8 = svget2_u8 (u8x2, one); /* { dg-error {argument 2 of 'svget2_u8' must be an integer constant expression} } */
+ u8 = svget2_u8 (u8x2, 3 - 2);
+ u8 = svget2_u8 (u8x2, 1.0);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+ int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16 = svget3 (f16x3); /* { dg-error {too few arguments to function 'svget3'} } */
+ f16 = svget3 (f16x3, 1, 2); /* { dg-error {too many arguments to function 'svget3'} } */
+ f16 = svget3 (f16, 0); /* { dg-error {passing single vector 'svfloat16_t' to argument 1 of 'svget3', which expects a tuple of 3 vectors} } */
+ f16 = svget3 (f16x4, 0); /* { dg-error {passing 'svfloat16x4_t' to argument 1 of 'svget3', which expects a tuple of 3 vectors} } */
+ f16 = svget3 (pg, 0); /* { dg-error {passing 'svbool_t' to argument 1 of 'svget3', which expects a tuple of 3 vectors} } */
+ f16 = svget3 (f16x3, x); /* { dg-error {argument 2 of 'svget3' must be an integer constant expression} } */
+ f16 = svget3 (f16x3, 0);
+ f64 = svget3 (f16x3, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16_t'} } */
+ f16 = svget3 (f16x3, 1);
+ f16 = svget3 (f16x3, 2);
+ f16 = svget3 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3 (f16x3, one); /* { dg-error {argument 2 of 'svget3' must be an integer constant expression} } */
+ f16 = svget3 (f16x3, 3 - 2);
+ f16 = svget3 (f16x3, 1.0);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat32x3_t f32x3,
+ svfloat16x4_t f16x4, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16 = svget3_f16 (f16x3); /* { dg-error {too few arguments to function 'svget3_f16'} } */
+ f16 = svget3_f16 (f16x3, 1, 2); /* { dg-error {too many arguments to function 'svget3_f16'} } */
+ f16 = svget3_f16 (f16, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+ f16 = svget3_f16 (f32x3, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+ f16 = svget3_f16 (f16x4, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+ f16 = svget3_f16 (pg, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+ f16 = svget3_f16 (f16x3, x); /* { dg-error {argument 2 of 'svget3_f16' must be an integer constant expression} } */
+ f16 = svget3_f16 (f16x3, 0);
+ f64 = svget3_f16 (f16x3, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16_t'} } */
+ f16 = svget3_f16 (f16x3, 1);
+ f16 = svget3_f16 (f16x3, 2);
+ f16 = svget3_f16 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+ f16 = svget3_f16 (f16x3, one); /* { dg-error {argument 2 of 'svget3_f16' must be an integer constant expression} } */
+ f16 = svget3_f16 (f16x3, 3 - 2);
+ f16 = svget3_f16 (f16x3, 1.0);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32 = svget4 (s32x4); /* { dg-error {too few arguments to function 'svget4'} } */
+ s32 = svget4 (s32x4, 1, 2); /* { dg-error {too many arguments to function 'svget4'} } */
+ s32 = svget4 (s32, 0); /* { dg-error {passing single vector 'svint32_t' to argument 1 of 'svget4', which expects a tuple of 4 vectors} } */
+ s32 = svget4 (s32x2, 0); /* { dg-error {passing 'svint32x2_t' to argument 1 of 'svget4', which expects a tuple of 4 vectors} } */
+ s32 = svget4 (pg, 0); /* { dg-error {passing 'svbool_t' to argument 1 of 'svget4', which expects a tuple of 4 vectors} } */
+ s32 = svget4 (s32x4, x); /* { dg-error {argument 2 of 'svget4' must be an integer constant expression} } */
+ s32 = svget4 (s32x4, 0);
+ f64 = svget4 (s32x4, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32_t'} } */
+ s32 = svget4 (s32x4, 1);
+ s32 = svget4 (s32x4, 2);
+ s32 = svget4 (s32x4, 3);
+ s32 = svget4 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4 (s32x4, one); /* { dg-error {argument 2 of 'svget4' must be an integer constant expression} } */
+ s32 = svget4 (s32x4, 3 - 2);
+ s32 = svget4 (s32x4, 1.0);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+ svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32 = svget4_s32 (s32x4); /* { dg-error {too few arguments to function 'svget4_s32'} } */
+ s32 = svget4_s32 (s32x4, 1, 2); /* { dg-error {too many arguments to function 'svget4_s32'} } */
+ s32 = svget4_s32 (s32, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+ s32 = svget4_s32 (f32x4, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+ s32 = svget4_s32 (s32x2, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+ s32 = svget4_s32 (pg, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+ s32 = svget4_s32 (s32x4, x); /* { dg-error {argument 2 of 'svget4_s32' must be an integer constant expression} } */
+ s32 = svget4_s32 (s32x4, 0);
+ f64 = svget4_s32 (s32x4, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32_t'} } */
+ s32 = svget4_s32 (s32x4, 1);
+ s32 = svget4_s32 (s32x4, 2);
+ s32 = svget4_s32 (s32x4, 3);
+ s32 = svget4_s32 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+ s32 = svget4_s32 (s32x4, one); /* { dg-error {argument 2 of 'svget4_s32' must be an integer constant expression} } */
+ s32 = svget4_s32 (s32x4, 3 - 2);
+ s32 = svget4_s32 (s32x4, 1.0);
+
+ return f64;
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f, int i)
+{
+ svqincb (sw); /* { dg-error {too few arguments to function 'svqincb'} } */
+ svqincb (sw, 1, 1); /* { dg-error {too many arguments to function 'svqincb'} } */
+
+ svqincb (pg, 1); /* { dg-error {'svqincb' has no form that takes 'svbool_t' arguments} } */
+ svqincb (s8, 1); /* { dg-error {'svqincb' has no form that takes 'svint8_t' arguments} } */
+ svqincb (u8, 1); /* { dg-error {'svqincb' has no form that takes 'svuint8_t' arguments} } */
+ svqincb (s16, 1); /* { dg-error {'svqincb' has no form that takes 'svint16_t' arguments} } */
+ svqincb (u16, 1); /* { dg-error {'svqincb' has no form that takes 'svuint16_t' arguments} } */
+ svqincb (s32, 1); /* { dg-error {'svqincb' has no form that takes 'svint32_t' arguments} } */
+ svqincb (u32, 1); /* { dg-error {'svqincb' has no form that takes 'svuint32_t' arguments} } */
+ svqincb (s64, 1); /* { dg-error {'svqincb' has no form that takes 'svint64_t' arguments} } */
+ svqincb (u64, 1); /* { dg-error {'svqincb' has no form that takes 'svuint64_t' arguments} } */
+ svqincb (sh, 1);
+ svqincb (sw, 1);
+ svqincb (sd, 1);
+ svqincb (uh, 1);
+ svqincb (uw, 1);
+ svqincb (ud, 1);
+ svqincb (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincb', which expects a 32-bit or 64-bit integer type} } */
+ svqincb (ud, i); /* { dg-error {argument 2 of 'svqincb' must be an integer constant expression} } */
+
+ svqincb (sw, -1); /* { dg-error {passing -1 to argument 2 of 'svqincb', which expects a value in the range \[1, 16\]} } */
+ svqincb (sw, 0); /* { dg-error {passing 0 to argument 2 of 'svqincb', which expects a value in the range \[1, 16\]} } */
+ svqincb (sw, 1);
+ svqincb (sw, 2);
+ svqincb (sw, 16);
+ svqincb (sw, 17); /* { dg-error {passing 17 to argument 2 of 'svqincb', which expects a value in the range \[1, 16\]} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (int32_t sw, int i)
+{
+ svqincb_n_s32 (sw, -1); /* { dg-error {passing -1 to argument 2 of 'svqincb_n_s32', which expects a value in the range \[1, 16\]} } */
+ svqincb_n_s32 (sw, 0); /* { dg-error {passing 0 to argument 2 of 'svqincb_n_s32', which expects a value in the range \[1, 16\]} } */
+ svqincb_n_s32 (sw, 1);
+ svqincb_n_s32 (sw, 2);
+ svqincb_n_s32 (sw, 16);
+ svqincb_n_s32 (sw, 17); /* { dg-error {passing 17 to argument 2 of 'svqincb_n_s32', which expects a value in the range \[1, 16\]} } */
+ svqincb_n_s32 (sw, i); /* { dg-error {argument 2 of 'svqincb_n_s32' must be an integer constant expression} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f)
+{
+ svqinch (pg, 1); /* { dg-error {'svqinch' has no form that takes 'svbool_t' arguments} } */
+ svqinch (s8, 1); /* { dg-error {'svqinch' has no form that takes 'svint8_t' arguments} } */
+ svqinch (u8, 1); /* { dg-error {'svqinch' has no form that takes 'svuint8_t' arguments} } */
+ svqinch (s16, 1);
+ svqinch (u16, 1);
+ svqinch (s32, 1); /* { dg-error {'svqinch' has no form that takes 'svint32_t' arguments} } */
+ svqinch (u32, 1); /* { dg-error {'svqinch' has no form that takes 'svuint32_t' arguments} } */
+ svqinch (s64, 1); /* { dg-error {'svqinch' has no form that takes 'svint64_t' arguments} } */
+ svqinch (u64, 1); /* { dg-error {'svqinch' has no form that takes 'svuint64_t' arguments} } */
+ svqinch (sh, 1);
+ svqinch (sw, 1);
+ svqinch (sd, 1);
+ svqinch (uh, 1);
+ svqinch (uw, 1);
+ svqinch (ud, 1);
+ svqinch (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqinch', which expects a 32-bit or 64-bit integer type} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f)
+{
+ svqincw (pg, 1); /* { dg-error {'svqincw' has no form that takes 'svbool_t' arguments} } */
+ svqincw (s8, 1); /* { dg-error {'svqincw' has no form that takes 'svint8_t' arguments} } */
+ svqincw (u8, 1); /* { dg-error {'svqincw' has no form that takes 'svuint8_t' arguments} } */
+ svqincw (s16, 1); /* { dg-error {'svqincw' has no form that takes 'svint16_t' arguments} } */
+ svqincw (u16, 1); /* { dg-error {'svqincw' has no form that takes 'svuint16_t' arguments} } */
+ svqincw (s32, 1);
+ svqincw (u32, 1);
+ svqincw (s64, 1); /* { dg-error {'svqincw' has no form that takes 'svint64_t' arguments} } */
+ svqincw (u64, 1); /* { dg-error {'svqincw' has no form that takes 'svuint64_t' arguments} } */
+ svqincw (sh, 1);
+ svqincw (sw, 1);
+ svqincw (sd, 1);
+ svqincw (uh, 1);
+ svqincw (uw, 1);
+ svqincw (ud, 1);
+ svqincw (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincw', which expects a 32-bit or 64-bit integer type} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f)
+{
+ svqincd (pg, 1); /* { dg-error {'svqincd' has no form that takes 'svbool_t' arguments} } */
+ svqincd (s8, 1); /* { dg-error {'svqincd' has no form that takes 'svint8_t' arguments} } */
+ svqincd (u8, 1); /* { dg-error {'svqincd' has no form that takes 'svuint8_t' arguments} } */
+ svqincd (s16, 1); /* { dg-error {'svqincd' has no form that takes 'svint16_t' arguments} } */
+ svqincd (u16, 1); /* { dg-error {'svqincd' has no form that takes 'svuint16_t' arguments} } */
+ svqincd (s32, 1); /* { dg-error {'svqincd' has no form that takes 'svint32_t' arguments} } */
+ svqincd (u32, 1); /* { dg-error {'svqincd' has no form that takes 'svuint32_t' arguments} } */
+ svqincd (s64, 1);
+ svqincd (u64, 1);
+ svqincd (sh, 1);
+ svqincd (sw, 1);
+ svqincd (sd, 1);
+ svqincd (uh, 1);
+ svqincd (uw, 1);
+ svqincd (ud, 1);
+ svqincd (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincd', which expects a 32-bit or 64-bit integer type} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (enum svpattern pat, svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f, int i)
+{
+ svqincb_pat (sw, pat); /* { dg-error {too few arguments to function 'svqincb_pat'} } */
+ svqincb_pat (sw, pat, 1, 1); /* { dg-error {too many arguments to function 'svqincb_pat'} } */
+
+ svqincb_pat (pg, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svbool_t' arguments} } */
+ svqincb_pat (s8, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint8_t' arguments} } */
+ svqincb_pat (u8, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint8_t' arguments} } */
+ svqincb_pat (s16, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint16_t' arguments} } */
+ svqincb_pat (u16, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint16_t' arguments} } */
+ svqincb_pat (s32, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint32_t' arguments} } */
+ svqincb_pat (u32, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint32_t' arguments} } */
+ svqincb_pat (s64, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint64_t' arguments} } */
+ svqincb_pat (u64, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint64_t' arguments} } */
+ svqincb_pat (sh, SV_ALL, 1);
+ svqincb_pat (sw, SV_ALL, 1);
+ svqincb_pat (sd, SV_ALL, 1);
+ svqincb_pat (uh, SV_ALL, 1);
+ svqincb_pat (uw, SV_ALL, 1);
+ svqincb_pat (ud, SV_ALL, 1);
+ svqincb_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincb_pat', which expects a 32-bit or 64-bit integer type} } */
+
+ svqincb_pat (sw, pat, 1); /* { dg-error {argument 2 of 'svqincb_pat' must be an integer constant expression} } */
+ svqincb_pat (sw, i, 1); /* { dg-error {argument 2 of 'svqincb_pat' must be an integer constant expression} } */
+ svqincb_pat (sw, (enum svpattern) -1, 1); /* { dg-error {passing 4294967295 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+ svqincb_pat (sw, (enum svpattern) 0, 1);
+ svqincb_pat (sw, (enum svpattern) 13, 1);
+ svqincb_pat (sw, (enum svpattern) 14, 1); /* { dg-error {passing 14 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+ svqincb_pat (sw, (enum svpattern) 28, 1); /* { dg-error {passing 28 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+ svqincb_pat (sw, (enum svpattern) 29, 1);
+ svqincb_pat (sw, (enum svpattern) 31, 1);
+ svqincb_pat (sw, (enum svpattern) 32, 1); /* { dg-error {passing 32 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+
+ svqincb_pat (sw, SV_POW2, -1); /* { dg-error {passing -1 to argument 3 of 'svqincb_pat', which expects a value in the range \[1, 16\]} } */
+ svqincb_pat (sw, SV_POW2, 0); /* { dg-error {passing 0 to argument 3 of 'svqincb_pat', which expects a value in the range \[1, 16\]} } */
+ svqincb_pat (sw, SV_POW2, 1);
+ svqincb_pat (sw, SV_POW2, 2);
+ svqincb_pat (sw, SV_POW2, 16);
+ svqincb_pat (sw, SV_POW2, 17); /* { dg-error {passing 17 to argument 3 of 'svqincb_pat', which expects a value in the range \[1, 16\]} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (int32_t sw, enum svpattern pat, int i)
+{
+ svqincb_pat_n_s32 (sw, pat, 1); /* { dg-error {argument 2 of 'svqincb_pat_n_s32' must be an integer constant expression} } */
+ svqincb_pat_n_s32 (sw, i, 1); /* { dg-error {argument 2 of 'svqincb_pat_n_s32' must be an integer constant expression} } */
+ svqincb_pat_n_s32 (sw, (enum svpattern) -1, 1); /* { dg-error {passing 4294967295 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+ svqincb_pat_n_s32 (sw, (enum svpattern) 0, 1);
+ svqincb_pat_n_s32 (sw, (enum svpattern) 13, 1);
+ svqincb_pat_n_s32 (sw, (enum svpattern) 14, 1); /* { dg-error {passing 14 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+ svqincb_pat_n_s32 (sw, (enum svpattern) 28, 1); /* { dg-error {passing 28 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+ svqincb_pat_n_s32 (sw, (enum svpattern) 29, 1);
+ svqincb_pat_n_s32 (sw, (enum svpattern) 31, 1);
+ svqincb_pat_n_s32 (sw, (enum svpattern) 32, 1); /* { dg-error {passing 32 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+
+ svqincb_pat_n_s32 (sw, SV_POW2, -1); /* { dg-error {passing -1 to argument 3 of 'svqincb_pat_n_s32', which expects a value in the range \[1, 16\]} } */
+ svqincb_pat_n_s32 (sw, SV_POW2, 0); /* { dg-error {passing 0 to argument 3 of 'svqincb_pat_n_s32', which expects a value in the range \[1, 16\]} } */
+ svqincb_pat_n_s32 (sw, SV_POW2, 1);
+ svqincb_pat_n_s32 (sw, SV_POW2, 2);
+ svqincb_pat_n_s32 (sw, SV_POW2, 16);
+ svqincb_pat_n_s32 (sw, SV_POW2, 17); /* { dg-error {passing 17 to argument 3 of 'svqincb_pat_n_s32', which expects a value in the range \[1, 16\]} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f)
+{
+ svqinch_pat (pg, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svbool_t' arguments} } */
+ svqinch_pat (s8, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svint8_t' arguments} } */
+ svqinch_pat (u8, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svuint8_t' arguments} } */
+ svqinch_pat (s16, SV_ALL, 1);
+ svqinch_pat (u16, SV_ALL, 1);
+ svqinch_pat (s32, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svint32_t' arguments} } */
+ svqinch_pat (u32, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svuint32_t' arguments} } */
+ svqinch_pat (s64, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svint64_t' arguments} } */
+ svqinch_pat (u64, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svuint64_t' arguments} } */
+ svqinch_pat (sh, SV_ALL, 1);
+ svqinch_pat (sw, SV_ALL, 1);
+ svqinch_pat (sd, SV_ALL, 1);
+ svqinch_pat (uh, SV_ALL, 1);
+ svqinch_pat (uw, SV_ALL, 1);
+ svqinch_pat (ud, SV_ALL, 1);
+ svqinch_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqinch_pat', which expects a 32-bit or 64-bit integer type} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f)
+{
+ svqincw_pat (pg, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svbool_t' arguments} } */
+ svqincw_pat (s8, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svint8_t' arguments} } */
+ svqincw_pat (u8, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svuint8_t' arguments} } */
+ svqincw_pat (s16, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svint16_t' arguments} } */
+ svqincw_pat (u16, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svuint16_t' arguments} } */
+ svqincw_pat (s32, SV_ALL, 1);
+ svqincw_pat (u32, SV_ALL, 1);
+ svqincw_pat (s64, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svint64_t' arguments} } */
+ svqincw_pat (u64, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svuint64_t' arguments} } */
+ svqincw_pat (sh, SV_ALL, 1);
+ svqincw_pat (sw, SV_ALL, 1);
+ svqincw_pat (sd, SV_ALL, 1);
+ svqincw_pat (uh, SV_ALL, 1);
+ svqincw_pat (uw, SV_ALL, 1);
+ svqincw_pat (ud, SV_ALL, 1);
+ svqincw_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincw_pat', which expects a 32-bit or 64-bit integer type} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+ float f)
+{
+ svqincd_pat (pg, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svbool_t' arguments} } */
+ svqincd_pat (s8, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svint8_t' arguments} } */
+ svqincd_pat (u8, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svuint8_t' arguments} } */
+ svqincd_pat (s16, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svint16_t' arguments} } */
+ svqincd_pat (u16, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svuint16_t' arguments} } */
+ svqincd_pat (s32, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svint32_t' arguments} } */
+ svqincd_pat (u32, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svuint32_t' arguments} } */
+ svqincd_pat (s64, SV_ALL, 1);
+ svqincd_pat (u64, SV_ALL, 1);
+ svqincd_pat (sh, SV_ALL, 1);
+ svqincd_pat (sw, SV_ALL, 1);
+ svqincd_pat (sd, SV_ALL, 1);
+ svqincd_pat (uh, SV_ALL, 1);
+ svqincd_pat (uw, SV_ALL, 1);
+ svqincd_pat (ud, SV_ALL, 1);
+ svqincd_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincd_pat', which expects a 32-bit or 64-bit integer type} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, int i)
+{
+ svqincp (s32); /* { dg-error {too few arguments to function 'svqincp'} } */
+ svqincp (s32, pg, pg); /* { dg-error {too many arguments to function 'svqincp'} } */
+ svqincp (i, pg); /* { dg-error {passing 'int' to argument 1 of 'svqincp', which expects an SVE vector type} } */
+ svqincp (pg, pg); /* { dg-error {'svqincp' has no form that takes 'svbool_t' arguments} } */
+ svqincp (s8, pg); /* { dg-error {'svqincp' has no form that takes 'svint8_t' arguments} } */
+ svqincp (u8, pg); /* { dg-error {'svqincp' has no form that takes 'svuint8_t' arguments} } */
+ svqincp (s16, pg);
+ svqincp (u16, pg);
+ svqincp (s32, pg);
+ svqincp (u32, pg);
+ svqincp (s64, pg);
+ svqincp (u64, pg);
+ svqincp (u64, 0); /* { dg-error {passing 'int' to argument 2 of 'svqincp', which expects 'svbool_t'} } */
+ svqincp (u64, u64); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svqincp', which expects 'svbool_t'} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint32_t s32, svuint64_t u64, int16_t sh, uint16_t uh,
+ int32_t sw, uint32_t uw, int64_t sd, uint64_t ud)
+{
+ svqincp_b8 (s32); /* { dg-error {too few arguments to function 'svqincp_b8'} } */
+ svqincp_b8 (s32, pg, pg); /* { dg-error {too many arguments to function 'svqincp_b8'} } */
+ svqincp_b8 (pg, pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svqincp_b8', which expects a 32-bit or 64-bit integer type} } */
+ svqincp_b8 (s32, pg); /* { dg-error {passing 'svint32_t' to argument 1 of 'svqincp_b8', which expects a 32-bit or 64-bit integer type} } */
+ svqincp_b8 (sh, pg);
+ svqincp_b8 (uh, pg);
+ svqincp_b8 (sw, pg);
+ svqincp_b8 (uw, pg);
+ svqincp_b8 (sd, pg);
+ svqincp_b8 (ud, pg);
+ svqincp_b8 (ud, 0); /* { dg-error {passing 'int' to argument 2 of 'svqincp_b8', which expects 'svbool_t'} } */
+ svqincp_b8 (ud, u64); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svqincp_b8', which expects 'svbool_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -Wpointer-sign" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, short *s16_ptr, unsigned short *u16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1sh_gather_index (pg, s16_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sh_gather_index'; did you mean 'svld1_gather_index'} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr); /* { dg-error {too few arguments to function 'svld1sh_gather_index_u32'} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sh_gather_index_u32'} } */
+ svld1sh_gather_index_u32 (pg, u16_ptr, s32); /* { dg-warning {pointer targets in passing argument 2 of 'svld1sh_gather_s32index_u32' differ in signedness} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s32);
+ svld1sh_gather_index_u32 (pg, s16_ptr, u32);
+ svld1sh_gather_index_u32 (pg, s16_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+
+ svld1sh_gather_index_u32 (pg, 0, s32);
+ svld1sh_gather_index_u32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sh_gather_index_u32', which expects a vector or pointer base address} } */
+
+ svld1sh_gather_index_u32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+ svld1sh_gather_index_u32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+ svld1sh_gather_index_u32 (pg, u32, 0);
+ svld1sh_gather_index_u32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+ float *f32_ptr, _Complex float *cf32_ptr, int **ptr_ptr)
+{
+ svld1 (pg); /* { dg-error {too few arguments to function 'svld1'} } */
+ svld1 (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1'} } */
+ svld1 (0, s8_ptr); /* { dg-error {passing 'int' to argument 1 of 'svld1', which expects 'svbool_t'} } */
+ svld1 (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1', which expects a pointer type} } */
+ svld1 (pg, (int *) 0);
+ svld1 (pg, void_ptr); /* { dg-error {passing 'void \*' to argument 2 of 'svld1', but 'void' is not a valid SVE element type} } */
+ svld1 (pg, s_ptr); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1', but 'struct s' is not a valid SVE element type} } */
+ svld1 (pg, f32_ptr);
+ svld1 (pg, cf32_ptr); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1', but 'complex float' is not a valid SVE element type} } */
+ svld1 (pg, ptr_ptr); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1', but 'int \*' is not a valid SVE element type} } */
+ return svld1 (pg, s8_ptr); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+ float *f32_ptr, _Complex float *cf32_ptr)
+{
+ svld1_s8 (pg); /* { dg-error {too few arguments to function 'svld1_s8'} } */
+ svld1_s8 (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1_s8'} } */
+ svld1_s8 (0, 0); /* { dg-error {incompatible type for argument 1 of 'svld1_s8'} } */
+ svld1_s8 (pg, 0);
+ svld1_s32 (pg, (int *) 0);
+ svld1_s8 (pg, void_ptr);
+ svld1_s8 (pg, s_ptr); /* { dg-warning {passing argument 2 of 'svld1_s8' from incompatible pointer type} } */
+ svld1_f32 (pg, f32_ptr);
+ svld1_f32 (pg, cf32_ptr); /* { dg-warning {passing argument 2 of 'svld1_f32' from incompatible pointer type} } */
+ return svld1_s8 (pg, s8_ptr); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, svint8_t s8)
+{
+ svld1_vnum (pg); /* { dg-error {too few arguments to function 'svld1_vnum'} } */
+ svld1_vnum (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1_vnum'} } */
+ svld1_vnum (pg, s8_ptr, 0, 0); /* { dg-error {too many arguments to function 'svld1_vnum'} } */
+ svld1_vnum (0, s8_ptr, 0); /* { dg-error {passing 'int' to argument 1 of 'svld1_vnum', which expects 'svbool_t'} } */
+ svld1_vnum (pg, 0, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1_vnum', which expects a pointer type} } */
+ svld1_vnum (pg, s8_ptr, s8_ptr); /* { dg-warning "passing argument 3 of 'svld1_vnum_s8' makes integer from pointer without a cast" } */
+ svld1_vnum (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1_vnum', which expects 'int64_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -Wpointer-sign" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, short *s16_ptr, unsigned short *u16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1sh_gather_index (pg, s16_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sh_gather_index'; did you mean 'svld1_gather_index'} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr); /* { dg-error {too few arguments to function 'svld1sh_gather_index_u32'} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sh_gather_index_u32'} } */
+ svld1sh_gather_index_u32 (pg, u16_ptr, s32); /* { dg-warning {pointer targets in passing argument 2 of 'svld1sh_gather_s32index_u32' differ in signedness} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s32);
+ svld1sh_gather_index_u32 (pg, s16_ptr, u32);
+ svld1sh_gather_index_u32 (pg, s16_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+ svld1sh_gather_index_u32 (pg, s16_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+
+ svld1sh_gather_index_u32 (pg, 0, s32);
+ svld1sh_gather_index_u32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sh_gather_index_u32', which expects a vector or pointer base address} } */
+
+ svld1sh_gather_index_u32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+ svld1sh_gather_index_u32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+ svld1sh_gather_index_u32 (pg, u32, 0);
+ svld1sh_gather_index_u32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1sb_gather_offset (pg, s8_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_s32'} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_s32'} } */
+ svld1sb_gather_offset_s32 (pg, s16_ptr, s32); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s32offset_s32' from incompatible pointer type} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, s32);
+ svld1sb_gather_offset_s32 (pg, s8_ptr, u32);
+ svld1sb_gather_offset_s32 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_s32 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+
+ svld1sb_gather_offset_s32 (pg, 0, s32);
+ svld1sb_gather_offset_s32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_s32', which expects a vector or pointer base address} } */
+
+ svld1sb_gather_offset_s32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_s32', which expects 'svuint32_t'} } */
+ svld1sb_gather_offset_s32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_s32', which expects 'svuint32_t'} } */
+ svld1sb_gather_offset_s32 (pg, u32, 0);
+ svld1sb_gather_offset_s32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sb_gather_offset_s32', which expects 'svuint32_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1sb_gather_offset (pg, s8_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_u32'} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_u32'} } */
+ svld1sb_gather_offset_u32 (pg, s16_ptr, s32); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s32offset_u32' from incompatible pointer type} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, s32);
+ svld1sb_gather_offset_u32 (pg, s8_ptr, u32);
+ svld1sb_gather_offset_u32 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+ svld1sb_gather_offset_u32 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+
+ svld1sb_gather_offset_u32 (pg, 0, s32);
+ svld1sb_gather_offset_u32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_u32', which expects a vector or pointer base address} } */
+
+ svld1sb_gather_offset_u32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_u32', which expects 'svuint32_t'} } */
+ svld1sb_gather_offset_u32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_u32', which expects 'svuint32_t'} } */
+ svld1sb_gather_offset_u32 (pg, u32, 0);
+ svld1sb_gather_offset_u32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sb_gather_offset_u32', which expects 'svuint32_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1sb_gather_offset (pg, s8_ptr, s64); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_s64'} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, s64, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_s64'} } */
+ svld1sb_gather_offset_s64 (pg, s16_ptr, s64); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s64offset_s64' from incompatible pointer type} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_s64 (pg, s8_ptr, s64);
+ svld1sb_gather_offset_s64 (pg, s8_ptr, u64);
+ svld1sb_gather_offset_s64 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+
+ svld1sb_gather_offset_s64 (pg, 0, s64);
+ svld1sb_gather_offset_s64 (pg, s, s64); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_s64', which expects a vector or pointer base address} } */
+
+ svld1sb_gather_offset_s64 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_s64', which expects 'svuint64_t'} } */
+ svld1sb_gather_offset_s64 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_s64', which expects 'svuint64_t'} } */
+ svld1sb_gather_offset_s64 (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1sb_gather_offset_s64', which expects 'svuint64_t'} } */
+ svld1sb_gather_offset_s64 (pg, u64, 0);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1sb_gather_offset (pg, s8_ptr, s64); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_u64'} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, s64, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_u64'} } */
+ svld1sb_gather_offset_u64 (pg, s16_ptr, s64); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s64offset_u64' from incompatible pointer type} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+ svld1sb_gather_offset_u64 (pg, s8_ptr, s64);
+ svld1sb_gather_offset_u64 (pg, s8_ptr, u64);
+ svld1sb_gather_offset_u64 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+
+ svld1sb_gather_offset_u64 (pg, 0, s64);
+ svld1sb_gather_offset_u64 (pg, s, s64); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_u64', which expects a vector or pointer base address} } */
+
+ svld1sb_gather_offset_u64 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_u64', which expects 'svuint64_t'} } */
+ svld1sb_gather_offset_u64 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_u64', which expects 'svuint64_t'} } */
+ svld1sb_gather_offset_u64 (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1sb_gather_offset_u64', which expects 'svuint64_t'} } */
+ svld1sb_gather_offset_u64 (pg, u64, 0);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, unsigned char *s8_ptr, unsigned short *s16_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svld1ub_gather_offset (pg, s8_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1ub_gather_offset'; did you mean 'svld1_gather_offset'} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1ub_gather_offset_s32'} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1ub_gather_offset_s32'} } */
+ svld1ub_gather_offset_s32 (pg, s16_ptr, s32); /* { dg-warning {passing argument 2 of 'svld1ub_gather_s32offset_s32' from incompatible pointer type} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, s32);
+ svld1ub_gather_offset_s32 (pg, s8_ptr, u32);
+ svld1ub_gather_offset_s32 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+ svld1ub_gather_offset_s32 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+
+ svld1ub_gather_offset_s32 (pg, 0, s32);
+ svld1ub_gather_offset_s32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1ub_gather_offset_s32', which expects a vector or pointer base address} } */
+
+ svld1ub_gather_offset_s32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1ub_gather_offset_s32', which expects 'svuint32_t'} } */
+ svld1ub_gather_offset_s32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1ub_gather_offset_s32', which expects 'svuint32_t'} } */
+ svld1ub_gather_offset_s32 (pg, u32, 0);
+ svld1ub_gather_offset_s32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1ub_gather_offset_s32', which expects 'svuint32_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+ int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+ void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr, int **ptr_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+ svld1_gather_offset (pg, s32_ptr); /* { dg-error {too few arguments to function 'svld1_gather_offset'} } */
+ svld1_gather_offset (pg, s32_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1_gather_offset'} } */
+ svld1_gather_offset (0, s32_ptr, s32); /* { dg-error {passing 'int' to argument 1 of 'svld1_gather_offset', which expects 'svbool_t'} } */
+ svld1_gather_offset (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svld1_gather_offset', which expects a pointer type} } */
+ svld1_gather_offset (pg, (int *) 0, s32);
+ svld1_gather_offset (pg, void_ptr, s32); /* { dg-error {passing 'void \*' to argument 2 of 'svld1_gather_offset', but 'void' is not a valid SVE element type} } */
+ svld1_gather_offset (pg, s_ptr, s32); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1_gather_offset', but 'struct s' is not a valid SVE element type} } */
+ svld1_gather_offset (pg, f32_ptr, s32);
+ svld1_gather_offset (pg, cf32_ptr, s32); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1_gather_offset', but 'complex float' is not a valid SVE element type} } */
+ svld1_gather_offset (pg, ptr_ptr, u64); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1_gather_offset', but 'int \*' is not a valid SVE element type} } */
+ svld1_gather_offset (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1_gather_offset', which expects a pointer type} } */
+ /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+ svld1_gather_offset (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1_gather_offset', which expects a pointer type} } */
+ /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+
+ svld1_gather_offset (pg, s8_ptr, s8); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+ svld1_gather_offset (pg, s8_ptr, s32); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+ svld1_gather_offset (pg, s16_ptr, s16); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+ svld1_gather_offset (pg, s16_ptr, s32); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+
+ svld1_gather_offset (pg, s32_ptr, s32);
+ svld1_gather_offset (pg, s32_ptr, u32);
+ svld1_gather_offset (pg, s32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, s32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, s32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, s32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+
+ svld1_gather_offset (pg, u32_ptr, s32);
+ svld1_gather_offset (pg, u32_ptr, u32);
+ svld1_gather_offset (pg, u32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, u32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, u32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, u32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+
+ svld1_gather_offset (pg, f32_ptr, s32);
+ svld1_gather_offset (pg, f32_ptr, u32);
+ svld1_gather_offset (pg, f32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, f32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, f32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_offset (pg, f32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+ svld1_gather_offset (pg, s64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, s64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, s64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, s64_ptr, s64);
+ svld1_gather_offset (pg, s64_ptr, u64);
+ svld1_gather_offset (pg, s64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+
+ svld1_gather_offset (pg, u64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, u64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, u64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, u64_ptr, s64);
+ svld1_gather_offset (pg, u64_ptr, u64);
+ svld1_gather_offset (pg, u64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+
+ svld1_gather_offset (pg, f64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, f64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, f64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_offset (pg, f64_ptr, s64);
+ svld1_gather_offset (pg, f64_ptr, u64);
+ svld1_gather_offset (pg, f64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+
+ return svld1_gather_offset (pg, s32_ptr, s32); /* { dg-error {incompatible types when returning type 'svint32_t' but 'svuint32_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+ int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+ void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr, int **ptr_ptr,
+ svint8_t s8, svint16_t s16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+ svld1_gather_index (pg, s32_ptr); /* { dg-error {too few arguments to function 'svld1_gather_index'} } */
+ svld1_gather_index (pg, s32_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1_gather_index'} } */
+ svld1_gather_index (0, s32_ptr, s32); /* { dg-error {passing 'int' to argument 1 of 'svld1_gather_index', which expects 'svbool_t'} } */
+ svld1_gather_index (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svld1_gather_index', which expects a pointer type} } */
+ svld1_gather_index (pg, (int *) 0, s32);
+ svld1_gather_index (pg, void_ptr, s32); /* { dg-error {passing 'void \*' to argument 2 of 'svld1_gather_index', but 'void' is not a valid SVE element type} } */
+ svld1_gather_index (pg, s_ptr, s32); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1_gather_index', but 'struct s' is not a valid SVE element type} } */
+ svld1_gather_index (pg, f32_ptr, s32);
+ svld1_gather_index (pg, cf32_ptr, s32); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1_gather_index', but 'complex float' is not a valid SVE element type} } */
+ svld1_gather_index (pg, ptr_ptr, u64); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1_gather_index', but 'int \*' is not a valid SVE element type} } */
+ svld1_gather_index (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1_gather_index', which expects a pointer type} } */
+ /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+ svld1_gather_index (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1_gather_index', which expects a pointer type} } */
+ /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+
+ svld1_gather_index (pg, s8_ptr, s8); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+ svld1_gather_index (pg, s8_ptr, s32); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+ svld1_gather_index (pg, s16_ptr, s16); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+ svld1_gather_index (pg, s16_ptr, s32); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+
+ svld1_gather_index (pg, s32_ptr, s32);
+ svld1_gather_index (pg, s32_ptr, u32);
+ svld1_gather_index (pg, s32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, s32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, s32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, s32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+
+ svld1_gather_index (pg, u32_ptr, s32);
+ svld1_gather_index (pg, u32_ptr, u32);
+ svld1_gather_index (pg, u32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, u32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, u32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, u32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+
+ svld1_gather_index (pg, f32_ptr, s32);
+ svld1_gather_index (pg, f32_ptr, u32);
+ svld1_gather_index (pg, f32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, f32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, f32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svld1_gather_index (pg, f32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+ svld1_gather_index (pg, s64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, s64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, s64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, s64_ptr, s64);
+ svld1_gather_index (pg, s64_ptr, u64);
+ svld1_gather_index (pg, s64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+
+ svld1_gather_index (pg, u64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, u64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, u64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, u64_ptr, s64);
+ svld1_gather_index (pg, u64_ptr, u64);
+ svld1_gather_index (pg, u64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+
+ svld1_gather_index (pg, f64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, f64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, f64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svld1_gather_index (pg, f64_ptr, s64);
+ svld1_gather_index (pg, f64_ptr, u64);
+ svld1_gather_index (pg, f64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+
+ return svld1_gather_index (pg, s32_ptr, s32); /* { dg-error {incompatible types when returning type 'svint32_t' but 'svuint32_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+ float *f32_ptr, _Complex float *cf32_ptr, int **ptr_ptr)
+{
+ svld1rq (pg); /* { dg-error {too few arguments to function 'svld1rq'} } */
+ svld1rq (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1rq'} } */
+ svld1rq (0, s8_ptr); /* { dg-error {passing 'int' to argument 1 of 'svld1rq', which expects 'svbool_t'} } */
+ svld1rq (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1rq', which expects a pointer type} } */
+ svld1rq (pg, (int *) 0);
+ svld1rq (pg, void_ptr); /* { dg-error {passing 'void \*' to argument 2 of 'svld1rq', but 'void' is not a valid SVE element type} } */
+ svld1rq (pg, s_ptr); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1rq', but 'struct s' is not a valid SVE element type} } */
+ svld1rq (pg, f32_ptr);
+ svld1rq (pg, cf32_ptr); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1rq', but 'complex float' is not a valid SVE element type} } */
+ svld1rq (pg, ptr_ptr); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1rq', but 'int \*' is not a valid SVE element type} } */
+ return svld1rq (pg, s8_ptr); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test ()
+{
+ svptrue_pat_b16 ((enum svpattern) -1); /* { dg-error {passing 4294967295 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+ svptrue_pat_b16 ((enum svpattern) 0);
+ svptrue_pat_b16 ((enum svpattern) 13);
+ svptrue_pat_b16 ((enum svpattern) 14); /* { dg-error {passing 14 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+ svptrue_pat_b16 ((enum svpattern) 28); /* { dg-error {passing 28 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+ svptrue_pat_b16 ((enum svpattern) 29);
+ svptrue_pat_b16 ((enum svpattern) 31);
+ svptrue_pat_b16 ((enum svpattern) 32); /* { dg-error {passing 32 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, enum svprfop op)
+{
+ svprfb (pg, s32_ptr, op); /* { dg-error {argument 3 of 'svprfb' must be an integer constant expression} } */
+ svprfb (pg, s32_ptr, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+ svprfb (pg, s32_ptr, (enum svprfop) 0);
+ svprfb (pg, s32_ptr, (enum svprfop) 5);
+ svprfb (pg, s32_ptr, (enum svprfop) 6); /* { dg-error {passing 6 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+ svprfb (pg, s32_ptr, (enum svprfop) 7); /* { dg-error {passing 7 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+ svprfb (pg, s32_ptr, (enum svprfop) 8);
+ svprfb (pg, s32_ptr, (enum svprfop) 14); /* { dg-error {passing 14 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, void *void_ptr, void **ptr_ptr,
+ svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, enum svprfop op,
+ struct s s)
+{
+ svprfh_gather_index (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svprfh_gather_index'} } */
+ svprfh_gather_index (pg, s32_ptr, s32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfh_gather_index'} } */
+ svprfh_gather_index (0, s32_ptr, s32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfh_gather_index', which expects 'svbool_t'} } */
+ svprfh_gather_index (pg, 0, s32, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, (int *) 0, s32, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, void_ptr, s32, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, ptr_ptr, s32, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, s, s32, SV_PLDL1KEEP); /* { dg-error {passing 'struct s' to argument 2 of 'svprfh_gather_index', which expects a vector or pointer base address} } */
+
+ svprfh_gather_index (pg, s32_ptr, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfh_gather_index (pg, s32_ptr, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfh_gather_index (pg, s32_ptr, s16, SV_PLDL1KEEP); /* { dg-error {passing 'svint16_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfh_gather_index (pg, s32_ptr, u16, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfh_gather_index (pg, s32_ptr, f16, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svprfh_gather_index', which expects a vector of integers} } */
+ svprfh_gather_index (pg, s32_ptr, s32, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, s32_ptr, u32, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, s32_ptr, f32, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svprfh_gather_index', which expects a vector of integers} } */
+ svprfh_gather_index (pg, s32_ptr, s64, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, s32_ptr, u64, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, s32_ptr, f64, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svprfh_gather_index', which expects a vector of integers} } */
+
+ svprfh_gather_index (pg, u8, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfh_gather_index (pg, u16, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfh_gather_index (pg, s32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint32_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfh_gather_index (pg, u32, 0, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, f32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfh_gather_index (pg, s64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint64_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfh_gather_index (pg, u64, 0, SV_PLDL1KEEP);
+ svprfh_gather_index (pg, f64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+ svprfh_gather_index (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfh_gather_index' must be an integer constant expression} } */
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 0);
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 5);
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 8);
+ svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, svint32_t s32, enum svprfop op)
+{
+ svprfh_gather_s32index (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfh_gather_s32index' must be an integer constant expression} } */
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 0);
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 5);
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 8);
+ svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, void *void_ptr, void **ptr_ptr,
+ svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, enum svprfop op,
+ struct s s)
+{
+ svprfb_gather_offset (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svprfb_gather_offset'} } */
+ svprfb_gather_offset (pg, s32_ptr, s32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfb_gather_offset'} } */
+ svprfb_gather_offset (0, s32_ptr, s32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfb_gather_offset', which expects 'svbool_t'} } */
+ svprfb_gather_offset (pg, 0, s32, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, (int *) 0, s32, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, void_ptr, s32, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, ptr_ptr, s32, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, s, s32, SV_PLDL1KEEP); /* { dg-error {passing 'struct s' to argument 2 of 'svprfb_gather_offset', which expects a vector or pointer base address} } */
+
+ svprfb_gather_offset (pg, s32_ptr, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfb_gather_offset (pg, s32_ptr, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfb_gather_offset (pg, s32_ptr, s16, SV_PLDL1KEEP); /* { dg-error {passing 'svint16_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfb_gather_offset (pg, s32_ptr, u16, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+ svprfb_gather_offset (pg, s32_ptr, f16, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of integers} } */
+ svprfb_gather_offset (pg, s32_ptr, s32, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, s32_ptr, u32, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, s32_ptr, f32, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of integers} } */
+ svprfb_gather_offset (pg, s32_ptr, s64, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, s32_ptr, u64, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, s32_ptr, f64, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of integers} } */
+
+ svprfb_gather_offset (pg, u8, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather_offset (pg, u16, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather_offset (pg, s32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint32_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather_offset (pg, u32, 0, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, f32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather_offset (pg, s64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint64_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather_offset (pg, u64, 0, SV_PLDL1KEEP);
+ svprfb_gather_offset (pg, f64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+ svprfb_gather_offset (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfb_gather_offset' must be an integer constant expression} } */
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 0);
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 5);
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 8);
+ svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, enum svprfop op)
+{
+ svprfb_gather (pg, u32); /* { dg-error {too few arguments to function 'svprfb_gather'} } */
+ svprfb_gather (pg, u32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfb_gather'} } */
+ svprfb_gather (0, u32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfb_gather', which expects 'svbool_t'} } */
+ svprfb_gather (pg, 0, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 2 of 'svprfb_gather', which expects an SVE vector type} } */
+
+ svprfb_gather (pg, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, s16, SV_PLDL1KEEP); /* { dg-error {passing 'svint16_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, u16, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, f16, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, s32, SV_PLDL1KEEP); /* { dg-error {passing 'svint32_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, u32, SV_PLDL1KEEP);
+ svprfb_gather (pg, f32, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, s64, SV_PLDL1KEEP); /* { dg-error {passing 'svint64_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+ svprfb_gather (pg, u64, SV_PLDL1KEEP);
+ svprfb_gather (pg, f64, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+ svprfb_gather (pg, u32, op); /* { dg-error {argument 3 of 'svprfb_gather' must be an integer constant expression} } */
+ svprfb_gather (pg, u32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather (pg, u32, (enum svprfop) 0);
+ svprfb_gather (pg, u32, (enum svprfop) 5);
+ svprfb_gather (pg, u32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather (pg, u32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather (pg, u32, (enum svprfop) 8);
+ svprfb_gather (pg, u32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, svint32_t s32, enum svprfop op)
+{
+ svprfb_gather_s32offset (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfb_gather_s32offset' must be an integer constant expression} } */
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 0);
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 5);
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 8);
+ svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint32_t u32, enum svprfop op)
+{
+ svprfb_gather_u32base (pg, u32, op); /* { dg-error {argument 3 of 'svprfb_gather_u32base' must be an integer constant expression} } */
+ svprfb_gather_u32base (pg, u32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_u32base (pg, u32, (enum svprfop) 0);
+ svprfb_gather_u32base (pg, u32, (enum svprfop) 5);
+ svprfb_gather_u32base (pg, u32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_u32base (pg, u32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+ svprfb_gather_u32base (pg, u32, (enum svprfop) 8);
+ svprfb_gather_u32base (pg, u32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svuint32x2_t u32x2)
+{
+ svorv (pg); /* { dg-error {too few arguments to function 'svorv'} } */
+ svorv (pg, u32, u32); /* { dg-error {too many arguments to function 'svorv'} } */
+ svorv (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svorv', which expects 'svbool_t'} } */
+ svorv (u32, u32); /* { dg-error {passing 'svuint32_t' to argument 1 of 'svorv', which expects 'svbool_t'} } */
+ svorv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svorv', which expects an SVE vector type} } */
+ svorv (pg, pg); /* { dg-error {'svorv' has no form that takes 'svbool_t' arguments} } */
+ svorv (pg, s32);
+ svorv (pg, u32);
+ svorv (pg, f32); /* { dg-error {'svorv' has no form that takes 'svfloat32_t' arguments} } */
+ svorv (pg, u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 2 of 'svorv', which expects a single SVE vector rather than a tuple} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svuint32x2_t u32x2)
+{
+ svaddv (pg); /* { dg-error {too few arguments to function 'svaddv'} } */
+ svaddv (pg, u32, u32); /* { dg-error {too many arguments to function 'svaddv'} } */
+ svaddv (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svaddv', which expects 'svbool_t'} } */
+ svaddv (u32, u32); /* { dg-error {passing 'svuint32_t' to argument 1 of 'svaddv', which expects 'svbool_t'} } */
+ svaddv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svaddv', which expects an SVE vector type} } */
+ svaddv (pg, pg); /* { dg-error {'svaddv' has no form that takes 'svbool_t' arguments} } */
+ svaddv (pg, s32);
+ svaddv (pg, u32);
+ svaddv (pg, f32);
+ svaddv (pg, u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 2 of 'svaddv', which expects a single SVE vector rather than a tuple} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8x2 = svset2 (u8x2); /* { dg-error {too few arguments to function 'svset2'} } */
+ u8x2 = svset2 (u8x2, 1); /* { dg-error {too few arguments to function 'svset2'} } */
+ u8x2 = svset2 (u8x2, 1, u8, 3); /* { dg-error {too many arguments to function 'svset2'} } */
+ u8x2 = svset2 (u8, 0, u8); /* { dg-error {passing single vector 'svuint8_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+ u8x2 = svset2 (u8x3, 0, u8); /* { dg-error {passing 'svuint8x3_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+ u8x2 = svset2 (pg, 0, u8); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+ u8x2 = svset2 (u8x2, 0, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 3 of 'svset2', which expects a single SVE vector rather than a tuple} } */
+ u8x2 = svset2 (u8x2, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svuint8_t' to argument 3 of 'svset2', after passing 'svuint8x2_t' to argument 1} } */
+ u8x2 = svset2 (u8x2, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svuint8_t' to argument 3 of 'svset2', after passing 'svuint8x2_t' to argument 1} } */
+ u8x2 = svset2 (u8x2, x, u8); /* { dg-error {argument 2 of 'svset2' must be an integer constant expression} } */
+ u8x2 = svset2 (u8x2, 0, u8);
+ f64 = svset2 (u8x2, 0, u8); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8x2_t'} } */
+ u8x2 = svset2 (u8x2, 1, u8);
+ u8x2 = svset2 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2 (u8x2, one, u8); /* { dg-error {argument 2 of 'svset2' must be an integer constant expression} } */
+ u8x2 = svset2 (u8x2, 3 - 2, u8);
+ u8x2 = svset2 (u8x2, 1.0, u8);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+ svuint8x3_t u8x3, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ u8x2 = svset2_u8 (u8x2); /* { dg-error {too few arguments to function 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x2, 1); /* { dg-error {too few arguments to function 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x2, 1, u8, 3); /* { dg-error {too many arguments to function 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (s8x2, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x3, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (pg, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x2, 0, u8x2); /* { dg-error {incompatible type for argument 3 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x2, 0, f64); /* { dg-error {incompatible type for argument 3 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x2, 0, pg); /* { dg-error {incompatible type for argument 3 of 'svset2_u8'} } */
+ u8x2 = svset2_u8 (u8x2, x, u8); /* { dg-error {argument 2 of 'svset2_u8' must be an integer constant expression} } */
+ u8x2 = svset2_u8 (u8x2, 0, u8);
+ f64 = svset2_u8 (u8x2, 0, u8); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8x2_t'} } */
+ u8x2 = svset2_u8 (u8x2, 1, u8);
+ u8x2 = svset2_u8 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+ u8x2 = svset2_u8 (u8x2, one, u8); /* { dg-error {argument 2 of 'svset2_u8' must be an integer constant expression} } */
+ u8x2 = svset2_u8 (u8x2, 3 - 2, u8);
+ u8x2 = svset2_u8 (u8x2, 1.0, u8);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+ int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16x3 = svset3 (f16x3); /* { dg-error {too few arguments to function 'svset3'} } */
+ f16x3 = svset3 (f16x3, 1); /* { dg-error {too few arguments to function 'svset3'} } */
+ f16x3 = svset3 (f16x3, 1, f16, 3); /* { dg-error {too many arguments to function 'svset3'} } */
+ f16x3 = svset3 (f16, 0, f16); /* { dg-error {passing single vector 'svfloat16_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+ f16x3 = svset3 (f16x4, 0, f16); /* { dg-error {passing 'svfloat16x4_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+ f16x3 = svset3 (pg, 0, f16); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+ f16x3 = svset3 (f16x3, 0, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 3 of 'svset3', which expects a single SVE vector rather than a tuple} } */
+ f16x3 = svset3 (f16x3, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svfloat16_t' to argument 3 of 'svset3', after passing 'svfloat16x3_t' to argument 1} } */
+ f16x3 = svset3 (f16x3, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svfloat16_t' to argument 3 of 'svset3', after passing 'svfloat16x3_t' to argument 1} } */
+ f16x3 = svset3 (f16x3, x, f16); /* { dg-error {argument 2 of 'svset3' must be an integer constant expression} } */
+ f16x3 = svset3 (f16x3, 0, f16);
+ f64 = svset3 (f16x3, 0, f16); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16x3_t'} } */
+ f16x3 = svset3 (f16x3, 1, f16);
+ f16x3 = svset3 (f16x3, 2, f16);
+ f16x3 = svset3 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3 (f16x3, one, f16); /* { dg-error {argument 2 of 'svset3' must be an integer constant expression} } */
+ f16x3 = svset3 (f16x3, 3 - 2, f16);
+ f16x3 = svset3 (f16x3, 1.0, f16);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svuint16x3_t u16x3,
+ svfloat16x4_t f16x4, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ f16x3 = svset3_f16 (f16x3); /* { dg-error {too few arguments to function 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x3, 1); /* { dg-error {too few arguments to function 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x3, 1, f16, 3); /* { dg-error {too many arguments to function 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (u16x3, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x4, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (pg, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x3, 0, f16x3); /* { dg-error {incompatible type for argument 3 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x3, 0, f64); /* { dg-error {incompatible type for argument 3 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x3, 0, pg); /* { dg-error {incompatible type for argument 3 of 'svset3_f16'} } */
+ f16x3 = svset3_f16 (f16x3, x, f16); /* { dg-error {argument 2 of 'svset3_f16' must be an integer constant expression} } */
+ f16x3 = svset3_f16 (f16x3, 0, f16);
+ f64 = svset3_f16 (f16x3, 0, f16); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16x3_t'} } */
+ f16x3 = svset3_f16 (f16x3, 1, f16);
+ f16x3 = svset3_f16 (f16x3, 2, f16);
+ f16x3 = svset3_f16 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+ f16x3 = svset3_f16 (f16x3, one, f16); /* { dg-error {argument 2 of 'svset3_f16' must be an integer constant expression} } */
+ f16x3 = svset3_f16 (f16x3, 3 - 2, f16);
+ f16x3 = svset3_f16 (f16x3, 1.0, f16);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32x4 = svset4 (s32x4); /* { dg-error {too few arguments to function 'svset4'} } */
+ s32x4 = svset4 (s32x4, 1); /* { dg-error {too few arguments to function 'svset4'} } */
+ s32x4 = svset4 (s32x4, 1, s32, 3); /* { dg-error {too many arguments to function 'svset4'} } */
+ s32x4 = svset4 (s32, 0, s32); /* { dg-error {passing single vector 'svint32_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+ s32x4 = svset4 (s32x2, 0, s32); /* { dg-error {passing 'svint32x2_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+ s32x4 = svset4 (pg, 0, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+ s32x4 = svset4 (s32x4, 0, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 3 of 'svset4', which expects a single SVE vector rather than a tuple} } */
+ s32x4 = svset4 (s32x4, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svint32_t' to argument 3 of 'svset4', after passing 'svint32x4_t' to argument 1} } */
+ s32x4 = svset4 (s32x4, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svint32_t' to argument 3 of 'svset4', after passing 'svint32x4_t' to argument 1} } */
+ s32x4 = svset4 (s32x4, x, s32); /* { dg-error {argument 2 of 'svset4' must be an integer constant expression} } */
+ s32x4 = svset4 (s32x4, 0, s32);
+ f64 = svset4 (s32x4, 0, s32); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32x4_t'} } */
+ s32x4 = svset4 (s32x4, 1, s32);
+ s32x4 = svset4 (s32x4, 2, s32);
+ s32x4 = svset4 (s32x4, 3, s32);
+ s32x4 = svset4 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4 (s32x4, one, s32); /* { dg-error {argument 2 of 'svset4' must be an integer constant expression} } */
+ s32x4 = svset4 (s32x4, 3 - 2, s32);
+ s32x4 = svset4 (s32x4, 1.0, s32);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+ svint32x2_t s32x2, int x)
+{
+ const int one = 1;
+ svfloat64_t f64;
+
+ s32x4 = svset4_s32 (s32x4); /* { dg-error {too few arguments to function 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x4, 1); /* { dg-error {too few arguments to function 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x4, 1, s32, 3); /* { dg-error {too many arguments to function 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (f32x4, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x2, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (pg, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x4, 0, s32x4); /* { dg-error {incompatible type for argument 3 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x4, 0, f64); /* { dg-error {incompatible type for argument 3 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x4, 0, pg); /* { dg-error {incompatible type for argument 3 of 'svset4_s32'} } */
+ s32x4 = svset4_s32 (s32x4, x, s32); /* { dg-error {argument 2 of 'svset4_s32' must be an integer constant expression} } */
+ s32x4 = svset4_s32 (s32x4, 0, s32);
+ f64 = svset4_s32 (s32x4, 0, s32); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32x4_t'} } */
+ s32x4 = svset4_s32 (s32x4, 1, s32);
+ s32x4 = svset4_s32 (s32x4, 2, s32);
+ s32x4 = svset4_s32 (s32x4, 3, s32);
+ s32x4 = svset4_s32 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+ s32x4 = svset4_s32 (s32x4, one, s32); /* { dg-error {argument 2 of 'svset4_s32' must be an integer constant expression} } */
+ s32x4 = svset4_s32 (s32x4, 3 - 2, s32);
+ s32x4 = svset4_s32 (s32x4, 1.0, s32);
+
+ return f64;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+ svint32_t s32, svint64_t s64, int x)
+{
+ const int one = 1;
+ u8 = svasrd_x (pg, u8, 1); /* { dg-error {'svasrd_x' has no form that takes 'svuint8_t' arguments} } */
+ s8 = svasrd_x (pg, s8, x); /* { dg-error {argument 3 of 'svasrd_x' must be an integer constant expression} } */
+ s8 = svasrd_x (pg, s8, one); /* { dg-error {argument 3 of 'svasrd_x' must be an integer constant expression} } */
+ s8 = svasrd_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_x (pg, s8, 1.0);
+ s8 = svasrd_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_x (pg, s8, 1);
+ s8 = svasrd_x (pg, s8, 1 + 1);
+ s8 = svasrd_x (pg, s8, 8);
+ s8 = svasrd_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_x (pg, s8, (1ULL << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+ s16 = svasrd_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+ s16 = svasrd_x (pg, s16, 1);
+ s16 = svasrd_x (pg, s16, 16);
+ s16 = svasrd_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+ s32 = svasrd_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+ s32 = svasrd_x (pg, s32, 1);
+ s32 = svasrd_x (pg, s32, 32);
+ s32 = svasrd_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+ s64 = svasrd_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+ s64 = svasrd_x (pg, s64, 1);
+ s64 = svasrd_x (pg, s64, 64);
+ s64 = svasrd_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svint16_t s16, svint32_t s32, svint64_t s64,
+ int x)
+{
+ const int one = 1;
+ s8 = svasrd_n_s8_x (pg, s8, x); /* { dg-error {argument 3 of 'svasrd_n_s8_x' must be an integer constant expression} } */
+ s8 = svasrd_n_s8_x (pg, s8, one); /* { dg-error {argument 3 of 'svasrd_n_s8_x' must be an integer constant expression} } */
+ s8 = svasrd_n_s8_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_n_s8_x (pg, s8, 1.0);
+ s8 = svasrd_n_s8_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_n_s8_x (pg, s8, 1);
+ s8 = svasrd_n_s8_x (pg, s8, 1 + 1);
+ s8 = svasrd_n_s8_x (pg, s8, 8);
+ s8 = svasrd_n_s8_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s8 = svasrd_n_s8_x (pg, s8, (1ULL << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+ s16 = svasrd_n_s16_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+ s16 = svasrd_n_s16_x (pg, s16, 1);
+ s16 = svasrd_n_s16_x (pg, s16, 16);
+ s16 = svasrd_n_s16_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+ s32 = svasrd_n_s32_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+ s32 = svasrd_n_s32_x (pg, s32, 1);
+ s32 = svasrd_n_s32_x (pg, s32, 32);
+ s32 = svasrd_n_s32_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+ s64 = svasrd_n_s64_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+ s64 = svasrd_n_s64_x (pg, s64, 1);
+ s64 = svasrd_n_s64_x (pg, s64, 64);
+ s64 = svasrd_n_s64_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+ float *f32_ptr, _Complex float *cf32_ptr, svint8_t s8, svfloat32_t f32,
+ struct s s)
+{
+ svst1 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svst1'} } */
+ svst1 (pg, s8_ptr, s8, 0); /* { dg-error {too many arguments to function 'svst1'} } */
+ svst1 (0, s8_ptr, s8); /* { dg-error {passing 'int' to argument 1 of 'svst1', which expects 'svbool_t'} } */
+ svst1 (pg, void_ptr, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1', which expects an SVE vector type} } */
+ svst1 (pg, void_ptr, pg); /* { dg-error {'svst1' has no form that takes 'svbool_t' arguments} } */
+ svst1 (pg, 0, s8);
+ svst1 (pg, (int *) 0, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+ svst1 (pg, void_ptr, s8);
+ svst1 (pg, s_ptr, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+ svst1 (pg, f32_ptr, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+ svst1 (pg, f32_ptr, f32);
+ svst1 (pg, cf32_ptr, f32); /* { dg-warning "passing argument 2 of 'svst1_f32' from incompatible pointer type" } */
+ svst1 (pg, s, s8); /* { dg-error {passing 'struct s' to argument 2 of 'svst1', which expects a scalar pointer} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+ float *f32_ptr, _Complex float *cf32_ptr, svint8_t s8, svfloat32_t f32)
+{
+ svst1_vnum (pg, s8_ptr, 0); /* { dg-error {too few arguments to function 'svst1_vnum'} } */
+ svst1_vnum (pg, s8_ptr, 0, s8, 0); /* { dg-error {too many arguments to function 'svst1_vnum'} } */
+ svst1_vnum (0, s8_ptr, 0, s8); /* { dg-error {passing 'int' to argument 1 of 'svst1_vnum', which expects 'svbool_t'} } */
+ svst1_vnum (pg, s8_ptr, pg, s8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_vnum', which expects 'int64_t'} } */
+ svst1_vnum (pg, s8_ptr, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svst1_vnum', which expects 'int64_t'} } */
+ svst1_vnum (pg, s8_ptr, void_ptr, s8); /* { dg-warning "passing argument 3 of 'svst1_vnum_s8' makes integer from pointer without a cast" } */
+ svst1_vnum (pg, void_ptr, 0, 0); /* { dg-error {passing 'int' to argument 4 of 'svst1_vnum', which expects an SVE vector type} } */
+ svst1_vnum (pg, void_ptr, 0, pg); /* { dg-error {'svst1_vnum' has no form that takes 'svbool_t' arguments} } */
+ svst1_vnum (pg, 0, 0, s8);
+ svst1_vnum (pg, (int *) 0, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+ svst1_vnum (pg, void_ptr, 0, s8);
+ svst1_vnum (pg, s_ptr, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+ svst1_vnum (pg, f32_ptr, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+ svst1_vnum (pg, f32_ptr, 0, f32);
+ svst1_vnum (pg, cf32_ptr, 0, f32); /* { dg-warning "passing argument 2 of 'svst1_vnum_f32' from incompatible pointer type" } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+ int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+ void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr,
+ svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svst1_scatter_index (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svst1_scatter_index'} } */
+ svst1_scatter_index (pg, s32_ptr, s32, s32, 0); /* { dg-error {too many arguments to function 'svst1_scatter_index'} } */
+ svst1_scatter_index (0, s32_ptr, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter_index', which expects 'svbool_t'} } */
+ svst1_scatter_index (pg, 0, s32, s32);
+ svst1_scatter_index (pg, (int *) 0, s32, s32);
+ svst1_scatter_index (pg, void_ptr, s32, s32);
+ svst1_scatter_index (pg, s_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32index_s32' from incompatible pointer type" } */
+ svst1_scatter_index (pg, f32_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32index_s32' from incompatible pointer type" } */
+ svst1_scatter_index (pg, f32_ptr, s32, f32);
+ svst1_scatter_index (pg, cf32_ptr, s32, f32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32index_f32' from incompatible pointer type" } */
+ svst1_scatter_index (pg, s, s32, s32); /* { dg-error {passing 'struct s' to argument 2 of 'svst1_scatter_index', which expects a vector or pointer base address} } */
+
+ svst1_scatter_index (pg, u32, void_ptr, s32); /* { dg-warning "passing argument 3 of 'svst1_scatter_u32base_index_s32' makes integer from pointer without a cast" } */
+ svst1_scatter_index (pg, u32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter_index', which expects 'int64_t'} } */
+ svst1_scatter_index (pg, u32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which expects 'int64_t'} } */
+
+ svst1_scatter_index (pg, void_ptr, u32, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter_index (pg, s8_ptr, u32, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter_index (pg, s8_ptr, u32, u8); /* { dg-error {passing 'svuint8_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter_index (pg, s16_ptr, u32, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter_index (pg, s16_ptr, u32, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter_index (pg, s16_ptr, u32, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter_index (pg, u32, 0, s32);
+ svst1_scatter_index (pg, s32, 0, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint32_t'} } */
+
+ svst1_scatter_index (pg, u32, 0, u32);
+ svst1_scatter_index (pg, s32, 0, u32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint32_t'} } */
+
+ svst1_scatter_index (pg, u32, 0, f32);
+ svst1_scatter_index (pg, s32, 0, f32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint32_t'} } */
+
+ svst1_scatter_index (pg, u64, 0, s64);
+ svst1_scatter_index (pg, s64, 0, s64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint64_t'} } */
+
+ svst1_scatter_index (pg, u64, 0, u64);
+ svst1_scatter_index (pg, s64, 0, u64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint64_t'} } */
+
+ svst1_scatter_index (pg, u64, 0, f64);
+ svst1_scatter_index (pg, s64, 0, f64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint64_t'} } */
+
+ svst1_scatter_index (pg, s32_ptr, s32, s32);
+ svst1_scatter_index (pg, s32_ptr, u32, s32);
+ svst1_scatter_index (pg, s32_ptr, f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, s32_ptr, s64, s32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, s32_ptr, u64, s32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, s32_ptr, f64, s32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+
+ svst1_scatter_index (pg, u32_ptr, s32, u32);
+ svst1_scatter_index (pg, u32_ptr, u32, u32);
+ svst1_scatter_index (pg, u32_ptr, f32, u32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, u32_ptr, s64, u32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, u32_ptr, u64, u32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, u32_ptr, f64, u32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+
+ svst1_scatter_index (pg, f32_ptr, s32, f32);
+ svst1_scatter_index (pg, f32_ptr, u32, f32);
+ svst1_scatter_index (pg, f32_ptr, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, f32_ptr, s64, f32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, f32_ptr, u64, f32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_index (pg, f32_ptr, f64, f32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+ svst1_scatter_index (pg, s64_ptr, s32, s64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, s64_ptr, u32, s64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, s64_ptr, f32, s64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, s64_ptr, s64, s64);
+ svst1_scatter_index (pg, s64_ptr, u64, s64);
+ svst1_scatter_index (pg, s64_ptr, f64, s64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+
+ svst1_scatter_index (pg, u64_ptr, s32, u64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, u64_ptr, u32, u64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, u64_ptr, f32, u64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, u64_ptr, s64, u64);
+ svst1_scatter_index (pg, u64_ptr, u64, u64);
+ svst1_scatter_index (pg, u64_ptr, f64, u64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+
+ svst1_scatter_index (pg, f64_ptr, s32, f64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, f64_ptr, u32, f64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, f64_ptr, f32, f64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_index (pg, f64_ptr, s64, f64);
+ svst1_scatter_index (pg, f64_ptr, u64, f64);
+ svst1_scatter_index (pg, f64_ptr, f64, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ svfloat16_t f16, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+ svst1_scatter (pg, u32); /* { dg-error {too few arguments to function 'svst1_scatter'} } */
+ svst1_scatter (pg, u32, u32, 0); /* { dg-error {too many arguments to function 'svst1_scatter'} } */
+ svst1_scatter (0, u32, u32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter', which expects 'svbool_t'} } */
+ svst1_scatter (pg, 0, u32); /* { dg-error {passing 'int' to argument 2 of 'svst1_scatter', which expects an SVE vector type} } */
+ svst1_scatter (pg, u32, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1_scatter', which expects an SVE vector type} } */
+
+ svst1_scatter (pg, u32, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter (pg, u32, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter (pg, u32, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter (pg, u32, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter (pg, u32, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter (pg, u32, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter (pg, u32, s32);
+ svst1_scatter (pg, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter', which expects 'svuint32_t'} } */
+
+ svst1_scatter (pg, u32, u32);
+ svst1_scatter (pg, s32, u32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter', which expects 'svuint32_t'} } */
+
+ svst1_scatter (pg, u32, f32);
+ svst1_scatter (pg, s32, f32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter', which expects 'svuint32_t'} } */
+
+ svst1_scatter (pg, u64, s64);
+ svst1_scatter (pg, s64, s64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter', which expects 'svuint64_t'} } */
+
+ svst1_scatter (pg, u64, u64);
+ svst1_scatter (pg, s64, u64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter', which expects 'svuint64_t'} } */
+
+ svst1_scatter (pg, u64, f64);
+ svst1_scatter (pg, s64, f64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter', which expects 'svuint64_t'} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+ int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+ int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+ void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr,
+ svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+ svst1_scatter_offset (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svst1_scatter_offset'} } */
+ svst1_scatter_offset (pg, s32_ptr, s32, s32, 0); /* { dg-error {too many arguments to function 'svst1_scatter_offset'} } */
+ svst1_scatter_offset (0, s32_ptr, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter_offset', which expects 'svbool_t'} } */
+ svst1_scatter_offset (pg, 0, s32, s32);
+ svst1_scatter_offset (pg, (int *) 0, s32, s32);
+ svst1_scatter_offset (pg, void_ptr, s32, s32);
+ svst1_scatter_offset (pg, s_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32offset_s32' from incompatible pointer type" } */
+ svst1_scatter_offset (pg, f32_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32offset_s32' from incompatible pointer type" } */
+ svst1_scatter_offset (pg, f32_ptr, s32, f32);
+ svst1_scatter_offset (pg, cf32_ptr, s32, f32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32offset_f32' from incompatible pointer type" } */
+ svst1_scatter_offset (pg, s, s32, s32); /* { dg-error {passing 'struct s' to argument 2 of 'svst1_scatter_offset', which expects a vector or pointer base address} } */
+
+ svst1_scatter_offset (pg, u32, void_ptr, s32); /* { dg-warning "passing argument 3 of 'svst1_scatter_u32base_offset_s32' makes integer from pointer without a cast" } */
+ svst1_scatter_offset (pg, u32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter_offset', which expects 'int64_t'} } */
+ svst1_scatter_offset (pg, u32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which expects 'int64_t'} } */
+
+ svst1_scatter_offset (pg, void_ptr, u32, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter_offset (pg, s8_ptr, u32, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter_offset (pg, s8_ptr, u32, u8); /* { dg-error {passing 'svuint8_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter_offset (pg, s16_ptr, u32, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter_offset (pg, s16_ptr, u32, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+ svst1_scatter_offset (pg, s16_ptr, u32, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+
+ svst1_scatter_offset (pg, u32, 0, s32);
+ svst1_scatter_offset (pg, s32, 0, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint32_t'} } */
+
+ svst1_scatter_offset (pg, u32, 0, u32);
+ svst1_scatter_offset (pg, s32, 0, u32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint32_t'} } */
+
+ svst1_scatter_offset (pg, u32, 0, f32);
+ svst1_scatter_offset (pg, s32, 0, f32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint32_t'} } */
+
+ svst1_scatter_offset (pg, u64, 0, s64);
+ svst1_scatter_offset (pg, s64, 0, s64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint64_t'} } */
+
+ svst1_scatter_offset (pg, u64, 0, u64);
+ svst1_scatter_offset (pg, s64, 0, u64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint64_t'} } */
+
+ svst1_scatter_offset (pg, u64, 0, f64);
+ svst1_scatter_offset (pg, s64, 0, f64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint64_t'} } */
+
+ svst1_scatter_offset (pg, s32_ptr, s32, s32);
+ svst1_scatter_offset (pg, s32_ptr, u32, s32);
+ svst1_scatter_offset (pg, s32_ptr, f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, s32_ptr, s64, s32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, s32_ptr, u64, s32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, s32_ptr, f64, s32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+
+ svst1_scatter_offset (pg, u32_ptr, s32, u32);
+ svst1_scatter_offset (pg, u32_ptr, u32, u32);
+ svst1_scatter_offset (pg, u32_ptr, f32, u32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, u32_ptr, s64, u32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, u32_ptr, u64, u32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, u32_ptr, f64, u32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+
+ svst1_scatter_offset (pg, f32_ptr, s32, f32);
+ svst1_scatter_offset (pg, f32_ptr, u32, f32);
+ svst1_scatter_offset (pg, f32_ptr, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, f32_ptr, s64, f32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, f32_ptr, u64, f32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+ svst1_scatter_offset (pg, f32_ptr, f64, f32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+ svst1_scatter_offset (pg, s64_ptr, s32, s64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, s64_ptr, u32, s64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, s64_ptr, f32, s64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, s64_ptr, s64, s64);
+ svst1_scatter_offset (pg, s64_ptr, u64, s64);
+ svst1_scatter_offset (pg, s64_ptr, f64, s64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+
+ svst1_scatter_offset (pg, u64_ptr, s32, u64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, u64_ptr, u32, u64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, u64_ptr, f32, u64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, u64_ptr, s64, u64);
+ svst1_scatter_offset (pg, u64_ptr, u64, u64);
+ svst1_scatter_offset (pg, u64_ptr, f64, u64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+
+ svst1_scatter_offset (pg, f64_ptr, s32, f64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, f64_ptr, u32, f64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, f64_ptr, f32, f64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+ svst1_scatter_offset (pg, f64_ptr, s64, f64);
+ svst1_scatter_offset (pg, f64_ptr, u64, f64);
+ svst1_scatter_offset (pg, f64_ptr, f64, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+ svint32_t s32, int i)
+{
+ svmla_lane (f32, f32, f32); /* { dg-error {too few arguments to function 'svmla_lane'} } */
+ svmla_lane (f32, f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svmla_lane'} } */
+ svmla_lane (pg, pg, pg, 0); /* { dg-error {'svmla_lane' has no form that takes 'svbool_t' arguments} } */
+ svmla_lane (s32, s32, s32, 0); /* { dg-error {'svmla_lane' has no form that takes 'svint32_t' arguments} } */
+ svmla_lane (1, f32, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmla_lane', which expects an SVE vector type} } */
+ svmla_lane (f32, 1, f32, 0); /* { dg-error {passing 'int' to argument 2 of 'svmla_lane', which expects an SVE vector type} } */
+ svmla_lane (f32, f32, 1, 0); /* { dg-error {passing 'int' to argument 3 of 'svmla_lane', which expects an SVE vector type} } */
+ svmla_lane (f32, f64, f32, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+ svmla_lane (f32, f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+ svmla_lane (f32, f32, f32, s32); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+ svmla_lane (f32, f32, f32, i); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+
+ svmla_lane (f16, f16, f16, 0);
+ svmla_lane (f16, f16, f16, 7);
+ svmla_lane (f16, f16, f16, 8); /* { dg-error {passing 8 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 7\]} } */
+ svmla_lane (f16, f16, f16, -1); /* { dg-error {passing -1 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 7\]} } */
+
+ svmla_lane (f32, f32, f32, 0);
+ svmla_lane (f32, f32, f32, 3);
+ svmla_lane (f32, f32, f32, 4); /* { dg-error {passing 4 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 3\]} } */
+ svmla_lane (f32, f32, f32, -1); /* { dg-error {passing -1 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 3\]} } */
+
+ svmla_lane (f64, f64, f64, 0);
+ svmla_lane (f64, f64, f64, 1);
+ svmla_lane (f64, f64, f64, 2); /* { dg-error {passing 2 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 1\]} } */
+ svmla_lane (f64, f64, f64, -1); /* { dg-error {passing -1 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 1\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+ svint32_t s32, int i)
+{
+ svcmla_lane (f32, f32, f32, 0); /* { dg-error {too few arguments to function 'svcmla_lane'} } */
+ svcmla_lane (f32, f32, f32, 0, 90, 90); /* { dg-error {too many arguments to function 'svcmla_lane'} } */
+ svcmla_lane (pg, pg, pg, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svbool_t' arguments} } */
+ svcmla_lane (s32, s32, s32, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svint32_t' arguments} } */
+ svcmla_lane (f64, f64, f64, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svfloat64_t' arguments} } */
+ svcmla_lane (1, f32, f32, 0, 90); /* { dg-error {passing 'int' to argument 1 of 'svcmla_lane', which expects an SVE vector type} } */
+ svcmla_lane (f32, 1, f32, 0, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_lane', which expects an SVE vector type} } */
+ svcmla_lane (f32, f32, 1, 0, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_lane', which expects an SVE vector type} } */
+ svcmla_lane (f32, f64, f32, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+ svcmla_lane (f32, f32, f64, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+ svcmla_lane (f32, f32, f32, s32, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+ svcmla_lane (f32, f32, f32, i, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+
+ svcmla_lane (f16, f16, f16, 0, 0);
+ svcmla_lane (f16, f16, f16, 3, 0);
+ svcmla_lane (f16, f16, f16, 4, 0); /* { dg-error {passing 4 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 3\]} } */
+ svcmla_lane (f16, f16, f16, -1, 0); /* { dg-error {passing -1 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 3\]} } */
+
+ svcmla_lane (f32, f32, f32, 0, 0);
+ svcmla_lane (f32, f32, f32, 1, 0);
+ svcmla_lane (f32, f32, f32, 2, 0); /* { dg-error {passing 2 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 1\]} } */
+ svcmla_lane (f32, f32, f32, -1, 0); /* { dg-error {passing -1 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 1\]} } */
+
+ svcmla_lane (f32, f32, f32, 0, -90); /* { dg-error {passing -90 to argument 5 of 'svcmla_lane', which expects 0, 90, 180 or 270} } */
+ svcmla_lane (f32, f32, f32, 0, 0);
+ svcmla_lane (f32, f32, f32, 0, 1); /* { dg-error {passing 1 to argument 5 of 'svcmla_lane', which expects 0, 90, 180 or 270} } */
+ svcmla_lane (f32, f32, f32, 0, 90);
+ svcmla_lane (f32, f32, f32, 0, 180);
+ svcmla_lane (f32, f32, f32, 0, 270);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+ svmla_x (pg, u8, u8); /* { dg-error {too few arguments to function 'svmla_x'} } */
+ svmla_x (pg, u8, u8, u8, u8); /* { dg-error {too many arguments to function 'svmla_x'} } */
+ svmla_x (u8, u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svmla_x', which expects 'svbool_t'} } */
+ svmla_x (pg, pg, pg, pg); /* { dg-error {'svmla_x' has no form that takes 'svbool_t' arguments} } */
+ svmla_x (pg, 1, u8, u8); /* { dg-error {passing 'int' to argument 2 of 'svmla_x', which expects an SVE vector type} } */
+ svmla_x (pg, u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u8, u8);
+ svmla_x (pg, u8, s16, u8); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u16, u8); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, f16, u8); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, pg, u8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, 0, u8); /* { dg-error {passing 'int' to argument 3 of 'svmla_x', which expects an SVE vector type} } */
+ svmla_x (pg, u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u8, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u8, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+ svmla_x (pg, u8, u8, 0);
+
+ svmla_x (pg, f16, s16, f16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+ svmla_x (pg, f16, u16, f16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+ svmla_x (pg, f16, f16, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+ svmla_x (pg, f16, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+ svmla_x (pg, f16, f16, f16);
+ svmla_x (pg, f16, f16, 1);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+ svint32_t s32, svuint32_t u32, svint64_t s64, svuint64_t u64,
+ svfloat32_t f32, int i)
+{
+ svdot_lane (u32, u8, u8); /* { dg-error {too few arguments to function 'svdot_lane'} } */
+ svdot_lane (u32, u8, u8, 0, 0); /* { dg-error {too many arguments to function 'svdot_lane'} } */
+ svdot_lane (0, u8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svdot_lane', which expects an SVE vector type} } */
+ svdot_lane (pg, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svbool_t' arguments} } */
+ svdot_lane (u8, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svuint8_t' arguments} } */
+ svdot_lane (f32, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svfloat32_t' arguments} } */
+ svdot_lane (u32, u8, u8, 0);
+ svdot_lane (u32, 0, u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svdot_lane', which expects an SVE vector type} } */
+ svdot_lane (u32, u8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svdot_lane', which expects an SVE vector type} } */
+
+ svdot_lane (s32, s8, s8, 0);
+ svdot_lane (s32, u8, s8, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+ svdot_lane (s32, s8, u8, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+ svdot_lane (s32, s32, s32, 0); /* { dg-error {passing 'svint32_t' instead of the expected 'svint8_t' to argument 2 of 'svdot_lane', after passing 'svint32_t' to argument 1} } */
+
+ svdot_lane (u32, u8, u8, 0);
+ svdot_lane (u32, s8, u8, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+ svdot_lane (u32, u8, s8, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+ svdot_lane (u32, u32, u32, 0); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svdot_lane', after passing 'svuint32_t' to argument 1} } */
+
+ svdot_lane (s64, s16, s16, 0);
+ svdot_lane (s64, u16, s16, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint64_t' and 'svuint16_t' respectively} } */
+ svdot_lane (s64, s16, u16, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint64_t' and 'svuint16_t' respectively} } */
+ svdot_lane (s64, s64, s64, 0); /* { dg-error {passing 'svint64_t' instead of the expected 'svint16_t' to argument 2 of 'svdot_lane', after passing 'svint64_t' to argument 1} } */
+
+ svdot_lane (u64, u16, u16, 0);
+ svdot_lane (u64, s16, u16, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint64_t' and 'svint16_t' respectively} } */
+ svdot_lane (u64, u16, s16, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint64_t' and 'svint16_t' respectively} } */
+ svdot_lane (u64, u64, u64, 0); /* { dg-error {passing 'svuint64_t' instead of the expected 'svuint16_t' to argument 2 of 'svdot_lane', after passing 'svuint64_t' to argument 1} } */
+
+ svdot_lane (s32, s8, s8, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+ svdot_lane (s32, s8, s8, 0);
+ svdot_lane (s32, s8, s8, 3);
+ svdot_lane (s32, s8, s8, 4); /* { dg-error {passing 4 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+ svdot_lane (s32, s8, s8, -1); /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+
+ svdot_lane (u32, u8, u8, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+ svdot_lane (u32, u8, u8, 0);
+ svdot_lane (u32, u8, u8, 3);
+ svdot_lane (u32, u8, u8, 4); /* { dg-error {passing 4 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+ svdot_lane (u32, u8, u8, -1); /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+
+ svdot_lane (s64, s16, s16, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+ svdot_lane (s64, s16, s16, 0);
+ svdot_lane (s64, s16, s16, 1);
+ svdot_lane (s64, s16, s16, 2); /* { dg-error {passing 2 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+ svdot_lane (s64, s16, s16, -1); /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+
+ svdot_lane (u64, u16, u16, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+ svdot_lane (u64, u16, u16, 0);
+ svdot_lane (u64, u16, u16, 1);
+ svdot_lane (u64, u16, u16, 2); /* { dg-error {passing 2 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+ svdot_lane (u64, u16, u16, -1); /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svint32_t
+f1 (svuint32_t u32, svuint8_t u8, svint8_t s8)
+{
+ svdot_u32 (u32); /* { dg-error {too few arguments to function 'svdot_u32'} } */
+ svdot_u32 (u32, u8, u8, u32); /* { dg-error {too many arguments to function 'svdot_u32'} } */
+ svdot_u32 (u32, u32, u8); /* { dg-error {incompatible type for argument 2 of 'svdot_u32'} } */
+ svdot_u32 (u32, s8, u8); /* { dg-error {incompatible type for argument 2 of 'svdot_u32'} } */
+ svdot_u32 (u32, u8, u32); /* { dg-error {incompatible type for argument 3 of 'svdot_u32'} } */
+ svdot_u32 (u32, u8, s8); /* { dg-error {incompatible type for argument 3 of 'svdot_u32'} } */
+ return svdot_u32 (u32, u8, u8); /* { dg-error {incompatible types when returning type 'svuint32_t' but 'svint32_t' was expected} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32,
+ svfloat32_t f32)
+{
+ svdot (u32, u8); /* { dg-error {too few arguments to function 'svdot'} } */
+ svdot (u32, u8, u8, u8); /* { dg-error {too many arguments to function 'svdot'} } */
+ svdot (0, u8, u8); /* { dg-error {passing 'int' to argument 1 of 'svdot', which expects an SVE vector type} } */
+ svdot (pg, u8, u8); /* { dg-error {'svdot' has no form that takes 'svbool_t' arguments} } */
+ svdot (u8, u8, u8); /* { dg-error {'svdot' has no form that takes 'svuint8_t' arguments} } */
+ svdot (f32, u8, u8); /* { dg-error {'svdot' has no form that takes 'svfloat32_t' arguments} } */
+ svdot (u32, u8, u8);
+ svdot (u32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svdot', which expects an SVE vector type} } */
+ svdot (u32, s8, u8); /* { dg-error {arguments 1 and 2 of 'svdot' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+ svdot (u32, u8, 0);
+ svdot (u32, u8, s8); /* { dg-error {arguments 1 and 3 of 'svdot' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+ svdot (u32, u32, u32); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svdot', after passing 'svuint32_t' to argument 1} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+{
+ svcmla_x (pg, f32, f32, f32); /* { dg-error {too few arguments to function 'svcmla_x'} } */
+ svcmla_x (pg, f32, f32, f32, 90, 90); /* { dg-error {too many arguments to function 'svcmla_x'} } */
+ svcmla_x (f32, f32, f32, f32, 90); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcmla_x', which expects 'svbool_t'} } */
+ svcmla_x (pg, pg, pg, pg, 90); /* { dg-error {'svcmla_x' has no form that takes 'svbool_t' arguments} } */
+ svcmla_x (pg, s32, s32, s32, 90); /* { dg-error {'svcmla_x' has no form that takes 'svint32_t' arguments} } */
+ svcmla_x (pg, 1, f32, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_x', which expects an SVE vector type} } */
+ svcmla_x (pg, f32, 1, f32, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_x', which expects an SVE vector type} } */
+ svcmla_x (pg, f32, f32, 1, 90); /* { dg-error {passing 'int' to argument 4 of 'svcmla_x', which expects an SVE vector type} } */
+ svcmla_x (pg, f32, f64, f32, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+ svcmla_x (pg, f32, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+ svcmla_x (pg, f32, f32, f32, s32); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+ svcmla_x (pg, f32, f32, f32, i); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+ svcmla_x (pg, f32, f32, f32, -90); /* { dg-error {passing -90 to argument 5 of 'svcmla_x', which expects 0, 90, 180 or 270} } */
+ svcmla_x (pg, f32, f32, f32, 0);
+ svcmla_x (pg, f32, f32, f32, 1); /* { dg-error {passing 1 to argument 5 of 'svcmla_x', which expects 0, 90, 180 or 270} } */
+ svcmla_x (pg, f32, f32, f32, 90);
+ svcmla_x (pg, f32, f32, f32, 180);
+ svcmla_x (pg, f32, f32, f32, 270);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+{
+ svtmad (f32, f32); /* { dg-error {too few arguments to function 'svtmad'} } */
+ svtmad (f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svtmad'} } */
+ svtmad (pg, pg, 0); /* { dg-error {'svtmad' has no form that takes 'svbool_t' arguments} } */
+ svtmad (s32, s32, 0); /* { dg-error {'svtmad' has no form that takes 'svint32_t' arguments} } */
+ svtmad (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svtmad', which expects an SVE vector type} } */
+ svtmad (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svtmad', which expects an SVE vector type} } */
+ svtmad (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svtmad', but previous arguments had type 'svfloat32_t'} } */
+ svtmad (f32, f32, s32); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+ svtmad (f32, f32, i); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+ svtmad (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svtmad', which expects a value in the range \[0, 7\]} } */
+ svtmad (f32, f32, 0);
+ svtmad (f32, f32, 1);
+ svtmad (f32, f32, 7);
+ svtmad (f32, f32, 8); /* { dg-error {passing 8 to argument 3 of 'svtmad', which expects a value in the range \[0, 7\]} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+int svbool_t; /* { dg-message "note: previous declaration of 'svbool_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svbool_t' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef struct svint8x2_t svint8x2_t; /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting types for 'svint8x2_t'} } */
--- /dev/null
+/* { dg-do compile } */
+
+/* This isn't explicitly allowed or disallowed, but mustn't ICE. */
+struct svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f (svint8x2_t *a, struct svint8x2_t *b)
+{
+ *a = *b; /* { dg-error {dereferencing pointer to incomplete type} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+/* This isn't explicitly allowed or disallowed, but mustn't ICE. */
+struct svint8x2_t { int x; };
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f (svint8x2_t *a, struct svint8x2_t *b)
+{
+ *a = *b; /* { dg-error {incompatible types} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+int svint8x2_t; /* { dg-error {'svint8x2_t' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+enum svpattern { FOO }; /* { dg-message "note: originally defined here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {redeclaration of 'enum svpattern'} } */
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "note: originally defined here" } */
+
+enum svpattern { FOO }; /* { dg-error {redeclaration of 'enum svpattern'} } */
+enum foo { SV_ALL }; /* { dg-error {redeclaration of enumerator 'SV_ALL'} } */
+typedef int SV_POW2; /* { dg-error {'SV_POW2' redeclared as different kind of symbol} } */
+int SV_VL3; /* { dg-error {'SV_VL3' redeclared as different kind of symbol} } */
--- /dev/null
+/* { dg-do compile } */
+
+struct svpattern { int x; };
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svpattern' defined as wrong kind of tag} } */
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+struct svpattern { int x; }; /* { dg-error {'svpattern' defined as wrong kind of tag} } */
--- /dev/null
+/* { dg-do compile } */
+
+int svpattern; /* OK in C. */
+
+#pragma GCC aarch64 "arm_sve.h"
--- /dev/null
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+int svpattern; /* OK in C. */
--- /dev/null
+/* { dg-do compile } */
+
+int svint8_t; /* { dg-message "note: previous declaration of 'svint8_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svint8_t' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+enum foo { SV_VL4 };
+typedef int SV_POW2;
+int SV_ALL;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {redeclaration of enumerator 'SV_VL4'} } */
+/* { dg-error {'SV_POW2' redeclared as different kind of symbol} "" { target *-*-* } .-1 } */
+/* { dg-error {'SV_ALL' redeclared as different kind of symbol} "" { target *-*-* } .-2 } */
--- /dev/null
+/* { dg-do compile } */
+
+int svuint16_t; /* { dg-message "note: previous declaration of 'svuint16_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint16_t' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+int svfloat32_t; /* { dg-message "note: previous declaration of 'svfloat32_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svfloat32_t' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef int svbool_t; /* { dg-message "note: previous declaration of 'svbool_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting types for 'svbool_t'} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef __SVBool_t svbool_t; /* { dg-message "note: previous declaration of 'svbool_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {redefinition of typedef 'svbool_t'} } */
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-std=gnu90" } */
+
+typedef __SVBool_t svbool_t;
+
+/* Without -pedantic-errors this should compile. */
+#pragma GCC aarch64 "arm_sve.h"
--- /dev/null
+/* { dg-do compile } */
+
+int svint8x2_t; /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svint8x2_t' redeclared} } */
--- /dev/null
+/* { dg-do compile } */
+
+typedef int svint8x2_t; /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting types for 'svint8x2_t'} } */
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32)
+{
+ svabs_m (s32, pg); /* { dg-error {too few arguments to function 'svabs_m'} } */
+ svabs_m (s32, pg, s32, s32); /* { dg-error {too many arguments to function 'svabs_m'} } */
+ svabs_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svabs_m', which expects an SVE vector type} } */
+ svabs_m (s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svabs_m', which expects 'svbool_t'} } */
+ svabs_m (s32, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svabs_m', which expects 'svbool_t'} } */
+ svabs_m (s32, pg, s32);
+ svabs_m (u32, pg, u32); /* { dg-error {'svabs_m' has no form that takes 'svuint32_t' arguments} } */
+ svabs_m (f32, pg, f32);
+ svabs_m (s32, pg, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+ svabs_m (s32, pg, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+ svabs_m (s32, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+ svabs_m (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svbool_t'} } */
+ svabs_m (pg, pg, pg); /* { dg-error {'svabs_m' has no form that takes 'svbool_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8)
+{
+ svabs_x (pg); /* { dg-error {too few arguments to function 'svabs_x'} } */
+ svabs_x (pg, s8, s8); /* { dg-error {too many arguments to function 'svabs_x'} } */
+ svabs_x (s8, s8); /* { dg-error {passing 'svint8_t' to argument 1 of 'svabs_x', which expects 'svbool_t'} } */
+ svabs_x (pg, pg); /* { dg-error {'svabs_x' has no form that takes 'svbool_t' arguments} } */
+ svabs_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svabs_x', which expects an SVE vector type} } */
+ svabs_x (pg, s8);
+ svabs_x (pg, u8); /* { dg-error {'svabs_x' has no form that takes 'svuint8_t' arguments} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, svfloat16_t f16, svfloat32_t f32,
+ svfloat64_t f64)
+{
+ svcvt_f64_x (pg); /* { dg-error {too few arguments to function 'svcvt_f64_x'} } */
+ svcvt_f64_x (pg, s32, 0); /* { dg-error {too many arguments to function 'svcvt_f64_x'} } */
+ svcvt_f64_x (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svcvt_f64_x', which expects 'svbool_t'} } */
+ svcvt_f64_x (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svcvt_f64_x', which expects an SVE vector type} } */
+
+ svcvt_f64_x (pg, s8); /* { dg-error {'svcvt_f64_x' has no form that takes 'svint8_t' arguments} } */
+ svcvt_f64_x (pg, s16); /* { dg-error {'svcvt_f64_x' has no form that takes 'svint16_t' arguments} } */
+ svcvt_f64_x (pg, s32);
+ svcvt_f64_x (pg, s64);
+ svcvt_f64_x (pg, u8); /* { dg-error {'svcvt_f64_x' has no form that takes 'svuint8_t' arguments} } */
+ svcvt_f64_x (pg, u16); /* { dg-error {'svcvt_f64_x' has no form that takes 'svuint16_t' arguments} } */
+ svcvt_f64_x (pg, u32);
+ svcvt_f64_x (pg, u64);
+ svcvt_f64_x (pg, f16);
+ svcvt_f64_x (pg, f32);
+ svcvt_f64_x (pg, f64); /* { dg-error {'svcvt_f64_x' has no form that takes 'svfloat64_t' arguments} } */
+
+ svcvt_f32_x (pg, s8); /* { dg-error {'svcvt_f32_x' has no form that takes 'svint8_t' arguments} } */
+ svcvt_f32_x (pg, s16); /* { dg-error {'svcvt_f32_x' has no form that takes 'svint16_t' arguments} } */
+ svcvt_f32_x (pg, s32);
+ svcvt_f32_x (pg, s64);
+ svcvt_f32_x (pg, u8); /* { dg-error {'svcvt_f32_x' has no form that takes 'svuint8_t' arguments} } */
+ svcvt_f32_x (pg, u16); /* { dg-error {'svcvt_f32_x' has no form that takes 'svuint16_t' arguments} } */
+ svcvt_f32_x (pg, u32);
+ svcvt_f32_x (pg, u64);
+ svcvt_f32_x (pg, f16);
+ svcvt_f32_x (pg, f32); /* { dg-error {'svcvt_f32_x' has no form that takes 'svfloat32_t' arguments} } */
+ svcvt_f32_x (pg, f64);
+
+ svcvt_f16_x (pg, s8); /* { dg-error {'svcvt_f16_x' has no form that takes 'svint8_t' arguments} } */
+ svcvt_f16_x (pg, s16);
+ svcvt_f16_x (pg, s32);
+ svcvt_f16_x (pg, s64);
+ svcvt_f16_x (pg, u8); /* { dg-error {'svcvt_f16_x' has no form that takes 'svuint8_t' arguments} } */
+ svcvt_f16_x (pg, u16);
+ svcvt_f16_x (pg, u32);
+ svcvt_f16_x (pg, u64);
+ svcvt_f16_x (pg, f16); /* { dg-error {'svcvt_f16_x' has no form that takes 'svfloat16_t' arguments} } */
+ svcvt_f16_x (pg, f32);
+ svcvt_f16_x (pg, f64);
+
+ svcvt_s64_x (pg, f16);
+ svcvt_s64_x (pg, f32);
+ svcvt_s64_x (pg, f64);
+
+ svcvt_s32_x (pg, f16);
+ svcvt_s32_x (pg, f32);
+ svcvt_s32_x (pg, f64);
+
+ svcvt_s16_x (pg, f16);
+ svcvt_s16_x (pg, f32); /* { dg-error {'svcvt_s16_x' has no form that takes 'svfloat32_t' arguments} } */
+ svcvt_s16_x (pg, f64); /* { dg-error {'svcvt_s16_x' has no form that takes 'svfloat64_t' arguments} } */
+
+ svcvt_u64_x (pg, f16);
+ svcvt_u64_x (pg, f32);
+ svcvt_u64_x (pg, f64);
+
+ svcvt_u32_x (pg, f16);
+ svcvt_u32_x (pg, f32);
+ svcvt_u32_x (pg, f64);
+
+ svcvt_u16_x (pg, f16);
+ svcvt_u16_x (pg, f32); /* { dg-error {'svcvt_u16_x' has no form that takes 'svfloat32_t' arguments} } */
+ svcvt_u16_x (pg, f64); /* { dg-error {'svcvt_u16_x' has no form that takes 'svfloat64_t' arguments} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+ svint64_t s64, svuint64_t u64, svfloat16_t f16, svfloat32_t f32,
+ svfloat64_t f64)
+{
+ svcvt_f64_m (f64, pg); /* { dg-error {too few arguments to function 'svcvt_f64_m'} } */
+ svcvt_f64_m (f64, pg, s32, 0); /* { dg-error {too many arguments to function 'svcvt_f64_m'} } */
+ svcvt_f64_m (f32, pg, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+ svcvt_f64_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+ svcvt_f64_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+ svcvt_f64_m (f64, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcvt_f64_m', which expects 'svbool_t'} } */
+ svcvt_f64_m (f64, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svcvt_f64_m', which expects an SVE vector type} } */
+
+ svcvt_f64_m (f64, pg, s8); /* { dg-error {'svcvt_f64_m' has no form that takes 'svint8_t' arguments} } */
+ svcvt_f64_m (f64, pg, s16); /* { dg-error {'svcvt_f64_m' has no form that takes 'svint16_t' arguments} } */
+ svcvt_f64_m (f64, pg, s32);
+ svcvt_f64_m (f64, pg, s64);
+ svcvt_f64_m (f64, pg, u8); /* { dg-error {'svcvt_f64_m' has no form that takes 'svuint8_t' arguments} } */
+ svcvt_f64_m (f64, pg, u16); /* { dg-error {'svcvt_f64_m' has no form that takes 'svuint16_t' arguments} } */
+ svcvt_f64_m (f64, pg, u32);
+ svcvt_f64_m (f64, pg, u64);
+ svcvt_f64_m (f64, pg, f16);
+ svcvt_f64_m (f64, pg, f32);
+ svcvt_f64_m (f64, pg, f64); /* { dg-error {'svcvt_f64_m' has no form that takes 'svfloat64_t' arguments} } */
+
+ svcvt_f32_m (f32, pg, s8); /* { dg-error {'svcvt_f32_m' has no form that takes 'svint8_t' arguments} } */
+ svcvt_f32_m (f32, pg, s16); /* { dg-error {'svcvt_f32_m' has no form that takes 'svint16_t' arguments} } */
+ svcvt_f32_m (f32, pg, s32);
+ svcvt_f32_m (f32, pg, s64);
+ svcvt_f32_m (f32, pg, u8); /* { dg-error {'svcvt_f32_m' has no form that takes 'svuint8_t' arguments} } */
+ svcvt_f32_m (f32, pg, u16); /* { dg-error {'svcvt_f32_m' has no form that takes 'svuint16_t' arguments} } */
+ svcvt_f32_m (f32, pg, u32);
+ svcvt_f32_m (f32, pg, u64);
+ svcvt_f32_m (f32, pg, f16);
+ svcvt_f32_m (f32, pg, f32); /* { dg-error {'svcvt_f32_m' has no form that takes 'svfloat32_t' arguments} } */
+ svcvt_f32_m (f32, pg, f64);
+
+ svcvt_f16_m (f16, pg, s8); /* { dg-error {'svcvt_f16_m' has no form that takes 'svint8_t' arguments} } */
+ svcvt_f16_m (f16, pg, s16);
+ svcvt_f16_m (f16, pg, s32);
+ svcvt_f16_m (f16, pg, s64);
+ svcvt_f16_m (f16, pg, u8); /* { dg-error {'svcvt_f16_m' has no form that takes 'svuint8_t' arguments} } */
+ svcvt_f16_m (f16, pg, u16);
+ svcvt_f16_m (f16, pg, u32);
+ svcvt_f16_m (f16, pg, u64);
+ svcvt_f16_m (f16, pg, f16); /* { dg-error {'svcvt_f16_m' has no form that takes 'svfloat16_t' arguments} } */
+ svcvt_f16_m (f16, pg, f32);
+ svcvt_f16_m (f16, pg, f64);
+
+ svcvt_s64_m (s64, pg, f16);
+ svcvt_s64_m (s64, pg, f32);
+ svcvt_s64_m (s64, pg, f64);
+
+ svcvt_s32_m (s32, pg, f16);
+ svcvt_s32_m (s32, pg, f32);
+ svcvt_s32_m (s32, pg, f64);
+
+ svcvt_s16_m (s16, pg, f16);
+ svcvt_s16_m (s16, pg, f32); /* { dg-error {'svcvt_s16_m' has no form that takes 'svfloat32_t' arguments} } */
+ svcvt_s16_m (s16, pg, f64); /* { dg-error {'svcvt_s16_m' has no form that takes 'svfloat64_t' arguments} } */
+
+ svcvt_u64_m (u64, pg, f16);
+ svcvt_u64_m (u64, pg, f32);
+ svcvt_u64_m (u64, pg, f64);
+
+ svcvt_u32_m (u32, pg, f16);
+ svcvt_u32_m (u32, pg, f32);
+ svcvt_u32_m (u32, pg, f64);
+
+ svcvt_u16_m (u16, pg, f16);
+ svcvt_u16_m (u16, pg, f32); /* { dg-error {'svcvt_u16_m' has no form that takes 'svfloat32_t' arguments} } */
+ svcvt_u16_m (u16, pg, f64); /* { dg-error {'svcvt_u16_m' has no form that takes 'svfloat64_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64)
+{
+ svclz_m (u32, pg); /* { dg-error {too few arguments to function 'svclz_m'} } */
+ svclz_m (u32, pg, s32, s32); /* { dg-error {too many arguments to function 'svclz_m'} } */
+ svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE vector type} } */
+ svclz_m (u32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+ svclz_m (u32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+ svclz_m (u32, pg, s32);
+ svclz_m (u32, pg, u32);
+ svclz_m (u32, pg, f32); /* { dg-error {'svclz_m' has no form that takes 'svfloat32_t' arguments} } */
+ svclz_m (u32, pg, pg); /* { dg-error {'svclz_m' has no form that takes 'svbool_t' arguments} } */
+
+ svclz_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (s32, pg, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (f32, pg, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (s64, pg, s32); /* { dg-error {passing 'svint64_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (u64, pg, s32); /* { dg-error {arguments 1 and 3 of 'svclz_m' must have the same element size, but the values passed here have type 'svuint64_t' and 'svint32_t' respectively} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-flax-vector-conversions" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64)
+{
+ svclz_m (u32, pg); /* { dg-error {too few arguments to function 'svclz_m'} } */
+ svclz_m (u32, pg, s32, s32); /* { dg-error {too many arguments to function 'svclz_m'} } */
+ svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE vector type} } */
+ svclz_m (u32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+ svclz_m (u32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+ svclz_m (u32, pg, s32);
+ svclz_m (u32, pg, u32);
+ svclz_m (u32, pg, f32); /* { dg-error {'svclz_m' has no form that takes 'svfloat32_t' arguments} } */
+ svclz_m (u32, pg, pg); /* { dg-error {'svclz_m' has no form that takes 'svbool_t' arguments} } */
+
+ svclz_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (s32, pg, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (f32, pg, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (s64, pg, s32); /* { dg-error {passing 'svint64_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+ svclz_m (u64, pg, s32); /* { dg-error {arguments 1 and 3 of 'svclz_m' must have the same element size, but the values passed here have type 'svuint64_t' and 'svint32_t' respectively} } */
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8)
+{
+ svcnt_x (pg); /* { dg-error {too few arguments to function 'svcnt_x'} } */
+ svcnt_x (pg, u8, u8); /* { dg-error {too many arguments to function 'svcnt_x'} } */
+ svcnt_x (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcnt_x', which expects 'svbool_t'} } */
+ svcnt_x (pg, pg); /* { dg-error {'svcnt_x' has no form that takes 'svbool_t' arguments} } */
+ svcnt_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svcnt_x', which expects an SVE vector type} } */
+ svcnt_x (pg, u8);
+}
--- /dev/null
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+ svexpa (); /* { dg-error {too few arguments to function 'svexpa'} } */
+ svexpa (u16, u16); /* { dg-error {too many arguments to function 'svexpa'} } */
+ svexpa (1); /* { dg-error {passing 'int' to argument 1 of 'svexpa', which expects an SVE vector type} } */
+ svexpa (pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+ svexpa (s8); /* { dg-error {passing 'svint8_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+ svexpa (s16); /* { dg-error {passing 'svint16_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+ svexpa (f16); /* { dg-error {passing 'svfloat16_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+
+ svexpa (u8); /* { dg-error {'svexpa' has no form that takes 'svuint8_t' arguments} } */
+ svexpa (u16);
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+ svint16_t s16, svuint16_t u16, svfloat16_t f16,
+ svint32_t s32, svuint32_t u32, svfloat32_t f32,
+ svint64_t s64, svuint64_t u64, svfloat64_t f64, float f, int i)
+{
+ svunpklo (); /* { dg-error {too few arguments to function 'svunpklo'} } */
+ svunpklo (pg, s8); /* { dg-error {too many arguments to function 'svunpklo'} } */
+ svunpklo (i); /* { dg-error {passing 'int' to argument 1 of 'svunpklo', which expects an SVE vector type} } */
+ svunpklo (f); /* { dg-error {passing 'float' to argument 1 of 'svunpklo', which expects an SVE vector type} } */
+ svunpklo (pg);
+ svunpklo (s8);
+ svunpklo (s16);
+ svunpklo (s32);
+ svunpklo (s64); /* { dg-error {'svunpklo' has no form that takes 'svint64_t' arguments} } */
+ svunpklo (u8);
+ svunpklo (u16);
+ svunpklo (u32);
+ svunpklo (u64); /* { dg-error {'svunpklo' has no form that takes 'svuint64_t' arguments} } */
+ svunpklo (f16); /* { dg-error {'svunpklo' has no form that takes 'svfloat16_t' arguments} } */
+ svunpklo (f32); /* { dg-error {'svunpklo' has no form that takes 'svfloat32_t' arguments} } */
+ svunpklo (f64); /* { dg-error {'svunpklo' has no form that takes 'svfloat64_t' arguments} } */
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+f (svint8_t s8, svuint16_t u16, svfloat32_t f32,
+ svint16x2_t s16x2, svuint32x3_t u32x3, svfloat64x4_t f64x4,
+ svbool_t pg)
+{
+ s8 = no_ret_s8 (); /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */
+ u16 = no_ret_u16 (); /* { dg-error {incompatible types when assigning to type 'svuint16_t' from type 'int'} } */
+ f32 = no_ret_f32 (); /* { dg-error {incompatible types when assigning to type 'svfloat32_t' from type 'int'} } */
+ s16x2 = no_ret_s16x2 (); /* { dg-error {incompatible types when assigning to type 'svint16x2_t' from type 'int'} } */
+ u32x3 = no_ret_u32x3 (); /* { dg-error {incompatible types when assigning to type 'svuint32x3_t' from type 'int'} } */
+ f64x4 = no_ret_f64x4 (); /* { dg-error {incompatible types when assigning to type 'svfloat64x4_t' from type 'int'} } */
+ pg = no_ret_pg (); /* { dg-error {incompatible types when assigning to type 'svbool_t' from type 'int'} } */
+
+ no_pass_args (pg, u16, f32, s16x2, u32x3, f64x4, pg);
+}
--- /dev/null
+#include <arm_sve.h>
+
+void
+f (svint8_t s8, svuint16_t u16, svfloat32_t f32,
+ svint16x2_t s16x2, svuint32x3_t u32x3, svfloat64x4_t f64x4,
+ svbool_t pg)
+{
+ s8 = svlsr_x (pg, s8, 1); /* { dg-error {'svlsr_x' has no form that takes 'svint8_t' arguments} } */
+ u16 = svneg_x (pg, u16); /* { dg-error {'svneg_x' has no form that takes 'svuint16_t' arguments} } */
+ f32 = svclz_x (pg, f32); /* { dg-error {'svclz_x' has no form that takes 'svfloat32_t' arguments} } */
+ s16x2 = svcreate2 (s8); /* { dg-error {too few arguments to function 'svcreate2'} } */
+ u32x3 = svcreate3 (u16, u16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svcreate3', but previous arguments had type 'svuint16_t'} } */
+ f64x4 = svcreate4 (f32, f32, f32, f32, f32); /* { dg-error {too many arguments to function 'svcreate4'} } */
+ pg = svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#include <arm_sve.h>
+
+void
+foo (svint8_t *res1, svint8_t *res2, svbool_t pg, svint8_t a, svint8_t b)
+{
+ *res1 = svadd_m (pg, a, b);
+ *res2 = svadd_m (pg, a, b);
+}
+
+/* { dg-final { scan-tree-dump-times {svadd_s8_m|svadd_m} 1 "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svand_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svand_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tands\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tand\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbic_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svbic_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbics\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrka_m (x, pg, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svbrka_m (x, pg, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkas\tp[0-9]+\.b, p[0-9]+/m,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrka\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrka_z (pg, x);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, int *any)
+{
+ svbool_t res = svbrka_z (pg, x);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkas\tp[0-9]+\.b, p[0-9]+/z,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrka\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrkb_m (x, pg, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svbrkb_m (x, pg, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkbs\tp[0-9]+\.b, p[0-9]+/m,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkb\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrkb_z (pg, x);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, int *any)
+{
+ svbool_t res = svbrkb_z (pg, x);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkbs\tp[0-9]+\.b, p[0-9]+/z,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkb\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrkn_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svbrkn_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkns\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkn\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrkpa_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svbrkpa_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkpas\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkpa\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svbrkpb_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svbrkpb_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkpbs\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkpb\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+ svbool_t res = svcmpeq_wide (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpeq\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpeq (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+ svbool_t res = svcmpeq (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpeq (pg, x, 10);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+ svbool_t res = svcmpeq (pg, x, 10);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpeq\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tcmpeq\t[^\n]*, #10} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svfloat32_t x, svfloat32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpeq (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y, int *any)
+{
+ svbool_t res = svcmpeq (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svfloat32_t x, int *any, svbool_t *ptr)
+{
+ svbool_t res = svcmpeq (pg, x, 0.0);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svfloat32_t x, int *any)
+{
+ svbool_t res = svcmpeq (pg, x, 0.0);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tfcmeq\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\t[^\n]*, #0\.0} 2 } } */
+/* { dg-final { scan-assembler-times {\tptest\t} 4 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cntb_pow2:
+** mov x0, #?32
+** ret
+*/
+uint64_t cntb_pow2 () { return svcntb_pat (SV_POW2); }
+
+/*
+** cntb_vl1:
+** mov x0, #?1
+** ret
+*/
+uint64_t cntb_vl1 () { return svcntb_pat (SV_VL1); }
+
+/*
+** cntb_vl2:
+** mov x0, #?2
+** ret
+*/
+uint64_t cntb_vl2 () { return svcntb_pat (SV_VL2); }
+
+/*
+** cntb_vl3:
+** mov x0, #?3
+** ret
+*/
+uint64_t cntb_vl3 () { return svcntb_pat (SV_VL3); }
+
+/*
+** cntb_vl4:
+** mov x0, #?4
+** ret
+*/
+uint64_t cntb_vl4 () { return svcntb_pat (SV_VL4); }
+
+/*
+** cntb_vl5:
+** mov x0, #?5
+** ret
+*/
+uint64_t cntb_vl5 () { return svcntb_pat (SV_VL5); }
+
+/*
+** cntb_vl6:
+** mov x0, #?6
+** ret
+*/
+uint64_t cntb_vl6 () { return svcntb_pat (SV_VL6); }
+
+/*
+** cntb_vl7:
+** mov x0, #?7
+** ret
+*/
+uint64_t cntb_vl7 () { return svcntb_pat (SV_VL7); }
+
+/*
+** cntb_vl8:
+** mov x0, #?8
+** ret
+*/
+uint64_t cntb_vl8 () { return svcntb_pat (SV_VL8); }
+
+/*
+** cntb_vl16:
+** mov x0, #?16
+** ret
+*/
+uint64_t cntb_vl16 () { return svcntb_pat (SV_VL16); }
+
+/*
+** cntb_vl32:
+** mov x0, #?32
+** ret
+*/
+uint64_t cntb_vl32 () { return svcntb_pat (SV_VL32); }
+
+/*
+** cntb_vl64:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntb_vl64 () { return svcntb_pat (SV_VL64); }
+
+/*
+** cntb_vl128:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntb_vl128 () { return svcntb_pat (SV_VL128); }
+
+/*
+** cntb_vl256:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntb_vl256 () { return svcntb_pat (SV_VL256); }
+
+/*
+** cntb_mul3:
+** mov x0, #?30
+** ret
+*/
+uint64_t cntb_mul3 () { return svcntb_pat (SV_MUL3); }
+
+/*
+** cntb_mul4:
+** mov x0, #?32
+** ret
+*/
+uint64_t cntb_mul4 () { return svcntb_pat (SV_MUL4); }
+
+/*
+** cntb_all:
+** mov x0, #?32
+** ret
+*/
+uint64_t cntb_all () { return svcntb_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cntd_pow2:
+** mov x0, #?4
+** ret
+*/
+uint64_t cntd_pow2 () { return svcntd_pat (SV_POW2); }
+
+/*
+** cntd_vl1:
+** mov x0, #?1
+** ret
+*/
+uint64_t cntd_vl1 () { return svcntd_pat (SV_VL1); }
+
+/*
+** cntd_vl2:
+** mov x0, #?2
+** ret
+*/
+uint64_t cntd_vl2 () { return svcntd_pat (SV_VL2); }
+
+/*
+** cntd_vl3:
+** mov x0, #?3
+** ret
+*/
+uint64_t cntd_vl3 () { return svcntd_pat (SV_VL3); }
+
+/*
+** cntd_vl4:
+** mov x0, #?4
+** ret
+*/
+uint64_t cntd_vl4 () { return svcntd_pat (SV_VL4); }
+
+/*
+** cntd_vl5:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl5 () { return svcntd_pat (SV_VL5); }
+
+/*
+** cntd_vl6:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl6 () { return svcntd_pat (SV_VL6); }
+
+/*
+** cntd_vl7:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl7 () { return svcntd_pat (SV_VL7); }
+
+/*
+** cntd_vl8:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl8 () { return svcntd_pat (SV_VL8); }
+
+/*
+** cntd_vl16:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl16 () { return svcntd_pat (SV_VL16); }
+
+/*
+** cntd_vl32:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl32 () { return svcntd_pat (SV_VL32); }
+
+/*
+** cntd_vl64:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl64 () { return svcntd_pat (SV_VL64); }
+
+/*
+** cntd_vl128:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl128 () { return svcntd_pat (SV_VL128); }
+
+/*
+** cntd_vl256:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntd_vl256 () { return svcntd_pat (SV_VL256); }
+
+/*
+** cntd_mul3:
+** mov x0, #?3
+** ret
+*/
+uint64_t cntd_mul3 () { return svcntd_pat (SV_MUL3); }
+
+/*
+** cntd_mul4:
+** mov x0, #?4
+** ret
+*/
+uint64_t cntd_mul4 () { return svcntd_pat (SV_MUL4); }
+
+/*
+** cntd_all:
+** mov x0, #?4
+** ret
+*/
+uint64_t cntd_all () { return svcntd_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cnth_pow2:
+** mov x0, #?16
+** ret
+*/
+uint64_t cnth_pow2 () { return svcnth_pat (SV_POW2); }
+
+/*
+** cnth_vl1:
+** mov x0, #?1
+** ret
+*/
+uint64_t cnth_vl1 () { return svcnth_pat (SV_VL1); }
+
+/*
+** cnth_vl2:
+** mov x0, #?2
+** ret
+*/
+uint64_t cnth_vl2 () { return svcnth_pat (SV_VL2); }
+
+/*
+** cnth_vl3:
+** mov x0, #?3
+** ret
+*/
+uint64_t cnth_vl3 () { return svcnth_pat (SV_VL3); }
+
+/*
+** cnth_vl4:
+** mov x0, #?4
+** ret
+*/
+uint64_t cnth_vl4 () { return svcnth_pat (SV_VL4); }
+
+/*
+** cnth_vl5:
+** mov x0, #?5
+** ret
+*/
+uint64_t cnth_vl5 () { return svcnth_pat (SV_VL5); }
+
+/*
+** cnth_vl6:
+** mov x0, #?6
+** ret
+*/
+uint64_t cnth_vl6 () { return svcnth_pat (SV_VL6); }
+
+/*
+** cnth_vl7:
+** mov x0, #?7
+** ret
+*/
+uint64_t cnth_vl7 () { return svcnth_pat (SV_VL7); }
+
+/*
+** cnth_vl8:
+** mov x0, #?8
+** ret
+*/
+uint64_t cnth_vl8 () { return svcnth_pat (SV_VL8); }
+
+/*
+** cnth_vl16:
+** mov x0, #?16
+** ret
+*/
+uint64_t cnth_vl16 () { return svcnth_pat (SV_VL16); }
+
+/*
+** cnth_vl32:
+** mov x0, #?0
+** ret
+*/
+uint64_t cnth_vl32 () { return svcnth_pat (SV_VL32); }
+
+/*
+** cnth_vl64:
+** mov x0, #?0
+** ret
+*/
+uint64_t cnth_vl64 () { return svcnth_pat (SV_VL64); }
+
+/*
+** cnth_vl128:
+** mov x0, #?0
+** ret
+*/
+uint64_t cnth_vl128 () { return svcnth_pat (SV_VL128); }
+
+/*
+** cnth_vl256:
+** mov x0, #?0
+** ret
+*/
+uint64_t cnth_vl256 () { return svcnth_pat (SV_VL256); }
+
+/*
+** cnth_mul3:
+** mov x0, #?15
+** ret
+*/
+uint64_t cnth_mul3 () { return svcnth_pat (SV_MUL3); }
+
+/*
+** cnth_mul4:
+** mov x0, #?16
+** ret
+*/
+uint64_t cnth_mul4 () { return svcnth_pat (SV_MUL4); }
+
+/*
+** cnth_all:
+** mov x0, #?16
+** ret
+*/
+uint64_t cnth_all () { return svcnth_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cntw_pow2:
+** mov x0, #?8
+** ret
+*/
+uint64_t cntw_pow2 () { return svcntw_pat (SV_POW2); }
+
+/*
+** cntw_vl1:
+** mov x0, #?1
+** ret
+*/
+uint64_t cntw_vl1 () { return svcntw_pat (SV_VL1); }
+
+/*
+** cntw_vl2:
+** mov x0, #?2
+** ret
+*/
+uint64_t cntw_vl2 () { return svcntw_pat (SV_VL2); }
+
+/*
+** cntw_vl3:
+** mov x0, #?3
+** ret
+*/
+uint64_t cntw_vl3 () { return svcntw_pat (SV_VL3); }
+
+/*
+** cntw_vl4:
+** mov x0, #?4
+** ret
+*/
+uint64_t cntw_vl4 () { return svcntw_pat (SV_VL4); }
+
+/*
+** cntw_vl5:
+** mov x0, #?5
+** ret
+*/
+uint64_t cntw_vl5 () { return svcntw_pat (SV_VL5); }
+
+/*
+** cntw_vl6:
+** mov x0, #?6
+** ret
+*/
+uint64_t cntw_vl6 () { return svcntw_pat (SV_VL6); }
+
+/*
+** cntw_vl7:
+** mov x0, #?7
+** ret
+*/
+uint64_t cntw_vl7 () { return svcntw_pat (SV_VL7); }
+
+/*
+** cntw_vl8:
+** mov x0, #?8
+** ret
+*/
+uint64_t cntw_vl8 () { return svcntw_pat (SV_VL8); }
+
+/*
+** cntw_vl16:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntw_vl16 () { return svcntw_pat (SV_VL16); }
+
+/*
+** cntw_vl32:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntw_vl32 () { return svcntw_pat (SV_VL32); }
+
+/*
+** cntw_vl64:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntw_vl64 () { return svcntw_pat (SV_VL64); }
+
+/*
+** cntw_vl128:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntw_vl128 () { return svcntw_pat (SV_VL128); }
+
+/*
+** cntw_vl256:
+** mov x0, #?0
+** ret
+*/
+uint64_t cntw_vl256 () { return svcntw_pat (SV_VL256); }
+
+/*
+** cntw_mul3:
+** mov x0, #?6
+** ret
+*/
+uint64_t cntw_mul3 () { return svcntw_pat (SV_MUL3); }
+
+/*
+** cntw_mul4:
+** mov x0, #?8
+** ret
+*/
+uint64_t cntw_mul4 () { return svcntw_pat (SV_MUL4); }
+
+/*
+** cntw_all:
+** mov x0, #?8
+** ret
+*/
+uint64_t cntw_all () { return svcntw_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* { dg-options "-g" } */
+
+#include <arm_sve.h>
+
+svbool_t f_b (svbool_t x) { return x; }
+svint8_t f_s8 (svint8_t x) { return x; }
+svuint8_t f_u8 (svuint8_t x) { return x; }
+svint16_t f_s16 (svint16_t x) { return x; }
+svuint16_t f_u16 (svuint16_t x) { return x; }
+svfloat16_t f_f16 (svfloat16_t x) { return x; }
+svint32_t f_s32 (svint32_t x) { return x; }
+svuint32_t f_u32 (svuint32_t x) { return x; }
+svfloat32_t f_f32 (svfloat32_t x) { return x; }
+svint64_t f_s64 (svint64_t x) { return x; }
+svuint64_t f_u64 (svuint64_t x) { return x; }
+svfloat64_t f_f64 (svfloat64_t x) { return x; }
--- /dev/null
+/* { dg-options "-g" } */
+
+#include <arm_sve.h>
+
+svbool_t f_b (svbool_t x) { return svptrue_b32 (); }
+svint8_t f_s8 (svint8_t x) { return svdup_s8 (0); }
+svuint8_t f_u8 (svuint8_t x) { return svdup_u8 (1); }
+svint16_t f_s16 (svint16_t x) { return svdup_s16 (2); }
+svuint16_t f_u16 (svuint16_t x) { return svdup_u16 (3); }
+svfloat16_t f_f16 (svfloat16_t x) { return svdup_f16 (4); }
+svint32_t f_s32 (svint32_t x) { return svdup_s32 (5); }
+svuint32_t f_u32 (svuint32_t x) { return svdup_u32 (6); }
+svfloat32_t f_f32 (svfloat32_t x) { return svdup_f32 (7); }
+svint64_t f_s64 (svint64_t x) { return svdup_s64 (8); }
+svuint64_t f_u64 (svuint64_t x) { return svdup_u64 (9); }
+svfloat64_t f_f64 (svfloat64_t x) { return svdup_f64 (10); }
--- /dev/null
+/* { dg-options "-g" } */
+
+#include <arm_sve.h>
+
+svint8x2_t f2_s8 (svint8x2_t x) { return x; }
+svuint8x2_t f2_u8 (svuint8x2_t x) { return x; }
+svint16x2_t f2_s16 (svint16x2_t x) { return x; }
+svuint16x2_t f2_u16 (svuint16x2_t x) { return x; }
+svfloat16x2_t f2_f16 (svfloat16x2_t x) { return x; }
+svint32x2_t f2_s32 (svint32x2_t x) { return x; }
+svuint32x2_t f2_u32 (svuint32x2_t x) { return x; }
+svfloat32x2_t f2_f32 (svfloat32x2_t x) { return x; }
+svint64x2_t f2_s64 (svint64x2_t x) { return x; }
+svuint64x2_t f2_u64 (svuint64x2_t x) { return x; }
+svfloat64x2_t f2_f64 (svfloat64x2_t x) { return x; }
+
+svint8x3_t f3_s8 (svint8x3_t x) { return x; }
+svuint8x3_t f3_u8 (svuint8x3_t x) { return x; }
+svint16x3_t f3_s16 (svint16x3_t x) { return x; }
+svuint16x3_t f3_u16 (svuint16x3_t x) { return x; }
+svfloat16x3_t f3_f16 (svfloat16x3_t x) { return x; }
+svint32x3_t f3_s32 (svint32x3_t x) { return x; }
+svuint32x3_t f3_u32 (svuint32x3_t x) { return x; }
+svfloat32x3_t f3_f32 (svfloat32x3_t x) { return x; }
+svint64x3_t f3_s64 (svint64x3_t x) { return x; }
+svuint64x3_t f3_u64 (svuint64x3_t x) { return x; }
+svfloat64x3_t f3_f64 (svfloat64x3_t x) { return x; }
+
+svint8x4_t f4_s8 (svint8x4_t x) { return x; }
+svuint8x4_t f4_u8 (svuint8x4_t x) { return x; }
+svint16x4_t f4_s16 (svint16x4_t x) { return x; }
+svuint16x4_t f4_u16 (svuint16x4_t x) { return x; }
+svfloat16x4_t f4_f16 (svfloat16x4_t x) { return x; }
+svint32x4_t f4_s32 (svint32x4_t x) { return x; }
+svuint32x4_t f4_u32 (svuint32x4_t x) { return x; }
+svfloat32x4_t f4_f42 (svfloat32x4_t x) { return x; }
+svint64x4_t f4_s64 (svint64x4_t x) { return x; }
+svuint64x4_t f4_u64 (svuint64x4_t x) { return x; }
+svfloat64x4_t f4_f64 (svfloat64x4_t x) { return x; }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* It doesn't really matter if this produces errors about redefinitions,
+ but it mustn't trigger an ICE. */
+#pragma GCC aarch64 "arm_sve.h"
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "duplicate definition of 'arm_sve.h'" } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlittle-endian" } */
+
+#include <arm_sve.h>
+
+svint32_t
+dupq (int x)
+{
+ return svdupq_s32 (x, 1, 2, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[0\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t1\n\t\.word\t2\n\t\.word\t3\n} } } */
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t __attribute__ ((noipa))
+make_b8 (int8_t x0, int8_t x1, int8_t x2, int8_t x3,
+ int8_t x4, int8_t x5, int8_t x6, int8_t x7,
+ int8_t x8, int8_t x9, int8_t xa, int8_t xb,
+ int8_t xc, int8_t xd, int8_t xe, int8_t xf)
+{
+ return svdupq_b8 (x0, x1, x2, x3, x4, x5, x6, x7,
+ x8, x9, xa, xb, xc, xd, xe, xf);
+}
+
+svbool_t __attribute__ ((noipa))
+make_b16 (int16_t x0, int16_t x1, int16_t x2, int16_t x3,
+ int16_t x4, int16_t x5, int16_t x6, int16_t x7)
+{
+ return svdupq_b16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svbool_t __attribute__ ((noipa))
+make_b32 (int32_t x0, int32_t x1, int32_t x2, int32_t x3)
+{
+ return svdupq_b32 (x0, x1, x2, x3);
+}
+
+svbool_t __attribute__ ((noipa))
+make_b64 (int64_t x0, int64_t x1)
+{
+ return svdupq_b64 (x0, x1);
+}
+
+int8_t a[16] = { 1, 0, 0, -3, 0, 9, 11, 0, 0, 1, 0, -4, 9, 9, 0, 0 };
+
+int
+main ()
+{
+ svbool_t pg = svptrue_pat_b8 (SV_VL16);
+ svbool_t b8 = make_b8 (a[0], a[1], a[2], a[3],
+ a[4], a[5], a[6], a[7],
+ a[8], a[9], a[10], a[11],
+ a[12], a[13], a[14], a[15]);
+ if (svptest_any (svptrue_b8 (),
+ sveor_z (pg, b8, svcmpne (pg, svld1 (pg, a), 0))))
+ __builtin_abort ();
+
+ svbool_t b16 = make_b16 (a[0], a[1], a[2], a[3],
+ a[4], a[5], a[6], a[7]);
+ if (svptest_any (svptrue_b16 (),
+ sveor_z (pg, b16, svcmpne (pg, svld1sb_u16 (pg, a), 0))))
+ __builtin_abort ();
+
+ svbool_t b32 = make_b32 (a[0], a[1], a[2], a[3]);
+ if (svptest_any (svptrue_b32 (),
+ sveor_z (pg, b32, svcmpne (pg, svld1sb_u32 (pg, a), 0))))
+ __builtin_abort ();
+
+ svbool_t b64 = make_b64 (a[0], a[1]);
+ if (svptest_any (svptrue_b64 (),
+ sveor_z (pg, b64, svcmpne (pg, svld1sb_u64 (pg, a), 0))))
+ __builtin_abort ();
+
+ return 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+/* To avoid needing big-endian header files. */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x)
+{
+ return svdupq_s32 (x, 1, 2, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[0\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t3\n\t\.word\t2\n\t\.word\t1\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlittle-endian" } */
+
+/* To avoid needing big-endian header files. */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x)
+{
+ return svdupq_s32 (0, 1, x, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t0\n\t\.word\t1\n\t\.word\t[^\n]*\n\t\.word\t3\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+/* To avoid needing big-endian header files. */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x)
+{
+ return svdupq_s32 (0, 1, x, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t3\n\t\.word\t[^\n]*\n\t\.word\t1\n\t\.word\t0\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlittle-endian" } */
+
+#include <arm_sve.h>
+
+svint32_t
+dupq (int x1, int x2, int x3, int x4)
+{
+ return svdupq_s32 (x1, x2, x3, x4);
+}
+
+/* { dg-final { scan-assembler-not {\tldr\t} } } */
+/* { dg-final { scan-assembler {, [wx]0\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[1\], w1\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w2\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[3\], w3\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+/* To avoid needing big-endian header files. */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x1, int x2, int x3, int x4)
+{
+ return svdupq_s32 (x1, x2, x3, x4);
+}
+
+/* { dg-final { scan-assembler-not {\tldr\t} } } */
+/* { dg-final { scan-assembler {, [wx]0\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[1\], w1\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w2\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[3\], w3\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svint8_t __attribute__ ((noipa))
+make_s8 (int8_t x0, int8_t x1, int8_t x2, int8_t x3,
+ int8_t x4, int8_t x5, int8_t x6, int8_t x7,
+ int8_t x8, int8_t x9, int8_t xa, int8_t xb,
+ int8_t xc, int8_t xd, int8_t xe, int8_t xf)
+{
+ return svdupq_s8 (x0, x1, x2, x3, x4, x5, x6, x7,
+ x8, x9, xa, xb, xc, xd, xe, xf);
+}
+
+svint16_t __attribute__ ((noipa))
+make_s16 (int16_t x0, int16_t x1, int16_t x2, int16_t x3,
+ int16_t x4, int16_t x5, int16_t x6, int16_t x7)
+{
+ return svdupq_s16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svint32_t __attribute__ ((noipa))
+make_s32 (int32_t x0, int32_t x1, int32_t x2, int32_t x3)
+{
+ return svdupq_s32 (x0, x1, x2, x3);
+}
+
+svint64_t __attribute__ ((noipa))
+make_s64 (int64_t x0, int64_t x1)
+{
+ return svdupq_s64 (x0, x1);
+}
+
+int8_t a[16] = { 1, -44, 91, -24, 101, -55, 77, 83,
+ -30, 69, 121, -128, -1, 13, 127, 26 };
+int16_t b[8] = { -716, -10288, 30604, -19258, -9418, -10435, -16001, 7300 };
+int32_t c[4] = { 1268374995, -1023602831, -891830021, -1793452959 };
+int64_t d[2] = { 0x123456789abcdefLL, -0x123456789abcdefLL };
+
+int
+main ()
+{
+ svbool_t pg = svptrue_pat_b8 (SV_VL16);
+ svint8_t s8 = make_s8 (a[0], a[1], a[2], a[3],
+ a[4], a[5], a[6], a[7],
+ a[8], a[9], a[10], a[11],
+ a[12], a[13], a[14], a[15]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, s8, svld1 (pg, a))))
+ __builtin_abort ();
+
+ svint16_t s16 = make_s16 (b[0], b[1], b[2], b[3],
+ b[4], b[5], b[6], b[7]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, s16, svld1 (pg, b))))
+ __builtin_abort ();
+
+ svint32_t s32 = make_s32 (c[0], c[1], c[2], c[3]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, s32, svld1 (pg, c))))
+ __builtin_abort ();
+
+ svint64_t s64 = make_s64 (d[0], d[1]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, s64, svld1 (pg, d))))
+ __builtin_abort ();
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svuint8_t __attribute__ ((noipa))
+make_u8 (uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
+ uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7,
+ uint8_t x8, uint8_t x9, uint8_t xa, uint8_t xb,
+ uint8_t xc, uint8_t xd, uint8_t xe, uint8_t xf)
+{
+ return svdupq_u8 (x0, x1, x2, x3, x4, x5, x6, x7,
+ x8, x9, xa, xb, xc, xd, xe, xf);
+}
+
+svuint16_t __attribute__ ((noipa))
+make_u16 (uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3,
+ uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7)
+{
+ return svdupq_u16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svuint32_t __attribute__ ((noipa))
+make_u32 (uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3)
+{
+ return svdupq_u32 (x0, x1, x2, x3);
+}
+
+svuint64_t __attribute__ ((noipa))
+make_u64 (uint64_t x0, uint64_t x1)
+{
+ return svdupq_u64 (x0, x1);
+}
+
+uint8_t a[16] = { 1, 212, 91, 232, 101, 201, 77, 83,
+ 226, 69, 121, 128, 255, 13, 127, 26 };
+uint16_t b[8] = { 64820, 55248, 30604, 46278, 56118, 55101, 49535, 7300 };
+uint32_t c[4] = { 1268374995, 3271364465, 3403137275, 2501514337 };
+uint64_t d[2] = { 0x123456789abcdefULL, 0xfedcba9876543210ULL };
+
+int
+main ()
+{
+ svbool_t pg = svptrue_pat_b8 (SV_VL16);
+ svuint8_t u8 = make_u8 (a[0], a[1], a[2], a[3],
+ a[4], a[5], a[6], a[7],
+ a[8], a[9], a[10], a[11],
+ a[12], a[13], a[14], a[15]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, u8, svld1 (pg, a))))
+ __builtin_abort ();
+
+ svuint16_t u16 = make_u16 (b[0], b[1], b[2], b[3],
+ b[4], b[5], b[6], b[7]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, u16, svld1 (pg, b))))
+ __builtin_abort ();
+
+ svuint32_t u32 = make_u32 (c[0], c[1], c[2], c[3]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, u32, svld1 (pg, c))))
+ __builtin_abort ();
+
+ svuint64_t u64 = make_u64 (d[0], d[1]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, u64, svld1 (pg, d))))
+ __builtin_abort ();
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svfloat16_t __attribute__ ((noipa))
+make_f16 (float16_t x0, float16_t x1, float16_t x2, float16_t x3,
+ float16_t x4, float16_t x5, float16_t x6, float16_t x7)
+{
+ return svdupq_f16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svfloat32_t __attribute__ ((noipa))
+make_f32 (float32_t x0, float32_t x1, float32_t x2, float32_t x3)
+{
+ return svdupq_f32 (x0, x1, x2, x3);
+}
+
+svfloat64_t __attribute__ ((noipa))
+make_f64 (float64_t x0, float64_t x1)
+{
+ return svdupq_f64 (x0, x1);
+}
+
+float16_t a[8] = { 1.0, -4.25, 9.75, 6.5, -2.125, 5.5, -3.75, 7.625 };
+float32_t b[4] = { 1.0, -90.25, -11.75, 141.5 };
+float64_t c[2] = { 9221.5, -4491.25 };
+
+int
+main ()
+{
+ svbool_t pg = svptrue_pat_b8 (SV_VL16);
+ svfloat16_t f16 = make_f16 (a[0], a[1], a[2], a[3],
+ a[4], a[5], a[6], a[7]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, f16, svld1 (pg, a))))
+ __builtin_abort ();
+
+ svfloat32_t f32 = make_f32 (b[0], b[1], b[2], b[3]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, f32, svld1 (pg, b))))
+ __builtin_abort ();
+
+ svfloat64_t f64 = make_f64 (c[0], c[1]);
+ if (svptest_any (svptrue_b8 (), svcmpne (pg, f64, svld1 (pg, c))))
+ __builtin_abort ();
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+#ifndef TYPE
+#define TYPE svint8_t
+#define DUPQ svdupq_lane_s8
+#define INDEX svindex_s8
+#define COUNT 16
+#endif
+
+#define BASE 42
+
+TYPE __attribute__ ((noipa))
+dupq_var (TYPE x, uint64_t y)
+{
+ return DUPQ (x, y);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_0 (TYPE x)
+{
+ return DUPQ (x, 0);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_1 (TYPE x)
+{
+ return DUPQ (x, 1);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_2 (TYPE x)
+{
+ return DUPQ (x, 2);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_3 (TYPE x)
+{
+ return DUPQ (x, 3);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_4 (TYPE x)
+{
+ return DUPQ (x, 4);
+}
+
+void __attribute__ ((noipa))
+check (TYPE x, uint64_t y)
+{
+ svbool_t pg = svptrue_b8 ();
+ if (y * 2 >= svcntd ())
+ {
+ if (svptest_any (pg, svcmpne (pg, x, 0)))
+ __builtin_abort ();
+ }
+ else
+ {
+ TYPE repeat = svand_x (pg, INDEX (0, 1), COUNT - 1);
+ TYPE expected = svadd_x (pg, repeat, BASE + y * COUNT);
+ if (svptest_any (pg, svcmpne (pg, x, expected)))
+ __builtin_abort ();
+ }
+}
+
+int
+main ()
+{
+ TYPE x = INDEX (BASE, 1);
+
+ check (dupq_0 (x), 0);
+ check (dupq_1 (x), 1);
+ check (dupq_2 (x), 2);
+ check (dupq_3 (x), 3);
+ check (dupq_4 (x), 4);
+
+ for (int i = 0; i < 63; ++i)
+ {
+ check (dupq_var (x, i), i);
+ check (dupq_var (x, (uint64_t) 1 << i), (uint64_t) 1 << i);
+ }
+
+ return 0;
+}
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint8_t
+#define DUPQ svdupq_lane_u8
+#define INDEX svindex_u8
+#define COUNT 16
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svint16_t
+#define DUPQ svdupq_lane_s16
+#define INDEX svindex_s16
+#define COUNT 8
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint16_t
+#define DUPQ svdupq_lane_u16
+#define INDEX svindex_u16
+#define COUNT 8
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svint32_t
+#define DUPQ svdupq_lane_s32
+#define INDEX svindex_s32
+#define COUNT 4
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint32_t
+#define DUPQ svdupq_lane_u32
+#define INDEX svindex_u32
+#define COUNT 4
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svint64_t
+#define DUPQ svdupq_lane_s64
+#define INDEX svindex_s64
+#define COUNT 2
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint64_t
+#define DUPQ svdupq_lane_u64
+#define INDEX svindex_u64
+#define COUNT 2
+
+#include "dupq_lane_1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = sveor_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = sveor_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\teors\t} 2 } } */
+/* { dg-final { scan-assembler-not {\teor\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** nop1:
+** ret
+*/
+void nop1 (int8_t *s) { svld1 (svptrue_b8 (), s); }
+
+/*
+** nop2:
+** ret
+*/
+void nop2 (svbool_t pg, int16_t *s) { svld1 (pg, s); }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that SETFFR comes first, however high the priority of the
+ LDFF1 is. */
+svint8_t
+foo (svbool_t pg, int8_t *ptr)
+{
+ svsetffr ();
+ svint8_t x = svldff1 (pg, ptr);
+ x = svadd_x (pg, x, x);
+ x = svmul_x (pg, x, x);
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that RDFFR comes after the LDFF1 and that the RDFFRs can
+ be CSEd. */
+svint8_t
+foo (svbool_t pg, int8_t *__restrict ptr,
+ svbool_t *__restrict *__restrict preds)
+{
+ svsetffr ();
+ svint8_t x = svldff1 (pg, ptr);
+ *preds[0] = svrdffr ();
+ *preds[1] = svrdffr ();
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffr\t} } } */
+/* { dg-final { scan-assembler-times {\trdffr\t} 1 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that LDFF1s can be reordered. The load of x should come due
+ to its longer dependence chain. */
+svint8_t
+foo (int8_t *ptr1, int8_t *ptr2)
+{
+ svsetffr ();
+ svbool_t pg = svptrue_b8 ();
+ svint8_t y = svldff1 (pg, ptr2);
+ svint8_t x = svldff1 (pg, ptr1);
+ x = svadd_x (pg, x, x);
+ x = svmul_x (pg, x, x);
+ x = svadd_x (pg, x, y);
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tldff1b\tz[0-9]+\.b, p[0-7]/z, \[x0\]\n.*\tldff1b\tz[0-9]+\.b, p[0-7]/z, \[x1\]\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to test for a fault. */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, int *fault)
+{
+ svsetffr ();
+ svint8_t x = svldff1 (pg, ptr);
+ *fault = svptest_any (pg, svrdffr_z (pg));
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to read the FFR while testing for a
+ fault. */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, svbool_t *pred, int *fault)
+{
+ svsetffr ();
+ svint8_t x = svldff1 (pg, ptr);
+ svbool_t ffr = svrdffr_z (pg);
+ *fault = svptest_any (pg, ffr);
+ *pred = ffr;
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to test for a fault. */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, int *fault)
+{
+ svsetffr ();
+ svint8_t x = svldff1 (pg, ptr);
+ *fault = svptest_any (svptrue_b8 (), svrdffr ());
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to read the FFR while testing for a
+ fault. */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, svbool_t *pred, int *fault)
+{
+ svsetffr ();
+ svint8_t x = svldff1 (pg, ptr);
+ svbool_t ffr = svrdffr ();
+ *fault = svptest_any (svptrue_b8 (), ffr);
+ *pred = ffr;
+ return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svnand_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svnand_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tnands\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tnand\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svnor_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svnor_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tnors\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tnor\t} } } */
--- /dev/null
+/* { dg-options "-march=armv8-a" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f (svbool_t *x, svint8_t *y)
+{
+ *x = svptrue_b8 (); /* { dg-error {ACLE function '(svbool_t svptrue_b8\(\)|svptrue_b8)' requires ISA extension 'sve'} } */
+ /* { dg-message {note: you can enable 'sve' using the command-line option '-march', or by using the 'target' attribute or pragma} "" { target *-*-* } .-1 } */
+ *x = svptrue_b8 ();
+ *x = svptrue_b8 ();
+ *x = svptrue_b8 ();
+ *x = svptrue_b8 ();
+ *x = svptrue_b8 ();
+ *x = svptrue_b8 ();
+ *y = svadd_m (*x, *y, 1);
+}
--- /dev/null
+/* { dg-options "-march=armv8-a" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+#pragma GCC target "+sve"
+
+void
+f (svbool_t *x, svint8_t *y)
+{
+ *x = svptrue_b8 ();
+ *y = svadd_m (*x, *y, 1);
+}
+
+/* { dg-final { scan-assembler {\tadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} } } */
--- /dev/null
+/* { dg-options "-march=armv8-a" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void __attribute__ ((target("+sve")))
+f (svbool_t *x, svint8_t *y)
+{
+ *x = svptrue_b8 ();
+ *y = svadd_m (*x, *y, 1);
+}
+
+/* { dg-final { scan-assembler {\tadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svorn_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svorn_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\torns\t} 2 } } */
+/* { dg-final { scan-assembler-not {\torn\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svorr_z (pg, x, y);
+ *any = svptest_any (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+ svbool_t res = svorr_z (pg, x, y);
+ return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\torrs\t} 2 } } */
+/* { dg-final { scan-assembler-not {\torr\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, int *last, svbool_t *ptr)
+{
+ svbool_t res = svpfirst (pg, svpfalse ());
+ *last = svptest_last (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg)
+{
+ svbool_t res = svpfirst (pg, svpfalse ());
+ return svptest_last (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tpfirst\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+ svbool_t res = svpnext_b8 (pg, prev);
+ *last = svptest_last (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t prev)
+{
+ svbool_t res = svpnext_b8 (pg, prev);
+ return svptest_last (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tpnext\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+ svbool_t res = svpnext_b16 (pg, prev);
+ *last = svptest_last (pg, res);
+ *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t prev)
+{
+ svbool_t res = svpnext_b16 (pg, prev);
+ return svptest_last (pg, res);
+}
+
+void
+test3 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+ svbool_t res = svpnext_b32 (pg, prev);
+ *last = svptest_last (pg, res);
+ *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svbool_t prev)
+{
+ svbool_t res = svpnext_b32 (pg, prev);
+ return svptest_last (pg, res);
+}
+
+void
+test5 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+ svbool_t res = svpnext_b64 (pg, prev);
+ *last = svptest_last (pg, res);
+ *ptr = res;
+}
+
+int
+test6 (svbool_t pg, svbool_t prev)
+{
+ svbool_t res = svpnext_b64 (pg, prev);
+ return svptest_last (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tpnext\t} 6 } } */
+/* { dg-final { scan-assembler-times {\tptest\t} 6 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *last, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL32);
+ *last = svptest_last (svptrue_b8 (), res);
+ *ptr = res;
+}
+
+int
+test2 ()
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL32);
+ return svptest_last (svptrue_b8 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.b, vl32\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *last, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL16);
+ *last = svptest_last (svptrue_b16 (), res);
+ *ptr = res;
+}
+
+int
+test2 ()
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL16);
+ return svptest_last (svptrue_b16 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.h, vl16\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *last, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL16);
+ *last = svptest_last (svptrue_b32 (), res);
+ *ptr = res;
+}
+
+int
+test2 ()
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL16);
+ return svptest_last (svptrue_b32 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.s, vl16\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL7);
+ *any = svptest_any (svptrue_b64 (), res);
+ *ptr = res;
+}
+
+int
+test2 ()
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL7);
+ return svptest_any (svptrue_b64 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.d, vl7\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+b8_b16_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL64);
+ *any = svptest_any (svptrue_b16 (), res);
+ *ptr = res;
+}
+
+int
+b8_b16_2 ()
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL64);
+ return svptest_any (svptrue_b16 (), res);
+}
+
+void
+b8_b32_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL32);
+ *any = svptest_any (svptrue_b32 (), res);
+ *ptr = res;
+}
+
+int
+b8_b32_2 ()
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL32);
+ return svptest_any (svptrue_b32 (), res);
+}
+
+void
+b8_b64_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL128);
+ *any = svptest_any (svptrue_b64 (), res);
+ *ptr = res;
+}
+
+int
+b8_b64_2 ()
+{
+ svbool_t res = svptrue_pat_b8 (SV_VL128);
+ return svptest_any (svptrue_b64 (), res);
+}
+
+void
+b16_b8_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL32);
+ *any = svptest_any (svptrue_b8 (), res);
+ *ptr = res;
+}
+
+int
+b16_b8_2 ()
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL32);
+ return svptest_any (svptrue_b8 (), res);
+}
+
+void
+b16_b32_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL16);
+ *any = svptest_any (svptrue_b32 (), res);
+ *ptr = res;
+}
+
+int
+b16_b32_2 ()
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL16);
+ return svptest_any (svptrue_b32 (), res);
+}
+
+void
+b16_b64_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL64);
+ *any = svptest_any (svptrue_b64 (), res);
+ *ptr = res;
+}
+
+int
+b16_b64_2 ()
+{
+ svbool_t res = svptrue_pat_b16 (SV_VL64);
+ return svptest_any (svptrue_b64 (), res);
+}
+
+void
+b32_b8_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL16);
+ *any = svptest_any (svptrue_b8 (), res);
+ *ptr = res;
+}
+
+int
+b32_b8_2 ()
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL16);
+ return svptest_any (svptrue_b8 (), res);
+}
+
+void
+b32_b16_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL6);
+ *any = svptest_any (svptrue_b16 (), res);
+ *ptr = res;
+}
+
+int
+b32_b16_2 ()
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL6);
+ return svptest_any (svptrue_b16 (), res);
+}
+
+void
+b32_b64_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL32);
+ *any = svptest_any (svptrue_b64 (), res);
+ *ptr = res;
+}
+
+int
+b32_b64_2 ()
+{
+ svbool_t res = svptrue_pat_b32 (SV_VL32);
+ return svptest_any (svptrue_b64 (), res);
+}
+
+void
+b64_b8_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL7);
+ *any = svptest_any (svptrue_b8 (), res);
+ *ptr = res;
+}
+
+int
+b64_b8_2 ()
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL7);
+ return svptest_any (svptrue_b8 (), res);
+}
+
+void
+b64_b16_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL16);
+ *any = svptest_any (svptrue_b16 (), res);
+ *ptr = res;
+}
+
+int
+b64_b16_2 ()
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL16);
+ return svptest_any (svptrue_b16 (), res);
+}
+
+void
+b64_b32_1 (int *any, svbool_t *ptr)
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL32);
+ *any = svptest_any (svptrue_b32 (), res);
+ *ptr = res;
+}
+
+int
+b64_b32_2 ()
+{
+ svbool_t res = svptrue_pat_b64 (SV_VL32);
+ return svptest_any (svptrue_b32 (), res);
+}
+
+/* { dg-final { scan-assembler-not {\tptrues\n} } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 48 } } */
+/* { dg-final { scan-assembler-times {\tptest\t} 24 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-additional-options "-O" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** qincb_s32_s:
+** sqincb x0, w0, all, mul #15
+** ret
+*/
+uint64_t qincb_s32_s (int32_t x) { return svqincb (x, 15); }
+
+/*
+** qincb_s32_z:
+** sqincb x([0-9]+), w0, all, mul #15
+** uxtw x0, w\1
+** ret
+*/
+uint64_t qincb_s32_z (int32_t x) { return (uint32_t) svqincb (x, 15); }
+
+/*
+** qincb_u32_s:
+** uqincb (w[0-9]+), all, mul #15
+** sxtw x0, \1
+** ret
+*/
+uint64_t qincb_u32_s (uint32_t x) { return (int32_t) svqincb (x, 15); }
+
+/*
+** qincb_u32_z:
+** uqincb w0, all, mul #15
+** ret
+*/
+uint64_t qincb_u32_z (uint32_t x) { return svqincb (x, 15); }
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+#include <arm_sve.h>
+
+void
+f (svint8x2_t *a, svint8x2_t *b)
+{
+ svint8_t *ptr;
+ svint8x2_t x = *a;
+ *a = *b;
+ a = &x;
+ (void) (a == b);
+ (void) (a != b);
+ (void) (a < b);
+ (void) (a > b);
+ (void) (a <= b);
+ (void) (a >= b);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svwhilele_b8 (x, y);
+ *any = svptest_last (svptrue_b8 (), res);
+ *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+ svbool_t res = svwhilele_b8 (x, y);
+ return svptest_last (svptrue_b8 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b32_u32 (-1, 0);
+}
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_u64 (0x80000000, 0);
+}
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b8_u64 (0x8000000000000001ULL, 0x7ffffffffffffffeULL);
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-7]\.b\n} 3 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svwhilele_b16 (x, y);
+ *any = svptest_last (svptrue_b16 (), res);
+ *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+ svbool_t res = svwhilele_b16 (x, y);
+ return svptest_last (svptrue_b16 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svwhilele_b32 (x, y);
+ *any = svptest_last (svptrue_b32 (), res);
+ *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+ svbool_t res = svwhilele_b32 (x, y);
+ return svptest_last (svptrue_b32 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+ svbool_t res = svwhilele_b64 (x, y);
+ *any = svptest_last (svptrue_b64 (), res);
+ *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+ svbool_t res = svwhilele_b64 (x, y);
+ return svptest_last (svptrue_b64 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b32_s32 (-8, -8);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.[bhsd], vl1\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_s64 (-1, 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl3\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_s32 (0x7ffffffb, 0x7fffffff);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl5\n} } } */
+
+void
+test4 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b8_s64 (svcntb (), svcntb () + 6);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, vl7\n} } } */
+
+void
+test5 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b64_s64 (0, 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.d, vl2\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b32_s32 (-8, -9);
+}
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_s64 (50, -1);
+}
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_s32 (0x7ffffffb, 0x80000000);
+}
+
+void
+test4 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b8_s64 (svcntb (), 15);
+}
+
+void
+test5 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b8_s64 (svcntb (), svcntw ());
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-7]\.b\n} 5 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilel[et]\t} } } */
+/* { dg-final { scan-assembler-not {\tpfalse\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b8_s32 (-svcnth (), svcnth () - 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, all\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_s64 (1, svcntw () * 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, all\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b32_s32 (svcntd (), svcntw () + svcntd () - 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s, all\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b32_u32 (1, 3);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s, vl3\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b16_u64 (svcntd (), svcntd () + 5);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl6\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilele_b8_u32 (0x7ffffffb, 0x80000002);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, vl8\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b32_s32 (-8, -7);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.[bhsd], vl1\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b16_s64 (-1, 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl3\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b16_s32 (0x7ffffffa, 0x7fffffff);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl5\n} } } */
+
+void
+test4 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b8_s64 (svcntb (), svcntb () + 7);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, vl7\n} } } */
+
+void
+test5 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b64_s64 (0, 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.d, vl2\n} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b32_s32 (0, 0);
+}
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b16_s64 (50, -1);
+}
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b16_s32 (0x7ffffffb, 0x80000000);
+}
+
+void
+test4 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b8_s64 (svcntb (), svcntb ());
+}
+
+void
+test5 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b8_s64 (svcntb (), svcntw ());
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-7]\.b\n} 5 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilel[et]\t} } } */
+/* { dg-final { scan-assembler-not {\tpfalse\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b8_s32 (-svcnth (), svcnth ());
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, all\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b16_s64 (0, svcntw () * 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, all\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+ *ptr = svwhilelt_b32_s32 (svcntd (), svcntw () + svcntd ());
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s, all\n} } } */