https://gcc.gnu.org/g:e87b4d0280685c691a56698b40d665eeae41dda3
commit r17-1427-ge87b4d0280685c691a56698b40d665eeae41dda3 Author: Alfie Richards <[email protected]> Date: Mon Jan 5 17:08:15 2026 +0000 aarch64: Add FEAT_FPRCVT support. gcc/ChangeLog: * config/aarch64/aarch64.h (TARGET_FPRCVT): New macro definition. * config/aarch64/aarch64.md (arches): Add fprcvt. (arch_enabled): Add fprcvt. (l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2): Add FEAT_FPRCVT variant. (<optab>_trunchf<GPI:mode>2): Likewise. (<optab>_trunc<fcvt_change_mode><GPI:mode>2): Likewise. (fix_to_zero_extend<mode>di2): Likewise. (<optab><fcvt_iesize><GPF:mode>2): Likewise. (define_insn "aarch64_fp16_<optab><mode>hf2): Likewise. * config/aarch64/iterators.md (fpw): Add SF and DF variants. gcc/testsuite/ChangeLog: * gcc.target/aarch64/acle/fprcvt.c: New test. * gcc.target/aarch64/fprcvt.c: New test. * gcc.target/aarch64/fprcvt.x: New test. * gcc.target/aarch64/fprcvt_float32_int32.c: New test. * gcc.target/aarch64/fprcvt_float32_int64.c: New test. * gcc.target/aarch64/fprcvt_float32_uint32.c: New test. * gcc.target/aarch64/fprcvt_float32_uint64.c: New test. * gcc.target/aarch64/fprcvt_float64_int32.c: New test. * gcc.target/aarch64/fprcvt_float64_int64.c: New test. * gcc.target/aarch64/fprcvt_float64_uint32.c: New test. * gcc.target/aarch64/fprcvt_float64_uint64.c: New test. Diff: --- gcc/config/aarch64/aarch64.h | 2 + gcc/config/aarch64/aarch64.md | 74 ++- gcc/config/aarch64/iterators.md | 2 +- gcc/testsuite/gcc.target/aarch64/acle/fprcvt.c | 651 +++++++++++++++++++++ gcc/testsuite/gcc.target/aarch64/fprcvt.c | 147 +++++ gcc/testsuite/gcc.target/aarch64/fprcvt.x | 87 +++ .../gcc.target/aarch64/fprcvt_float32_int32.c | 18 + .../gcc.target/aarch64/fprcvt_float32_int64.c | 16 + .../gcc.target/aarch64/fprcvt_float32_uint32.c | 18 + .../gcc.target/aarch64/fprcvt_float32_uint64.c | 18 + .../gcc.target/aarch64/fprcvt_float64_int32.c | 18 + .../gcc.target/aarch64/fprcvt_float64_int64.c | 16 + .../gcc.target/aarch64/fprcvt_float64_uint32.c | 18 + .../gcc.target/aarch64/fprcvt_float64_uint64.c | 18 + 14 files changed, 1073 insertions(+), 30 deletions(-) diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 45467991f26c..c3c61c6939c0 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -583,6 +583,8 @@ through +ssve-fp8dot2. */ && (AARCH64_HAVE_ISA (SSVE_FEXPA) \ || TARGET_NON_STREAMING)) +#define TARGET_FPRCVT (AARCH64_HAVE_ISA (FPRCVT)) + /* Standard register usage. */ /* 31 64-bit general purpose registers R0-R30: diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 6c141df40a4b..2cc5b93082cc 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -503,7 +503,7 @@ ;; Q registers and is equivalent to "simd". (define_enum "arches" [any rcpc8_4 fp fp_q base_simd nobase_simd - simd nosimd sve fp16 sme cssc sve2p2_or_sme2p2]) + simd nosimd sve fp16 sme cssc fprcvt sve2p2_or_sme2p2]) (define_enum_attr "arch" "arches" (const_string "any")) @@ -585,7 +585,10 @@ (match_test "TARGET_SME")) (and (eq_attr "arch" "sve2p2_or_sme2p2") - (match_test "TARGET_SVE2p2_OR_SME2p2")))) + (match_test "TARGET_SVE2p2_OR_SME2p2")) + + (and (eq_attr "arch" "fprcvt") + (match_test "TARGET_FPRCVT")))) (const_string "yes") (const_string "no"))) @@ -3156,8 +3159,8 @@ (define_insn "*adds_<optab><ALLX:mode>_shift_<GPI:mode>" [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ - (plus:GPI (ashift:GPI - (ANY_EXTEND:GPI + (plus:GPI (ashift:GPI + (ANY_EXTEND:GPI (match_operand:ALLX 1 "register_operand" "r")) (match_operand 2 "aarch64_imm3" "Ui3")) (match_operand:GPI 3 "register_operand" "rk")) @@ -3175,7 +3178,7 @@ [(set (reg:CC_NZ CC_REGNUM) (compare:CC_NZ (minus:GPI (match_operand:GPI 1 "register_operand" "rk") - (ashift:GPI + (ashift:GPI (ANY_EXTEND:GPI (match_operand:ALLX 2 "register_operand" "r")) (match_operand 3 "aarch64_imm3" "Ui3"))) @@ -7101,13 +7104,15 @@ ;; frcvt floating-point round to integer and convert standard patterns. ;; Expands to lbtrunc, lceil, lfloor, lround. (define_insn "l<fcvt_pattern><su_optab><GPF_F16:mode><GPI:mode>2" - [(set (match_operand:GPI 0 "register_operand" "=r") + [(set (match_operand:GPI 0 "register_operand") (FIXUORS:GPI - (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand" "w")] + (unspec:GPF_F16 [(match_operand:GPF_F16 1 "register_operand")] FCVT)))] - "TARGET_FLOAT" - "fcvt<frint_suffix><su>\\t%<GPI:w>0, %<GPF_F16:s>1" - [(set_attr "type" "f_cvtf2i")] + "" + {@ [ cons: =0 , 1 ; attrs: type , arch ] + [ r , w ; f_cvtf2i , fp ] fcvt<frint_suffix><su>\t%<GPI:w>0, %<GPF_F16:s>1 + [ w , w ; f_cvtf2i , fprcvt ] fcvt<frint_suffix><su>\t%<GPI:v>0, %<GPF_F16:s>1 + } ) (define_insn "*aarch64_fcvt<su_optab><GPF:mode><GPI:mode>2_mult" @@ -7288,32 +7293,38 @@ ;; Convert HF -> SI or DI (define_insn "<optab>_trunchf<GPI:mode>2" - [(set (match_operand:GPI 0 "register_operand" "=r") - (FIXUORS:GPI (match_operand:HF 1 "register_operand" "w")))] + [(set (match_operand:GPI 0 "register_operand") + (FIXUORS:GPI (match_operand:HF 1 "register_operand")))] "TARGET_FP_F16INST" - "fcvtz<su>\t%<w>0, %h1" - [(set_attr "type" "f_cvtf2i")] + {@ [ cons: =0 , 1 ; attrs: type , arch ] + [ r , w ; f_cvtf2i , fp ] fcvtz<su>\t%<w>0, %h1 + [ w , w ; f_cvtf2i , fprcvt ] fcvtz<su>\t%<s>0, %h1 + } ) ;; Convert DF -> SI or SF -> DI which can only be accomplished with ;; input in a fp register and output in a integer register (define_insn "<optab>_trunc<fcvt_change_mode><GPI:mode>2" - [(set (match_operand:GPI 0 "register_operand" "=r") - (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand" "w")))] + [(set (match_operand:GPI 0 "register_operand") + (FIXUORS:GPI (match_operand:<FCVT_CHANGE_MODE> 1 "register_operand")))] "TARGET_FLOAT" - "fcvtz<su>\t%<w>0, %<fpw>1" - [(set_attr "type" "f_cvtf2i")] + {@ [ cons: =0 , 1 ; attrs: type , arch ] + [ r , w ; f_cvtf2i , fp ] fcvtz<su>\t%<w>0, %<fpw>1 + [ w , w ; f_cvtf2i , fprcvt ] fcvtz<su>\t%<s>0, %<fpw>1 + } ) (define_insn "*fix_to_zero_extend<mode>di2" - [(set (match_operand:DI 0 "register_operand" "=r") + [(set (match_operand:DI 0 "register_operand") (zero_extend:DI (unsigned_fix:SI - (match_operand:GPF 1 "register_operand" "w"))))] + (match_operand:GPF 1 "register_operand"))))] "TARGET_FLOAT" - "fcvtzu\t%w0, %<s>1" - [(set_attr "type" "f_cvtf2i")] + {@ [ cons: =0 , 1 ; attrs: type , arch ] + [ r , w ; f_cvtf2i , fp ] fcvtzu\t%w0, %<s>1 + [ w , w ; f_cvtf2i , fprcvt ] fcvtzu\t%s0, %<s>1 + } ) ;; Equal width integer to fp and multiply combine. @@ -7366,10 +7377,13 @@ ;; Unequal width integer to fp conversions. (define_insn "<optab><fcvt_iesize><GPF:mode>2" - [(set (match_operand:GPF 0 "register_operand" "=w") - (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand" "r")))] + [(set (match_operand:GPF 0 "register_operand") + (FLOATUORS:GPF (match_operand:<FCVT_IESIZE> 1 "register_operand")))] "TARGET_FLOAT" - "<su_optab>cvtf\t%<GPF:s>0, %<w2>1" + {@ [ cons: =0 , 1 ; attrs: type , arch ] + [ w , r ; f_cvti2f , fp ] <su_optab>cvtf\t%<GPF:s>0, %<w2>1 + [ w , w ; f_cvti2f , fprcvt ] <su_optab>cvtf\t%<GPF:s>0, %<fpw>1 + } [(set_attr "type" "f_cvti2f")] ) @@ -7381,11 +7395,13 @@ ;; of the mid-end logic. (define_insn "aarch64_fp16_<optab><mode>hf2" - [(set (match_operand:HF 0 "register_operand" "=w") - (FLOATUORS:HF (match_operand:GPI 1 "register_operand" "r")))] + [(set (match_operand:HF 0 "register_operand") + (FLOATUORS:HF (match_operand:GPI 1 "register_operand")))] "TARGET_FP_F16INST" - "<su_optab>cvtf\t%h0, %<w>1" - [(set_attr "type" "f_cvti2f")] + {@ [ cons: =0 , 1 ; attrs: type , arch ] + [ w , r ; f_cvti2f , fp ] <su_optab>cvtf\t%h0, %<w>1 + [ w , w ; f_cvti2f , fprcvt ] <su_optab>cvtf\t%h0, %<v>1 + } ) (define_expand "<optab>sihf2" diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 948dcefa63e9..2d1522a348ac 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -1427,7 +1427,7 @@ (define_mode_attr w2 [(HF "x") (SF "x") (DF "w")]) ;; For width of fp registers in fcvt instruction -(define_mode_attr fpw [(DI "s") (SI "d")]) +(define_mode_attr fpw [(DI "s") (SI "d") (DF "s") (SF "d")]) (define_mode_attr short_mask [(HI "65535") (QI "255")]) diff --git a/gcc/testsuite/gcc.target/aarch64/acle/fprcvt.c b/gcc/testsuite/gcc.target/aarch64/acle/fprcvt.c new file mode 100644 index 000000000000..603e72d8c5a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/fprcvt.c @@ -0,0 +1,651 @@ +/* { dg-do compile } */ +/* { dg-options "-save-temps -fno-inline -O1 -march=armv9-a+fprcvt" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include <stdint.h> +#include <arm_fp16.h> +#include <arm_acle.h> +#include <arm_neon.h> + +#define FORCE_FP_REG(a) asm volatile("fmov %d0, %d1" : "=w"(a) : "w"(a) :) +#define CONVERT_INTRINSIC(T_FROM, T_TO, INTRINSIC) \ + void convert_##INTRINSIC (T_FROM *from, T_TO *to) \ + { \ + T_FROM from_val = *from; \ + FORCE_FP_REG (from_val); \ + T_TO to_val = INTRINSIC (from_val); \ + FORCE_FP_REG (to_val); \ + *to = to_val; \ + } + +CONVERT_INTRINSIC (float32_t, int32_t, vcvts_s32_f32) +/* +** convert_vcvts_s32_f32: +**... +** fcvtzs s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int64_t, vcvts_s64_f32) +/* +** convert_vcvts_s64_f32: +**... +** fcvtzs d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint32_t, vcvts_u32_f32) +/* +** convert_vcvts_u32_f32: +**... +** fcvtzu s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint64_t, vcvts_u64_f32) +/* +** convert_vcvts_u64_f32: +**... +** fcvtzu d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int32_t, vcvtns_s32_f32) +/* +** convert_vcvtns_s32_f32: +**... +** fcvtns s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int64_t, vcvtns_s64_f32) +/* +** convert_vcvtns_s64_f32: +**... +** fcvtns d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint32_t, vcvtns_u32_f32) +/* +** convert_vcvtns_u32_f32: +**... +** fcvtnu s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint64_t, vcvtns_u64_f32) +/* +** convert_vcvtns_u64_f32: +**... +** fcvtnu d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int32_t, vcvtms_s32_f32) +/* +** convert_vcvtms_s32_f32: +**... +** fcvtms s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int64_t, vcvtms_s64_f32) +/* +** convert_vcvtms_s64_f32: +**... +** fcvtms d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint32_t, vcvtms_u32_f32) +/* +** convert_vcvtms_u32_f32: +**... +** fcvtmu s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint64_t, vcvtms_u64_f32) +/* +** convert_vcvtms_u64_f32: +**... +** fcvtmu d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int32_t, vcvtps_s32_f32) +/* +** convert_vcvtps_s32_f32: +**... +** fcvtps s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int64_t, vcvtps_s64_f32) +/* +** convert_vcvtps_s64_f32: +**... +** fcvtps d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint32_t, vcvtps_u32_f32) +/* +** convert_vcvtps_u32_f32: +**... +** fcvtpu s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint64_t, vcvtps_u64_f32) +/* +** convert_vcvtps_u64_f32: +**... +** fcvtpu d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int32_t, vcvtas_s32_f32) +/* +** convert_vcvtas_s32_f32: +**... +** fcvtas s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, int64_t, vcvtas_s64_f32) +/* +** convert_vcvtas_s64_f32: +**... +** fcvtas d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint32_t, vcvtas_u32_f32) +/* +** convert_vcvtas_u32_f32: +**... +** fcvtau s[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float32_t, uint64_t, vcvtas_u64_f32) +/* +** convert_vcvtas_u64_f32: +**... +** fcvtau d[0-9]+, s[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int32_t, vcvtd_s32_f64) +/* +** convert_vcvtd_s32_f64: +**... +** fcvtzs s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int64_t, vcvtd_s64_f64) +/* +** convert_vcvtd_s64_f64: +**... +** fcvtzs d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint32_t, vcvtd_u32_f64) +/* +** convert_vcvtd_u32_f64: +**... +** fcvtzu s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint64_t, vcvtd_u64_f64) +/* +** convert_vcvtd_u64_f64: +**... +** fcvtzu d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int32_t, vcvtnd_s32_f64) +/* +** convert_vcvtnd_s32_f64: +**... +** fcvtns s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int64_t, vcvtnd_s64_f64) +/* +** convert_vcvtnd_s64_f64: +**... +** fcvtns d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint32_t, vcvtnd_u32_f64) +/* +** convert_vcvtnd_u32_f64: +**... +** fcvtnu s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint64_t, vcvtnd_u64_f64) +/* +** convert_vcvtnd_u64_f64: +**... +** fcvtnu d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int32_t, vcvtmd_s32_f64) +/* +** convert_vcvtmd_s32_f64: +**... +** fcvtms s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int64_t, vcvtmd_s64_f64) +/* +** convert_vcvtmd_s64_f64: +**... +** fcvtms d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint32_t, vcvtmd_u32_f64) +/* +** convert_vcvtmd_u32_f64: +**... +** fcvtmu s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint64_t, vcvtmd_u64_f64) +/* +** convert_vcvtmd_u64_f64: +**... +** fcvtmu d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int32_t, vcvtpd_s32_f64) +/* +** convert_vcvtpd_s32_f64: +**... +** fcvtps s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int64_t, vcvtpd_s64_f64) +/* +** convert_vcvtpd_s64_f64: +**... +** fcvtps d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint32_t, vcvtpd_u32_f64) +/* +** convert_vcvtpd_u32_f64: +**... +** fcvtpu s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint64_t, vcvtpd_u64_f64) +/* +** convert_vcvtpd_u64_f64: +**... +** fcvtpu d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int32_t, vcvtad_s32_f64) +/* +** convert_vcvtad_s32_f64: +**... +** fcvtas s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, int64_t, vcvtad_s64_f64) +/* +** convert_vcvtad_s64_f64: +**... +** fcvtas d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint32_t, vcvtad_u32_f64) +/* +** convert_vcvtad_u32_f64: +**... +** fcvtau s[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float64_t, uint64_t, vcvtad_u64_f64) +/* +** convert_vcvtad_u64_f64: +**... +** fcvtau d[0-9]+, d[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int16_t, vcvth_s16_f16) +/* +** convert_vcvth_s16_f16: +**... +** fcvtzs h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int32_t, vcvth_s32_f16) +/* +** convert_vcvth_s32_f16: +**... +** fcvtzs s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int64_t, vcvth_s64_f16) +/* +** convert_vcvth_s64_f16: +**... +** fcvtzs d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint16_t, vcvth_u16_f16) +/* +** convert_vcvth_u16_f16: +**... +** fcvtzu h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint32_t, vcvth_u32_f16) +/* +** convert_vcvth_u32_f16: +**... +** fcvtzu s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint64_t, vcvth_u64_f16) +/* +** convert_vcvth_u64_f16: +**... +** fcvtzu d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int16_t, vcvtah_s16_f16) +/* +** convert_vcvtah_s16_f16: +**... +** fcvtas h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int32_t, vcvtah_s32_f16) +/* +** convert_vcvtah_s32_f16: +**... +** fcvtas s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int64_t, vcvtah_s64_f16) +/* +** convert_vcvtah_s64_f16: +**... +** fcvtas d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint16_t, vcvtah_u16_f16) +/* +** convert_vcvtah_u16_f16: +**... +** fcvtau h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint32_t, vcvtah_u32_f16) +/* +** convert_vcvtah_u32_f16: +**... +** fcvtau s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint64_t, vcvtah_u64_f16) +/* +** convert_vcvtah_u64_f16: +**... +** fcvtau d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int16_t, vcvtmh_s16_f16) +/* +** convert_vcvtmh_s16_f16: +**... +** fcvtms h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int32_t, vcvtmh_s32_f16) +/* +** convert_vcvtmh_s32_f16: +**... +** fcvtms s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int64_t, vcvtmh_s64_f16) +/* +** convert_vcvtmh_s64_f16: +**... +** fcvtms d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint16_t, vcvtmh_u16_f16) +/* +** convert_vcvtmh_u16_f16: +**... +** fcvtmu h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint32_t, vcvtmh_u32_f16) +/* +** convert_vcvtmh_u32_f16: +**... +** fcvtmu s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint64_t, vcvtmh_u64_f16) +/* +** convert_vcvtmh_u64_f16: +**... +** fcvtmu d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int16_t, vcvtnh_s16_f16) +/* +** convert_vcvtnh_s16_f16: +**... +** fcvtns h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int32_t, vcvtnh_s32_f16) +/* +** convert_vcvtnh_s32_f16: +**... +** fcvtns s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int64_t, vcvtnh_s64_f16) +/* +** convert_vcvtnh_s64_f16: +**... +** fcvtns d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint16_t, vcvtnh_u16_f16) +/* +** convert_vcvtnh_u16_f16: +**... +** fcvtnu h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint32_t, vcvtnh_u32_f16) +/* +** convert_vcvtnh_u32_f16: +**... +** fcvtnu s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint64_t, vcvtnh_u64_f16) +/* +** convert_vcvtnh_u64_f16: +**... +** fcvtnu d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int16_t, vcvtph_s16_f16) +/* +** convert_vcvtph_s16_f16: +**... +** fcvtps h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int32_t, vcvtph_s32_f16) +/* +** convert_vcvtph_s32_f16: +**... +** fcvtps s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, int64_t, vcvtph_s64_f16) +/* +** convert_vcvtph_s64_f16: +**... +** fcvtps d[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint16_t, vcvtph_u16_f16) +/* +** convert_vcvtph_u16_f16: +**... +** fcvtpu h[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint32_t, vcvtph_u32_f16) +/* +** convert_vcvtph_u32_f16: +**... +** fcvtpu s[0-9]+, h[0-9]+ +**... +*/ + +CONVERT_INTRINSIC (float16_t, uint64_t, vcvtph_u64_f16) +/* +** convert_vcvtph_u64_f16: +**... +** fcvtpu d[0-9]+, h[0-9]+ +**... +*/ + + +CONVERT_INTRINSIC (int32_t, float32_t, vcvts_f32_s32) +/* +** convert_vcvts_f32_s32: +**... +** scvtf s[0-9]+, s[0-9]+ +**... +*/ +CONVERT_INTRINSIC (uint32_t, float32_t, vcvts_f32_u32) +/* +** convert_vcvts_f32_u32: +**... +** ucvtf s[0-9]+, s[0-9]+ +**... +*/ +CONVERT_INTRINSIC (int64_t, float64_t, vcvtd_f64_s64) +/* +** convert_vcvtd_f64_s64: +**... +** scvtf d[0-9]+, d[0-9]+ +**... +*/ +CONVERT_INTRINSIC (uint64_t, float64_t, vcvtd_f64_u64) +/* +** convert_vcvtd_f64_u64: +**... +** ucvtf d[0-9]+, d[0-9]+ +**... +*/ +CONVERT_INTRINSIC (int16_t, float16_t, vcvth_f16_s16) +/* +** convert_vcvth_f16_s16: +**... +** scvtf h[0-9]+, h[0-9]+ +**... +*/ +CONVERT_INTRINSIC (int32_t, float16_t, vcvth_f16_s32) +/* +** convert_vcvth_f16_s32: +**... +** scvtf h[0-9]+, s[0-9]+ +**... +*/ +CONVERT_INTRINSIC (int64_t, float16_t, vcvth_f16_s64) +/* +** convert_vcvth_f16_s64: +**... +** scvtf h[0-9]+, d[0-9]+ +**... +*/ +CONVERT_INTRINSIC (uint16_t, float16_t, vcvth_f16_u16) +/* +** convert_vcvth_f16_u16: +**... +** ucvtf h[0-9]+, h[0-9]+ +**... +*/ +CONVERT_INTRINSIC (uint32_t, float16_t, vcvth_f16_u32) +/* +** convert_vcvth_f16_u32: +**... +** ucvtf h[0-9]+, s[0-9]+ +**... +*/ +CONVERT_INTRINSIC (uint64_t, float16_t, vcvth_f16_u64) +/* +** convert_vcvth_f16_u64: +**... +** ucvtf h[0-9]+, d[0-9]+ +**... +*/ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt.c b/gcc/testsuite/gcc.target/aarch64/fprcvt.c new file mode 100644 index 000000000000..1bca48b9a153 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt.c @@ -0,0 +1,147 @@ +/* { dg-do compile } */ +/* { dg-options "-save-temps -fno-inline -O2 -march=armv9-a+fprcvt" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include <stdint.h> +#include <arm_fp16.h> +#include <arm_acle.h> +#include <arm_neon.h> + +#define FORCE_FP_REG(a) asm volatile("fmov %d0, %d1" : "=w"(a) : "w"(a) :) +#define CONVERT(T_FROM, T_TO) \ + void convert_##T_FROM##_to_##T_TO (T_FROM *from, T_TO *to) \ + { \ + T_FROM from_val = *from; \ + FORCE_FP_REG (from_val); \ + T_TO to_val = (T_TO) from_val; \ + FORCE_FP_REG (to_val); \ + *to = to_val; \ + } + +/* +** convert_float16_t_to_int32_t: +**... +** fcvtzs s[0-9]+, h[0-9]+ +**... +*/ +CONVERT (float16_t, int32_t) + +/* +** convert_float64_t_to_int32_t: +**... +** fcvtzs s[0-9]+, d[0-9]+ +**... +*/ +CONVERT (float64_t, int32_t) + +/* +** convert_float16_t_to_int64_t: +**... +** fcvtzs d[0-9]+, h[0-9]+ +**... +*/ +CONVERT (float16_t, int64_t) + +/* +** convert_float32_t_to_int64_t: +**... +** fcvtzs d[0-9]+, s[0-9]+ +**... +*/ +CONVERT (float32_t, int64_t) + +/* +** convert_float16_t_to_uint32_t: +**... +** fcvtzu s[0-9]+, h[0-9]+ +**... +*/ +CONVERT (float16_t, uint32_t) + +/* +** convert_float64_t_to_uint32_t: +**... +** fcvtzu s[0-9]+, d[0-9]+ +**... +*/ +CONVERT (float64_t, uint32_t) + +/* +** convert_float16_t_to_uint64_t: +**... +** fcvtzu d[0-9]+, h[0-9]+ +**... +*/ +CONVERT (float16_t, uint64_t) + +/* +** convert_float32_t_to_uint64_t: +**... +** fcvtzu d[0-9]+, s[0-9]+ +**... +*/ +CONVERT (float32_t, uint64_t) + +/* +** convert_int32_t_to_float16_t: +**... +** scvtf h[0-9]+, s[0-9]+ +**... +*/ +CONVERT (int32_t, float16_t) + +/* +** convert_int32_t_to_float64_t: +**... +** scvtf d[0-9]+, s[0-9]+ +**... +*/ +CONVERT (int32_t, float64_t) + +/* +** convert_int64_t_to_float16_t: +**... +** scvtf h[0-9]+, d[0-9]+ +**... +*/ +CONVERT (int64_t, float16_t) + +/* +** convert_int64_t_to_float32_t: +**... +** scvtf s[0-9]+, d[0-9]+ +**... +*/ +CONVERT (int64_t, float32_t) + +/* +** convert_uint32_t_to_float16_t: +**... +** ucvtf h[0-9]+, s[0-9]+ +**... +*/ +CONVERT (uint32_t, float16_t) + +/* +** convert_uint32_t_to_float64_t: +**... +** ucvtf d[0-9]+, s[0-9]+ +**... +*/ +CONVERT (uint32_t, float64_t) + +/* +** convert_uint64_t_to_float16_t: +**... +** ucvtf h[0-9]+, d[0-9]+ +**... +*/ +CONVERT (uint64_t, float16_t) + +/* +** convert_uint64_t_to_float32_t: +**... +** ucvtf s[0-9]+, d[0-9]+ +**... +*/ +CONVERT (uint64_t, float32_t) diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt.x b/gcc/testsuite/gcc.target/aarch64/fprcvt.x new file mode 100644 index 000000000000..a4e8fc395058 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt.x @@ -0,0 +1,87 @@ +extern GPF SUFFIX(trunc) (GPF); +extern GPF SUFFIX(ceil) (GPF); +extern GPF SUFFIX(floor) (GPF); +extern GPF SUFFIX(round) (GPF); + +#define FORCE_FP_REG(a) asm volatile("fmov %d0, %d1" : "=w"(a) : "w"(a) :) + +GPI test1a (GPF x) { + FORCE_FP_REG(x); + GPI res = SUFFIX(__builtin_trunc)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test1b (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(trunc)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test2a (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(__builtin_lceil)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test2b (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(ceil)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test2c (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(__builtin_ceil)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test3a (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(__builtin_lfloor)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test3b (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(floor)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test3c (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(__builtin_floor)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test4a (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(__builtin_round)(x); + FORCE_FP_REG(res); + return res; +} + +GPI test4b (GPF x) +{ + FORCE_FP_REG(x); + GPI res = SUFFIX(round)(x); + FORCE_FP_REG(res); + return res; +} + + diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_int32.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_int32.c new file mode 100644 index 000000000000..6a086339e1b1 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_int32.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float32_t +#define SUFFIX(x) x##f +#define GPI int32_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzs\ts\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *s\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtps\ts\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *s\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtms\ts\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtas\ts\[0-9\]+, *s\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_int64.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_int64.c new file mode 100644 index 000000000000..22464157d2fd --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_int64.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float32_t +#define SUFFIX(x) x##f +#define GPI int64_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzs\td\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *s\[0-9\]" 3 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *s\[0-9\]" 3 } } */ +/* { dg-final { scan-assembler-times "fcvtas\td\[0-9\]+, *s\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_uint32.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_uint32.c new file mode 100644 index 000000000000..87e4686edd33 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_uint32.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float32_t +#define SUFFIX(x) x##f +#define GPI uint32_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzu\ts\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *s\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtpu\ts\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *s\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtmu\ts\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtau\ts\[0-9\]+, *s\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_uint64.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_uint64.c new file mode 100644 index 000000000000..76922b33edf2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float32_uint64.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float32_t +#define SUFFIX(x) x##f +#define GPI uint64_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzu\td\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *s\[0-9\]" 1 } } * +/* { dg-final { scan-assembler-times "fcvtpu\td\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *s\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtmu\td\[0-9\]+, *s\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtau\td\[0-9\]+, *s\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_int32.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_int32.c new file mode 100644 index 000000000000..dd772600e0d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_int32.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float64_t +#define SUFFIX(x) x +#define GPI int32_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzs\ts\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *d\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtps\ts\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *d\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtms\ts\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtas\ts\[0-9\]+, *d\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_int64.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_int64.c new file mode 100644 index 000000000000..c28960a46014 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_int64.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float64_t +#define SUFFIX(x) x +#define GPI int64_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzs\td\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *d\[0-9\]" 3 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *d\[0-9\]" 3 } } */ +/* { dg-final { scan-assembler-times "fcvtas\td\[0-9\]+, *d\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_uint32.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_uint32.c new file mode 100644 index 000000000000..7dcd0cc41f61 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_uint32.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float64_t +#define SUFFIX(x) x +#define GPI uint32_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzu\ts\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *d\[0-9\]" 1 } } * +/* { dg-final { scan-assembler-times "fcvtpu\ts\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *d\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtmu\ts\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtau\ts\[0-9\]+, *d\[0-9\]" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_uint64.c b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_uint64.c new file mode 100644 index 000000000000..f0d385d44c1d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/fprcvt_float64_uint64.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv9-a+fprcvt" } */ + +#include <stdint.h> +#include <arm_neon.h> + +#define GPF float64_t +#define SUFFIX(x) x +#define GPI uint64_t + +#include "fprcvt.x" + +/* { dg-final { scan-assembler-times "fcvtzu\td\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtpu\td\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtps\td\[0-9\]+, *d\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtmu\td\[0-9\]+, *d\[0-9\]" 2 } } */ +/* { dg-final { scan-assembler-times "fcvtms\td\[0-9\]+, *d\[0-9\]" 1 } } */ +/* { dg-final { scan-assembler-times "fcvtau\td\[0-9\]+, *d\[0-9\]" 2 } } */
