Hi all,This patch implements the {lceil, lfloor, lround}si{sf, df}2 optabs in a similar way to fcvt in aarch64. We use the new ARMv8 FP convert with rounding instructions vcvt{a,p,m} for that.
Bootstrapped and tested on arm-none-linux-gnueabihf. Ok for trunk? Thanks, Kyrill 2014-09-02 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR target/62275 * config/arm/iterators.md (FIXUORS): New code iterator. (VCVT): New int iterator. (su_optab): New code attribute. (su): Likewise. * config/arm/vfp.md (l<vrint_pattern><su_optab><mode>si2): New pattern. 2014-09-02 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR target/62275 * gcc.target/arm/lceil-vcvt_1.c: New test. * gcc.target/arm/lfloor-vcvt_1.c: Likewise. * gcc.target/arm/lround-vcvt_1.c: Likewise.
commit ba3ec05be54d74ee53d287dfa4eb7b5508292e59 Author: Kyrylo Tkachov <kyrylo.tkac...@arm.com> Date: Thu Aug 21 12:28:00 2014 +0100 [ARM] Implement ARMv8-A vcvt* optabs diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 6fe6eef..f7e0e14 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -194,6 +194,9 @@ (define_code_iterator SE [sign_extend zero_extend]) ;; Right shifts (define_code_iterator rshifts [ashiftrt lshiftrt]) +;; Iterator for integer conversions +(define_code_iterator FIXUORS [fix unsigned_fix]) + ;; Binary operators whose second operand can be shifted. (define_code_iterator shiftable_ops [plus minus ior xor and]) @@ -215,6 +218,8 @@ (define_code_attr arith_shift_insn (define_int_iterator VRINT [UNSPEC_VRINTZ UNSPEC_VRINTP UNSPEC_VRINTM UNSPEC_VRINTR UNSPEC_VRINTX UNSPEC_VRINTA]) +(define_int_iterator VCVT [UNSPEC_VRINTP UNSPEC_VRINTM UNSPEC_VRINTA]) + (define_int_iterator NEON_VRINT [UNSPEC_NVRINTP UNSPEC_NVRINTZ UNSPEC_NVRINTM UNSPEC_NVRINTX UNSPEC_NVRINTA UNSPEC_NVRINTN]) @@ -519,6 +524,13 @@ (define_code_attr optab [(ltu "ltu") (geu "geu")]) ;; Assembler mnemonics for signedness of widening operations. (define_code_attr US [(sign_extend "s") (zero_extend "u")]) +;; Signedness suffix for float->fixed conversions. Empty for signed +;; conversion. +(define_code_attr su_optab [(fix "") (unsigned_fix "u")]) + +;; Sign prefix to use in instruction type suffixes, i.e. s32, u32. +(define_code_attr su [(fix "s") (unsigned_fix "u")]) + ;; Right shifts (define_code_attr shift [(ashiftrt "ashr") (lshiftrt "lshr")]) (define_code_attr shifttype [(ashiftrt "signed") (lshiftrt "unsigned")]) diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md index 90e001c..a203449 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -1306,6 +1306,18 @@ (define_insn "<vrint_pattern><SDF:mode>2" (set_attr "conds" "<vrint_conds>")] ) +;; Implements the lround, lfloor and lceil optabs. +(define_insn "l<vrint_pattern><su_optab><mode>si2" + [(set (match_operand:SI 0 "register_operand" "=t") + (FIXUORS:SI (unspec:SDF + [(match_operand:SDF 1 + "register_operand" "<F_constraint>")] VCVT)))] + "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>" + "vcvt<vrint_variant>%?.<su>32.<V_if_elem>\\t%0, %<V_reg>1" + [(set_attr "predicable" "no") + (set_attr "type" "f_cvtf2i")] +) + ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL. ;; The 'smax' and 'smin' RTL standard pattern names do not specify which ;; operand will be returned when both operands are zero (i.e. they may not diff --git a/gcc/testsuite/gcc.target/arm/lceil-vcvt_1.c b/gcc/testsuite/gcc.target/arm/lceil-vcvt_1.c new file mode 100644 index 0000000..bbe4271 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/lceil-vcvt_1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_vfp_ok } */ +/* { dg-options "-O2 -march=armv8-a" } */ +/* { dg-add-options arm_v8_vfp } */ + +int +foofloat (float x) +{ + return __builtin_lceilf (x); +} + +/* { dg-final { scan-assembler-times "vcvtp.s32.f32\ts\[0-9\]+, s\[0-9\]+" 1 } } */ + + +int +foodouble (double x) +{ + return __builtin_lceil (x); +} + +/* { dg-final { scan-assembler-times "vcvtp.s32.f64\ts\[0-9\]+, d\[0-9\]+" 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/lfloor-vcvt_1.c b/gcc/testsuite/gcc.target/arm/lfloor-vcvt_1.c new file mode 100644 index 0000000..88671d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/lfloor-vcvt_1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_vfp_ok } */ +/* { dg-options "-O2 -march=armv8-a" } */ +/* { dg-add-options arm_v8_vfp } */ + +int +foofloat (float x) +{ + return __builtin_lfloorf (x); +} + +/* { dg-final { scan-assembler-times "vcvtm.s32.f32\ts\[0-9\]+, s\[0-9\]+" 1 } } */ + + +int +foodouble (double x) +{ + return __builtin_lfloor (x); +} + +/* { dg-final { scan-assembler-times "vcvtm.s32.f64\ts\[0-9\]+, d\[0-9\]+" 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/lround-vcvt_1.c b/gcc/testsuite/gcc.target/arm/lround-vcvt_1.c new file mode 100644 index 0000000..8b1f6a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/lround-vcvt_1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_vfp_ok } */ +/* { dg-options "-O2 -march=armv8-a -ffast-math" } */ +/* { dg-add-options arm_v8_vfp } */ + +int +foofloat (float x) +{ + return __builtin_lroundf (x); +} + +/* { dg-final { scan-assembler-times "vcvta.s32.f32\ts\[0-9\]+, s\[0-9\]+" 1 } } */ + + +int +foodouble (double x) +{ + return __builtin_lround (x); +} + +/* { dg-final { scan-assembler-times "vcvta.s32.f64\ts\[0-9\]+, d\[0-9\]+" 1 } } */